<commit_before>/* Unfortunately there are few unique classes and no ids, which makes targeting specific info rather unwieldy and brittle. If any of the classes or structure changes this will have to be adjusted manually. */

var $entries = $('.concept_light');
$entries.hover(hoverOn, hoverOff);

$('body').on('click', '.concept_light', function() {
  var obj = buildJRE($(this));
  sendText(obj); // obj must be JSON
  console.log('Copied:\n', (obj));
  // TODO: append a stylish toastr top right that fades in showing what was copied, and fades out again.
  // TODO: box says when jisho2json is ready too
});

console.log('jisho2json loaded');

function parseKana(el) {
  return (el.find('.f-dropdown li:nth-of-type(2)').text().match(/(?!\b)\W+$/) || [])[0];
}

function parseKanji(el) {
  return el.find('.text').text().trim();
}

function parseMeanings(el) {
  var defs = [];
  var defNodes = el.find('.meaning-wrapper').not('.meaning-tags:contains("Wikipedia") + .meaning-wrapper');

  defNodes.each(function(i, el) {
    var tags = parseTags(el);

    // only numbered meanings have this class followed by meaning text
    var text = $(el).find('.meaning-definition-section_divider + span').text().trim();

    if (text.length) {
      defs.push({
        meanings: text.split('; '),
        notes: parseInfo(el),
        tags: tags,
        sentences: parseSentences(el),
      });
    }
  });

  return defs;
}

function parseTags(el) {
  var tags = $(el).prev('.meaning-tags').text();
  return tags === '' ? [] : tags.split(', ').map(function(x) { return x.trim(); });
}

function parseSentences(el) {
  return $.map($(el).find('.sentence'), function(x) {
    return {
      "ja": $(x).find('.unlinked').text(),
      "en": $(x).find('.english').text()
    };
  });
}

function parseInfo(el) {
  return $.map($(el).find('.supplemental_info .tag-tag'), function(x) {
    return $(x).text().trim();
  });
}

function buildJRE($entry) {
  return JSON.stringify({
    common: !!$entry.find('.concept_light-common').length,
    jlpt: $entry.find('.concept_light-tag:contains("JLPT")').text() || null,
    ja: {
      characters: parseKanji($entry),
      readings: parseKana($entry) || ja, // sometimes no kana if characters were hiragana to begin with
    },
    en: parseMeanings($entry),
  });
}

function sendText(text) {
  chrome.extension.sendMessage({ text: text });
}

function hoverOn() {
  $(this).css({
    boxShadow: '0 0 4px 0 tomato',
    cursor: 'pointer'
  });
}

function hoverOff() {
 $(this).css({
    boxShadow: 'none'
  });
}
<commit_msg>re-reference characters in readings if pure kana word selected<commit_after>/* Unfortunately there are few unique classes and no ids, which makes targeting specific info rather unwieldy and brittle. If any of the classes or structure changes this will have to be adjusted manually. */

var $entries = $('.concept_light');
$entries.hover(hoverOn, hoverOff);

$('body').on('click', '.concept_light', function() {
  var obj = buildJRE($(this));
  sendText(obj); // obj must be JSON
  console.log('Copied:\n', (obj));
  // TODO: append a stylish toastr top right that fades in showing what was copied, and fades out again.
  // TODO: box says when jisho2json is ready too
});

console.log('jisho2json loaded');

function parseKana(el) {
  return (el.find('.f-dropdown li:nth-of-type(2)').text().match(/(?!\b)\W+$/) || [])[0];
}

function parseKanji(el) {
  return el.find('.text').text().trim();
}

function parseMeanings(el) {
  var defs = [];
  var defNodes = el.find('.meaning-wrapper').not('.meaning-tags:contains("Wikipedia") + .meaning-wrapper');

  defNodes.each(function(i, el) {
    var tags = parseTags(el);

    // only numbered meanings have this class followed by meaning text
    var text = $(el).find('.meaning-definition-section_divider + span').text().trim();

    if (text.length) {
      defs.push({
        meanings: text.split('; '),
        notes: parseInfo(el),
        tags: tags,
        sentences: parseSentences(el),
      });
    }
  });

  return defs;
}

function parseTags(el) {
  var tags = $(el).prev('.meaning-tags').text();
  return tags === '' ? [] : tags.split(', ').map(function(x) { return x.trim(); });
}

function parseSentences(el) {
  return $.map($(el).find('.sentence'), function(x) {
    return {
      "ja": $(x).find('.unlinked').text(),
      "en": $(x).find('.english').text()
    };
  });
}

function parseInfo(el) {
  return $.map($(el).find('.supplemental_info .tag-tag'), function(x) {
    return $(x).text().trim();
  });
}

function buildJRE($entry) {
  let characters = parseKanji($entry);
  return JSON.stringify({
    common: !!$entry.find('.concept_light-common').length,
    jlpt: $entry.find('.concept_light-tag:contains("JLPT")').text() || null,
    ja: {
      characters: parseKanji($entry),
      readings: parseKana($entry) || characters, // sometimes no kana if characters were hiragana to begin with
    },
    en: parseMeanings($entry),
  });
}

function sendText(text) {
  chrome.extension.sendMessage({ text: text });
}

function hoverOn() {
  $(this).css({
    boxShadow: '0 0 4px 0 tomato',
    cursor: 'pointer'
  });
}

function hoverOff() {
 $(this).css({
    boxShadow: 'none'
  });
}
<|endoftext|>


<commit_before>$(document).ready(function() {
    $("#contribute-why").popup("#contribute-more-info", {
        pointTo: "#contribute-more-info"
    });
    $('div.contribute a.suggested-amount,button.paypal').live('click', function(event) {
        var el = this,
            url = $(el).attr('href') + '&result_type=json',
            classes = 'ajax-loading loading-submit disabled';
        if ($(el).attr('data-realurl')) {
            url += '&realurl=' + encodeURIComponent($(el).attr('data-realurl'));
        }
        $(el).addClass(classes);
        $.ajax({
            url: url,
            dataType: 'json',
            /* false so that the action is considered within bounds of
             * user interaction and does not trigger the Firefox popup blocker.
             */
            async: false,
            success: function(json) {
                $(el).removeClass(classes);
                $('.modal').trigger('close'); // Hide all modals
                if (json.paykey) {
                    /* This is supposed to be a global */
                    //dgFlow = new PAYPAL.apps.DGFlow({expType:'mini'});
                    dgFlow = new PAYPAL.apps.DGFlow({clicked: el.id});
                    dgFlow.startFlow(json.url);
                } else {
                    if (!$('#paypal-error').length) {
                        $(el).closest('div').append('

');
                    }
                    $('#paypal-error').text(json.error).popup(el, {pointTo:el}).render();
                }
            }
        });
        return false;
    });
    if ($('#paypal-result').length) {
        top_dgFlow = top.dgFlow || (top.opener && top.opener.top.dgFlow);
        if (top_dgFlow !== null) {
            var thanks_url = $('#paypal-thanks').attr('href');
            if(thanks_url) {
                var top_opener = top;
                if (top.opener && top.opener.top.dgFlow) {
                    top_opener = top.opener.top;
                }

                top_opener.modalFromURL(thanks_url, {'callback': function() {
                    // Change the add-on buttons
                    var context  = $(this).closest('body'),
                        addon_id = $('#addon_info', this).attr('data-addon'),
                        install = $('.install[data-addon='+ addon_id +']', context);

                    install.removeClass('premium').find('.premium').removeClass('premium');
                    install.find('a').unbind('click')
                    install.installButton();

                    // Trigger install
                    z.installAddon($(".addon-title", this).text(),
                                   $(".trigger_download", this).attr('href'));
                }});
            }
            top_dgFlow.closeFlow();

            if (top !== null) {
                top.close();
            }
        }
    }
});

/**
 * Contributions Lightbox
 * TODO(jbalogh): save from amo2009.
 */
var contributions = {
    commentlimit: 255, // paypal-imposed comment length limit

    init: function() {
        // prepare overlay content
        var cb = $('#contribute-box');
        var contrib_limit = parseFloat($('#contrib-too-much').attr('data-max-amount'));
        cb.find('li label').click(function(e) {
            e.preventDefault();
            $(this).siblings(':radio').attr('checked', 'checked');
            $(this).children('input:text').focus();
        }).end()
        .find('input:text').keypress(function() {
            $(this).parent().siblings(':radio').attr('checked', 'checked');
        }).end()
        .find('textarea').keyup(function() {
            var txt = $(this).val(),
                limit = contributions.commentlimit,
                counter = $(this).siblings('.commentlen');
            if (txt.length > limit) {
                $(this).val(txt.substr(0, limit));
            }
            counter.text(limit - Math.min(txt.length, limit));
        }).keyup().end()
        .find('#contrib-too-much').hide().end()
        .find('#contrib-too-little').hide().end()
        .find('#contrib-not-entered').hide().end()
        .find('form').submit(function() {
            var contrib_type = $(this).find('input:checked').val();
            if (contrib_type == 'onetime') {
                var amt = $(this).find('input[name="'+contrib_type+'-amount"]').val();
                $(this).find('.error').hide();
                // parseFloat will catch everything except 1@, +amt will though
                if (isNaN(parseFloat(amt)) || ((+amt) != amt)) {
                    $(this).find('#contrib-not-entered').show();
                    return false;
                }
                if (amt > contrib_limit) {
                    $(this).find('#contrib-too-much').show();
                    return false;
                }
                if (parseFloat(amt) < 0.01) {
                    $(this).find('#contrib-too-little').show();
                    return false;
                }
            }
            var $self = $(this);
            $self.find('#contribute-actions').children().toggleClass('js-hidden');
            $.ajax({type: 'GET',
                url: $(this).attr('action') + '?result_type=json',
                data: $(this).serialize(),
                /* So popup blocker doesn't fire */
                async: false,
                success: function(json) {
                    if (json.paykey) {
                        /* This is supposed to be a global */
                        //dgFlow = new PAYPAL.apps.DGFlow({expType:'mini'});
                        dgFlow = new PAYPAL.apps.DGFlow({clicked: 'contribute-box'});
                        dgFlow.startFlow(json.url);
                        $self.find('span.cancel a').click();
                    } else {
                        $self.find('#paypal-error').show();
                    }
                }
            });
            $self.find('#contribute-actions').children().toggleClass('js-hidden');
            return false;
        });

        // enable overlay; make sure we have the jqm package available.
        if (!cb.jqm) {
            return;
        }
        cb.jqm({
                overlay: 100,
                overlayClass: 'contrib-overlay',
                onShow: function(hash) {
                    // avoid bleeding-through form elements
                    if ($.browser.opera) {
                        this.inputs = $(':input:visible').css('visibility', 'hidden');
                    }
                    // clean up, then show box
                    hash.w.find('.error').hide();
                    hash.w
                        .find('input:text').val('').end()
                        .find('textarea').val('').keyup().end()
                        .find('input:radio:first').attr('checked', 'checked').end()
                        .fadeIn();

                },
                onHide: function(hash) {
                    if ($.browser.opera) {
                        this.inputs.css('visibility', 'visible');
                    }
                    hash.w.find('.error').hide();
                    hash.w.fadeOut();
                    hash.o.remove();
                },
                trigger: '#contribute-button',
                toTop: true
            })
            .jqmAddClose(cb.find('.cancel a'));

        if (window.location.hash === '#contribute-confirm') {
            $('#contribute-button').click();
        }
    }

};
<commit_msg>Don't figure out dgFlow twice<commit_after>$(document).ready(function() {
    $("#contribute-why").popup("#contribute-more-info", {
        pointTo: "#contribute-more-info"
    });
    $('div.contribute a.suggested-amount,button.paypal').live('click', function(event) {
        var el = this,
            url = $(el).attr('href') + '&result_type=json',
            classes = 'ajax-loading loading-submit disabled';
        if ($(el).attr('data-realurl')) {
            url += '&realurl=' + encodeURIComponent($(el).attr('data-realurl'));
        }
        $(el).addClass(classes);
        $.ajax({
            url: url,
            dataType: 'json',
            /* false so that the action is considered within bounds of
             * user interaction and does not trigger the Firefox popup blocker.
             */
            async: false,
            success: function(json) {
                $(el).removeClass(classes);
                $('.modal').trigger('close'); // Hide all modals
                if (json.paykey) {
                    /* This is supposed to be a global */
                    //dgFlow = new PAYPAL.apps.DGFlow({expType:'mini'});
                    dgFlow = new PAYPAL.apps.DGFlow({clicked: el.id});
                    dgFlow.startFlow(json.url);
                } else {
                    if (!$('#paypal-error').length) {
                        $(el).closest('div').append('

');
                    }
                    $('#paypal-error').text(json.error).popup(el, {pointTo:el}).render();
                }
            }
        });
        return false;
    });
    if ($('#paypal-result').length) {
        var top_opener = top;
        if (top.opener && top.opener.top.dgFlow) {
            top_opener = top.opener.top;
        }
        top_dgFlow = top_opener.dgFlow;

        if (top_dgFlow !== null) {
            var thanks_url = $('#paypal-thanks').attr('href');
            if(thanks_url) {
                top_opener.modalFromURL(thanks_url, {'callback': function() {
                    // Change the add-on buttons
                    var context  = $(this).closest('body'),
                        addon_id = $('#addon_info', this).attr('data-addon'),
                        install = $('.install[data-addon='+ addon_id +']', context);

                    install.removeClass('premium').find('.premium').removeClass('premium');
                    install.find('a').unbind('click')
                    install.installButton();

                    // Trigger install
                    z.installAddon($(".addon-title", this).text(),
                                   $(".trigger_download", this).attr('href'));
                }});
            }
            top_dgFlow.closeFlow();

            if (top !== null) {
                top.close();
            }
        }
    }
});

/**
 * Contributions Lightbox
 * TODO(jbalogh): save from amo2009.
 */
var contributions = {
    commentlimit: 255, // paypal-imposed comment length limit

    init: function() {
        // prepare overlay content
        var cb = $('#contribute-box');
        var contrib_limit = parseFloat($('#contrib-too-much').attr('data-max-amount'));
        cb.find('li label').click(function(e) {
            e.preventDefault();
            $(this).siblings(':radio').attr('checked', 'checked');
            $(this).children('input:text').focus();
        }).end()
        .find('input:text').keypress(function() {
            $(this).parent().siblings(':radio').attr('checked', 'checked');
        }).end()
        .find('textarea').keyup(function() {
            var txt = $(this).val(),
                limit = contributions.commentlimit,
                counter = $(this).siblings('.commentlen');
            if (txt.length > limit) {
                $(this).val(txt.substr(0, limit));
            }
            counter.text(limit - Math.min(txt.length, limit));
        }).keyup().end()
        .find('#contrib-too-much').hide().end()
        .find('#contrib-too-little').hide().end()
        .find('#contrib-not-entered').hide().end()
        .find('form').submit(function() {
            var contrib_type = $(this).find('input:checked').val();
            if (contrib_type == 'onetime') {
                var amt = $(this).find('input[name="'+contrib_type+'-amount"]').val();
                $(this).find('.error').hide();
                // parseFloat will catch everything except 1@, +amt will though
                if (isNaN(parseFloat(amt)) || ((+amt) != amt)) {
                    $(this).find('#contrib-not-entered').show();
                    return false;
                }
                if (amt > contrib_limit) {
                    $(this).find('#contrib-too-much').show();
                    return false;
                }
                if (parseFloat(amt) < 0.01) {
                    $(this).find('#contrib-too-little').show();
                    return false;
                }
            }
            var $self = $(this);
            $self.find('#contribute-actions').children().toggleClass('js-hidden');
            $.ajax({type: 'GET',
                url: $(this).attr('action') + '?result_type=json',
                data: $(this).serialize(),
                /* So popup blocker doesn't fire */
                async: false,
                success: function(json) {
                    if (json.paykey) {
                        /* This is supposed to be a global */
                        //dgFlow = new PAYPAL.apps.DGFlow({expType:'mini'});
                        dgFlow = new PAYPAL.apps.DGFlow({clicked: 'contribute-box'});
                        dgFlow.startFlow(json.url);
                        $self.find('span.cancel a').click();
                    } else {
                        $self.find('#paypal-error').show();
                    }
                }
            });
            $self.find('#contribute-actions').children().toggleClass('js-hidden');
            return false;
        });

        // enable overlay; make sure we have the jqm package available.
        if (!cb.jqm) {
            return;
        }
        cb.jqm({
                overlay: 100,
                overlayClass: 'contrib-overlay',
                onShow: function(hash) {
                    // avoid bleeding-through form elements
                    if ($.browser.opera) {
                        this.inputs = $(':input:visible').css('visibility', 'hidden');
                    }
                    // clean up, then show box
                    hash.w.find('.error').hide();
                    hash.w
                        .find('input:text').val('').end()
                        .find('textarea').val('').keyup().end()
                        .find('input:radio:first').attr('checked', 'checked').end()
                        .fadeIn();

                },
                onHide: function(hash) {
                    if ($.browser.opera) {
                        this.inputs.css('visibility', 'visible');
                    }
                    hash.w.find('.error').hide();
                    hash.w.fadeOut();
                    hash.o.remove();
                },
                trigger: '#contribute-button',
                toTop: true
            })
            .jqmAddClose(cb.find('.cancel a'));

        if (window.location.hash === '#contribute-confirm') {
            $('#contribute-button').click();
        }
    }

};
<|endoftext|>


<commit_before>/**
 * @jsx React.DOM
 * @copyright Prometheus Research, LLC 2014
 */
'use strict';

var React           = require('react');
var PropTypes       = React.PropTypes;
var cloneWithProps  = React.addons.cloneWithProps;
var Label           = require('./Label');
var Element         = require('./Element');
var FormPropTypes   = require('./PropTypes');
var {List}          = require('./schema');
var emptyFunction   = require('./emptyFunction');

var Item = React.createClass({

  render() {
    return this.transferPropsTo(

        {this.props.children}
        <button
          onClick={this.props.onRemove}
          type="button"
          className="rf-RepeatingFieldset__remove">×</button>

    );
  }
});

/**
 * A component which renders values which correspond to List schema node.
 */
var RepeatingFieldset = React.createClass({

  propTypes: {
    value: FormPropTypes.ValueOfType(List),
    onAdd: PropTypes.func,
    onRemove: PropTypes.func,
    label: PropTypes.string,
    hint: PropTypes.string
  },

  render() {
    var {item, value} = this.props;
    return this.transferPropsTo(

        {value.map((value, key) => {
          var onRemove = this.onRemove.bind(null, key);
          var children = <Element value={value} />;
          return React.isValidComponent(item) ?
            cloneWithProps(item, {key, onRemove, children}) :
            <item key={key} onRemove={onRemove}>{children}</item>;
        })}
        <button
          type="button"
          onClick={this.onAdd}
          className="rf-RepeatingFieldset__add">Add</button>

    );
  },

  getDefaultProps() {
    return {
      item: Item,
      onAdd: emptyFunction,
      onRemove: emptyFunction
    };
  },

  onAdd() {
    var defaultValue = this.props.value.emptyChild();
    var value = this.props.value.push(defaultValue).notify();
    this.props.onAdd(value.value[value.value.length - 1]);
  },

  onRemove(index) {
    this.props.value.splice(index, 1).notify();
    this.props.onRemove(index);
  }

});

module.exports = RepeatingFieldset;
module.exports.Item = Item;
<commit_msg><RepeatingFieldset />: index prop<commit_after>/**
 * @jsx React.DOM
 * @copyright Prometheus Research, LLC 2014
 */
'use strict';

var React           = require('react');
var PropTypes       = React.PropTypes;
var cloneWithProps  = React.addons.cloneWithProps;
var Label           = require('./Label');
var Element         = require('./Element');
var FormPropTypes   = require('./PropTypes');
var {List}          = require('./schema');
var emptyFunction   = require('./emptyFunction');

var Item = React.createClass({

  render() {
    return this.transferPropsTo(

        {this.props.children}
        <button
          onClick={this.props.onRemove}
          type="button"
          className="rf-RepeatingFieldset__remove">×</button>

    );
  }
});

/**
 * A component which renders values which correspond to List schema node.
 */
var RepeatingFieldset = React.createClass({

  propTypes: {
    value: FormPropTypes.ValueOfType(List),
    onAdd: PropTypes.func,
    onRemove: PropTypes.func,
    label: PropTypes.string,
    hint: PropTypes.string
  },

  render() {
    var {item, value} = this.props;
    return this.transferPropsTo(

        {value.map((value, key) => {
          var onRemove = this.onRemove.bind(null, key);
          var children = <Element value={value} />;
          return React.isValidComponent(item) ?
            cloneWithProps(item, {key, onRemove, children, index: key}) :
            <item key={key} onRemove={onRemove}>{children}</item>;
        })}
        {!this.noAddButton &&
          <button
            type="button"
            onClick={this.onAdd}
            className="rf-RepeatingFieldset__add">
            Add
          </button>}

    );
  },

  getDefaultProps() {
    return {
      item: Item,
      onAdd: emptyFunction,
      onRemove: emptyFunction,
      noAddButton: false
    };
  },

  onAdd() {
    var defaultValue = this.props.value.emptyChild();
    var value = this.props.value.push(defaultValue).notify();
    this.props.onAdd(value.value[value.value.length - 1]);
  },

  onRemove(index) {
    this.props.value.splice(index, 1).notify();
    this.props.onRemove(index);
  }

});

module.exports = RepeatingFieldset;
module.exports.Item = Item;
<|endoftext|>


<commit_before>/**
 * @package assets
 */

(function($) {

	/**
	 * Create collapsible elements.
	 *
	 * @name $.symphonyCollapsible
	 * @class
	 *
	 * @param {Object} options An object specifying containing the attributes specified below
	 * @param {String} [options.items='.instance'] Selector to find collapsible items within the container
	 * @param {String} [options.handles='.header:first'] Selector to find clickable handles to trigger interaction
	 * @param {String} [options.content='.content'] Selector to find hideable content area
	 * @param {String} [options.save_state=true] Stores states of instances using local storage
	 * @param {String} [options.storage='symphony.collapsible.area.page.id'] Namespace used for local storage
	 *
	 * @example

			var collapsible = $('#duplicator').symphonyCollapsible({
				items:		'.instance',
				handles:	'.header span'
			});
			collapsible.collapseAll();
	 */
	$.fn.symphonyCollapsible = function(options) {
		var objects = this,
			settings = {
				items:				'.instance',
				handles:			'.header:first',
				content:			'.content',
				ignore:				'.ignore',
				save_state:			true,
				storage:			'symphony.collapsible.' + window.location.href.split(Symphony.Context.get('root') + '/')[1].replace(/\/(edit|new|created|saved)/g, '').replace(/\//g, '.')
			};

		$.extend(settings, options);

	/*-----------------------------------------------------------------------*/

		objects.each(function collapsible(index) {
			var object = $(this),
				storage = settings.storage + index + '.collapsed';

		/*---------------------------------------------------------------------
			Events
		---------------------------------------------------------------------*/

			// Collapse item
			object.on('collapse.collapsible', settings.items, function collapse(event, duration) {
				var item = $(this),
					heightMin = item.data('heightMin') || item.find(settings.handles).outerHeight() - 1;

				// Check duration
				if(duration !== 0) {
					item.addClass('js-animate');
				}

				// Collapse item
				item.trigger('collapsestart.collapsible')
					.addClass('collapsed')
					.css('max-height', heightMin);
			});

			// Collapse all items
			object.on('collapseall.collapsible', function collapseAll(event) {
				var items = object.find(settings.items),
					visibles = Symphony.Utilities.inSight(items),
					invisibles = visibles.nextAll();

				invisibles.each(function() {
					var item = $(this);
					item.css('max-height', item.data('heightMin'));
				});
				visibles.trigger('collapse.collapsible');
				invisibles.trigger('collapsestop.collapsible');
			});

			// Expand item
			object.on('expand.collapsible', settings.items, function expand(event, duration) {
				var item = $(this),
					heightMax = item.data('heightMax') || item[0].scrollHeight;

				// Check duration
				if(duration !== 0) {
					item.addClass('js-animate');
				}

				// Collapse item
				item.trigger('expandstart.collapsible')
					.removeClass('collapsed')
					.css('max-height', heightMax);
			});

			// Expand all items
			object.on('expandall.collapsible', function expandAll(event) {
				var items = object.find(settings.items),
					firsts = items.filter('.collapsed:lt(2)');

				firsts.trigger('expand.collapsible');
				setTimeout(function() {
					items.not(firsts).each(function() {
						var item = $(this);
						item.css('max-height', item.data('heightMax'));
					}).removeClass('collapsed').trigger('expandstop.collapsible');
				}, 250);
			});

			// Finish animations
			object.on('webkitTransitionEnd transitionend oTransitionEnd otransitionend MSTransitionEnd', settings.items, function finish(event) {
				var item = $(this);

				setTimeout(function() {
					item.removeClass('js-animate');
				}, 200);

				// Trigger events
				if(item.is('.collapsed')) {
					item.trigger('collapsestop.collapsible');
				}
				else {
					item.trigger('expandstop.collapsible');
				}
			});

			// Toggle single item
			object.on('click.collapsible', settings.handles, function toggle(event) {
				var handle = $(this),
					item = handle.parents(settings.items);

				if(!handle.is(settings.ignore) && !$(event.target).is(settings.ignore) && !item.is('.locked')) {

					// Expand
					if(item.is('.collapsed')) {
						item.trigger('expand.collapsible');
					}

					// Collapse
					else {
						item.trigger('collapse.collapsible');
					}
				}
			});

			// Toggle all
			object.on('dblclick.collapsible', settings.handles, function toogleAll(event) {
				var handle = $(this),
					item = handle.parents(settings.items),
					items = object.find(settings.items);

				if(!handle.is(settings.ignore) && !$(event.target).is(settings.ignore)) {

					// Expand all
					if(item.is('.collapsed')) {
						items.trigger('expand.collapsible');
					}

					// Collaps all
					else {
						items.trigger('collapse.collapsible');
					}
				}
			});

			// Save states
			object.on('collapsestop.collapsible expandstop.collapsible store.collapsible', settings.items, function saveState(event) {
				if(settings.save_state === true && Symphony.Support.localStorage === true) {
					var collapsed = object.find(settings.items).map(function(index) {
						if($(this).is('.collapsed')) {
							return index;
						};
					});

					// Put in a try/catch incase something goes wrong (no space, privileges etc)
					try {
						window.localStorage[storage] = collapsed.get().join(',');
					}
					catch(e) {
						window.onerror(e.message);
					}
				}
			});

			// Restore states
			object.on('restore.collapsible', function restoreState(event) {
				if(settings.save_state === true && Symphony.Support.localStorage === true && window.localStorage[storage]) {
					$.each(window.localStorage[storage].split(','), function(index, value) {
						var collapsed = object.find(settings.items).eq(value);
						if(collapsed.has('.invalid').length == 0) {
							collapsed.trigger('collapse.collapsible', [0]);
						}
					});
				}
			});

			// Refresh state storage
			object.on('orderstop.orderable', function refreshState(event) {
				object.find(settings.items).trigger('store.collapsible');
			});

		/*---------------------------------------------------------------------
			Initialisation
		---------------------------------------------------------------------*/

			// Prepare interface
			object.addClass('collapsible');

			// Restore states
			object.trigger('restore.collapsible');
			object.find(settings.items).each(function() {
				var item = $(this),
					min = item.find(settings.handles).outerHeight() - 1,
					max = item[0].scrollHeight;

				item.css('max-height', max);
				item.data('heightMin', min);
				item.data('heightMax', max);
				// item.addClass('instance');
			});
			object.trigger('restore.collapsible');
		});

	/*-----------------------------------------------------------------------*/

		return objects;
	};

})(window.jQuery);
<commit_msg>Add `.instance` classe to collapsible items for compatibility reasons.<commit_after>/**
 * @package assets
 */

(function($) {

	/**
	 * Create collapsible elements.
	 *
	 * @name $.symphonyCollapsible
	 * @class
	 *
	 * @param {Object} options An object specifying containing the attributes specified below
	 * @param {String} [options.items='.instance'] Selector to find collapsible items within the container
	 * @param {String} [options.handles='.header:first'] Selector to find clickable handles to trigger interaction
	 * @param {String} [options.content='.content'] Selector to find hideable content area
	 * @param {String} [options.save_state=true] Stores states of instances using local storage
	 * @param {String} [options.storage='symphony.collapsible.area.page.id'] Namespace used for local storage
	 *
	 * @example

			var collapsible = $('#duplicator').symphonyCollapsible({
				items:		'.instance',
				handles:	'.header span'
			});
			collapsible.collapseAll();
	 */
	$.fn.symphonyCollapsible = function(options) {
		var objects = this,
			settings = {
				items:				'.instance',
				handles:			'.header:first',
				content:			'.content',
				ignore:				'.ignore',
				save_state:			true,
				storage:			'symphony.collapsible.' + window.location.href.split(Symphony.Context.get('root') + '/')[1].replace(/\/(edit|new|created|saved)/g, '').replace(/\//g, '.')
			};

		$.extend(settings, options);

	/*-----------------------------------------------------------------------*/

		objects.each(function collapsible(index) {
			var object = $(this),
				storage = settings.storage + index + '.collapsed';

		/*---------------------------------------------------------------------
			Events
		---------------------------------------------------------------------*/

			// Collapse item
			object.on('collapse.collapsible', settings.items, function collapse(event, duration) {
				var item = $(this),
					heightMin = item.data('heightMin') || item.find(settings.handles).outerHeight() - 1;

				// Check duration
				if(duration !== 0) {
					item.addClass('js-animate');
				}

				// Collapse item
				item.trigger('collapsestart.collapsible')
					.addClass('collapsed')
					.css('max-height', heightMin);
			});

			// Collapse all items
			object.on('collapseall.collapsible', function collapseAll(event) {
				var items = object.find(settings.items),
					visibles = Symphony.Utilities.inSight(items),
					invisibles = visibles.nextAll();

				invisibles.each(function() {
					var item = $(this);
					item.css('max-height', item.data('heightMin'));
				});
				visibles.trigger('collapse.collapsible');
				invisibles.trigger('collapsestop.collapsible');
			});

			// Expand item
			object.on('expand.collapsible', settings.items, function expand(event, duration) {
				var item = $(this),
					heightMax = item.data('heightMax') || item[0].scrollHeight;

				// Check duration
				if(duration !== 0) {
					item.addClass('js-animate');
				}

				// Collapse item
				item.trigger('expandstart.collapsible')
					.removeClass('collapsed')
					.css('max-height', heightMax);
			});

			// Expand all items
			object.on('expandall.collapsible', function expandAll(event) {
				var items = object.find(settings.items),
					firsts = items.filter('.collapsed:lt(2)');

				firsts.trigger('expand.collapsible');
				setTimeout(function() {
					items.not(firsts).each(function() {
						var item = $(this);
						item.css('max-height', item.data('heightMax'));
					}).removeClass('collapsed').trigger('expandstop.collapsible');
				}, 250);
			});

			// Finish animations
			object.on('webkitTransitionEnd transitionend oTransitionEnd otransitionend MSTransitionEnd', settings.items, function finish(event) {
				var item = $(this);

				setTimeout(function() {
					item.removeClass('js-animate');
				}, 200);

				// Trigger events
				if(item.is('.collapsed')) {
					item.trigger('collapsestop.collapsible');
				}
				else {
					item.trigger('expandstop.collapsible');
				}
			});

			// Toggle single item
			object.on('click.collapsible', settings.handles, function toggle(event) {
				var handle = $(this),
					item = handle.parents(settings.items);

				if(!handle.is(settings.ignore) && !$(event.target).is(settings.ignore) && !item.is('.locked')) {

					// Expand
					if(item.is('.collapsed')) {
						item.trigger('expand.collapsible');
					}

					// Collapse
					else {
						item.trigger('collapse.collapsible');
					}
				}
			});

			// Toggle all
			object.on('dblclick.collapsible', settings.handles, function toogleAll(event) {
				var handle = $(this),
					item = handle.parents(settings.items),
					items = object.find(settings.items);

				if(!handle.is(settings.ignore) && !$(event.target).is(settings.ignore)) {

					// Expand all
					if(item.is('.collapsed')) {
						items.trigger('expand.collapsible');
					}

					// Collaps all
					else {
						items.trigger('collapse.collapsible');
					}
				}
			});

			// Save states
			object.on('collapsestop.collapsible expandstop.collapsible store.collapsible', settings.items, function saveState(event) {
				if(settings.save_state === true && Symphony.Support.localStorage === true) {
					var collapsed = object.find(settings.items).map(function(index) {
						if($(this).is('.collapsed')) {
							return index;
						};
					});

					// Put in a try/catch incase something goes wrong (no space, privileges etc)
					try {
						window.localStorage[storage] = collapsed.get().join(',');
					}
					catch(e) {
						window.onerror(e.message);
					}
				}
			});

			// Restore states
			object.on('restore.collapsible', function restoreState(event) {
				if(settings.save_state === true && Symphony.Support.localStorage === true && window.localStorage[storage]) {
					$.each(window.localStorage[storage].split(','), function(index, value) {
						var collapsed = object.find(settings.items).eq(value);
						if(collapsed.has('.invalid').length == 0) {
							collapsed.trigger('collapse.collapsible', [0]);
						}
					});
				}
			});

			// Refresh state storage
			object.on('orderstop.orderable', function refreshState(event) {
				object.find(settings.items).trigger('store.collapsible');
			});

		/*---------------------------------------------------------------------
			Initialisation
		---------------------------------------------------------------------*/

			// Prepare interface
			object.addClass('collapsible');

			// Restore states
			object.trigger('restore.collapsible');
			object.find(settings.items).each(function() {
				var item = $(this),
					min = item.find(settings.handles).outerHeight() - 1,
					max = item[0].scrollHeight;

				item.css('max-height', max);
				item.data('heightMin', min);
				item.data('heightMax', max);
				item.addClass('instance');
			});
			object.trigger('restore.collapsible');
		});

	/*-----------------------------------------------------------------------*/

		return objects;
	};

})(window.jQuery);
<|endoftext|>


<commit_before>'use strict';

function factory (type, config, load, typed) {

  var matrix = load(require('../../../type/matrix/function/matrix'));
  var divideScalar = load(require('../../arithmetic/divideScalar'));
  var multiply = load(require('../../arithmetic/multiply'));
  var subtract = load(require('../../arithmetic/subtract'));
  var equalScalar = load(require('../../relational/equalScalar'));

  var substitutionValidation = load(require('./substitutionValidation'));

  var SparseMatrix = type.SparseMatrix;
  var DenseMatrix = type.DenseMatrix;

  /**
   * Solves the linear equation system by backward substitution. Matrix must be an upper triangular matrix.
   *
   * U * x = b
   *
   * @param {Matrix, Array}         A N x N matrix or array (U)
   * @param {Matrix, Array}         A column vector with the b values
   *
   * @return {Matrix}               A column vector with the linear system solution (x)
   */
  var usolve = typed('backwardSubstitution', {
    'Matrix, Array | Matrix': function (m, b) {
      // process matrix storage format
      switch (m.storage()) {
        case 'dense':
          return _denseBackwardSubstitution(m, b);
        case 'sparse':
          return _sparseBackwardSubstitution(m, b);
      }
    },
    'Array, Array | Matrix': function (a, b) {
      // create dense matrix from array
      var m = matrix(a);
      // use matrix implementation
      var r = usolve(m, b);
      // result
      return r.valueOf();
    }
  });

  var _denseBackwardSubstitution = function (m, b) {
    // validate matrix and vector, return copy of column vector b
    b = substitutionValidation(m, b);
    // rows & columns
    var rows = m._size[0];
    var columns = m._size[1];
    // result
    var x = [];
    // arrays
    var data = m._data;
    // backward solve m * x = b, loop columns (backwards)
    for (var j = columns - 1; j >= 0 ; j--) {
      // b[j]
      var bj = b[j] || 0;
      // x[j]
      var xj;
      // backward substitution (outer product) avoids inner looping when bj == 0
      if (!equalScalar(bj, 0)) {
        // value @ [j, j]
        var vjj = data[j][j];
        // check vjj
        if (equalScalar(vjj, 0)) {
          // system cannot be solved
          throw new Error('Linear system cannot be solved since matrix is singular');
        }
        // calculate xj
        xj = divideScalar(bj, vjj);
        // loop rows
        for (var i = j - 1; i >= 0; i--) {
          // update copy of b
          b[i] = subtract(b[i] || 0, multiply(xj, data[i][j]));
        }
      }
      else {
        // zero value @ j
        xj = 0;
      }
      // update x
      x[j] = [xj];
    }
    // return column vector
    return new DenseMatrix({
      data: x,
      size: [rows, 1]
    });
  };

  var _sparseBackwardSubstitution = function (m, b) {
    // validate matrix and vector, return copy of column vector b
    b = substitutionValidation(m, b);
    // rows & columns
    var rows = m._size[0];
    var columns = m._size[1];
    // matrix arrays
    var values = m._values;
    var index = m._index;
    var ptr = m._ptr;
    // result arrays
    var xvalues = [];
    var xindex = [];
    var xptr = [];
    // vars
    var i, k;
    // init ptr
    xptr.push(0);
    // backward solve m * x = b, loop columns (backwards)
    for (var j = columns - 1; j >= 0 ; j--) {
      // b[j]
      var bj = b[j] || 0;
      // backward substitution (outer product) avoids inner looping when bj == 0
      if (!equalScalar(bj, 0)) {
        // value @ [j, j]
        var vjj = 0;
        // first & last indeces in column
        var f = ptr[j];
        var l = ptr[j + 1];
        // values in column, find value @ [j, j], loop backwards
        for (k = l - 1; k >= f; k--) {
          // row
          i = index[k];
          // check row
          if (i === j) {
            // update vjj
            vjj = values[k];
          }
          else if (i < j) {
            // exit loop
            break;
          }
        }
        // at this point we must have a value @ [j, j]
        if (equalScalar(vjj, 0)) {
          // system cannot be solved, there is no value @ [j, j]
          throw new Error('Linear system cannot be solved since matrix is singular');
        }
        // calculate xj
        var xj = divideScalar(bj, vjj);
        // values in column, continue from last loop
        for (; k >= f; k--) {
          // row
          i = index[k];
          // update copy of b
          b[i] = subtract(b[i] || 0, multiply(xj, values[k]));
        }
        // check for non zero
        if (!equalScalar(xj, 0)) {
          // push to values (at the beginning since we are looping backwards)
          xvalues.unshift(xj);
          // row
          xindex.unshift(j);
        }
      }
    }
    // update ptr
    xptr.push(xvalues.length);
    // return column vector
    return new SparseMatrix({
      values: xvalues,
      index: xindex,
      ptr: xptr,
      size: [rows, 1]
    });
  };

  return usolve;
}

exports.name = 'usolve';
exports.factory = factory;
<commit_msg>usolve() update<commit_after>'use strict';

function factory (type, config, load, typed) {

  var matrix = load(require('../../../type/matrix/function/matrix'));
  var divideScalar = load(require('../../arithmetic/divideScalar'));
  var multiply = load(require('../../arithmetic/multiply'));
  var subtract = load(require('../../arithmetic/subtract'));
  var equalScalar = load(require('../../relational/equalScalar'));

  var substitutionValidation = load(require('./substitutionValidation'));

  var SparseMatrix = type.SparseMatrix;
  var DenseMatrix = type.DenseMatrix;

  /**
   * Solves the linear equation system by backward substitution. Matrix must be an upper triangular matrix.
   *
   * U * x = b
   *
   * @param {Matrix, Array}         A N x N matrix or array (U)
   * @param {Matrix, Array}         A column vector with the b values
   *
   * @return {Matrix}               A column vector with the linear system solution (x)
   */
  var usolve = typed('usolve', {
    'Matrix, Array | Matrix': function (m, b) {
      // process matrix storage format
      switch (m.storage()) {
        case 'dense':
          return _denseBackwardSubstitution(m, b);
        case 'sparse':
          return _sparseBackwardSubstitution(m, b);
      }
    },
    'Array, Array | Matrix': function (a, b) {
      // create dense matrix from array
      var m = matrix(a);
      // use matrix implementation
      var r = usolve(m, b);
      // result
      return r.valueOf();
    }
  });

  var _denseBackwardSubstitution = function (m, b) {
    // validate matrix and vector, return copy of column vector b
    b = substitutionValidation(m, b);
    // rows & columns
    var rows = m._size[0];
    var columns = m._size[1];
    // result
    var x = [];
    // arrays
    var data = m._data;
    // backward solve m * x = b, loop columns (backwards)
    for (var j = columns - 1; j >= 0 ; j--) {
      // b[j]
      var bj = b[j] || 0;
      // x[j]
      var xj;
      // backward substitution (outer product) avoids inner looping when bj == 0
      if (!equalScalar(bj, 0)) {
        // value @ [j, j]
        var vjj = data[j][j];
        // check vjj
        if (equalScalar(vjj, 0)) {
          // system cannot be solved
          throw new Error('Linear system cannot be solved since matrix is singular');
        }
        // calculate xj
        xj = divideScalar(bj, vjj);
        // loop rows
        for (var i = j - 1; i >= 0; i--) {
          // update copy of b
          b[i] = subtract(b[i] || 0, multiply(xj, data[i][j]));
        }
      }
      else {
        // zero value @ j
        xj = 0;
      }
      // update x
      x[j] = [xj];
    }
    // return column vector
    return new DenseMatrix({
      data: x,
      size: [rows, 1]
    });
  };

  var _sparseBackwardSubstitution = function (m, b) {
    // validate matrix and vector, return copy of column vector b
    b = substitutionValidation(m, b);
    // rows & columns
    var rows = m._size[0];
    var columns = m._size[1];
    // matrix arrays
    var values = m._values;
    var index = m._index;
    var ptr = m._ptr;
    // result arrays
    var xvalues = [];
    var xindex = [];
    var xptr = [];
    // vars
    var i, k;
    // init ptr
    xptr.push(0);
    // backward solve m * x = b, loop columns (backwards)
    for (var j = columns - 1; j >= 0 ; j--) {
      // b[j]
      var bj = b[j] || 0;
      // backward substitution (outer product) avoids inner looping when bj == 0
      if (!equalScalar(bj, 0)) {
        // value @ [j, j]
        var vjj = 0;
        // first & last indeces in column
        var f = ptr[j];
        var l = ptr[j + 1];
        // values in column, find value @ [j, j], loop backwards
        for (k = l - 1; k >= f; k--) {
          // row
          i = index[k];
          // check row
          if (i === j) {
            // update vjj
            vjj = values[k];
          }
          else if (i < j) {
            // exit loop
            break;
          }
        }
        // at this point we must have a value @ [j, j]
        if (equalScalar(vjj, 0)) {
          // system cannot be solved, there is no value @ [j, j]
          throw new Error('Linear system cannot be solved since matrix is singular');
        }
        // calculate xj
        var xj = divideScalar(bj, vjj);
        // values in column, continue from last loop
        for (; k >= f; k--) {
          // row
          i = index[k];
          // update copy of b
          b[i] = subtract(b[i] || 0, multiply(xj, values[k]));
        }
        // check for non zero
        if (!equalScalar(xj, 0)) {
          // push to values (at the beginning since we are looping backwards)
          xvalues.unshift(xj);
          // row
          xindex.unshift(j);
        }
      }
    }
    // update ptr
    xptr.push(xvalues.length);
    // return column vector
    return new SparseMatrix({
      values: xvalues,
      index: xindex,
      ptr: xptr,
      size: [rows, 1]
    });
  };

  return usolve;
}

exports.name = 'usolve';
exports.factory = factory;
<|endoftext|>


<commit_before>/**
 * Created by Stefano on 31/03/14.
 */

/**
 * The single node of the list.
 * @param item The item to store in the node.
 * @constructor
 */
function Node(item) {
	/**
	 * The item stored.
	 * @type {Object}
	 */
	this.item = item;
	/**
	 * The next node. It's null if there's no a next node.
	 * @type {Node|null}
	 */
	this.next = null;
}

/**
 * Class for managing a linked list.
 * @constructor
 */
function LinkedList() {
	/**
	 * The first node of the list.
	 * @type {Node|null}
	 */
	this.first = null;
	/**
	 * The last node of the list.
	 * @type {Node|null}
	 */
	this.last = null;
	/**
	 * The length of the list.
	 * @type {number}
	 */
	this.length = 0;
}

/**
 * Add an item at the head of the list.
 * @param item The item to add.
 * @return {void}
 */
LinkedList.prototype.pushFront = function (item) {
	var node = new Node(item);
	node.next = this.first;
	this.first = node;
	if (!this.last)
		this.last = node;
	this.length++;
};

/**
 * Add an item at the tail of the list.
 * @param item The item to add.
 * @return {void}
 */
LinkedList.prototype.pushBack = function (item) {
	var node = new Node(item);
	if(this.last)
		this.last.next = node;
	else
		this.first = node;
	this.last = node;
	this.length++;
};

/**
 * Remove the first element of the list.
 * @return {Object|undefined} The element removed. It's undefined if the list is empty.
 */
LinkedList.prototype.popFront = function() {
	if(this.length) {
		var node = this.first;
		this.first = this.first.next;
		this.length--;
		node.next = null;
		return node.item;
	}
	return undefined;
};

/**
 * Remove the last element of the list.
 * @return {Object|undefined} The element removed. It's undefined if the list is empty.
 */
LinkedList.prototype.popBack = function() {
	if(this.length) {
		var node = this.last;
		var next = this.first;
		while(next.next && next.next.next) {
			next = next.next;
		}
		if(node === next)
			this.last = null;
		else
			this.last = next;
		next.next = null;
		this.length--;
		return node.item;
	}
	return undefined;
};

/**
 * Remove the item at the position index.
 * @param index The position of the item to remove.
 * @return {Object|undefined}
 */
LinkedList.prototype.removeAt = function(index) {
	if(index < 0 || index > this.length - 1)
		return undefined;
	if(index === 0)
		return this.popFront();
	if(index === this.length - 1)
		return this.popBack();
	var node = this.first;
	for( ; index > 1; index--)
		node = node.next;
	//now node is the node before the node to remove
	//node to remove
	var next = node.next;
	if(next === this.last)
		this.last = node;
	//noinspection JSPrimitiveTypeWrapperUsage
	node.next = next.next;
	this.length--;
	return next.item;
};

/**
 * Get the item at the position index.
 * @param index The position of the item.
 * @return {Object|undefined}. It's undefined if index isn't in the queue bounds.
 */
LinkedList.prototype.getItem = function(index) {
	if(index < 0 || index > this.length)
		return undefined;
	var node = this.first;
	for( ; index > 0; index--)
		node = node.next;
	return node.item;
};<commit_msg>Added methods filter, fromArray and toArray<commit_after>/**
 * Created by Stefano on 31/03/14.
 */

/**
 * The single node of the list.
 * @param item {*} The item to store in the node.
 * @constructor
 */
function Node(item) {
	/**
	 * The item stored.
	 * @type {*}
	 */
	this.item = item;
	/**
	 * The next node. It's null if there's no a next node.
	 * @type {Node|null}
	 */
	this.next = null;
}

LinkedList.prototype = new Aggregate();
LinkedList.prototype.constructor = LinkedList;

/**
 * Class for managing a linked list.
 * @constructor
 */
function LinkedList() {
	/**
	 * The first node of the list.
	 * @type {Node|null}
	 */
	this.first = null;
	/**
	 * The last node of the list.
	 * @type {Node|null}
	 */
	this.last = null;
	/**
	 * The length of the list.
	 * @type {number}
	 */
	this.length = 0;
}

/**
 * @inheritDoc
 */
LinkedList.prototype.getIterator = function () {
	return new LinkedListIterator(this);
};

/**
 * Add an item at the head of the list.
 * @param item {*} The item to add.
 * @return {void}
 */
LinkedList.prototype.pushFront = function (item) {
	var node = new Node(item);
	node.next = this.first;
	this.first = node;
	if (!this.last)
		this.last = node;
	this.length++;
};

/**
 * Add an item at the tail of the list.
 * @param item {*} The item to add.
 * @return {void}
 */
LinkedList.prototype.pushBack = function (item) {
	var node = new Node(item);
	if (this.last)
		this.last.next = node;
	else
		this.first = node;
	this.last = node;
	this.length++;
};

/**
 * Remove the first element of the list.
 * @return {*} The element removed. It's undefined if the list is empty.
 */
LinkedList.prototype.popFront = function () {
	if (this.length) {
		var node = this.first;
		this.first = this.first.next;
		this.length--;
		node.next = null;
		return node.item;
	}
	return undefined;
};

/**
 * Remove the last element of the list.
 * @return {*} The element removed. It's undefined if the list is empty.
 */
LinkedList.prototype.popBack = function () {
	if (this.length) {
		var node = this.last;
		var next = this.first;
		while (next.next && next.next.next) {
			next = next.next;
		}
		if (node === next)
			this.last = null;
		else
			this.last = next;
		next.next = null;
		this.length--;
		return node.item;
	}
	return undefined;
};

/**
 * Remove the item at the position index.
 * @param index {Number} The position of the item to remove.
 * @return {*} The item stored at the position index. It's undefined if the index is out of bounds.
 */
LinkedList.prototype.removeAt = function (index) {
	if (index < 0 || index > this.length - 1)
		return undefined;
	if (index === 0)
		return this.popFront();
	if (index === this.length - 1)
		return this.popBack();
	var node = this.first;
	for (; index > 1; index--)
		node = node.next;
	//now node is the node before the node to remove
	//node to remove
	var next = node.next;
	if (next === this.last)
		this.last = node;

	node.next = next.next;
	this.length--;
	return next.item;
};

/**
 * Get the item at the position index.
 * @param index {Number} The position of the item.
 * @return {*} The item stored at the position index. It's undefined if index isn't in the queue bounds.
 */
LinkedList.prototype.getItem = function (index) {
	if (index < 0 || index > this.length - 1)
		return undefined;
	var node = this.first;
	for (; index > 0; index--)
		node = node.next;
	return node.item;
};

/**
 * Transform the list into an array.
 * @return {Array<*>} The array built.
 */
LinkedList.prototype.toArray = function () {
	var array = [];
	for (var node = this.first, i = 0; node; node = node.next, i++)
		array[i] = node.item;
	return array;
};

/**
 * Build the list from the array.
 * @param array {Array<*>} The array from which build the list.
 * @return {void}
 */
LinkedList.prototype.fromArray = function (array) {
	var node = this.first;
	for (var i = 0; i < Math.min(this.length, array.length); i++, node = node.next)
		node.item = array[i];
	if (this.length < array.length)
		for (var j = this.length; j < array.length; j++)
			this.pushBack(array[j]);
	else
		for (var k = array.length; k < this.length;)
			this.popBack();
};

/**
 * Return the items that satisfy the condition determined by the callback.
 * @param callback {function} The function that implements the condition.
 * @return {Array<*>} The array that contains the items that satisfy the condition.
 */
LinkedList.prototype.filter = function (callback) {
	var result = [];
	for (var node = this.first; node; node = node.next) {
		if (callback(node.item))
			result.push(node.item);
	}
	return result;
};<|endoftext|>


<commit_before>const fs = require('fs-extra');

module.exports = {
  checkModulesWebpackConfig(modules, t) {
    const allowedProperties = [ 'extensions', 'bundles' ];
    for (const mod of Object.values(modules)) {
      const webpackConfig = mod.__meta.webpack[mod.__meta.name];

      if (!webpackConfig) {
        continue;
      }

      if (
        typeof webpackConfig !== 'object' ||
        webpackConfig === null ||
        Array.isArray(webpackConfig) ||
        Object.keys(webpackConfig).some((prop) => !allowedProperties.includes(prop))
      ) {
        const error = t('apostrophe:assetWebpackConfigWarning', {
          module: mod.__meta.name
        });

        throw new Error(error);
      }

      if (webpackConfig && webpackConfig.bundles) {
        const bundles = Object.values(webpackConfig.bundles);

        bundles.forEach(bundle => {
          const bundleProps = Object.keys(bundle);
          if (
            bundleProps.length > 1 ||
            (bundleProps.length === 1 && !bundle.templates) ||
            (bundle.templates && !Array.isArray(bundle.templates))
          ) {
            const error = t('apostrophe:assetWebpackBundlesWarning', {
              module: mod.__meta.name
            });

            throw new Error(error);
          }
        });
      }
    }
  },

  async getWebpackExtensions ({
    getMetadata, modulesToInstantiate
  }) {
    const modulesMeta = modulesToInstantiate
      .map((name) => getMetadata(name));

    const { extensions, foundBundles } = getModulesWebpackConfigs(
      modulesMeta
    );

    const verifiedBundles = await verifyBundlesEntryPoints(foundBundles);

    return {
      extensions,
      verifiedBundles
    };
  },

  fillExtraBundles (verifiedBundles = {}) {
    return Object.entries(verifiedBundles).reduce((acc, [ bundleName, { js, scss } ]) => {
      return {
        js: [
          ...acc.js,
          ...(js.length && !acc.js.includes(bundleName)) ? [ bundleName ] : []
        ],
        css: [
          ...acc.css,
          ...(scss.length && !acc.css.includes(bundleName)) ? [ bundleName ] : []
        ]
      };
    }, {
      js: [],
      css: []
    });
  },

  getBundlesNames (bundles, es5 = false) {
    return Object.entries(bundles).reduce((acc, [ ext, bundlesNames ]) => {
      const nameExtension = ext === 'css'
        ? '-bundle'
        : '-module-bundle';

      const es5Bundles = es5 && ext === 'js'
        ? bundlesNames.map((name) => `${name}-nomodule-bundle.${ext}`)
        : [];

      return [
        ...acc,
        ...bundlesNames.map((name) => `${name}${nameExtension}.${ext}`),
        ...es5Bundles
      ];
    }, []);
  },

  writeBundlesImportFiles ({
    name,
    buildDir,
    mainBundleName,
    verifiedBundles,
    getImportFileOutput,
    writeImportFile
  }) {
    if (!name.includes('src')) {
      return [];
    }

    const bundlesOutputs = Object.entries(verifiedBundles)
      .map(([ bundleName, paths ]) => {
        return {
          bundleName,
          importFile: `${buildDir}/${bundleName}-import.js`,
          js: getImportFileOutput(paths.js, {
            invokeApps: true,
            enumerateImports: true,
            requireDefaultExport: true
          }),
          scss: getImportFileOutput(paths.scss, {
            enumerateImports: true,
            importSuffix: 'Stylesheet'
          })
        };
      });

    for (const output of bundlesOutputs) {
      writeImportFile({
        importFile: output.importFile,
        indexJs: output.js,
        indexSass: output.scss
      });
    }

    return bundlesOutputs.reduce((acc, { bundleName, importFile }) => {
      return {
        ...acc,
        [bundleName]: {
          import: importFile,
          dependOn: mainBundleName
        }
      };
    }, {});
  }
};

function getModulesWebpackConfigs (modulesMeta) {
  const { extensions, bundles } = modulesMeta.reduce((acc, meta) => {
    const { webpack, __meta } = meta;

    const configs = formatConfigs(__meta.chain, webpack);

    if (!configs.length) {
      return acc;
    }

    const moduleBundles = configs.reduce((acc, conf) => {
      return {
        ...acc,
        ...conf.bundles
      };
    }, {});

    return {
      extensions: {
        ...acc.extensions,
        ...configs.reduce((acc, config) => ({
          ...acc,
          ...config.extensions
        }), {})
      },
      bundles: {
        ...acc.bundles,
        ...moduleBundles
      }
    };
  }, {
    extensions: {},
    bundles: {}
  });

  return {
    extensions,
    foundBundles: flattenBundles(bundles)
  };
};

async function verifyBundlesEntryPoints (bundles) {
  const checkPathsPromises = bundles.map(async ({ bundleName, modulePath }) => {
    const jsPath = `${modulePath}/ui/src/${bundleName}.js`;
    const scssPath = `${modulePath}/ui/src/${bundleName}.scss`;

    const jsFileExists = await fs.pathExists(jsPath);
    const scssFileExists = await fs.pathExists(scssPath);

    return {
      bundleName,
      ...jsFileExists && { jsPath: jsPath },
      ...scssFileExists && { scssPath: scssPath }
    };
  });

  const bundlesPaths = (await Promise.all(checkPathsPromises));

  const packedFilesByBundle = bundlesPaths.reduce((acc, {
    bundleName, jsPath, scssPath
  }) => {
    if (!jsPath && !scssPath) {
      return acc;
    }

    return {
      ...acc,
      [bundleName]: {
        js: [
          ...acc[bundleName] ? acc[bundleName].js : [],
          ...jsPath ? [ jsPath ] : []
        ],
        scss: [
          ...acc[bundleName] ? acc[bundleName].scss : [],
          ...scssPath ? [ scssPath ] : []
        ]
      }
    };
  }, {});

  return packedFilesByBundle;
};

function formatConfigs (chain, webpackConfigs) {
  return Object.entries(webpackConfigs)
    .map(([ name, config ], i) => {

      if (!config) {
        return null;
      }

      const { bundles = {}, extensions = {} } = config;

      return {
        extensions,
        bundles: {
          [name]: {
            bundleNames: Object.keys(bundles),
            modulePath: chain[i].dirname
          }
        }
      };
    }).filter((config) => config);
}

function flattenBundles (bundles) {
  return Object.values(bundles)
    .reduce((acc, { bundleNames, modulePath }) => {
      return [
        ...acc,
        ...bundleNames.map((bundleName) => ({
          bundleName,
          modulePath
        }))
      ];
    }, []);
}
<commit_msg>feedback<commit_after>const fs = require('fs-extra');

module.exports = {
  checkModulesWebpackConfig(modules, t) {
    const allowedProperties = [ 'extensions', 'bundles' ];
    for (const mod of Object.values(modules)) {
      const webpackConfig = mod.__meta.webpack[mod.__meta.name];

      if (!webpackConfig) {
        continue;
      }

      if (
        typeof webpackConfig !== 'object' ||
        webpackConfig === null ||
        Array.isArray(webpackConfig) ||
        Object.keys(webpackConfig).some((prop) => !allowedProperties.includes(prop))
      ) {
        const error = t('apostrophe:assetWebpackConfigWarning', {
          module: mod.__meta.name
        });

        throw new Error(error);
      }

      if (webpackConfig && webpackConfig.bundles) {
        const bundles = Object.values(webpackConfig.bundles);

        bundles.forEach(bundle => {
          const bundleProps = Object.keys(bundle);
          if (
            bundleProps.length > 1 ||
            (bundleProps.length === 1 && !bundle.templates) ||
            (bundle.templates && !Array.isArray(bundle.templates))
          ) {
            const error = t('apostrophe:assetWebpackBundlesWarning', {
              module: mod.__meta.name
            });

            throw new Error(error);
          }
        });
      }
    }
  },

  async getWebpackExtensions ({
    getMetadata, modulesToInstantiate
  }) {
    const modulesMeta = modulesToInstantiate
      .map((name) => getMetadata(name));

    const { extensions, foundBundles } = getModulesWebpackConfigs(
      modulesMeta
    );

    const verifiedBundles = await verifyBundlesEntryPoints(foundBundles);

    return {
      extensions,
      verifiedBundles
    };
  },

  fillExtraBundles (verifiedBundles = {}) {
    return Object.entries(verifiedBundles).reduce((acc, [ bundleName, { js, scss } ]) => {
      return {
        js: [
          ...acc.js,
          ...(js.length && !acc.js.includes(bundleName)) ? [ bundleName ] : []
        ],
        css: [
          ...acc.css,
          ...(scss.length && !acc.css.includes(bundleName)) ? [ bundleName ] : []
        ]
      };
    }, {
      js: [],
      css: []
    });
  },

  getBundlesNames (bundles, es5 = false) {
    return Object.entries(bundles).reduce((acc, [ ext, bundlesNames ]) => {
      const nameExtension = ext === 'css'
        ? '-bundle'
        : '-module-bundle';

      const es5Bundles = es5 && ext === 'js'
        ? bundlesNames.map((name) => `${name}-nomodule-bundle.${ext}`)
        : [];

      return [
        ...acc,
        ...bundlesNames.map((name) => `${name}${nameExtension}.${ext}`),
        ...es5Bundles
      ];
    }, []);
  },

  writeBundlesImportFiles ({
    name,
    buildDir,
    mainBundleName,
    verifiedBundles,
    getImportFileOutput,
    writeImportFile
  }) {
    if (!name.includes('src')) {
      return [];
    }

    const bundlesOutputs = Object.entries(verifiedBundles)
      .map(([ bundleName, paths ]) => {
        return {
          bundleName,
          importFile: `${buildDir}/${bundleName}-import.js`,
          js: getImportFileOutput(paths.js, {
            invokeApps: true,
            enumerateImports: true,
            requireDefaultExport: true
          }),
          scss: getImportFileOutput(paths.scss, {
            enumerateImports: true,
            importSuffix: 'Stylesheet'
          })
        };
      });

    for (const output of bundlesOutputs) {
      writeImportFile({
        importFile: output.importFile,
        indexJs: output.js,
        indexSass: output.scss
      });
    }

    return bundlesOutputs.reduce((acc, { bundleName, importFile }) => {
      return {
        ...acc,
        [bundleName]: {
          import: importFile,
          dependOn: mainBundleName
        }
      };
    }, {});
  }
};

function getModulesWebpackConfigs (modulesMeta) {
  const { extensions, bundles } = modulesMeta.reduce((acc, meta) => {
    const { webpack, __meta } = meta;

    const configs = formatConfigs(__meta.chain, webpack);

    if (!configs.length) {
      return acc;
    }

    const moduleBundles = configs.reduce((acc, conf) => {
      return {
        ...acc,
        ...conf.bundles
      };
    }, {});

    return {
      extensions: {
        ...acc.extensions,
        ...configs.reduce((acc, config) => ({
          ...acc,
          ...config.extensions
        }), {})
      },
      bundles: {
        ...acc.bundles,
        ...moduleBundles
      }
    };
  }, {
    extensions: {},
    bundles: {}
  });

  return {
    extensions,
    foundBundles: flattenBundles(bundles)
  };
};

async function verifyBundlesEntryPoints (bundles) {
  const checkPathsPromises = bundles.map(async ({ bundleName, modulePath }) => {
    const jsPath = `${modulePath}/ui/src/${bundleName}.js`;
    const scssPath = `${modulePath}/ui/src/${bundleName}.scss`;

    const jsFileExists = await fs.pathExists(jsPath);
    const scssFileExists = await fs.pathExists(scssPath);

    return {
      bundleName,
      ...jsFileExists && { jsPath: jsPath },
      ...scssFileExists && { scssPath: scssPath }
    };
  });

  const bundlesPaths = await Promise.all(checkPathsPromises);

  const packedFilesByBundle = bundlesPaths.reduce((acc, {
    bundleName, jsPath, scssPath
  }) => {
    if (!jsPath && !scssPath) {
      return acc;
    }

    return {
      ...acc,
      [bundleName]: {
        js: [
          ...acc[bundleName] ? acc[bundleName].js : [],
          ...jsPath ? [ jsPath ] : []
        ],
        scss: [
          ...acc[bundleName] ? acc[bundleName].scss : [],
          ...scssPath ? [ scssPath ] : []
        ]
      }
    };
  }, {});

  return packedFilesByBundle;
};

function formatConfigs (chain, webpackConfigs) {
  return Object.entries(webpackConfigs)
    .map(([ name, config ], i) => {

      if (!config) {
        return null;
      }

      const { bundles = {}, extensions = {} } = config;

      return {
        extensions,
        bundles: {
          [name]: {
            bundleNames: Object.keys(bundles),
            modulePath: chain[i].dirname
          }
        }
      };
    }).filter((config) => config);
}

function flattenBundles (bundles) {
  return Object.values(bundles)
    .reduce((acc, { bundleNames, modulePath }) => {
      return [
        ...acc,
        ...bundleNames.map((bundleName) => ({
          bundleName,
          modulePath
        }))
      ];
    }, []);
}
<|endoftext|>


<commit_before>"use strict";

angular.module("hikeio").
	directive("fancybox", ["$http", "$log", "$rootScope", "$timeout", "resourceCache", function($http, $log, $rootScope, $timeout, resourceCache) {
		return {
			link: function (scope, element, attrs) {
				var flickrLicenses = {
					"0": {"name":"All Rights Reserved", "url":"" },
					"1": {"name":"Attribution-NonCommercial-ShareAlike License", "short":"CC BY-NC-SA 2.0", "url":"http://creativecommons.org/licenses/by-nc-sa/2.0/"},
					"2": {"name":"Attribution-NonCommercial License", "short":"CC BY-NC 2.0", "url":"http://creativecommons.org/licenses/by-nc/2.0/"},
					"3": {"name":"Attribution-NonCommercial-NoDerivs License", "short":"CC BY-NC-ND 2.0", "url":"http://creativecommons.org/licenses/by-nc-nd/2.0/"},
					"4": {"name":"Attribution License", "short":"CC BY 2.0", "url":"http://creativecommons.org/licenses/by/2.0/"},
					"5": {"name":"Attribution-ShareAlike License", "short":"CC BY-SA 2.0", "url":"http://creativecommons.org/licenses/by-sa/2.0/"},
					"6": {"name":"Attribution-NoDerivs License", "short":"CC BY-ND 2.0", "url":"http://creativecommons.org/licenses/by-nd/2.0/"},
					"7": {"name":"No known copyright restrictions", "url":"http://www.flickr.com/commons/usage/"},
					"8": {"name":"United States Government Work", "url":"http://www.usa.gov/copyright.shtml"}
				};
				var context = {
					beforeLoad: function() {
						var fancyboxElement = this.element;
						var attributionLink = fancyboxElement.attr("data-attribution-link");
						if (!attributionLink) {
							return;
						} else if (attributionLink.indexOf("flickr.com") === -1) {
							$log.error("Unable to fetch attribution data for: " + attributionLink);
							return;
						}
						if (attributionLink.endsWith("/")) {
							attributionLink = attributionLink.slice(0, -1);
						}
						var splitAttributionLink = attributionLink.split("/");
						var photoId = splitAttributionLink[splitAttributionLink.length - 1];
						if (photoId) {
							$http({method: "GET", url: "http://api.flickr.com/services/rest/?method=flickr.photos.getInfo&api_key=d99915ff009f20c36657c94263e52674&photo_id=" + photoId + "&format=json&nojsoncallback=1", cache: resourceCache}).
								success(function(data, status, headers, config) {
									if (data.stat === "ok") {
										var attributionDiv = $("

");
										var authorName = data.photo.owner.realname ? data.photo.owner.realname : data.photo.owner.username;
										var nameAndTitleAnchor = $("\"" + data.photo.title._content + "\" by " + authorName + "");
										var separator = $(" • ");
										var br = $("
");
										var licenseName = flickrLicenses[data.photo.license].short || flickrLicenses[data.photo.license].name;
										var licenseAnchor = $(" • " + licenseName + "");
										var modified = $(" Resized from original ");
										attributionDiv.append(nameAndTitleAnchor);
										attributionDiv.append(br);
										attributionDiv.append(separator);
										attributionDiv.append(modified);
										attributionDiv.append(licenseAnchor);
										$(".fancybox-inner").append(attributionDiv);
										$timeout(function() {
											attributionDiv.css("opacity", "1");
										});
									}
								}).
								error(function(data, status, headers, config) {
									$log.error(config);
								});
						}
					},
					afterLoad: function() {
						$rootScope.$broadcast("fancyboxLoaded");
						var attributionLink = this.element.attr("data-attribution-link");
						if (attributionLink) {
							var anchor = $(".attribution-link").clone();
							anchor.attr("href", attributionLink);
							anchor.addClass("active");
							anchor.click(function(event) {
								event.stopPropagation();
							});
							$(".fancybox-inner").append(anchor);
						}
					},
					afterClose: function() {
						$rootScope.$broadcast("fancyboxClosed");
					},
					margin: 30,
					padding : 2,
					nextEffect : "none",
					prevEffect : "none",
					closeEffect : "none",
					closeBtn : true,
					arrows : false,
					keys : true,
					nextClick : true
				};

				scope.$on("$routeChangeStart", function () {
					$.fancybox.close();
				});
				scope.$on("fancyboxClose", function () {
					$.fancybox.close();
				});
				scope.$on("$destroy", function () {
					context.afterLoad = null;
					context.afterClose = null;
				});

				$(element).find(attrs.fancybox).fancybox(context);
			}
		};
	}]);<commit_msg>Remove old
 from francs box attribution line.<commit_after>"use strict";

angular.module("hikeio").
	directive("fancybox", ["$http", "$log", "$rootScope", "$timeout", "resourceCache", function($http, $log, $rootScope, $timeout, resourceCache) {
		return {
			link: function (scope, element, attrs) {
				var flickrLicenses = {
					"0": {"name":"All Rights Reserved", "url":"" },
					"1": {"name":"Attribution-NonCommercial-ShareAlike License", "short":"CC BY-NC-SA 2.0", "url":"http://creativecommons.org/licenses/by-nc-sa/2.0/"},
					"2": {"name":"Attribution-NonCommercial License", "short":"CC BY-NC 2.0", "url":"http://creativecommons.org/licenses/by-nc/2.0/"},
					"3": {"name":"Attribution-NonCommercial-NoDerivs License", "short":"CC BY-NC-ND 2.0", "url":"http://creativecommons.org/licenses/by-nc-nd/2.0/"},
					"4": {"name":"Attribution License", "short":"CC BY 2.0", "url":"http://creativecommons.org/licenses/by/2.0/"},
					"5": {"name":"Attribution-ShareAlike License", "short":"CC BY-SA 2.0", "url":"http://creativecommons.org/licenses/by-sa/2.0/"},
					"6": {"name":"Attribution-NoDerivs License", "short":"CC BY-ND 2.0", "url":"http://creativecommons.org/licenses/by-nd/2.0/"},
					"7": {"name":"No known copyright restrictions", "url":"http://www.flickr.com/commons/usage/"},
					"8": {"name":"United States Government Work", "url":"http://www.usa.gov/copyright.shtml"}
				};
				var context = {
					beforeLoad: function() {
						var fancyboxElement = this.element;
						var attributionLink = fancyboxElement.attr("data-attribution-link");
						if (!attributionLink) {
							return;
						} else if (attributionLink.indexOf("flickr.com") === -1) {
							$log.error("Unable to fetch attribution data for: " + attributionLink);
							return;
						}
						if (attributionLink.endsWith("/")) {
							attributionLink = attributionLink.slice(0, -1);
						}
						var splitAttributionLink = attributionLink.split("/");
						var photoId = splitAttributionLink[splitAttributionLink.length - 1];
						if (photoId) {
							$http({method: "GET", url: "http://api.flickr.com/services/rest/?method=flickr.photos.getInfo&api_key=d99915ff009f20c36657c94263e52674&photo_id=" + photoId + "&format=json&nojsoncallback=1", cache: resourceCache}).
								success(function(data, status, headers, config) {
									if (data.stat === "ok") {
										var attributionDiv = $("

");
										var authorName = data.photo.owner.realname ? data.photo.owner.realname : data.photo.owner.username;
										var nameAndTitleAnchor = $("\"" + data.photo.title._content + "\" by " + authorName + "");
										var separator = $(" • ");
										var licenseName = flickrLicenses[data.photo.license].short || flickrLicenses[data.photo.license].name;
										var licenseAnchor = $(" • " + licenseName + "");
										var modified = $(" Resized from original ");
										attributionDiv.append(nameAndTitleAnchor);
										attributionDiv.append(separator);
										attributionDiv.append(modified);
										attributionDiv.append(licenseAnchor);
										$(".fancybox-inner").append(attributionDiv);
										$timeout(function() {
											attributionDiv.css("opacity", "1");
										});
									}
								}).
								error(function(data, status, headers, config) {
									$log.error(config);
								});
						}
					},
					afterLoad: function() {
						$rootScope.$broadcast("fancyboxLoaded");
						var attributionLink = this.element.attr("data-attribution-link");
						if (attributionLink) {
							var anchor = $(".attribution-link").clone();
							anchor.attr("href", attributionLink);
							anchor.addClass("active");
							anchor.click(function(event) {
								event.stopPropagation();
							});
							$(".fancybox-inner").append(anchor);
						}
					},
					afterClose: function() {
						$rootScope.$broadcast("fancyboxClosed");
					},
					margin: 30,
					padding : 2,
					nextEffect : "none",
					prevEffect : "none",
					closeEffect : "none",
					closeBtn : true,
					arrows : false,
					keys : true,
					nextClick : true
				};

				scope.$on("$routeChangeStart", function () {
					$.fancybox.close();
				});
				scope.$on("fancyboxClose", function () {
					$.fancybox.close();
				});
				scope.$on("$destroy", function () {
					context.afterLoad = null;
					context.afterClose = null;
				});

				$(element).find(attrs.fancybox).fancybox(context);
			}
		};
	}]);<|endoftext|>


<commit_before>"use strict";

var http = require("http");
var q = require("q");

var Router = require("./router");
var statuses = require("./statuses");

var Server = function Server(options) {
	var self = this;
	this._router = new Router(options.routes || []);
	this._server = http.createServer();
	this._server.on("request", function (request, response) {
		self._handleRequest(request, response);
	});
};
module.exports = Server;

Server.prototype.listen = function listen() {
	var args = Array.prototype.slice.call(arguments);
	return this._server.listen.apply(this._server, args);
};

Server.prototype._handleRequest = function _handleRequest(request, response) {
	// Augment request
	request.authentication = this._basicAuthentication(request);
	// Handle
	var server = this;
	server._router.dispatch(request, response)
	.then(function () {
		// Request has been handled
		response.end();
		return true;
	})
	.fail(function (error) {
		// An error has occurred whilst handling the request
		response.statusCode = error.statusCode;
		response.end(error.message + "\n");
	});
};

Server.prototype._basicAuthentication = function _basicAuthentication(request) {
	return function () {
		var authorization = request.headers.authorization;
		var fields;
		var pieces;
		var index;
		var decoded;
		if (!authorization) {
			return q.reject(statuses.errors.UNAUTHORIZED);
		}
		try {
			fields = authorization.split(" ", 2);
			// fields[0] should be "Basic"
			// fields[1] should be base64(sprintf("%s:%s", username, password))
			if (
				   !fields
				|| fields.length != 2
				|| fields[0].toLowerCase() != "basic"
			) {
				// Invalid header
				// OR unknown scheme
				throw new Error();
			}
			decoded = (new Buffer(fields[1], "base64")).toString("utf-8");
			if (!decoded) {
				throw new Error();
			}
			index = decoded.indexOf(":");
			pieces = [decoded.slice(0, index), decoded.slice(index + 1)]; // [username, password]
			if (!pieces[0] || !pieces[1]) {
				throw new Error();
			}
		}
		catch (e) {
			return q.reject(statuses.errors.BAD_REQUEST);
		}
		return q(pieces);
	};
};
<commit_msg>Close server on SIGINT<commit_after>"use strict";

var http = require("http");
var q = require("q");

var Router = require("./router");
var statuses = require("./statuses");

var Server = function Server(options) {
	var self = this;
	this._router = new Router(options.routes || []);
	this._server = http.createServer();
	this._server.on("request", function (request, response) {
		self._handleRequest(request, response);
	});
	process.on("SIGINT", function () {
		console.log(); // \n
		self._server.close();
	});
};
module.exports = Server;

Server.prototype.listen = function listen() {
	var args = Array.prototype.slice.call(arguments);
	return this._server.listen.apply(this._server, args);
};

Server.prototype._handleRequest = function _handleRequest(request, response) {
	// Augment request
	request.authentication = this._basicAuthentication(request);
	// Handle
	var server = this;
	server._router.dispatch(request, response)
	.then(function () {
		// Request has been handled
		response.end();
		return true;
	})
	.fail(function (error) {
		// An error has occurred whilst handling the request
		response.statusCode = error.statusCode;
		response.end(error.message + "\n");
	});
};

Server.prototype._basicAuthentication = function _basicAuthentication(request) {
	return function () {
		var authorization = request.headers.authorization;
		var fields;
		var pieces;
		var index;
		var decoded;
		if (!authorization) {
			return q.reject(statuses.errors.UNAUTHORIZED);
		}
		try {
			fields = authorization.split(" ", 2);
			// fields[0] should be "Basic"
			// fields[1] should be base64(sprintf("%s:%s", username, password))
			if (
				   !fields
				|| fields.length != 2
				|| fields[0].toLowerCase() != "basic"
			) {
				// Invalid header
				// OR unknown scheme
				throw new Error();
			}
			decoded = (new Buffer(fields[1], "base64")).toString("utf-8");
			if (!decoded) {
				throw new Error();
			}
			index = decoded.indexOf(":");
			pieces = [decoded.slice(0, index), decoded.slice(index + 1)]; // [username, password]
			if (!pieces[0] || !pieces[1]) {
				throw new Error();
			}
		}
		catch (e) {
			return q.reject(statuses.errors.BAD_REQUEST);
		}
		return q(pieces);
	};
};
<|endoftext|>


<commit_before>'use strict';

var copy           = require('es5-ext/object/copy')
  , ensureString   = require('es5-ext/object/validate-stringifiable-value')
  , escape         = require('es5-ext/reg-exp/escape')
  , startsWith     = require('es5-ext/string/#/starts-with')
  , deferred       = require('deferred')
  , findRequires   = require('find-requires')
  , readdir        = require('fs2/readdir')
  , stat           = require('fs2/stat')
  , readFile       = require('fs2/read-file')
  , writeFile      = require('fs2/write-file')
  , unlink         = require('fs2/unlink')
  , path           = require('path')
  , resolveModule  = require('cjs-module/resolve')
  , resolveRoot    = require('cjs-module/resolve-package-root')
  , isPathExternal = require('cjs-module/utils/is-path-external')
  , isJsModule     = require('./lib/is-js-module')

  , push = Array.prototype.push, stringify = JSON.stringify
  , basename = path.basename, extname = path.extname, sep = path.sep, dirname = path.dirname
  , relative = path.relative, resolve = path.resolve
  , findRequiresOpts = { raw: true };

var readdirOpts = { depth: Infinity, type: { file: true }, stream: true,
	dirFilter: function (path) { return (basename(path) !== 'node_modules'); },
	ignoreRules: 'git', pattern: new RegExp(escape(sep) + '(?:[^.]+|.+\\.js)$') };

module.exports = function (from, to) {
	from = resolve(ensureString(from));
	to = resolve(ensureString(to));

	// Validate arguments and resolve initial data
	return deferred(stat(from), resolveRoot(dirname(from)), stat(to).then(function () {
		throw new Error("Target path " + stringify(to) + " is not empty");
	}, function (err) {
		if (err.code === 'ENOENT') return null;
		throw err;
	}))(function (data) {
		var fileStats = data[0], root = data[1], dirReader, filePromises, modulesToUpdate;

		if (!fileStats.isFile()) throw new Error("Input module " + stringify(from) + " is not a file");
		if (!root) {
			throw new Error("Unable to resolve package root (renamed module is expected to be placed " +
				"in scope of some package");
		}
		if (!startsWith.call(to, root + sep)) {
			throw new Error("Cannot reliably move module out of current package");
		}

		// Find all JS modules in a package
		dirReader = readdir(root, readdirOpts);
		filePromises = [];
		modulesToUpdate = [];
		dirReader.on('change', function (event) {
			push.apply(filePromises, event.added.map(function (path) {
				var filename = resolve(root, path);
				if (filename === from) return;
				return isJsModule(filename)(function (isJs) {
					var dir;
					if (!isJs) return;

					// Find if JS module contains a require to renamed module
					dir = dirname(filename);
					return readFile(filename)(function (code) {
						code = String(code);
						return deferred.map(findRequires(code, findRequiresOpts), function (data) {
							if (isPathExternal(data.value)) return;
							return resolveModule(dir, data.value)(function (requiredFilename) {
								if (from === requiredFilename) return data;
							});
						})(function (result) {
							result = result.filter(Boolean);
							if (!result.length) return;
							modulesToUpdate.push({ filename: filename, dirname: dir,
								code: code, requires: result });
						});
					});
				});
			}));
		});
		return dirReader(function () { return deferred.map(filePromises); })(function () {
			if (!modulesToUpdate.length) return;

			// Update affected requires in modules that require renamed module
			return deferred.map(modulesToUpdate, function (data) {
				var nuPath = relative(data.dirname, to)
				  , nuPathExt = extname(nuPath)
				  , diff = 0
				  , code = data.code;
				if (nuPath[0] !== '.') nuPath = './' + nuPath;
				data.requires.forEach(function (reqData) {
					var nuRaw = stringify((nuPathExt && !extname(reqData.value))
						? nuPath.slice(0, -nuPathExt.length) : nuPath).slice(1, -1);
					code = code.slice(0, reqData.point + diff) + nuRaw +
						code.slice(reqData.point + diff + reqData.raw.length - 2);
					diff += nuRaw.length - (reqData.raw.length - 2);
				});
				return writeFile(data.filename, code);
			});
		})(function () {
			// Rename module, and update require paths within it
			return readFile(from)(function (code) {
				var dir = dirname(from), ext = extname(from);
				code = String(code);
				if (ext && (ext !== '.js')) return code;
				return isJsModule(from)(function (isJs) {
					if (!isJs) return code;
					return deferred.map(findRequires(code, findRequiresOpts).filter(function (data) {
						return !isPathExternal(data.value);
					}), function (data) {
						return resolveModule(dir, data.value)(function (path) {
							data.modulePath = path;
							return data;
						});
					})(function (requires) {
						var diff = 0, dir = dirname(to);
						requires.forEach(function (reqData) {
							var nuPath = relative(dir, reqData.modulePath)
							  , nuPathExt = extname(nuPath);
							if (nuPath[0] !== '.') nuPath = './' + nuPath;
							var nuRaw = stringify((nuPathExt && !extname(reqData.value))
								? nuPath.slice(0, -nuPathExt.length) : nuPath).slice(1, -1);
							code = code.slice(0, reqData.point + diff) + nuRaw +
								code.slice(reqData.point + diff + reqData.raw.length - 2);
							diff += nuRaw.length - (reqData.raw.length - 2);
						});
						return code;
					});
				});
			});
		})(function (nuCode) {
			return deferred(writeFile(to, nuCode, { mode: fileStats.mode, intermediate: true }),
				unlink(from));
		});
	});
};
<commit_msg>-- lint<commit_after>'use strict';

var ensureString   = require('es5-ext/object/validate-stringifiable-value')
  , escape         = require('es5-ext/reg-exp/escape')
  , startsWith     = require('es5-ext/string/#/starts-with')
  , deferred       = require('deferred')
  , findRequires   = require('find-requires')
  , readdir        = require('fs2/readdir')
  , stat           = require('fs2/stat')
  , readFile       = require('fs2/read-file')
  , writeFile      = require('fs2/write-file')
  , unlink         = require('fs2/unlink')
  , path           = require('path')
  , resolveModule  = require('cjs-module/resolve')
  , resolveRoot    = require('cjs-module/resolve-package-root')
  , isPathExternal = require('cjs-module/utils/is-path-external')
  , isJsModule     = require('./lib/is-js-module')

  , push = Array.prototype.push, stringify = JSON.stringify
  , basename = path.basename, extname = path.extname, sep = path.sep, dirname = path.dirname
  , relative = path.relative, resolve = path.resolve
  , findRequiresOpts = { raw: true };

var readdirOpts = { depth: Infinity, type: { file: true }, stream: true,
	dirFilter: function (path) { return (basename(path) !== 'node_modules'); },
	ignoreRules: 'git', pattern: new RegExp(escape(sep) + '(?:[^.]+|.+\\.js)$') };

module.exports = function (from, to) {
	from = resolve(ensureString(from));
	to = resolve(ensureString(to));

	// Validate arguments and resolve initial data
	return deferred(stat(from), resolveRoot(dirname(from)), stat(to).then(function () {
		throw new Error("Target path " + stringify(to) + " is not empty");
	}, function (err) {
		if (err.code === 'ENOENT') return null;
		throw err;
	}))(function (data) {
		var fileStats = data[0], root = data[1], dirReader, filePromises, modulesToUpdate;

		if (!fileStats.isFile()) throw new Error("Input module " + stringify(from) + " is not a file");
		if (!root) {
			throw new Error("Unable to resolve package root (renamed module is expected to be placed " +
				"in scope of some package");
		}
		if (!startsWith.call(to, root + sep)) {
			throw new Error("Cannot reliably move module out of current package");
		}

		// Find all JS modules in a package
		dirReader = readdir(root, readdirOpts);
		filePromises = [];
		modulesToUpdate = [];
		dirReader.on('change', function (event) {
			push.apply(filePromises, event.added.map(function (path) {
				var filename = resolve(root, path);
				if (filename === from) return;
				return isJsModule(filename)(function (isJs) {
					var dir;
					if (!isJs) return;

					// Find if JS module contains a require to renamed module
					dir = dirname(filename);
					return readFile(filename)(function (code) {
						code = String(code);
						return deferred.map(findRequires(code, findRequiresOpts), function (data) {
							if (isPathExternal(data.value)) return;
							return resolveModule(dir, data.value)(function (requiredFilename) {
								if (from === requiredFilename) return data;
							});
						})(function (result) {
							result = result.filter(Boolean);
							if (!result.length) return;
							modulesToUpdate.push({ filename: filename, dirname: dir,
								code: code, requires: result });
						});
					});
				});
			}));
		});
		return dirReader(function () { return deferred.map(filePromises); })(function () {
			if (!modulesToUpdate.length) return;

			// Update affected requires in modules that require renamed module
			return deferred.map(modulesToUpdate, function (data) {
				var nuPath = relative(data.dirname, to)
				  , nuPathExt = extname(nuPath)
				  , diff = 0
				  , code = data.code;
				if (nuPath[0] !== '.') nuPath = './' + nuPath;
				data.requires.forEach(function (reqData) {
					var nuRaw = stringify((nuPathExt && !extname(reqData.value))
						? nuPath.slice(0, -nuPathExt.length) : nuPath).slice(1, -1);
					code = code.slice(0, reqData.point + diff) + nuRaw +
						code.slice(reqData.point + diff + reqData.raw.length - 2);
					diff += nuRaw.length - (reqData.raw.length - 2);
				});
				return writeFile(data.filename, code);
			});
		})(function () {
			// Rename module, and update require paths within it
			return readFile(from)(function (code) {
				var dir = dirname(from), ext = extname(from);
				code = String(code);
				if (ext && (ext !== '.js')) return code;
				return isJsModule(from)(function (isJs) {
					if (!isJs) return code;
					return deferred.map(findRequires(code, findRequiresOpts).filter(function (data) {
						return !isPathExternal(data.value);
					}), function (data) {
						return resolveModule(dir, data.value)(function (path) {
							data.modulePath = path;
							return data;
						});
					})(function (requires) {
						var diff = 0, dir = dirname(to);
						requires.forEach(function (reqData) {
							var nuPath = relative(dir, reqData.modulePath)
							  , nuPathExt = extname(nuPath);
							if (nuPath[0] !== '.') nuPath = './' + nuPath;
							var nuRaw = stringify((nuPathExt && !extname(reqData.value))
								? nuPath.slice(0, -nuPathExt.length) : nuPath).slice(1, -1);
							code = code.slice(0, reqData.point + diff) + nuRaw +
								code.slice(reqData.point + diff + reqData.raw.length - 2);
							diff += nuRaw.length - (reqData.raw.length - 2);
						});
						return code;
					});
				});
			});
		})(function (nuCode) {
			return deferred(writeFile(to, nuCode, { mode: fileStats.mode, intermediate: true }),
				unlink(from));
		});
	});
};
<|endoftext|>


<commit_before>'use strict';

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

app.get('/hello', (req, res) => {

    const msgInABottle = '
Hello World!!!!
';

    console.log(req.method, req.url);
    res.writeHead(200, {
      'Content-type': 'text/html'
    });

    msgInABottle.split('').forEach((char, i) => {
      const events = [];
      setTimeout(() => {
        res.write(char);
        events.pop();
        console.log(char);
    }, 1000 * i);
      events.push(i)
  });

  setTimeout(() => {
    res.end();
  }, 25000);
});

app.get('/random', (req, res) => {
    res.end(Math.random().toString());
});

app.all('*', (req, res) => {
  res.status(403);
  res.send('
access denied
');
});

app.listen(PORT, () => {
  console.log(`Node.js server started. Listening on ${ PORT }.`);
});<commit_msg>Used Jade in example.<commit_after>'use strict';

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.set('view engine', 'jade');

app.get('/', (req, res) => {
  res.render('index', {
      title: 'Super Cool App',
      date: new Date()
  });
});

app.get('/hello', (req, res) => {

    const msgInABottle = '
Hello World!!!!
';
    console.log(req.method, req.url);
    res.writeHead(200, {
      'Content-type': 'text/html'
    });
  console.log(req.query);
    msgInABottle.split('').forEach((char, i) => {
      const events = [];
      setTimeout(() => {
        res.write(char);
        events.pop();
        console.log(char);
    }, 1000 * i);
      events.push(i)
  });

  setTimeout(() => {
    res.end();
  }, 25000);
});

app.get('/random:min/:max', (req, res) => {
  const min = req.params.min;
  const max = req.params.max;

  res.send(getRandomInt(+min, +max).toString());
});

// app.get('/cal') => {

// }

app.all('*', (req, res) => {
  res.status(403);
  res.send('
access denied
');
});

app.listen(PORT, () => {
  console.log(`Node.js server started. Listening on ${ PORT }.`);
});

// Child process exec
// Use npm to install cal to this directory.
// Interface directly with cal
<|endoftext|>