<commit_before>var EventEmitter = require('events').EventEmitter;
var async        = require('async');
var LimitdClient = require('./client');
var _            = require('lodash');
var util         = require('util');

function LimitdPool (options, done) {
  EventEmitter.call(this);

  var size = options.size || 5;
  var created = 0;
  var clients = this._clients = [];

  done = done || _.noop;

  this._current_client = 0;

  var pool = this;

  async.whilst(
    function () { return created < size; },
    function (done) {
      var client = new LimitdClient(options, function (err) {
        created++;

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

        client.on('error', function (err) {
          pool.emit('error', err, client);
        });

        clients.push(client);
        done();
      });
    }, done);
}

util.inherits(LimitdPool, EventEmitter);

LimitdPool.prototype._getClient = function () {
  if (this._clients.length === 0) {
    return;
  }

  this._current_client++;

  if (this._current_client >= this._clients.length) {
    this._current_client = 0;
  }

  return this._clients[this._current_client];
};

Object.keys(LimitdClient).forEach(function (method) {
  LimitdPool.prototype[method] = function () {
   var client = this._getClient();
   client[method].apply(client, arguments);
  };
});

module.exports = LimitdPool;<commit_msg>fix pool implementation<commit_after>var EventEmitter = require('events').EventEmitter;
var async        = require('async');
var LimitdClient = require('./client');
var _            = require('lodash');
var util         = require('util');

function LimitdPool (options, done) {
  EventEmitter.call(this);

  var size = options.size || 5;
  var created = 0;
  var clients = this._clients = [];

  done = done || _.noop;

  this._current_client = 0;

  var pool = this;

  async.whilst(
    function () { return created < size; },
    function (done) {
      var client = new LimitdClient(options, function (err) {
        created++;

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

        client.on('error', function (err) {
          pool.emit('error', err, client);
        });

        clients.push(client);
        done();
      });
    }, done);
}

util.inherits(LimitdPool, EventEmitter);

LimitdPool.prototype._getClient = function () {
  if (this._clients.length === 0) {
    return;
  }

  this._current_client++;

  if (this._current_client >= this._clients.length) {
    this._current_client = 0;
  }

  return this._clients[this._current_client];
};

Object.keys(LimitdClient.prototype).forEach(function (method) {
  LimitdPool.prototype[method] = function () {
   var client = this._getClient();
   client[method].apply(client, arguments);
  };
});

module.exports = LimitdPool;<|endoftext|>


<commit_before>jQuery(document).ready(function($) {

    /*
     * jQuery simple and accessible hide-show system (collapsible regions), using ARIA
     * @version v1.7.0
     * Website: https://a11y.nicolas-hoffmann.net/hide-show/
     * License MIT: https://github.com/nico3333fr/jquery-accessible-hide-show-aria/blob/master/LICENSE
     */
    // loading expand paragraphs
    // these are recommended settings by a11y experts. You may update to fulfill your needs, but be sure of what you’re doing.
    var attr_control = 'data-controls',
        attr_expanded = 'aria-expanded',
        attr_labelledby = 'data-labelledby',
        attr_hidden = 'data-hidden',
        $expandmore = $('.js-expandmore'),
        $body = $('body'),
        delay = 1500,
        hash = window.location.hash.replace("#", ""),
        multiexpandable = true,
        expand_all_text = 'Expand All',
        collapse_all_text = 'Collapse All';

    if ($expandmore.length) { // if there are at least one :)
        $expandmore.each(function(index_to_expand) {
            var $this = $(this),
                index_lisible = index_to_expand + 1,
                options = $this.data(),
                $hideshow_prefix_classes = typeof options.hideshowPrefixClass !== 'undefined' ? options.hideshowPrefixClass + '-' : '',
                $to_expand = $this.next(".js-to_expand"),
                $expandmore_text = $this.html();

            $this.html('<button type="button" class="' + $hideshow_prefix_classes + 'expandmore__button js-expandmore-button">' + $expandmore_text + '</button>');
            var $button = $this.children('.js-expandmore-button');

            $to_expand.addClass($hideshow_prefix_classes + 'expandmore__to_expand').stop().delay(delay).queue(function() {
                var $this = $(this);
                if ($this.hasClass('js-first_load')) {
                    $this.removeClass('js-first_load');
                }
            });

            $button.attr('id', 'label_expand_' + index_lisible);
            $button.attr(attr_control, 'expand_' + index_lisible);
            $button.attr(attr_expanded, 'false');

            $to_expand.attr('id', 'expand_' + index_lisible);
            $to_expand.attr(attr_hidden, 'true');
            $to_expand.attr(attr_labelledby, 'label_expand_' + index_lisible);

            // quick tip to open (if it has class is-opened or if hash is in expand)
            if ($to_expand.hasClass('is-opened') || (hash !== "" && $to_expand.find($("#" + hash)).length)) {
                $button.addClass('is-opened').attr(attr_expanded, 'true');
                $to_expand.removeClass('is-opened').removeAttr(attr_hidden);
            }

        });

    }

    $body.on('click', '.js-expandmore-button', function(event) {
        var $this = $(this),
            $destination = $('#' + $this.attr(attr_control));

        if ($this.attr(attr_expanded) === 'false') {

            if (multiexpandable === false) {
                $('.js-expandmore-button').removeClass('is-opened').attr(attr_expanded, 'false');
                $('.js-to_expand').attr(attr_hidden, 'true');
            }

            $this.addClass('is-opened').attr(attr_expanded, 'true');
            $destination.removeAttr(attr_hidden);
        } else {
            $this.removeClass('is-opened').attr(attr_expanded, 'false');
            $destination.attr(attr_hidden, 'true');
        }

        event.preventDefault();

    });

    $body.on('click keydown', '.js-expandmore', function(event) {
        var $this = $(this),
            $target = $(event.target),
            $button_in = $this.find('.js-expandmore-button');

        if (!$target.is($button_in) && !$target.closest($button_in).length) {

            if (event.type === 'click') {
                $button_in.trigger('click');
                return false;
            }
            if (event.type === 'keydown' && (event.keyCode === 13 || event.keyCode === 32)) {
                $button_in.trigger('click');
                return false;
            }

        }

    });

    $body.on('click keydown', '.js-expandmore-all', function(event) {
        var $this = $(this),
            is_expanded = $this.attr('data-expand'),
            $all_buttons = $('.js-expandmore-button'),
            $all_destinations = $('.js-to_expand');

        if (
            event.type === 'click' ||
            (event.type === 'keydown' && (event.keyCode === 13 || event.keyCode === 32))
        ) {
            if (is_expanded === 'true') {

                $all_buttons.addClass('is-opened').attr(attr_expanded, 'true');
                $all_destinations.removeAttr(attr_hidden);
                $this.attr('data-expand', 'false').html(collapse_all_text);
            } else {
                $all_buttons.removeClass('is-opened').attr(attr_expanded, 'false');
                $all_destinations.attr(attr_hidden, 'true');
                $this.attr('data-expand', 'true').html(expand_all_text);
            }

        }

    });

});
<commit_msg>Accessibility : add a span in button.expandmore__button (avoid ::before or ::after content directly added to the button to be read by some AT)<commit_after>jQuery(document).ready(function($) {

    /*
     * jQuery simple and accessible hide-show system (collapsible regions), using ARIA
     * @version v1.7.0
     * Website: https://a11y.nicolas-hoffmann.net/hide-show/
     * License MIT: https://github.com/nico3333fr/jquery-accessible-hide-show-aria/blob/master/LICENSE
     */
    // loading expand paragraphs
    // these are recommended settings by a11y experts. You may update to fulfill your needs, but be sure of what you’re doing.
    var attr_control = 'data-controls',
        attr_expanded = 'aria-expanded',
        attr_labelledby = 'data-labelledby',
        attr_hidden = 'data-hidden',
        $expandmore = $('.js-expandmore'),
        $body = $('body'),
        delay = 1500,
        hash = window.location.hash.replace("#", ""),
        multiexpandable = true,
        expand_all_text = 'Expand All',
        collapse_all_text = 'Collapse All';

    if ($expandmore.length) { // if there are at least one :)
        $expandmore.each(function(index_to_expand) {
            var $this = $(this),
                index_lisible = index_to_expand + 1,
                options = $this.data(),
                $hideshow_prefix_classes = typeof options.hideshowPrefixClass !== 'undefined' ? options.hideshowPrefixClass + '-' : '',
                $to_expand = $this.next(".js-to_expand"),
                $expandmore_text = $this.html();

            $this.html('<button type="button" class="' + $hideshow_prefix_classes + 'expandmore__button js-expandmore-button">' + $expandmore_text + '</button>');
            var $button = $this.children('.js-expandmore-button');

            $to_expand.addClass($hideshow_prefix_classes + 'expandmore__to_expand').stop().delay(delay).queue(function() {
                var $this = $(this);
                if ($this.hasClass('js-first_load')) {
                    $this.removeClass('js-first_load');
                }
            });

            $button.attr('id', 'label_expand_' + index_lisible);
            $button.attr(attr_control, 'expand_' + index_lisible);
            $button.attr(attr_expanded, 'false');

            $to_expand.attr('id', 'expand_' + index_lisible);
            $to_expand.attr(attr_hidden, 'true');
            $to_expand.attr(attr_labelledby, 'label_expand_' + index_lisible);

            // quick tip to open (if it has class is-opened or if hash is in expand)
            if ($to_expand.hasClass('is-opened') || (hash !== "" && $to_expand.find($("#" + hash)).length)) {
                $button.addClass('is-opened').attr(attr_expanded, 'true');
                $to_expand.removeClass('is-opened').removeAttr(attr_hidden);
            }

        });

    }

    $body.on('click', '.js-expandmore-button', function(event) {
        var $this = $(this),
            $destination = $('#' + $this.attr(attr_control));

        if ($this.attr(attr_expanded) === 'false') {

            if (multiexpandable === false) {
                $('.js-expandmore-button').removeClass('is-opened').attr(attr_expanded, 'false');
                $('.js-to_expand').attr(attr_hidden, 'true');
            }

            $this.addClass('is-opened').attr(attr_expanded, 'true');
            $destination.removeAttr(attr_hidden);
        } else {
            $this.removeClass('is-opened').attr(attr_expanded, 'false');
            $destination.attr(attr_hidden, 'true');
        }

        event.preventDefault();

    });

    $body.on('click keydown', '.js-expandmore', function(event) {
        var $this = $(this),
            $target = $(event.target),
            $button_in = $this.find('.js-expandmore-button');

        if (!$target.is($button_in) && !$target.closest($button_in).length) {

            if (event.type === 'click') {
                $button_in.trigger('click');
                return false;
            }
            if (event.type === 'keydown' && (event.keyCode === 13 || event.keyCode === 32)) {
                $button_in.trigger('click');
                return false;
            }

        }

    });

    $body.on('click keydown', '.js-expandmore-all', function(event) {
        var $this = $(this),
            is_expanded = $this.attr('data-expand'),
            $all_buttons = $('.js-expandmore-button'),
            $all_destinations = $('.js-to_expand');

        if (
            event.type === 'click' ||
            (event.type === 'keydown' && (event.keyCode === 13 || event.keyCode === 32))
        ) {
            if (is_expanded === 'true') {

                $all_buttons.addClass('is-opened').attr(attr_expanded, 'true');
                $all_destinations.removeAttr(attr_hidden);
                $this.attr('data-expand', 'false').html(collapse_all_text);
            } else {
                $all_buttons.removeClass('is-opened').attr(attr_expanded, 'false');
                $all_destinations.attr(attr_hidden, 'true');
                $this.attr('data-expand', 'true').html(expand_all_text);
            }

        }

    });

});
<|endoftext|>


<commit_before>const CssParse = imports.app.compat.cssParse;
const Lang = imports.lang;

function get_knobs_from_css (css, template_type) {
    let lines = css.split('\n');

    let knob_map = lines.filter((line) => line.startsWith('@define'))
        .reduce(definitions_to_knobs, {});

    let css_parse_tree = CssParse.parse(lines.filter((line) => !line.startsWith('@define'))
        .join('\n'));

    return css_parse_tree.stylesheet.rules.filter((rule) => rule.type === 'rule')
        .reduce((knobs, rule) => {
            let props = rule.declarations.reduce(css_declation_to_properties, {});
            if (template_type === 'reader') {
                rule.selectors.forEach((selector) => {
                    selector_to_knob_reader(knobs, props, selector);
                });
            } else {
                rule.selectors.forEach((selector) => {
                    selector_to_knob_ka(knobs, props, selector);
                });
            }
            return knobs;
        }, knob_map);
}

/*
 * A helper function to merge the properties of two objects, giving preference
 * to obj2's values in the case of a conflict.
*/
function merge_object_properties (obj1={}, obj2={}) {
    Lang.copyProperties(obj2, obj1);
    return obj1;
}

/*
 * A reduce function that takes in the <knobs> object that is being populated
 * and a single <definition>, which is a CSS constant definition such as:
 * @define-color template-b-text-color #FFCCF8;
 * It converts this definition to a knob and adds it to the <knobs> object
*/
function definitions_to_knobs (knobs, definition) {
    let terms = definition.split(' ');
    let name = terms[1];
    let value = terms[2].substring(0, terms[2].length - 1);
    switch (name) {
        case 'template-b-text-color':
            knobs['section_card'] = merge_object_properties(knobs['section_card'], {'title-color': value});
            knobs['article_card'] = merge_object_properties(knobs['article_card'], {'title-color': value});
            break;
        case 'template-b-text-color-hover':
            knobs['section_card'] = merge_object_properties(knobs['section_card'], {'hover-color': value});
            knobs['article_card'] = merge_object_properties(knobs['article_card'], {'hover-color': value});
            break;
        case 'tab-button-background':
            knobs['tab_button'] = merge_object_properties(knobs['tab_button'], {'module-background-color': value});
            break;
    }
    return knobs;
}

/*
 * A reduce function that takes 1) the properties object that is being populated
 * with CSS styles for a module and 2) a CSS declaration. The CSS info is
 * extracted from the declaration and included into the properties object.
 * So, at the end, the properties object will look something like:
 * {
 *   color: "blue",
 *   font-weight: "bold",
 *   font-family: "Lato",
 * }
*/
function css_declation_to_properties (props, declaration) {
    if (declaration.type === 'declaration') {
        props[declaration.property] = declaration.value;
    }
    return props;
}

function prefix_keys_with(props, prefix) {
    let retval = {};
    for (let key in props) {
        retval[prefix + key] = props[key];
    }
    return retval;
}

function selector_to_knob_reader (knobs, props, selector) {
    let num = (selector.match(/\d+/) || [])[0];
    if (/.article\-page[0-2] .article\-page\-attribution/.test(selector)) {
        knobs['article_page' + num] = merge_object_properties(knobs['article_page' + num], prefix_keys_with(props, 'module-'));
    } else if (/.article\-page[0-2].*/.test(selector)) {
        knobs['article_page' + num] = merge_object_properties(knobs['article_page' + num], prefix_keys_with(props, 'title-'));
    } else if (/.snippet[0-2] .title/.test(selector)) {
        knobs['snippet' + num] = merge_object_properties(knobs['snippet' + num], prefix_keys_with(props, 'title-'));
    } else if (/.reader-card[0-2] .reader-attribution/.test(selector)) {
        knobs['reader_card' + num] = merge_object_properties(knobs['reader_card' + num], prefix_keys_with(props, 'module-'));
    } else if (/.reader-card[0-2].*/.test(selector)) {
        knobs['reader_card' + num] = merge_object_properties(knobs['reader_card' + num], prefix_keys_with(props, 'title-'));
    } else {
        switch (selector) {
            case '.overview-frame':
                knobs['overview_page'] = merge_object_properties(knobs['overview_page'], prefix_keys_with(props, 'module-'));
                break;
            case '.article-snippet .synopsis':
                for (let i = 0; i < 3; i++) {
                    knobs['snippet' + i] = merge_object_properties(knobs['snippet' + i], prefix_keys_with(props, 'module-'));
                }
                break;
            case '.done-page .bottom-line':
                knobs['back_cover'] = merge_object_properties(knobs['back_cover'], prefix_keys_with(props, 'module-'));
                break;
            case '.done-page .headline':
                knobs['back_cover'] = merge_object_properties(knobs['back_cover'], prefix_keys_with(props, 'title-'));
                break;
        }
    }

}

function selector_to_knob_ka (knobs, props, selector) {
    switch (selector) {
        case '.section-page-title':
            knobs['section_page'] = merge_object_properties(knobs['section_page'], prefix_keys_with(props, 'title-'));
            break;
        case '.search-page-title':
            knobs['search_page'] = merge_object_properties(knobs['search_page'], prefix_keys_with(props, 'title-'));
            break;
        case '.no-search-results-page-title':
            knobs['no_search_results_page'] = merge_object_properties(knobs['no_search_results_page'], prefix_keys_with(props, 'title-'));
            break;
        case '.home-page .card-title':
            knobs['section_card'] = merge_object_properties(knobs['section_card'], prefix_keys_with(props, 'title-'));
            break;
        case '.card':
            knobs['section_card'] = merge_object_properties(knobs['section_card'], prefix_keys_with(props, 'module-'));
            knobs['article_card'] = merge_object_properties(knobs['article_card'], prefix_keys_with(props, 'module-'));
            break;
        case '.card-title':
        case '.card .card-title':
            knobs['section_card'] = merge_object_properties(knobs['section_card'], prefix_keys_with(props, 'title-'));
            knobs['article_card'] = merge_object_properties(knobs['article_card'], prefix_keys_with(props, 'title-'));
            break;
        default:
            break;
    }
}
<commit_msg>styleKnobGenerator: add compat theme override for search pages<commit_after>const CssParse = imports.app.compat.cssParse;
const Lang = imports.lang;

function get_knobs_from_css (css, template_type) {
    let lines = css.split('\n');

    let knob_map = lines.filter((line) => line.startsWith('@define'))
        .reduce(definitions_to_knobs, {});

    let css_parse_tree = CssParse.parse(lines.filter((line) => !line.startsWith('@define'))
        .join('\n'));

    return css_parse_tree.stylesheet.rules.filter((rule) => rule.type === 'rule')
        .reduce((knobs, rule) => {
            let props = rule.declarations.reduce(css_declation_to_properties, {});
            if (template_type === 'reader') {
                rule.selectors.forEach((selector) => {
                    selector_to_knob_reader(knobs, props, selector);
                });
            } else {
                rule.selectors.forEach((selector) => {
                    selector_to_knob_ka(knobs, props, selector);
                });
            }
            return knobs;
        }, knob_map);
}

/*
 * A helper function to merge the properties of two objects, giving preference
 * to obj2's values in the case of a conflict.
*/
function merge_object_properties (obj1={}, obj2={}) {
    Lang.copyProperties(obj2, obj1);
    return obj1;
}

/*
 * A reduce function that takes in the <knobs> object that is being populated
 * and a single <definition>, which is a CSS constant definition such as:
 * @define-color template-b-text-color #FFCCF8;
 * It converts this definition to a knob and adds it to the <knobs> object
*/
function definitions_to_knobs (knobs, definition) {
    let terms = definition.split(' ');
    let name = terms[1];
    let value = terms[2].substring(0, terms[2].length - 1);
    switch (name) {
        case 'template-b-text-color':
            knobs['section_card'] = merge_object_properties(knobs['section_card'], {'title-color': value});
            knobs['article_card'] = merge_object_properties(knobs['article_card'], {'title-color': value});
            break;
        case 'template-b-text-color-hover':
            knobs['section_card'] = merge_object_properties(knobs['section_card'], {'hover-color': value});
            knobs['article_card'] = merge_object_properties(knobs['article_card'], {'hover-color': value});
            break;
        case 'tab-button-background':
            knobs['tab_button'] = merge_object_properties(knobs['tab_button'], {'module-background-color': value});
            break;
    }
    return knobs;
}

/*
 * A reduce function that takes 1) the properties object that is being populated
 * with CSS styles for a module and 2) a CSS declaration. The CSS info is
 * extracted from the declaration and included into the properties object.
 * So, at the end, the properties object will look something like:
 * {
 *   color: "blue",
 *   font-weight: "bold",
 *   font-family: "Lato",
 * }
*/
function css_declation_to_properties (props, declaration) {
    if (declaration.type === 'declaration') {
        props[declaration.property] = declaration.value;
    }
    return props;
}

function prefix_keys_with(props, prefix) {
    let retval = {};
    for (let key in props) {
        retval[prefix + key] = props[key];
    }
    return retval;
}

function selector_to_knob_reader (knobs, props, selector) {
    let num = (selector.match(/\d+/) || [])[0];
    if (/.article\-page[0-2] .article\-page\-attribution/.test(selector)) {
        knobs['article_page' + num] = merge_object_properties(knobs['article_page' + num], prefix_keys_with(props, 'module-'));
    } else if (/.article\-page[0-2].*/.test(selector)) {
        knobs['article_page' + num] = merge_object_properties(knobs['article_page' + num], prefix_keys_with(props, 'title-'));
    } else if (/.snippet[0-2] .title/.test(selector)) {
        knobs['snippet' + num] = merge_object_properties(knobs['snippet' + num], prefix_keys_with(props, 'title-'));
    } else if (/.reader-card[0-2] .reader-attribution/.test(selector)) {
        knobs['reader_card' + num] = merge_object_properties(knobs['reader_card' + num], prefix_keys_with(props, 'module-'));
    } else if (/.reader-card[0-2].*/.test(selector)) {
        knobs['reader_card' + num] = merge_object_properties(knobs['reader_card' + num], prefix_keys_with(props, 'title-'));
    } else {
        switch (selector) {
            case '.overview-frame':
                knobs['overview_page'] = merge_object_properties(knobs['overview_page'], prefix_keys_with(props, 'module-'));
                break;
            case '.article-snippet .synopsis':
                for (let i = 0; i < 3; i++) {
                    knobs['snippet' + i] = merge_object_properties(knobs['snippet' + i], prefix_keys_with(props, 'module-'));
                }
                break;
            case '.done-page .bottom-line':
                knobs['back_cover'] = merge_object_properties(knobs['back_cover'], prefix_keys_with(props, 'module-'));
                break;
            case '.done-page .headline':
                knobs['back_cover'] = merge_object_properties(knobs['back_cover'], prefix_keys_with(props, 'title-'));
                break;
        }
    }

}

function selector_to_knob_ka (knobs, props, selector) {
    switch (selector) {
        case '.section-page-title':
            knobs['section_page'] = merge_object_properties(knobs['section_page'], prefix_keys_with(props, 'title-'));
            knobs['search_page'] = merge_object_properties(knobs['search_page'], prefix_keys_with(props, 'title-'));
            break;
        case '.no-search-results-page-title':
            knobs['no_search_results_page'] = merge_object_properties(knobs['no_search_results_page'], prefix_keys_with(props, 'title-'));
            break;
        case '.home-page .card-title':
            knobs['section_card'] = merge_object_properties(knobs['section_card'], prefix_keys_with(props, 'title-'));
            break;
        case '.card':
            knobs['section_card'] = merge_object_properties(knobs['section_card'], prefix_keys_with(props, 'module-'));
            knobs['article_card'] = merge_object_properties(knobs['article_card'], prefix_keys_with(props, 'module-'));
            break;
        case '.card-title':
        case '.card .card-title':
            knobs['section_card'] = merge_object_properties(knobs['section_card'], prefix_keys_with(props, 'title-'));
            knobs['article_card'] = merge_object_properties(knobs['article_card'], prefix_keys_with(props, 'title-'));
            break;
        default:
            break;
    }
}
<|endoftext|>


<commit_before>/*!
 * SWIF-OpenSTC
 * Copyright 2013-2014 Siclic <contact@siclic.fr>
 * Licensed under AGPL-3.0 (https://www.gnu.org/licenses/agpl.txt)
 */

define([

	'app',
	'filterModel'

], function(app, FilterModel){

	'use strict';

	/******************************************
	* Recording filter view
	*/
	var FilterView = Backbone.View.extend({

		templateHTML   : 'templates/others/recordFilter.html',

		components : [],

		filters    : [],

		//Static variables uses to build url
		URL_CTXT    : '/filter/',
		SLASH_CHAR	: '/',

		// The DOM events //
		events: {
			'click a.disabled'               : 'preventDefault',
			'click [href^=#filter-state]'    : 'filterByState',
			'click .delete-filter'           : 'deleteFilter'
		},

		/** View Initialization
		*/
		initialize: function(options){

			//init view parameters
			this.el = options.el;
			this.metaDataModel = options.metaDataModel;
			this.states = options.states;
			this.listView = options.listView;

			//prepares variables to construct url filter in template
			this.prepareUrls();

			//Fetch meta model
			this.metaDataModel.fetch();
		},

		/** View Render
		*/
		render: function(){
			var self = this;

			//After get filters render view
			this.initFilters().done(function(){

				// Retrieve the template //
				$.get(self.templateHTML, function(templateData){

					self.buildUrls();

					// Seperate the Pre Recorded filter //
					var filtersArray = _.partition(self.filters, function(f){
						return f.pre_recorded == 1;
					});

					var template = _.template(templateData, {
						lang               : app.lang,
						states             : self.states,
						preRecordedFilters : filtersArray[0],
						myFilters          : filtersArray[1]
					});

					$(self.el).html(template);

					// Tooltip for the filter description //
					$('*[data-toggle="tooltip"]').tooltip({ delay: { show: 500, hide: 0 }, container: 'body' });

				});

				$(this.el).hide().fadeIn();

			});

			return this;
		},

		/** Get recording filters for model
		*/
		initFilters: function(){
			return this.metaDataModel.filters();
		},

		/** Init Urls varaiables using to buils url filters in templates
		*/
		prepareUrls: function(){
			this.urlLeftPart = Backbone.history.fragment;
			this.urlRightPart = null;

			if( _.str.include(this.urlLeftPart, this.URL_CTXT) ) {

				this.urlArray = _.words(this.urlLeftPart, this.URL_CTXT);
				this.urlLeftPart = this.urlArray[0];
				this.urlRightPart = _(this.urlArray[1]).strRight(this.SLASH_CHAR);
				var filter = parseInt(this.urlArray[1][0]);
				if( _.isNaN(filter) ) {
					this.urlRightPart = this.SLASH_CHAR + this.urlRightPart;
				}
				else{
					if( _.str.include(this.urlRightPart,this.SLASH_CHAR) ){
						this.urlRightPart = this.SLASH_CHAR + this.urlRightPart;
					}
					else{
						this.urlRightPart = null;
					}
				}
			}
		},

		/** Builds url for each filters in template
		*/
		buildUrls: function() {
			this.filters = [];

			var self = this;
			_.each(self.metaDataModel.getFilters(),function(f){
				if ( !_.isNull( self.urlRightPart ) ) {
					f.route = _.join(self.URL_CTXT, self.urlLeftPart , _(self.urlRightPart).splice(0, 0, f.id) );
				}
				else {
					f.route = _.join(self.URL_CTXT, self.urlLeftPart, f.id);
				}
				self.filters.push(f);
			});
		},

		/** Filter list by state
		*/
		filterByState: function(e){
			e.preventDefault();

			var state = _(e.currentTarget.href).strRight('_');
			var filters = [{field: 'state', operator: 'in', value: [state] }];

			this.listView.applyAdvancedFilters(filters);
		},

		/** Delete the filter
		*/
		deleteFilter: function(e){
			e.preventDefault();

			var selectedFilter = $(e.currentTarget).parents('a').data('filter-name');

			var filterModels = _.filter(this.metaDataModel.getFilters(), function(f){
				return _.slugify(f.name) === selectedFilter;
			});

			var filterModel = new FilterModel();
			filterModel.setName(filterModels[0].name);
			filterModel.setId(filterModels[0].id);

			// Delete the Model //
			filterModel.destroy()
			.done(function(){
				app.notify('', 'success', app.lang.infoMessages.information, app.lang.infoMessages.filterDeleteOk);
			})
			.fail(function(){
				app.notify('', 'error', app.lang.errorMessages.unablePerformAction, '');
			});

		},

		preventDefault: function(e){
			e.preventDefault();
		}

	});

	return FilterView;

});<commit_msg>refs #2500 : Recherche rapide puis sélection d'un filtre enregistrée<commit_after>/*!
 * SWIF-OpenSTC
 * Copyright 2013-2014 Siclic <contact@siclic.fr>
 * Licensed under AGPL-3.0 (https://www.gnu.org/licenses/agpl.txt)
 */

define([

	'app',
	'filterModel'

], function(app, FilterModel){

	'use strict';

	/******************************************
	* Recording filter view
	*/
	var FilterView = Backbone.View.extend({

		templateHTML   : 'templates/others/recordFilter.html',

		components : [],

		filters    : [],

		//Static variables uses to build url
		URL_FILTER_CTXT    : '/filter/',
		URL_SORT_CTXT    : '/sort/',
		SLASH_CHAR	: '/',

		// The DOM events //
		events: {
			'click a.disabled'               : 'preventDefault',
			'click [href^=#filter-state]'    : 'filterByState',
			'click .delete-filter'           : 'deleteFilter'
		},

		/** View Initialization
		*/
		initialize: function(options){

			//init view parameters
			this.el = options.el;
			this.metaDataModel = options.metaDataModel;
			this.states = options.states;
			this.listView = options.listView;

			//prepares variables to construct url filter in template
			this.prepareUrls();

			//Fetch meta model
			this.metaDataModel.fetch();
		},

		/** View Render
		*/
		render: function(){
			var self = this;

			//After get filters render view
			this.initFilters().done(function(){

				// Retrieve the template //
				$.get(self.templateHTML, function(templateData){

					self.buildUrls();

					// Seperate the Pre Recorded filter //
					var filtersArray = _.partition(self.filters, function(f){
						return f.pre_recorded == 1;
					});

					var template = _.template(templateData, {
						lang               : app.lang,
						states             : self.states,
						preRecordedFilters : filtersArray[0],
						myFilters          : filtersArray[1]
					});

					$(self.el).html(template);

					// Tooltip for the filter description //
					$('*[data-toggle="tooltip"]').tooltip({ delay: { show: 500, hide: 0 }, container: 'body' });

				});

				$(this.el).hide().fadeIn();

			});

			return this;
		},

		/** Get recording filters for model
		*/
		initFilters: function(){
			return this.metaDataModel.filters();
		},

		/** Init Urls varaiables using to buils url recorded filters in templates
		*/
		prepareUrls: function(){
			this.urlLeftPart = Backbone.history.fragment;
			this.urlRightPart = null;

			if( _.str.include(this.urlLeftPart, this.URL_FILTER_CTXT) ) {
				//url contains filter
				this.urlArray = _.words(this.urlLeftPart, this.URL_FILTER_CTXT);
				this.urlLeftPart = this.urlArray[0];
				this.urlRightPart = _(this.urlArray[1]).strRight(this.SLASH_CHAR);
				var filter = parseInt(this.urlArray[1][0]);
				if( _.isNaN(filter) ) {
					this.urlRightPart = this.SLASH_CHAR + this.urlRightPart;
				}
				else{
					if( _.str.include(this.urlRightPart,this.SLASH_CHAR) ){
						this.urlRightPart = this.SLASH_CHAR + this.urlRightPart;
					}
					else{
						this.urlRightPart = null;
					}
				}
			}
			else if ( _.str.include(this.urlLeftPart, this.URL_SORT_CTXT) ) {
				//url contains sort
				this.urlArray = _.words(this.urlLeftPart, this.URL_SORT_CTXT);
				this.urlLeftPart = this.urlArray[0];
				this.urlRightPart =  this.URL_SORT_CTXT + this.urlArray[1];
			}
		},

		/** Builds url for each filters in template
		*/
		buildUrls: function() {
			this.filters = [];

			var self = this;
			_.each(self.metaDataModel.getFilters(),function(f){
				if ( !_.isNull( self.urlRightPart ) ) {
					f.route = _.join(self.URL_FILTER_CTXT, self.urlLeftPart , _(self.urlRightPart).splice(0, 0, f.id) );
				}
				else {
					f.route = _.join(self.URL_FILTER_CTXT, self.urlLeftPart, f.id);
				}
				self.filters.push(f);
			});
		},

		/** Filter list by state
		*/
		filterByState: function(e){
			e.preventDefault();

			var state = _(e.currentTarget.href).strRight('_');
			var filters = [{field: 'state', operator: 'in', value: [state] }];

			this.listView.applyAdvancedFilters(filters);
		},

		/** Delete the filter
		*/
		deleteFilter: function(e){
			e.preventDefault();

			var selectedFilter = $(e.currentTarget).parents('a').data('filter-name');

			var filterModels = _.filter(this.metaDataModel.getFilters(), function(f){
				return _.slugify(f.name) === selectedFilter;
			});

			var filterModel = new FilterModel();
			filterModel.setName(filterModels[0].name);
			filterModel.setId(filterModels[0].id);

			// Delete the Model //
			filterModel.destroy()
			.done(function(){
				app.notify('', 'success', app.lang.infoMessages.information, app.lang.infoMessages.filterDeleteOk);
			})
			.fail(function(){
				app.notify('', 'error', app.lang.errorMessages.unablePerformAction, '');
			});

		},

		preventDefault: function(e){
			e.preventDefault();
		}

	});

	return FilterView;

});<|endoftext|>


<commit_before>define([
    'jquery',
    'underscore',
    'backbone',
    '../../app/tableFacade',
    'app/filters',
    'views/tableView',
    'text!templates/region/summaryDefaultTemplate.html',
    'text!templates/region/detailsDefaultTemplate.html',
    'text!templates/region/threatsSummaryTemplate.html'
], function ($, _, Backbone, tables, filters, TableView, summaryTemplate, detailsTemplate, threatsCellTemplate) {

    return Backbone.View.extend({

        el: '#faunaTab',

        idTemplate: _.template(
            '<%= id %>'
        ),
        threatsTemplate: _.template(threatsCellTemplate),
        trendsTemplate: _.template(
            '<a  id="trends_<%= id %>">details'
        ),
        statusTemplate: _.template(
            '<%= status %>'
        ),
        managementTemplate: _.template(
            '<a id="management_<%= id %>">details'
        ),

        columnDefinitions: [
            {
                title: 'Taxon',
                width: '25%',
                data: 'id',
                render: function (data) {
                    return data.rendered
                }
            },
            {
                title: 'Threats',
                width: '25%',
                data: 'threats',
                render: function (data) {
                    return data.rendered
                }
            },
            {
                title: 'Status WA',
                width: '15%',
                data: 'status',
                render: function (data) {
                    return data.rendered
                }
            },
            {
                title: 'Trends',
                data: 'trends',
                width: '15%',
                render: function (data) {
                    return data.rendered
                }
            },
            {
                title: 'Management Requirement',
                width: '15%',
                data: 'management',
                render: function (data) {
                    return data.rendered
                }
            }
        ],

        buildSummaryThreats: function (records) {
            var pastCount = 0,
                futureCount = 0;
            _.each(records, function (r) {
                var past = r.get('PASTPRESSURES_CAT');
                var fut = r.get('FUTURETHREATS_CAT');
                if (filters.notEmpty(past)) {
                    past = past.toLowerCase();
                    if (_.contains(past, 'unknown')) {
                        pastCount = '??';
                    } else if (_.contains(past, 'no known')) {
                        pastCount = 0; //'No known';
                    } else {
                        pastCount += 1;
                    }
                }
                if (filters.notEmpty(fut)) {
                    fut = fut.toLowerCase();
                    if (_.contains(fut, 'unknown')) {
                        futureCount = 'unknown';
                    } else if (_.contains(fut, 'no known')) {
                        futureCount = 0; //'No known';
                    } else {
                        futureCount += 1;
                    }
                }
            });

            return {
                pastCount: pastCount,
                futureCount: futureCount
            }
        },

        getStatusWA: function (records) {
            var filter = _(records)
                .filter(function (r) {
                    return filters.notEmpty(r.get('STATUSWA'))
                }).value();
            if (filter.length > 0) {
                return filter[0].get('STATUSWA');
            } else {
                return ''; //'?????';
            }
        },

        buildSummaryRow: function (records, id) {
            var id_ = {
                    rendered: this.idTemplate({id: id})
                },
                threats = {
                    rendered: this.threatsTemplate(_.extend({id: id},this.buildSummaryThreats(records)))
                },
                trends = {
                    rendered: this.trendsTemplate({id: id})
                },
                status = {
                    rendered: this.statusTemplate({status: this.getStatusWA(records)})
                },
                management = {
                    rendered: this.managementTemplate({id: id})
                };

            return {
                id: id_,
                threats: threats,
                trends: trends,
                status: status,
                management: management
            };

        },

        initialize: function () {
            _.bindAll(this, 'render');
        },

        render: function () {
            if (this.model) {
                this.renderSummary()
            }
        },

        renderSummary: function () {
            this.setSummaryContent(this.buildSummaryContent());
            var tableSelector = this.getSummaryTableElement();
            var table = tables.initTable(tableSelector, {}, this.columnDefinitions);
            var buildRow = _.bind(this.buildSummaryRow, this);
            var rows = _(this.model)
                .map(function (v, k) {
                    return buildRow(v, k);
                })
                .value();
            var renderDetails = _.bind(this.renderDetails, this);
            //bind details links (should be done with the router)
            table.on('draw.dt', function () {
                $(tableSelector).find('tr a').on('click', function (e) {
                    var split = e.target.id.split('_');
                    renderDetails(split[0], split[1]);
                });

            });
            table.populate(rows);
        },

        buildSummaryContent: function () {
            var values = {label: this.label || ""};
            return _.template(summaryTemplate)(values);
        },

        renderDetails: function (type, id) {
            var records = this.model[id];
            if (type == 'threats') {
                this.renderThreatDetails(id, records);
            }
            else if (type === 'trends') {
                this.renderTrendsDetails(id, records);
            }
            else if (type === 'management') {
                this.renderManagementDetails(id, records);
            }
            else {
                console.error('No details for type:', type)
            }

        },

        setSummaryContent: function (html) {
            var container = this.$el.find('#summary_content');
            container.html(html);
            return container;
        },

        getSummaryContentElement: function () {
            return this.$el.find('#summary_content');
        },

        getSummaryTableElement: function () {
            return this.getSummaryContentElement().find('#summary_table');
        },

        getDetailsContentElement: function () {
            return this.$el.find('#details_content');
        },

        getDetailsTableElement: function () {
            return this.getDetailsContentElement().find('#details_table');
        },

        setDetailsContent: function (html) {
            var container = this.getDetailsContentElement();
            container.html(html);
            return container;
        },

        renderThreatDetails: function (id, records) {
            var tableFields = ['PASTPRESSURES_CAT', 'PASTPRESSURES_SPECIFY', 'FUTURETHREATS_CAT',
                'FUTURETHREATS_SPECIFY', 'RECOVERYPLANCOMMENCE'];
            var tableElement = this.getDetailsTableElement();
            var tableView = new TableView({
                el: tableElement.selector,
                model: records,
                fields: tableFields,
                filters: [
                    {
                        field: '__one__',
                        predicate: filters.notEmpty
                    }
                ]
            });
            var compiled = _.template(detailsTemplate);
            var table;
            this.setDetailsContent(compiled({type: 'Threats', id: id}));
            table = tableView.render();
            // reverse order to put blank line at the end
            table.order([0, 'desc']).draw();
        },

        renderTrendsDetails: function (id, records) {
            function getValue(column, def) {
                var vals = getValues(column);
                var result = vals[0] || def || '';
                if (vals.length > 1) {
                    console.error("More than one value for ", column, vals, ".Species:", id);
                }
                return result;
            }

            function getValues(column) {
                return _(records)
                    .map(function (r) {
                        return r.get(column);
                    })
                    .filter(function (val) {
                        return filters.notEmpty(val);
                    })
                    .value()
            }

            function buildESURow() {
                return {
                    type: 'ESU',
                    raw: getValue('KNOWNESU_NUM'),
                    trans: 'N/A',
                    trend: getValue('KNOWNESU_TREND'),
                    reliability: getValue('KNOWNESU_TRENDRELIAB'),
                    notes: getValue('KNOWNESU_NOTES'),
                    IUCN: 'N/A'
                };

            }

            function buildPopRow() {
                return {
                    type: 'Pop',
                    raw: getValue('KNOWNPOPS_NUM'),
                    trans: getValue('KNOWNPOPS_TRANS'),
                    trend: getValue('KNOWNPOPS_TREND'),
                    reliability: getValue('KNOWNPOPS_TRENDRELIAB'),
                    notes: getValue('KNOWNPOPS_NOTES'),
                    IUCN: getValue('KNOWNPOPS_CAT')
                };

            }

            function buildIndRow() {
                return {
                    type: '# Ind',
                    raw: getValue('MATIND_RAW'),
                    trans: 'N/A',
                    trend: getValue('MATIND_TREND'),
                    reliability: getValue('MATIND_TRENDRELIAB'),
                    notes: getValue('MATIND_NOTES'),
                    IUCN: getValue('MATIND_CAT')
                };

            }

            function buildEOORow() {
                return {
                    type: 'EOO',
                    raw: getValue('EOOAREA_RAW'),
                    trans: 'N/A',
                    trend: getValue('EOOAREA_TREND'),
                    reliability: 'N/A',
                    notes: getValue('EOOAREA_NOTES'),
                    IUCN: getValue('EOOAREA_CAT')
                };

            }

            function buildAOORow() {
                return {
                    type: 'AOO',
                    raw: getValue('AOOAREA_RAW'),
                    trans: 'N/A',
                    trend: getValue('AOOAREA_TREND'),
                    reliability: 'N/A',
                    notes: getValue('AOOAREA_NOTES'),
                    IUCN: getValue('AOOAREA_CAT')
                };

            }

            var columnDefs = [
                {
                    title: 'Trend Type',
                    data: 'type',
                    width: '5%',
                    orderable: false
                },
                {
                    title: 'Raw #',
                    width: '5%',
                    data: 'raw'
                },
                {
                    title: '# Translocated',
                    width: '5%',
                    data: 'trans'
                },
                {
                    title: 'Trend',
                    width: '10%',
                    data: 'trend'
                },
                {
                    title: 'Trend Reliability',
                    width: '20%',
                    data: 'reliability'
                },
                {
                    title: 'Notes',
                    data: 'notes'
                }

            ];
            var compiled = _.template(detailsTemplate);
            this.setDetailsContent(compiled({type: 'Trends', id: id}));
            var table = tables.initTable(this.getDetailsTableElement(), {paging: false, info: false, searching: false, ordering: false}, columnDefs);

            table.populate([buildESURow(), buildPopRow(), buildIndRow(), buildEOORow(), buildAOORow()]);

            // add foot note
            var html = 'ESU: Evolutionary Significant Units    ' +
                'Pop: Populations    ' +
                '#Ind: Number of Mature Individuals    ' +
                'EOO: Extent Of Occurrence     ' +
                'AOO: Area Of Occupancy';
            this.$el.find('#details_footer').html(html);
        },

        renderManagementDetails: function (id, records) {

            function getNotEmptyValues(column) {
                return _(records)
                    .map(function (r) {
                        return r.get(column);
                    })
                    .filter(function (val) {
                        return filters.notEmpty(val);
                    })
                    .value();
            }

            function renderAsList(values) {
                var compiled = _.template('
<% _.forEach(values, function(value) { %>
<%- value %>
<% }); %>
');
                return compiled({ values: values });
            }

            function buildResearchRow() {
                return {
                    type: 'Research',
                    category: getNotEmptyValues('MANREQ_RESEARCH_CAT'),
                    comment: getNotEmptyValues('MANREQ_RESEARCH_SPECIFY')
                };
            }

            function buildEvalRow() {
                return {
                    type: 'Evaluation',
                    category: getNotEmptyValues('MANREQ_EVALUATION_CAT'),
                    comment: getNotEmptyValues('MANREQ_EVALUATION_SPECIFY')
                };
            }

            function buildPlanningRow() {
                return {
                    type: 'Conservation Planning',
                    category: getNotEmptyValues('MANREQ_CONSPLAN_CAT'),
                    comment: getNotEmptyValues('MANREQ_CONSPLAN_SPECIFY')
                };
            }

            function buildDirectRow() {
                return {
                    type: 'Direct Intervention',
                    category: getNotEmptyValues('MANREQ_DIRECT_CAT'),
                    comment: getNotEmptyValues('MANREQ_DIRECT_SPECIFY')
                };
            }

            function buildIndirectRow() {
                return {
                    type: 'Indirect Intervention',
                    category: getNotEmptyValues('MANREQ_INDIRECT_CAT'),
                    comment: getNotEmptyValues('MANREQ_INDIRECT_SPECIFY')
                };
            }

            function buildOtherRow() {
                return {
                    type: 'Other',
                    category: getNotEmptyValues('MANREQ_OTHER_CAT'),
                    comment: getNotEmptyValues('MANREQ_OTHER_SPECIFY')
                };
            }

            var columnDefs = [
                {
                    title: 'Type',
                    data: 'type',
                    width: '15%'
                },
                {
                    title: 'Category',
                    data: 'category',
                    render: function (data) {
                        return renderAsList(data)
                    }
                },
                {
                    title: 'Comment',
                    data: 'comment',
                    render: function (data) {
                        return renderAsList(data)
                    }
                }
            ];

            var compiled = _.template(detailsTemplate);
            this.setDetailsContent(compiled({type: 'Management', id: id}));
            var table = tables.initTable(this.getDetailsTableElement(), {paging: false, info: false, searching: false, ordering: false}, columnDefs);

            table.populate([buildResearchRow(), buildEvalRow(), buildPlanningRow(), buildDirectRow(), buildIndirectRow(), buildOtherRow()]);
        }
    });
});<commit_msg>- added common name/distribution columns for fauna and flora summary tables.<commit_after>define([
    'jquery',
    'underscore',
    'backbone',
    '../../app/tableFacade',
    'app/filters',
    'views/tableView',
    'text!templates/region/summaryDefaultTemplate.html',
    'text!templates/region/detailsDefaultTemplate.html',
    'text!templates/region/threatsSummaryTemplate.html'
], function ($, _, Backbone, tables, filters, TableView, summaryTemplate, detailsTemplate, threatsCellTemplate) {

    return Backbone.View.extend({

        el: '#faunaTab',

        idTemplate: _.template(
            '<%= id %>'
        ),
        nameTemplate: _.template(
            '<%= name %>'
        ),
        distTemplate: _.template(
            '<%= value %>'
        ),
        threatsTemplate: _.template(threatsCellTemplate),
        trendsTemplate: _.template(
            '<a  id="trends_<%= id %>">details'
        ),
        statusTemplate: _.template(
            '<%= status %>'
        ),
        managementTemplate: _.template(
            '<a id="management_<%= id %>">details'
        ),

        columnDefinitions: [
            {
                title: 'Taxon',
                width: '15vw',
                data: 'id',
                render: function (data) {
                    return data.rendered
                }
            },
            {
                title: 'Common Name',
                width: '20vw',
                data: 'name',
                render: function (data) {
                    return data.rendered
                }
            },
            {
                title: 'Distribution',
                width: '20vw',
                data: 'dist',
                render: function (data) {
                    return data.rendered
                }
            },
            {
                title: 'Threats',
                width: '12vw',
                data: 'threats',
                render: function (data) {
                    return data.rendered
                }
            },
            {
                title: 'Status WA',
                width: '11vw',
                data: 'status',
                render: function (data) {
                    return data.rendered
                }
            },
            {
                title: 'Trends',
                data: 'trends',
                width: '11vw',
                render: function (data) {
                    return data.rendered
                }
            },
            {
                title: 'Management Requirement',
                width: '11vw',
                data: 'management',
                render: function (data) {
                    return data.rendered
                }
            }
        ],

        buildSummaryThreats: function (records) {
            var pastCount = 0,
                futureCount = 0;
            _.each(records, function (r) {
                var past = r.get('PASTPRESSURES_CAT');
                var fut = r.get('FUTURETHREATS_CAT');
                if (filters.notEmpty(past)) {
                    past = past.toLowerCase();
                    if (_.contains(past, 'unknown')) {
                        pastCount = '??';
                    } else if (_.contains(past, 'no known')) {
                        pastCount = 0; //'No known';
                    } else {
                        pastCount += 1;
                    }
                }
                if (filters.notEmpty(fut)) {
                    fut = fut.toLowerCase();
                    if (_.contains(fut, 'unknown')) {
                        futureCount = 'unknown';
                    } else if (_.contains(fut, 'no known')) {
                        futureCount = 0; //'No known';
                    } else {
                        futureCount += 1;
                    }
                }
            });

            return {
                pastCount: pastCount,
                futureCount: futureCount
            }
        },

        getStatusWA: function (records) {
            var filter = _(records)
                .filter(function (r) {
                    return filters.notEmpty(r.get('STATUSWA'))
                }).value();
            if (filter.length > 0) {
                return filter[0].get('STATUSWA');
            } else {
                return ''; //'?????';
            }
        },

        getDistribution: function (records) {
            var filter = _(records)
                .filter(function (r) {
                    return filters.notEmpty(r.get('DIST'))
                }).value();
            if (filter.length > 0) {
                return filter[0].get('DIST');
            } else {
                return ''; //'?????';
            }
        },

        buildSummaryRow: function (records, id) {
            var id_ = {
                    rendered: this.idTemplate({id: id})
                },
                name = {
                    rendered: this.nameTemplate({name: records[0].get('NAMECOMMON')})
                },
                dist = {
                    rendered: this.distTemplate({value: this.getDistribution(records)})
                },
                threats = {
                    rendered: this.threatsTemplate(_.extend({id: id},this.buildSummaryThreats(records)))
                },
                trends = {
                    rendered: this.trendsTemplate({id: id})
                },
                status = {
                    rendered: this.statusTemplate({status: this.getStatusWA(records)})
                },
                management = {
                    rendered: this.managementTemplate({id: id})
                };

            return {
                id: id_,
                name: name,
                dist: dist,
                threats: threats,
                trends: trends,
                status: status,
                management: management
            };

        },

        initialize: function () {
            _.bindAll(this, 'render');
        },

        render: function () {
            if (this.model) {
                this.renderSummary()
            }
        },

        renderSummary: function () {
            this.setSummaryContent(this.buildSummaryContent());
            var tableSelector = this.getSummaryTableElement();
            var table = tables.initTable(tableSelector, {}, this.columnDefinitions);
            var buildRow = _.bind(this.buildSummaryRow, this);
            var rows = _(this.model)
                .map(function (v, k) {
                    return buildRow(v, k);
                })
                .value();
            var renderDetails = _.bind(this.renderDetails, this);
            //bind details links (should be done with the router)
            table.on('draw.dt', function () {
                $(tableSelector).find('tr a').on('click', function (e) {
                    var split = e.target.id.split('_');
                    renderDetails(split[0], split[1]);
                });

            });
            table.populate(rows);
        },

        buildSummaryContent: function () {
            var values = {label: this.label || ""};
            return _.template(summaryTemplate)(values);
        },

        renderDetails: function (type, id) {
            var records = this.model[id];
            if (type == 'threats') {
                this.renderThreatDetails(id, records);
            }
            else if (type === 'trends') {
                this.renderTrendsDetails(id, records);
            }
            else if (type === 'management') {
                this.renderManagementDetails(id, records);
            }
            else {
                console.error('No details for type:', type)
            }

        },

        setSummaryContent: function (html) {
            var container = this.$el.find('#summary_content');
            container.html(html);
            return container;
        },

        getSummaryContentElement: function () {
            return this.$el.find('#summary_content');
        },

        getSummaryTableElement: function () {
            return this.getSummaryContentElement().find('#summary_table');
        },

        getDetailsContentElement: function () {
            return this.$el.find('#details_content');
        },

        getDetailsTableElement: function () {
            return this.getDetailsContentElement().find('#details_table');
        },

        setDetailsContent: function (html) {
            var container = this.getDetailsContentElement();
            container.html(html);
            return container;
        },

        renderThreatDetails: function (id, records) {
            var tableFields = ['PASTPRESSURES_CAT', 'PASTPRESSURES_SPECIFY', 'FUTURETHREATS_CAT',
                'FUTURETHREATS_SPECIFY', 'RECOVERYPLANCOMMENCE'];
            var tableElement = this.getDetailsTableElement();
            var tableView = new TableView({
                el: tableElement.selector,
                model: records,
                fields: tableFields,
                filters: [
                    {
                        field: '__one__',
                        predicate: filters.notEmpty
                    }
                ]
            });
            var compiled = _.template(detailsTemplate);
            var table;
            this.setDetailsContent(compiled({type: 'Threats', id: id}));
            table = tableView.render();
            // reverse order to put blank line at the end
            table.order([0, 'desc']).draw();
        },

        renderTrendsDetails: function (id, records) {
            function getValue(column, def) {
                var vals = getValues(column);
                var result = vals[0] || def || '';
                if (vals.length > 1) {
                    console.error("More than one value for ", column, vals, ".Species:", id);
                }
                return result;
            }

            function getValues(column) {
                return _(records)
                    .map(function (r) {
                        return r.get(column);
                    })
                    .filter(function (val) {
                        return filters.notEmpty(val);
                    })
                    .value()
            }

            function buildESURow() {
                return {
                    type: 'ESU',
                    raw: getValue('KNOWNESU_NUM'),
                    trans: 'N/A',
                    trend: getValue('KNOWNESU_TREND'),
                    reliability: getValue('KNOWNESU_TRENDRELIAB'),
                    notes: getValue('KNOWNESU_NOTES'),
                    IUCN: 'N/A'
                };

            }

            function buildPopRow() {
                return {
                    type: 'Pop',
                    raw: getValue('KNOWNPOPS_NUM'),
                    trans: getValue('KNOWNPOPS_TRANS'),
                    trend: getValue('KNOWNPOPS_TREND'),
                    reliability: getValue('KNOWNPOPS_TRENDRELIAB'),
                    notes: getValue('KNOWNPOPS_NOTES'),
                    IUCN: getValue('KNOWNPOPS_CAT')
                };

            }

            function buildIndRow() {
                return {
                    type: '# Ind',
                    raw: getValue('MATIND_RAW'),
                    trans: 'N/A',
                    trend: getValue('MATIND_TREND'),
                    reliability: getValue('MATIND_TRENDRELIAB'),
                    notes: getValue('MATIND_NOTES'),
                    IUCN: getValue('MATIND_CAT')
                };

            }

            function buildEOORow() {
                return {
                    type: 'EOO',
                    raw: getValue('EOOAREA_RAW'),
                    trans: 'N/A',
                    trend: getValue('EOOAREA_TREND'),
                    reliability: 'N/A',
                    notes: getValue('EOOAREA_NOTES'),
                    IUCN: getValue('EOOAREA_CAT')
                };

            }

            function buildAOORow() {
                return {
                    type: 'AOO',
                    raw: getValue('AOOAREA_RAW'),
                    trans: 'N/A',
                    trend: getValue('AOOAREA_TREND'),
                    reliability: 'N/A',
                    notes: getValue('AOOAREA_NOTES'),
                    IUCN: getValue('AOOAREA_CAT')
                };

            }

            var columnDefs = [
                {
                    title: 'Trend Type',
                    data: 'type',
                    width: '5%',
                    orderable: false
                },
                {
                    title: 'Raw #',
                    width: '5%',
                    data: 'raw'
                },
                {
                    title: '# Translocated',
                    width: '5%',
                    data: 'trans'
                },
                {
                    title: 'Trend',
                    width: '10%',
                    data: 'trend'
                },
                {
                    title: 'Trend Reliability',
                    width: '20%',
                    data: 'reliability'
                },
                {
                    title: 'Notes',
                    data: 'notes'
                }

            ];
            var compiled = _.template(detailsTemplate);
            this.setDetailsContent(compiled({type: 'Trends', id: id}));
            var table = tables.initTable(this.getDetailsTableElement(), {paging: false, info: false, searching: false, ordering: false}, columnDefs);

            table.populate([buildESURow(), buildPopRow(), buildIndRow(), buildEOORow(), buildAOORow()]);

            // add foot note
            var html = 'ESU: Evolutionary Significant Units    ' +
                'Pop: Populations    ' +
                '#Ind: Number of Mature Individuals    ' +
                'EOO: Extent Of Occurrence     ' +
                'AOO: Area Of Occupancy';
            this.$el.find('#details_footer').html(html);
        },

        renderManagementDetails: function (id, records) {

            function getNotEmptyValues(column) {
                return _(records)
                    .map(function (r) {
                        return r.get(column);
                    })
                    .filter(function (val) {
                        return filters.notEmpty(val);
                    })
                    .value();
            }

            function renderAsList(values) {
                var compiled = _.template('
<% _.forEach(values, function(value) { %>
<%- value %>
<% }); %>
');
                return compiled({ values: values });
            }

            function buildResearchRow() {
                return {
                    type: 'Research',
                    category: getNotEmptyValues('MANREQ_RESEARCH_CAT'),
                    comment: getNotEmptyValues('MANREQ_RESEARCH_SPECIFY')
                };
            }

            function buildEvalRow() {
                return {
                    type: 'Evaluation',
                    category: getNotEmptyValues('MANREQ_EVALUATION_CAT'),
                    comment: getNotEmptyValues('MANREQ_EVALUATION_SPECIFY')
                };
            }

            function buildPlanningRow() {
                return {
                    type: 'Conservation Planning',
                    category: getNotEmptyValues('MANREQ_CONSPLAN_CAT'),
                    comment: getNotEmptyValues('MANREQ_CONSPLAN_SPECIFY')
                };
            }

            function buildDirectRow() {
                return {
                    type: 'Direct Intervention',
                    category: getNotEmptyValues('MANREQ_DIRECT_CAT'),
                    comment: getNotEmptyValues('MANREQ_DIRECT_SPECIFY')
                };
            }

            function buildIndirectRow() {
                return {
                    type: 'Indirect Intervention',
                    category: getNotEmptyValues('MANREQ_INDIRECT_CAT'),
                    comment: getNotEmptyValues('MANREQ_INDIRECT_SPECIFY')
                };
            }

            function buildOtherRow() {
                return {
                    type: 'Other',
                    category: getNotEmptyValues('MANREQ_OTHER_CAT'),
                    comment: getNotEmptyValues('MANREQ_OTHER_SPECIFY')
                };
            }

            var columnDefs = [
                {
                    title: 'Type',
                    data: 'type',
                    width: '15%'
                },
                {
                    title: 'Category',
                    data: 'category',
                    render: function (data) {
                        return renderAsList(data)
                    }
                },
                {
                    title: 'Comment',
                    data: 'comment',
                    render: function (data) {
                        return renderAsList(data)
                    }
                }
            ];

            var compiled = _.template(detailsTemplate);
            this.setDetailsContent(compiled({type: 'Management', id: id}));
            var table = tables.initTable(this.getDetailsTableElement(), {paging: false, info: false, searching: false, ordering: false}, columnDefs);

            table.populate([buildResearchRow(), buildEvalRow(), buildPlanningRow(), buildDirectRow(), buildIndirectRow(), buildOtherRow()]);
        }
    });
});<|endoftext|>


<commit_before>(function(appConfig) {

  'use strict';

  // *** main dependencies *** //
  const path = require('path');
  const cookieParser = require('cookie-parser');
  const bodyParser = require('body-parser');
  const session = require('express-session');
  const flash = require('connect-flash');
  const morgan = require('morgan');
  const nunjucks = require('nunjucks');

  // *** view folders *** //
  const viewFolders = [
    path.join(__dirname, '..', 'views')
  ];

  // *** load environment variables *** //
  if (prprocess.env.NODE_ENV !== 'production') {
    require('dotenv').config();
  }

  appConfig.init = function(app, express) {

    // *** view engine *** //
    nunjucks.configure(viewFolders, {
      express: app,
      autoescape: true
    });
    app.set('view engine', 'html');

    // *** app middleware *** //
    if (process.env.NODE_ENV !== 'test') {
      app.use(morgan('dev'));
    }
    app.use(cookieParser());
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    // uncomment if using express-session
    app.use(session({
      secret: process.env.SECRET_KEY,
      resave: false,
      saveUninitialized: false
    }));
    app.use(flash());
    app.use(express.static(path.join(__dirname, '..', '..', 'client')));

  };

})(module.exports);
<commit_msg>fixing env issues<commit_after>(function(appConfig) {

  'use strict';

  // *** main dependencies *** //
  const path = require('path');
  const cookieParser = require('cookie-parser');
  const bodyParser = require('body-parser');
  const session = require('express-session');
  const flash = require('connect-flash');
  const morgan = require('morgan');
  const nunjucks = require('nunjucks');

  // *** view folders *** //
  const viewFolders = [
    path.join(__dirname, '..', 'views')
  ];

  // *** load environment variables *** //
  if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config();
  }

  appConfig.init = function(app, express) {

    // *** view engine *** //
    nunjucks.configure(viewFolders, {
      express: app,
      autoescape: true
    });
    app.set('view engine', 'html');

    // *** app middleware *** //
    if (process.env.NODE_ENV !== 'test') {
      app.use(morgan('dev'));
    }
    app.use(cookieParser());
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    // uncomment if using express-session
    app.use(session({
      secret: process.env.SECRET_KEY,
      resave: false,
      saveUninitialized: false
    }));
    app.use(flash());
    app.use(express.static(path.join(__dirname, '..', '..', 'client')));

  };

})(module.exports);
<|endoftext|>


<commit_before>Ti.include('/includes/lib/json.i18n.js');

var win = Ti.UI.currentWindow,
	Utils = require('/includes/utils'),
	Ui = require('/includes/ui'),

searchBar = Ti.UI.createSearchBar({
	barColor: Utils.getNavColor(),
	hintText: I('addProcess.search.searchHint'),
	width: Ti.UI.FILL
}),

darkenView = Ti.UI.createView({
	backgroundColor: 'black',
	top: 0,
	bottom: 0,
	left: 0,
	right: 0
}),

containerView = null,

lbl_indicator = Ti.UI.createLabel({
	top: 20,
	left: 25,
	right: 20,
	font: {
		fontSize: 19,
		fontFamily: 'HelveticaNeue-Italic'
	},
	height: 20,
	color: 'white'
});

searchBar.addEventListener('return', function(e) {
	e.source.blur();
	getSkinsFromSearch(e.source.getValue());
});

searchBar.addEventListener('focus', function(e) {
	darkenView.setOpacity(0);

	win.add(darkenView);

	darkenView.animate({
		opacity: 0.6,
		duration: 200
	});
});

searchBar.addEventListener('blur', function(e) {
	darkenView.animate({
		opacity: 0,
		duration: 200
	}, function(e) {
		win.remove(darkenView);
	});
});

win.setTitleControl(searchBar);

darkenView.addEventListener('click', function() {
	searchBar.blur();

	if(searchBar.getValue() == '') {
		getRandomSkins();
	}
});

if(!Utils.isiPad()) {
	win.add(lbl_indicator);
}

if(Utils.isiPad()) {
	containerView = Ti.UI.createScrollView({
		layout: 'horizontal',
	  	left: 5,
	  	top: 0,
	  	bottom: 0,
	  	right: 5,
	  	contentWidth: 290
	});
} else {
	containerView = Ti.UI.createScrollableView({
		top: 10,
		bottom: 0,
		width: 270,
		clipViews: false,
		disableBounce: false
	});

	containerView.addEventListener('scrollend', loadSkinPreview);
}

win.add(containerView);

getRandomSkins();

function getSkinsFromSearch(match) {
	lbl_indicator.setText(I('addProcess.search.indicator.searchResults', match));

	getRequestResults({
		method: 'searchSkinByName',
		match: searchBar.getValue()
	});
}

function getRandomSkins() {
	lbl_indicator.setText(I('addProcess.search.indicator.random'));

	getRequestResults({
		method: 'getRandomSkins'
	});
}

function getRequestResults(params) {
	var xhr = Ti.Network.createHTTPClient({
		onload: function(e) {
			var resultArray = [], i, currentSkinResult;

			try {
				resultArray = JSON.parse(this.responseText);

				if(resultArray.error != null) {
					alert(I('addProcess.search.indicator.error.network'));
				} else {
					//resetting the list
					if(Utils.isiPad()) {
						if(containerView.children[0] != null) {
							var i, currentSkin;

							for(i = 0; i < containerView.children.length; i++) {
								currentSkin = containerView.children[i];
								containerView.remove(currentSkin);
								currentSkin = null;
							}
						}

						containerView.add(lbl_indicator);
					} else {
						containerView.setViews([]);
					}

					if(resultArray.length == 0 && params.match != null) {
						lbl_indicator.setText(I('addProcess.search.indicator.noResults', params.match));
					}

					for(i = 0; i < resultArray.length; i++) {
						currentSkinResult = Ui.getSingleSearchResult(resultArray[i], selectSkin);

						if(Utils.isiPad()) {
							containerView.add(currentSkinResult);
						} else {
							containerView.addView(currentSkinResult);
						}

						if(i == 0 || Utils.isiPad()) {
							loadSkinPreview({
								view: currentSkinResult
							});
						}
					}
				}
			} catch(e) {
				alert(I('addProcess.search.indicator.error.network'));
			}
		},
		onerror: function(e) {
			alert(I('addProcess.search.indicator.error.network'));
		}
	});

	xhr.open('POST', 'http://skinmanager.fr.nf/json/');
	xhr.send(params);
}

function loadSkinPreview(e) {
	if(!e.view.frontImg.isLoaded) {
		var xhr_front = Ti.Network.createHTTPClient({
			onload: function() {
				if(this.getResponseData() != null && this.responseText.error == null) {
					e.view.frontImg.animate({
						opacity: 0,
						duration: 60
					}, function() {
						e.view.frontImg.setImage(xhr_front.getResponseData());
						e.view.frontImg.isLoaded = true;

						e.view.frontImg.animate({
							opacity: 1,
							duration: 60
						});
					});
				}

				if(!e.view.backImg.isLoaded) {
					var xhr_back = Ti.Network.createHTTPClient({
						onload: function() {
							if(this.getResponseData() != null && this.responseText.error == null) {
								e.view.backImg.setImage(this.getResponseData());
								e.view.backImg.isLoaded = true;
							}
						},
						cache: true
					});

					xhr_back.open('GET', 'http://apps.outadoc.fr/skinswitch/skinpreview.php?side=back&url=' + encodeURIComponent('http://skinmanager.fr.nf/json/?method=getSkin&id=' + parseInt(e.view.skinData.id) + '&base64=false'));
					xhr_back.send();
				}
			},
			cache: true
		});

		xhr_front.open('GET', 'http://apps.outadoc.fr/skinswitch/skinpreview.php?url=' + encodeURIComponent('http://skinmanager.fr.nf/json/?method=getSkin&id=' + parseInt(e.view.skinData.id) + '&base64=false'));
		xhr_front.send();
	}
}

function selectSkin(skinData) {
	var win_process = Ti.UI.createWindow({
		title: I('addProcess.process.title'),
		url: 'processing.js',
		backgroundImage: Utils.getBGImage(),
		barColor: Utils.getNavColor(),
		backgroundRepeat: true,

		skinUrl: 'http://skinmanager.fr.nf/json/?method=getSkin&id=' + parseInt(skinData.id) + '&base64=false',
		skinName: win.skinName,
		skinDesc: win.skinDesc
	});

	if(Utils.isiPad()) {
		win_process.masterGroup = win.masterGroup;
		win_process.prevWins = [win.prevWins[0], win];
		win.masterGroup.open(win_process);
	} else {
		win_process.container = win.container;
		win.navGroup.open(win_process);
	}
}
<commit_msg>Translation fix + fix search on ipad<commit_after>Ti.include('/includes/lib/json.i18n.js');

var win = Ti.UI.currentWindow,
	Utils = require('/includes/utils'),
	Ui = require('/includes/ui'),

searchBar = Ti.UI.createSearchBar({
	barColor: Utils.getNavColor(),
	hintText: I('addProcess.search.searchHint'),
	width: Ti.UI.FILL
}),

darkenView = Ti.UI.createView({
	backgroundColor: 'black',
	top: 0,
	bottom: 0,
	left: 0,
	right: 0
}),

containerView = null,

lbl_indicator = Ti.UI.createLabel({
	top: 20,
	left: 25,
	right: 20,
	font: {
		fontSize: 19,
		fontFamily: 'HelveticaNeue-Italic'
	},
	height: 20,
	color: 'white'
});

searchBar.addEventListener('return', function(e) {
	e.source.blur();
	getSkinsFromSearch(e.source.getValue());
});

searchBar.addEventListener('focus', function(e) {
	darkenView.setOpacity(0);

	win.add(darkenView);

	darkenView.animate({
		opacity: 0.6,
		duration: 200
	});
});

searchBar.addEventListener('blur', function(e) {
	darkenView.animate({
		opacity: 0,
		duration: 200
	}, function(e) {
		win.remove(darkenView);
	});
});

win.setTitleControl(searchBar);

darkenView.addEventListener('click', function() {
	searchBar.blur();

	if(searchBar.getValue() == '') {
		getRandomSkins();
	}
});

if(!Utils.isiPad()) {
	win.add(lbl_indicator);
}

if(Utils.isiPad()) {
	containerView = Ti.UI.createScrollView({
		layout: 'horizontal',
	  	left: 5,
	  	top: 0,
	  	bottom: 0,
	  	right: 5,
	  	contentWidth: 290
	});
} else {
	containerView = Ti.UI.createScrollableView({
		top: 10,
		bottom: 0,
		width: 270,
		clipViews: false,
		disableBounce: false
	});

	containerView.addEventListener('scrollend', loadSkinPreview);
}

win.add(containerView);

getRandomSkins();

function getSkinsFromSearch(match) {
	lbl_indicator.setText(I('addProcess.search.indicator.searchResults', match));

	getRequestResults({
		method: 'searchSkinByName',
		match: searchBar.getValue()
	});
}

function getRandomSkins() {
	lbl_indicator.setText(I('addProcess.search.indicator.random'));

	getRequestResults({
		method: 'getRandomSkins'
	});
}

function getRequestResults(params) {
	var xhr = Ti.Network.createHTTPClient({
		onload: function(e) {
			var resultArray = [], i, currentSkinResult;

			try {
				resultArray = JSON.parse(this.responseText);

				if(resultArray.error != null) {
					alert(I('addProcess.search.error.network'));
				} else {
					//resetting the list
					if(Utils.isiPad()) {
						if(containerView.children[0] != null) {
							var i, currentSkin,
								childrenArray = containerView.children;

							for(i = 0; i < childrenArray.length; i++) {
								containerView.remove(childrenArray[i]);
								childrenArray[i] = null;
							}
						}

						containerView.add(lbl_indicator);
					} else {
						containerView.setViews([]);
					}

					if(resultArray.length == 0 && params.match != null) {
						lbl_indicator.setText(I('addProcess.search.indicator.noResults', params.match));
					}

					for(i = 0; i < resultArray.length; i++) {
						currentSkinResult = Ui.getSingleSearchResult(resultArray[i], selectSkin);

						if(Utils.isiPad()) {
							containerView.add(currentSkinResult);
						} else {
							containerView.addView(currentSkinResult);
						}

						if(i == 0 || Utils.isiPad()) {
							loadSkinPreview({
								view: currentSkinResult
							});
						}
					}
				}
			} catch(e) {
				alert(I('addProcess.search.indicator.error.network'));
			}
		},
		onerror: function(e) {
			alert(I('addProcess.search.error.network'));
		}
	});

	xhr.open('POST', 'http://skinmanager.fr.nf/json/');
	xhr.send(params);
}

function loadSkinPreview(e) {
	if(!e.view.frontImg.isLoaded) {
		var xhr_front = Ti.Network.createHTTPClient({
			onload: function() {
				if(this.getResponseData() != null && this.responseText.error == null) {
					e.view.frontImg.animate({
						opacity: 0,
						duration: 60
					}, function() {
						e.view.frontImg.setImage(xhr_front.getResponseData());
						e.view.frontImg.isLoaded = true;

						e.view.frontImg.animate({
							opacity: 1,
							duration: 60
						});
					});
				}

				if(!e.view.backImg.isLoaded) {
					var xhr_back = Ti.Network.createHTTPClient({
						onload: function() {
							if(this.getResponseData() != null && this.responseText.error == null) {
								e.view.backImg.setImage(this.getResponseData());
								e.view.backImg.isLoaded = true;
							}
						},
						cache: true
					});

					xhr_back.open('GET', 'http://apps.outadoc.fr/skinswitch/skinpreview.php?side=back&url=' + encodeURIComponent('http://skinmanager.fr.nf/json/?method=getSkin&id=' + parseInt(e.view.skinData.id) + '&base64=false'));
					xhr_back.send();
				}
			},
			cache: true
		});

		xhr_front.open('GET', 'http://apps.outadoc.fr/skinswitch/skinpreview.php?url=' + encodeURIComponent('http://skinmanager.fr.nf/json/?method=getSkin&id=' + parseInt(e.view.skinData.id) + '&base64=false'));
		xhr_front.send();
	}
}

function selectSkin(skinData) {
	var win_process = Ti.UI.createWindow({
		title: I('addProcess.process.title'),
		url: 'processing.js',
		backgroundImage: Utils.getBGImage(),
		barColor: Utils.getNavColor(),
		backgroundRepeat: true,

		skinUrl: 'http://skinmanager.fr.nf/json/?method=getSkin&id=' + parseInt(skinData.id) + '&base64=false',
		skinName: win.skinName,
		skinDesc: win.skinDesc
	});

	if(Utils.isiPad()) {
		win_process.masterGroup = win.masterGroup;
		win_process.prevWins = [win.prevWins[0], win];
		win.masterGroup.open(win_process);
	} else {
		win_process.container = win.container;
		win.navGroup.open(win_process);
	}
}
<|endoftext|>


<commit_before>/**
 *  Copyright (C) 2014 3D Repo Ltd
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

var express = require('express');
var config = require('./js/core/config.js');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var compress = require('compression');

module.exports.createApp = function(template)
{
	var app = express();

	app.use(bodyParser.urlencoded({
		extended: true
	}));
	app.use(bodyParser.json());
	app.use(compress());

	app.set('views', './views');
	app.set('view_engine', 'jade');
	app.locals.pretty = true;

	app.get('/public/js/config.js', function(req, res) {
		var params = {};

		params['config_js'] = 'var server_config = {}; server_config.apiUrl = function(path) { return "//' +
		config.apiServer.url + '/" + path; };';

		if("wayfinder" in config)
		{
			// TODO: Make a public section in config for vars to be revealed
			params['config_js'] += '\nserver_config.democompany = "' + config.wayfinder.democompany + '";';
			params['config_js'] += '\nserver_config.demoproject = "' + config.wayfinder.demoproject + '";';
		}

		params['config_js'] += '\n\nvar realOpen = XMLHttpRequest.prototype.open;\n\nXMLHttpRequest.prototype.open = function(method, url, async, unk1, unk2) {\nthis.withCredentials = true;\nrealOpen.apply(this, arguments);\n};';

		res.header('Content-Type', 'text/javascript');
		res.render('config.jade', params);
	});

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

	app.get('*', function(req, res) {
		var params = {};

		Object.keys(config.external).forEach(function(key) {
			params[key] = config.external[key];
		});

		res.render(template, params);
	});

	return app;
};
<commit_msg>MASTER Using config.apiServer.hostname and .port explicitly, instead of .url<commit_after>/**
 *  Copyright (C) 2014 3D Repo Ltd
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

var express = require('express');
var config = require('./js/core/config.js');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var compress = require('compression');

module.exports.createApp = function(template)
{
	var app = express();

	app.use(bodyParser.urlencoded({
		extended: true
	}));
	app.use(bodyParser.json());
	app.use(compress());

	app.set('views', './views');
	app.set('view_engine', 'jade');
	app.locals.pretty = true;

	app.get('/public/js/config.js', function(req, res) {
		var params = {};

		params['config_js'] = 'var server_config = {}; server_config.apiUrl = function(path) { return "//' +
		config.apiServer.hostname + ":" + config.apiServer.port + '/" + path; };';

		if("wayfinder" in config)
		{
			// TODO: Make a public section in config for vars to be revealed
			params['config_js'] += '\nserver_config.democompany = "' + config.wayfinder.democompany + '";';
			params['config_js'] += '\nserver_config.demoproject = "' + config.wayfinder.demoproject + '";';
		}

		params['config_js'] += '\n\nvar realOpen = XMLHttpRequest.prototype.open;\n\nXMLHttpRequest.prototype.open = function(method, url, async, unk1, unk2) {\nthis.withCredentials = true;\nrealOpen.apply(this, arguments);\n};';

		res.header('Content-Type', 'text/javascript');
		res.render('config.jade', params);
	});

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

	app.get('*', function(req, res) {
		var params = {};

		Object.keys(config.external).forEach(function(key) {
			params[key] = config.external[key];
		});

		res.render(template, params);
	});

	return app;
};
<|endoftext|>


<commit_before>const
    errors = require('feathers-errors'),
    SequelizeService = require('feathers-sequelize').Service,
    {applyOwnerId} = require('hooks/common.js'),
    config = require('config.js'),
    {locator} = require('locator.js'),
    {addURL} = require('hooks/clip/clip.js'),
    {isClipMediaRef} = require('constants.js');

class ClipService extends SequelizeService {

  constructor () {

    const Models = locator.get('Models');

    super({
      Model: Models.MediaRef
    });
    this.Models = Models;

    // Hooks
    // -----
    this.before = {
      create: [applyOwnerId]
    };

    this.after = {
      get: [addURL],
      create: [addURL],
      update: [addURL]
    };

  }

  get (id, params={}) {
    return super.get(id, params);
  }

  find (params={}) {
    if (!params.sequelize) {
      params.sequelize = {
        where: isClipMediaRef
      };
    }

    return super.find(params);
  }

  create (data, params={}) {

    return new Promise((resolve, reject) => {

      const {MediaRef, Playlist, User} = this.Models;
      const PlaylistService = locator.get('PlaylistService');

      return MediaRef.create(data)
        .then((c) => {

          // If user is logged in, then add the clip to their My Clips playlist
          if (params.userId) {

            return User.findById(params.userId)
              .then(user => {
                let ownerName = user.name || '';
                let myClipsPlaylist = {};
                myClipsPlaylist.title = 'My Clips';
                myClipsPlaylist.isMyClips = true;
                myClipsPlaylist.ownerName = ownerName;

                return Playlist.findOrCreate({
                  where: {
                    ownerId: params.userId,
                    $and: {
                      isMyClips: true
                    }
                  },
                  defaults: myClipsPlaylist
                }).then(playlists => {
                    let playlist = playlists[0];
                    return user.addPlaylists([playlist.id])
                      .then(() => {
                        playlist.dataValues.playlistItems = [c.id];
                        return PlaylistService.update(playlist.dataValues.id, playlist.dataValues, { userId: params.userId })
                          .then(updatedPlaylist => {
                            resolve(c);
                          })
                      })
                })
            })
          } else {
            resolve(c);
          }

        })
        .catch(e => {
          console.log(e);
          reject(new errors.GeneralError(e));
        });

    });
  }

  update (id, data, params={}) {

    return this.Models.MediaRef.findById(id)
      .then(mediaRef => {

        if (!mediaRef.ownerId || mediaRef.ownerId !== params.userId) {
          throw new errors.Forbidden();
        } else {
          return super.update(id, data, params);
        }

      });
  }

}

ClipService.prototype.remove = undefined;
ClipService.prototype.patch = undefined;

module.exports = ClipService;
<commit_msg>Prevent error when mediaRef endTime is an empty string<commit_after>const
    errors = require('feathers-errors'),
    SequelizeService = require('feathers-sequelize').Service,
    {applyOwnerId} = require('hooks/common.js'),
    config = require('config.js'),
    {locator} = require('locator.js'),
    {addURL} = require('hooks/clip/clip.js'),
    {isClipMediaRef} = require('constants.js');

class ClipService extends SequelizeService {

  constructor () {

    const Models = locator.get('Models');

    super({
      Model: Models.MediaRef
    });
    this.Models = Models;

    // Hooks
    // -----
    this.before = {
      create: [applyOwnerId]
    };

    this.after = {
      get: [addURL],
      create: [addURL],
      update: [addURL]
    };

  }

  get (id, params={}) {
    return super.get(id, params);
  }

  find (params={}) {
    if (!params.sequelize) {
      params.sequelize = {
        where: isClipMediaRef
      };
    }

    return super.find(params);
  }

  create (data, params={}) {

    return new Promise((resolve, reject) => {

      const {MediaRef, Playlist, User} = this.Models;
      const PlaylistService = locator.get('PlaylistService');

      if (data.endTime === '') {
        data.endTime = null;
      }

      return MediaRef.create(data)
        .then((c) => {

          // If user is logged in, then add the clip to their My Clips playlist
          if (params.userId) {

            return User.findById(params.userId)
              .then(user => {
                let ownerName = user.name || '';
                let myClipsPlaylist = {};
                myClipsPlaylist.title = 'My Clips';
                myClipsPlaylist.isMyClips = true;
                myClipsPlaylist.ownerName = ownerName;

                return Playlist.findOrCreate({
                  where: {
                    ownerId: params.userId,
                    $and: {
                      isMyClips: true
                    }
                  },
                  defaults: myClipsPlaylist
                }).then(playlists => {
                    let playlist = playlists[0];
                    return user.addPlaylists([playlist.id])
                      .then(() => {
                        playlist.dataValues.playlistItems = [c.id];
                        return PlaylistService.update(playlist.dataValues.id, playlist.dataValues, { userId: params.userId })
                          .then(updatedPlaylist => {
                            resolve(c);
                          })
                      })
                })
            })
          } else {
            resolve(c);
          }

        })
        .catch(e => {
          console.log(e);
          reject(new errors.GeneralError(e));
        });

    });
  }

  update (id, data, params={}) {

    return this.Models.MediaRef.findById(id)
      .then(mediaRef => {

        if (!mediaRef.ownerId || mediaRef.ownerId !== params.userId) {
          throw new errors.Forbidden();
        } else {
          return super.update(id, data, params);
        }

      });
  }

}

ClipService.prototype.remove = undefined;
ClipService.prototype.patch = undefined;

module.exports = ClipService;
<|endoftext|>


<commit_before>/* eslint-env node, mocha */
const expect = require('chai').expect
const sinon = require('sinon')
const rewire = require('rewire')
const storage = rewire('../../src/helpers/sharedStorage.js')
const EventEmitter = require('events').EventEmitter

const loggerMock = {success: sinon.spy(), info: sinon.spy(), error: sinon.spy()}
storage.__set__('logger', loggerMock)

const redisMock = {get: sinon.spy(), set: sinon.spy()}

describe('helpers > shared storage', () => {
  afterEach(() => {
    loggerMock.info.reset()
    loggerMock.success.reset()
    loggerMock.error.reset()
    storage.__set__('state', {})
    storage.__set__('redis', redisMock)
  })

  it('shows the error if redis errors out', done => {
    let redis = new EventEmitter()
    storage.__set__('redis', redis)

    redis.on('error', storage.__get__('onError'))
    redis.emit('error')

    setTimeout(() => {
      expect(loggerMock.error.calledOnce).to.be.true
      done()
    }, 10)
  })

  it('loads the storage from redis', () => {
    redisMock.get = (k, c) => c(null, JSON.stringify({key: 123}))

    storage.load()
    expect(storage.get('key')).to.equal(123)
    expect(loggerMock.info.calledOnce).to.be.true
  })

  it('cancels if the storage is non existent', () => {
    redisMock.get = (k, c) => c(null, null)

    storage.load()
    expect(storage.get('key')).to.equal(undefined)
    expect(loggerMock.info.calledOnce).to.be.true
  })

  it('cancels if the redis operation failed', () => {
    redisMock.get = (k, c) => c('some error', null)

    storage.load()
    expect(storage.get('key')).to.equal(undefined)
    expect(loggerMock.error.calledOnce).to.be.true
  })

  it('cancels if the json decoding failed', () => {
    redisMock.get = (k, c) => c(null, 'lol')

    storage.load()
    expect(storage.get('key')).to.equal(undefined)
    expect(loggerMock.error.calledOnce).to.be.true
  })

  it('saves the storage into redis', () => {
    redisMock.set = sinon.stub().callsArg(2)

    storage.set('mykey', 42)

    storage.save()
    expect(redisMock.set.args[0][1]).to.equal(JSON.stringify({mykey: 42}))
    expect(loggerMock.info.calledOnce).to.be.true
  })

  it('can set and get a storage key', () => {
    storage.set('foo', {bar: 1337})
    expect(storage.get('foo')).to.deep.equal({bar: 1337})
    expect(storage.get('nofoo', 123)).to.deep.equal(123)
  })
})
<commit_msg>Fix race condition in unit tests? ~2~<commit_after>/* eslint-env node, mocha */
const expect = require('chai').expect
const sinon = require('sinon')
const rewire = require('rewire')
const storage = rewire('../../src/helpers/sharedStorage.js')
const EventEmitter = require('events').EventEmitter

const loggerMock = {success: sinon.spy(), info: sinon.spy(), error: sinon.spy()}
storage.__set__('logger', loggerMock)

const redisMock = {get: sinon.spy(), set: sinon.spy()}

describe('helpers > shared storage', () => {
  afterEach(() => {
    loggerMock.info.reset()
    loggerMock.success.reset()
    loggerMock.error.reset()
    storage.__set__('state', {})
    storage.__set__('redis', redisMock)
  })

  it('shows the error if redis errors out', done => {
    let redis = new EventEmitter()
    storage.__set__('redis', redis)

    redis.on('error', storage.__get__('onError'))
    redis.emit('error')

    setTimeout(() => {
      expect(loggerMock.error.callCount).to.be.above(0)
      done()
    }, 10)
  })

  it('loads the storage from redis', () => {
    redisMock.get = (k, c) => c(null, JSON.stringify({key: 123}))

    storage.load()
    expect(storage.get('key')).to.equal(123)
    expect(loggerMock.info.calledOnce).to.be.true
  })

  it('cancels if the storage is non existent', () => {
    redisMock.get = (k, c) => c(null, null)

    storage.load()
    expect(storage.get('key')).to.equal(undefined)
    expect(loggerMock.info.calledOnce).to.be.true
  })

  it('cancels if the redis operation failed', () => {
    redisMock.get = (k, c) => c('some error', null)

    storage.load()
    expect(storage.get('key')).to.equal(undefined)
    expect(loggerMock.error.calledOnce).to.be.true
  })

  it('cancels if the json decoding failed', () => {
    redisMock.get = (k, c) => c(null, 'lol')

    storage.load()
    expect(storage.get('key')).to.equal(undefined)
    expect(loggerMock.error.calledOnce).to.be.true
  })

  it('saves the storage into redis', () => {
    redisMock.set = sinon.stub().callsArg(2)

    storage.set('mykey', 42)

    storage.save()
    expect(redisMock.set.args[0][1]).to.equal(JSON.stringify({mykey: 42}))
    expect(loggerMock.info.calledOnce).to.be.true
  })

  it('can set and get a storage key', () => {
    storage.set('foo', {bar: 1337})
    expect(storage.get('foo')).to.deep.equal({bar: 1337})
    expect(storage.get('nofoo', 123)).to.deep.equal(123)
  })
})
<|endoftext|>


<commit_before>function FindProxyForURL(url, host)
{
  if (host == "music.163.com")
    return "PROXY 111.13.12.216:80;PROXY 116.228.80.186:8080;PROXY 101.4.136.101:80;PROXY 115.239.210.199:80;PROXY 218.200.66.201:8080;";

  return "DIRECT";
}
<commit_msg>get ip list from <commit_after>function FindProxyForURL(url, host) {
if (host == "music.163.com") return

"PROXY 221.176.14.72:80;"+
"PROXY 203.195.172.147:80;"+
"PROXY 115.182.83.38:8080;"+
"PROXY 203.195.162.96:8080;"+
"PROXY 202.194.96.46:80;"+
"PROXY 219.143.158.214:80;"+
"PROXY 116.228.80.186:8080;"+
"PROXY 1.172.58.215:8080;"+
"PROXY 59.125.26.31:80;"+
"PROXY 114.35.178.76:80;"+

"";

return "DIRECT";
}
<|endoftext|>