<commit_before>/*
 * Place all the behaviors and hooks related to the matching controller here.
 * All this logic will automatically be available in application.js.
 */

var Editor = (function($, autosize) {

    /*
     * Creates an instance of the Editor class
     *
     * @constructor
     * @param {jQuery} $editor The wrapping text editor element
     */
    function Editor($editor) {
        this.options = {
            selector: {
                toolbar: '.text-editor__toolbar:first',
                field:   '.text-editor__field',
            }
        }

        this.$editor  = $editor;
        this.$toolbar = $editor.find(this.options.selector.toolbar);
        this.$fields  = $editor.find(this.options.selector.field);
        this.data = this.$editor.data('editorData');

        this.lastFocus = null;

        this.init();

        var self = this;

        /*
         * By adding or removing elements to the commands property,
         * you can add custom commands, e. g. to insert the markup
         * for an image or a link.
         *
         * @type {function[]}
         */
        this.commands = {
            text: function($context) {
                return $context.data().editorMarkupText;
            },
        };
    };

    /*
     * Sets event listeners on the editor and its child elements
     *
     * @returns {Editor}
     */
    Editor.prototype.init = function() {
        var self = this;

        // set all event handlers on toolbar buttons
        self.$toolbar.find('[data-editor-markup-button]').on('click', function(e) {
            e.preventDefault();

            var command = $(this).data().editorMarkupCommand;

            self.recoverFocus();
            self.runCommand(command, $(this));
        });

        self.$toolbar.find('[data-editor-markup-select]').on('change', function(e) {
            var $option = $(this).find(':selected');
            var command = $option.data().editorMarkupCommand;

            self.recoverFocus();
            self.runCommand(command, $option);
        });

        // initiate all fields
        self.$fields.each(function() {
            var field = new Field($(this), self);
            $(this).data('editor-field', field);
        });

        return this;
    };

    /*
     * Inserts a string at the current cursor position in the
     * currently active field
     *
     * @param {string} string The text to be inserted
     * @returns {Editor}
     */
    Editor.prototype.insertText = function(string) {
        var activeField = this.findActiveField();

        if(activeField) {
            activeField.insertText(string);
        }

        return this;
    };

    /*
     * Run a command to manipulate editor field contents
     *
     * @param {String} command
     * @param {jQuery} $context
     * @returns {Editor}
     */
    Editor.prototype.runCommand = function(command, $context) {
        var command = this.commands[command];

        if(typeof command !== 'function') throw new Error('Command not defined: ' + $context.data().editorMarkupCommand);

        this.insertText(command($context));

        return this;
    };

    /*
     * Return a focussed field
     *
     * @returns {Field}
     */
    Editor.prototype.findActiveField = function() {
        var $field = this.$fields.filter(function() {
            return $(this).data('editorField').isFocussed();
        });

        if($field.length > 0) {
            return $field.data('editorField');
        } else {
            return null;
        }
    };

    /*
     * Saves the passed (focused) field to recover the current
     * focus state later
     *
     * @param {Field} field
     * @returns {Editor}
     */
    Editor.prototype.saveFocus = function(field) {
        this.lastFocus = field;

        return this;
    };

    /*
     * Set the focus to a previously saved field
     *
     * @returns {Editor}
     */
    Editor.prototype.recoverFocus = function() {
        if(this.lastFocus) {
            this.lastFocus.focus();
        }

        return this;
    };

    /*
     * Creates an instance of the Field class
     *
     * @constructor
     * @param {jQuery} $field The field element
     * @param {Editor} editor The editor the field belongs to
     */
    function Field($field, editor) {
        this.editor = editor;

        this.$field = $field;
        this.$input = $field.find('.field__input');
        this.$mirror = null;
        this.$count = $field.find('.field__count');

        this.init();
    };

    /*
     *
     */
    Field.prototype.filters = {
        sensors: {
            pattern: /{\s*value\(\s*(\d+)\s*\)\s*}/g,
            markup: function(markup, id) {
                var cls = ['markup', 'markup--sensor'];
                if(!this.editor.data.sensors[id]) cls.push('markup--error');

                return '' + markup + '';
            },
            tooltip: function(markup, id) {
                if(name = this.editor.data.sensors[id]) {
                    return name;
                }
                return false;
            }
        },
        events: {
            pattern: /{\s*date\(\s*(\d+)\s*\)\s*}/g,
            markup: function(markup, id) {
                var cls = ['markup', 'markup--event'];
                if(!this.editor.data.events[id]) cls.push('markup--error');

                return '' + markup + '';
            },
            tooltip: function(markup, id) {
                if(name = this.editor.data.events[id]) {
                    return name;
                }
                return false;
            },
        },
    };

    /*
     * Initiate the field's dom node
     *
     * @return {Field}
     */
    Field.prototype.init = function() {
        var self = this;

        self.$mirror = $('
').addClass('field__mirror').appendTo(self.$field);
        self.$tooltip = $('
').addClass('field__tooltip').appendTo(self.$field);

        self.$input
            .on('blur', function() {
                self.editor.saveFocus(self);
            })
            .on('input keydown mousedown blur focus', function() {
                window.setTimeout(function() {
                    self.handleCursor();
                    self.render();
                    self.updateCount();
                }, 1);
            })

        self.render();
        self.updateCount();
        autosize(self.$input);

        return this;
    };

    /*
     * Renders the fields content, e. g. to highlight markup
     *
     * @returns {Field
     */
    Field.prototype.render = function() {
        var self = this;

        var text = self.$input.val();

        $.each(self.filters, function(name, filter) {
            text = text.replace(filter.pattern, function() {
                return filter.markup.apply(self, arguments);
            });
        });

        self.$mirror.html(text);
    };

    /*
     * Handles a change of the cursor position
     */
    Field.prototype.handleCursor = function() {
        var self = this;
        var selection = self.getSelection();
        var markup = self.findMarkup();
        var activeMarkup = null;
        var tooltip = false;

        // check if there are intersections between
        // the cursor position and the markup ranges
        $.each(markup, function(index, markup) {
            var min = markup.start < selection.start ? markup : selection;
            var max = markup.start < selection.start ? selection : markup;

            if(min.end > max.start) activeMarkup = markup;
        });

        if(activeMarkup) {
            tooltip = self.filters[activeMarkup.type].tooltip.apply(self, activeMarkup.matches);
        }

        if(tooltip && self.isFocussed()) {
            var text   = self.value();
            self.$mirror.html(text.substring(0, activeMarkup.start) + '' + text.substring(activeMarkup.start, activeMarkup.end) + '' + text.substring(activeMarkup.end, text.length));
            var $activeMarkup = self.$mirror.find('.field__markup--active');

            var pos = {
                top: $activeMarkup.offset().top - self.$field.offset().top,
                left: $activeMarkup.offset().left + .5 * $activeMarkup.width() - self.$field.offset().left,
            }

            self.$tooltip.show().text(tooltip).css({
                top: pos.top,
                left: pos.left,
            });
        } else {
            self.$tooltip.hide();
        }
    };

    /*
     *
     */
    Field.prototype.updateCount = function() {
        if(this.$count.length > 0) {
            var length = this.value().length;
            this.$count.text(length > 0 ? length : '');
        }
    }

    /*
     *
     */
    Field.prototype.findMarkup = function() {
        var markup = [];
        var text = this.value();

        $.each(this.filters, function(name, filter) {
            while((match = filter.pattern.exec(text)) !== null) {
                var matches = [];

                $.each(match, function(key, item) {
                    if(!isNaN(key)) matches.push(item);
                });

                markup.push({
                    type:  name,
                    matches: matches,
                    start: match.index,
                    end:   match.index + match[0].length,
                    length:match[0].length,
                });
            }
        });

        return markup;
    };

    /*
     * Gets the start and end position of the selection in the
     * field. If no text is selected, returns the position of the
     * character after the cursor. If the field is not active,
     * returns the position after the last character.
     *
     * @returns {Object} Object with 'start' and 'end' properties
     * representing the start end end of the selection
     */
    Field.prototype.getSelection = function() {
        var start  = this.$input.get(0).selectionStart,
            end    = this.$input.get(0).selectionEnd,
            length = this.$input.val().length;

        return {
            start: start !== undefined ? start : length,
            end:   end !== undefined ? end : length,
        };
    };

    /*
     * Inserts text at the current cursor position. If text is
     * selected, the current selection will be replaced.
     *
     * @param {string} string The text to be inserted
     * @returns {Field}
     */
    Field.prototype.insertText = function(string) {
        var value     = this.$input.val(),
            selection = this.getSelection();

        this.value(value.substring(0, selection.start) + string + value.substring(selection.end, value.length));

        return this;
    };

    /*
     * Get/set the value of the field
     *
     * @param {String} string
     * @return {Field|String}
     */
    Field.prototype.value = function(string) {
        if(typeof string === 'string') {
            this.$input.val(string);
            this.render();
            this.updateCount();
            autosize.update(this.$input);
        } else {
            return this.$input.val();
        }
        return this;
    };

    /*
     * Set the focus on the field's dom node
     *
     * @return {Field}
     */
    Field.prototype.focus = function() {
        this.$input.focus();

        return this;
    };

    /*
     * Checks wether the field is focused
     *
     * @return {boolean}
     */
    Field.prototype.isFocussed = function() {
        return this.$input.is(':focus');
    };

    return Editor;

})(jQuery, autosize);

(function($, Editor) {

    $.fn.editor = function() {
        this.each(function() {
            var editor = new Editor($(this));
            $(this).data('editor', editor);
        });
    };

})(jQuery, Editor);<commit_msg>fix #652<commit_after>/*
 * Place all the behaviors and hooks related to the matching controller here.
 * All this logic will automatically be available in application.js.
 */

var Editor = (function($, autosize) {

    /*
     * Creates an instance of the Editor class
     *
     * @constructor
     * @param {jQuery} $editor The wrapping text editor element
     */
    function Editor($editor) {
        this.options = {
            selector: {
                toolbar: '.text-editor__toolbar:first',
                field:   '.text-editor__field',
            }
        }

        this.$editor  = $editor;
        this.$toolbar = $editor.find(this.options.selector.toolbar);
        this.$fields  = $editor.find(this.options.selector.field);
        this.data = this.$editor.data('editorData');

        this.lastFocus = null;

        this.init();

        var self = this;

        /*
         * By adding or removing elements to the commands property,
         * you can add custom commands, e. g. to insert the markup
         * for an image or a link.
         *
         * @type {function[]}
         */
        this.commands = {
            text: function($context) {
                return $context.data().editorMarkupText;
            },
        };
    };

    /*
     * Sets event listeners on the editor and its child elements
     *
     * @returns {Editor}
     */
    Editor.prototype.init = function() {
        var self = this;

        // set all event handlers on toolbar buttons
        self.$toolbar.find('[data-editor-markup-button]').on('click', function(e) {
            e.preventDefault();

            var command = $(this).data().editorMarkupCommand;

            self.recoverFocus();
            self.runCommand(command, $(this));
        });

        self.$toolbar.find('[data-editor-markup-select]').on('change', function(e) {
            var $option = $(this).find(':selected');
            var command = $option.data().editorMarkupCommand;

            self.recoverFocus();
            self.runCommand(command, $option);
        });

        // initiate all fields
        self.$fields.each(function() {
            var field = new Field($(this), self);
            $(this).data('editor-field', field);
        });

        return this;
    };

    /*
     * Inserts a string at the current cursor position in the
     * currently active field
     *
     * @param {string} string The text to be inserted
     * @returns {Editor}
     */
    Editor.prototype.insertText = function(string) {
        var activeField = this.findActiveField();

        if(activeField) {
            activeField.insertText(string);
        }

        return this;
    };

    /*
     * Run a command to manipulate editor field contents
     *
     * @param {String} command
     * @param {jQuery} $context
     * @returns {Editor}
     */
    Editor.prototype.runCommand = function(command, $context) {
        var command = this.commands[command];

        if(typeof command !== 'function') throw new Error('Command not defined: ' + $context.data().editorMarkupCommand);

        this.insertText(command($context));

        return this;
    };

    /*
     * Return a focussed field
     *
     * @returns {Field}
     */
    Editor.prototype.findActiveField = function() {
        var $field = this.$fields.filter(function() {
            return $(this).data('editorField').isFocussed();
        });

        if($field.length > 0) {
            return $field.data('editorField');
        } else {
            return null;
        }
    };

    /*
     * Saves the passed (focused) field to recover the current
     * focus state later
     *
     * @param {Field} field
     * @returns {Editor}
     */
    Editor.prototype.saveFocus = function(field) {
        this.lastFocus = field;

        return this;
    };

    /*
     * Set the focus to a previously saved field
     *
     * @returns {Editor}
     */
    Editor.prototype.recoverFocus = function() {
        if(this.lastFocus) {
            this.lastFocus.focus();
        }

        return this;
    };

    /*
     * Creates an instance of the Field class
     *
     * @constructor
     * @param {jQuery} $field The field element
     * @param {Editor} editor The editor the field belongs to
     */
    function Field($field, editor) {
        this.editor = editor;

        this.$field = $field;
        this.$input = $field.find('.field__input');
        this.$mirror = null;
        this.$count = $field.find('.field__count');

        this.init();
    };

    /*
     *
     */
    Field.prototype.filters = {
        sensors: {
            pattern: /{\s*value\(\s*(\d+)\s*\)\s*}/g,
            markup: function(markup, id) {
                var cls = ['markup', 'markup--sensor'];
                if(!this.editor.data.sensors[id]) cls.push('markup--error');

                return '' + markup + '';
            },
            tooltip: function(markup, id) {
                if(name = this.editor.data.sensors[id]) {
                    return name;
                }
                return false;
            }
        },
        events: {
            pattern: /{\s*date\(\s*(\d+)\s*\)\s*}/g,
            markup: function(markup, id) {
                var cls = ['markup', 'markup--event'];
                if(!this.editor.data.events[id]) cls.push('markup--error');

                return '' + markup + '';
            },
            tooltip: function(markup, id) {
                if(name = this.editor.data.events[id]) {
                    return name;
                }
                return false;
            },
        },
    };

    /*
     * Initiate the field's dom node
     *
     * @return {Field}
     */
    Field.prototype.init = function() {
        var self = this;

        self.$mirror = $('
').addClass('field__mirror').appendTo(self.$field);
        self.$tooltip = $('
').addClass('field__tooltip').appendTo(self.$field);

        self.$input
            .on('blur', function() {
                self.editor.saveFocus(self);
            })
            .on('input keydown mousedown blur focus', function() {
                window.setTimeout(function() {
                    self.handleCursor();
                    self.render();
                    self.updateCount();
                }, 1);
            })

        self.render();
        self.updateCount();
        autosize(self.$input);

        return this;
    };

    /*
     * Renders the fields content, e. g. to highlight markup
     *
     * @returns {Field
     */
    Field.prototype.render = function() {
        var self = this;

        var text = self.$input.val();

        // escape html entities
        var entityMap = {
          '&': '&',
          '<': '<',
          '>': '>',
          '"': '"',
          "'": ''',
          '/': '/',
          '`': '`',
          '=': '='
        };

        text = text.replace(/[&<>"'`=\/]/g, function(char) {
            return entityMap[char];
        });

        $.each(self.filters, function(name, filter) {
            text = text.replace(filter.pattern, function() {
                return filter.markup.apply(self, arguments);
            });
        });

        self.$mirror.html(text);
    };

    /*
     * Handles a change of the cursor position
     */
    Field.prototype.handleCursor = function() {
        var self = this;
        var selection = self.getSelection();
        var markup = self.findMarkup();
        var activeMarkup = null;
        var tooltip = false;

        // check if there are intersections between
        // the cursor position and the markup ranges
        $.each(markup, function(index, markup) {
            var min = markup.start < selection.start ? markup : selection;
            var max = markup.start < selection.start ? selection : markup;

            if(min.end > max.start) activeMarkup = markup;
        });

        if(activeMarkup) {
            tooltip = self.filters[activeMarkup.type].tooltip.apply(self, activeMarkup.matches);
        }

        if(tooltip && self.isFocussed()) {
            var text   = self.value();
            self.$mirror.html(text.substring(0, activeMarkup.start) + '' + text.substring(activeMarkup.start, activeMarkup.end) + '' + text.substring(activeMarkup.end, text.length));
            var $activeMarkup = self.$mirror.find('.field__markup--active');

            var pos = {
                top: $activeMarkup.offset().top - self.$field.offset().top,
                left: $activeMarkup.offset().left + .5 * $activeMarkup.width() - self.$field.offset().left,
            }

            self.$tooltip.show().text(tooltip).css({
                top: pos.top,
                left: pos.left,
            });
        } else {
            self.$tooltip.hide();
        }
    };

    /*
     *
     */
    Field.prototype.updateCount = function() {
        if(this.$count.length > 0) {
            var length = this.value().length;
            this.$count.text(length > 0 ? length : '');
        }
    }

    /*
     *
     */
    Field.prototype.findMarkup = function() {
        var markup = [];
        var text = this.value();

        $.each(this.filters, function(name, filter) {
            while((match = filter.pattern.exec(text)) !== null) {
                var matches = [];

                $.each(match, function(key, item) {
                    if(!isNaN(key)) matches.push(item);
                });

                markup.push({
                    type:  name,
                    matches: matches,
                    start: match.index,
                    end:   match.index + match[0].length,
                    length:match[0].length,
                });
            }
        });

        return markup;
    };

    /*
     * Gets the start and end position of the selection in the
     * field. If no text is selected, returns the position of the
     * character after the cursor. If the field is not active,
     * returns the position after the last character.
     *
     * @returns {Object} Object with 'start' and 'end' properties
     * representing the start end end of the selection
     */
    Field.prototype.getSelection = function() {
        var start  = this.$input.get(0).selectionStart,
            end    = this.$input.get(0).selectionEnd,
            length = this.$input.val().length;

        return {
            start: start !== undefined ? start : length,
            end:   end !== undefined ? end : length,
        };
    };

    /*
     * Inserts text at the current cursor position. If text is
     * selected, the current selection will be replaced.
     *
     * @param {string} string The text to be inserted
     * @returns {Field}
     */
    Field.prototype.insertText = function(string) {
        var value     = this.$input.val(),
            selection = this.getSelection();

        this.value(value.substring(0, selection.start) + string + value.substring(selection.end, value.length));

        return this;
    };

    /*
     * Get/set the value of the field
     *
     * @param {String} string
     * @return {Field|String}
     */
    Field.prototype.value = function(string) {
        if(typeof string === 'string') {
            this.$input.val(string);
            this.render();
            this.updateCount();
            autosize.update(this.$input);
        } else {
            return this.$input.val();
        }
        return this;
    };

    /*
     * Set the focus on the field's dom node
     *
     * @return {Field}
     */
    Field.prototype.focus = function() {
        this.$input.focus();

        return this;
    };

    /*
     * Checks wether the field is focused
     *
     * @return {boolean}
     */
    Field.prototype.isFocussed = function() {
        return this.$input.is(':focus');
    };

    return Editor;

})(jQuery, autosize);

(function($, Editor) {

    $.fn.editor = function() {
        this.each(function() {
            var editor = new Editor($(this));
            $(this).data('editor', editor);
        });
    };

})(jQuery, Editor);<|endoftext|>


<commit_before>$(function() {
  $( document ).on('turbolinks:render, turbolinks:load', function() {
    $('#add_volunteers').prop('disabled', true).attr('disabled', true);
    $('#add_volunteers_text').show();
    $('input:radio[name="group_offer[volunteer_state]"]').on('change', ({target}) => {
      $('#add_volunteers').prop('disabled', false).attr('disabled', false);
      $('#add_volunteers_text').hide();
      populate_dropdowns(target);
    });

    $(document).on('cocoon:after-insert', function(e, insertedItem) {
      populate_dropdowns('input:radio[name="group_offer[volunteer_state]"]:checked');
    });
  });
});

const populate_dropdowns = (target) => {
  var selectInternals = $('.new-group-offer-volunteer-collection');
  var items=[];
  if($(target).val() == 'internal_volunteer') {
    items = JSON.parse($('input[name=internals]').val());
  } else {
    items = JSON.parse($('input[name=externals]').val());
  }

  selectInternals.empty();
  for (var i = 0; i < items.length; i++) {
    var opt = document.createElement('option');
    opt.value = items[i].id;
    opt.innerHTML = items[i].value;
    selectInternals.append(opt);
  }
}
<commit_msg>diff on edit<commit_after>$(function() {
  $( document ).on('turbolinks:render, turbolinks:load', function() {
    if (window.location.href.indexOf('new') > 0) {
      $('#add_volunteers').prop('disabled', true).attr('disabled', true);
    } else {
      $('#add_volunteers_text').hide();
    }

    $('input:radio[name="group_offer[volunteer_state]"]').on('change', ({target}) => {
      $('#add_volunteers').prop('disabled', false).attr('disabled', false);
      $('#add_volunteers_text').hide();
      populate_dropdowns(target);
    });

    $(document).on('cocoon:after-insert', function(e, insertedItem) {
      populate_dropdowns('input:radio[name="group_offer[volunteer_state]"]:checked');
    });
  });
});

const populate_dropdowns = (target) => {
  var selectInternals = $('.new-group-offer-volunteer-collection');
  var items=[];
  if($(target).val() == 'internal_volunteer') {
    items = JSON.parse($('input[name=internals]').val());
  } else {
    items = JSON.parse($('input[name=externals]').val());
  }

  selectInternals.empty();
  for (var i = 0; i < items.length; i++) {
    var opt = document.createElement('option');
    opt.value = items[i].id;
    opt.innerHTML = items[i].value;
    selectInternals.append(opt);
  }
}
<|endoftext|>


<commit_before>/**
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @author benvanik@google.com (Ben Vanik)
 */

goog.provide('gf.ui.ScreenManager');

goog.require('gf.log');
goog.require('gf.ui.Screen');
goog.require('goog.Disposable');
goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.history.EventType');

/**
 * Screen stack manager.
 * Enables multiple overlapping game screens to be added to a scene at once.
 * @constructor
 * @extends {goog.Disposable}
 * @param {!goog.dom.DomHelper} dom DOM helper.
 */
gf.ui.ScreenManager = function(dom) {
  goog.base(this);

  /**
   * DOM helper.
   * @type {!goog.dom.DomHelper}
   */
  this.dom = dom;

  /**
   * Screen stack, where the last item in the array top-most screen.
   * @private
   * @type {!Array.<!gf.ui.Screen>}
   */
  this.stack_ = [];

  /**
   * HTML5 history manager, used for navigation.
   * @private
   * @type {!goog.history.Html5History}
   */
  this.history_ = null;
  // TODO(benvanik): need to figure out issues with duplicate events/etc
  // if (goog.history.Html5History.isSupported()) {
  //   this.history_ = new goog.history.Html5History();
  //   goog.events.listen(this.history_, goog.history.EventType.NAVIGATE,
  //       this.historyNavigated_, false, this);
  //   this.history_.setEnabled(true);
  // }
};
goog.inherits(gf.ui.ScreenManager, goog.Disposable);

/**
 * @override
 */
gf.ui.ScreenManager.prototype.disposeInternal = function() {
  if (this.history_) {
    goog.events.unlisten(this.history_, goog.history.EventType.NAVIGATE,
        this.historyNavigated_, false, this);
    goog.dispose(this.history_);
    this.history_ = null;
  }

  while (this.stack_.length) {
    var screen = this.stack_.pop();
    screen.setScreenManager(null);
    goog.dispose(screen);
  }

  goog.base(this, 'disposeInternal');
};

/**
 * Handles HTML5 history change events.
 * @private
 * @param {!goog.history.Event} e Event.
 */
gf.ui.ScreenManager.prototype.historyNavigated_ = function(e) {
  gf.log.write('navigate: ', e.token, e.isNavigation);
};

/**
 * Updates the URL to the current stack.
 * @private
 */
gf.ui.ScreenManager.prototype.updateHistory_ = function() {
  if (!this.history_) {
    return;
  }

  var tokens = [];
  for (var n = 0; n < this.stack_.length; n++) {
    var screen = this.stack_[n];
    tokens.push(screen.getHashToken());
  }
  var token = tokens.join('/');

  this.history_.replaceToken(token);
};

/**
 * @return {gf.ui.Screen} The screen at the top of the stack, if any.
 */
gf.ui.ScreenManager.prototype.getTopScreen = function() {
  return this.stack_.length ? this.stack_[this.stack_.length - 1] : null;
};

/**
 * Enumerates all screens in stack order from bottom to top.
 * Do not modify the screen manager while enumerating.
 * @param {!function(!gf.ui.Screen):boolean|undefined} callback Function called
 *     once for each screen.
 * @param {Object=} opt_scope Scope to call the callback in.
 */
gf.ui.ScreenManager.prototype.forEachScreen = function(callback, opt_scope) {
  for (var n = 0; n < this.stack_.length; n++) {
    var screen = this.stack_[n];
    if (callback.call(opt_scope || goog.global, screen) === false) {
      break;
    }
  }
};

/**
 * Replaces the entire screen stack with the given screen.
 * @param {!gf.ui.Screen} screen Screen to display.
 * @param {boolean=} opt_suppressHistory Suppress history updates.
 */
gf.ui.ScreenManager.prototype.setScreen = function(
    screen, opt_suppressHistory) {
  this.popAllScreens(true);
  this.pushScreen(screen, true);

  if (!opt_suppressHistory) {
    this.updateHistory_();
  }
};

/**
 * Pushes a new screen on to the stack.
 * @param {!gf.ui.Screen} screen Screen to display.
 * @param {boolean=} opt_suppressHistory Suppress history updates.
 */
gf.ui.ScreenManager.prototype.pushScreen = function(
    screen, opt_suppressHistory) {
  goog.asserts.assert(!screen.getScreenManager());
  screen.setScreenManager(this);
  this.stack_.push(screen);
  this.updateScreenStates_();
  screen.enterDocument();

  if (!opt_suppressHistory) {
    this.updateHistory_();
  }
};

/**
 * Pops the screen at the top of the stack and disposes it.
 * @param {boolean=} opt_suppressHistory Suppress history updates.
 */
gf.ui.ScreenManager.prototype.popScreen = function(opt_suppressHistory) {
  goog.asserts.assert(this.stack_.length);
  var screen = this.stack_.pop();
  screen.setScreenManager(null);
  goog.dispose(screen);

  this.updateScreenStates_();

  if (!opt_suppressHistory) {
    this.updateHistory_();
  }
};

/**
 * Pops all screens and disposes them.
 * @param {boolean=} opt_suppressHistory Suppress history updates.
 */
gf.ui.ScreenManager.prototype.popAllScreens = function(opt_suppressHistory) {
  while (this.stack_.length) {
    this.popScreen(true);
  }
  if (!opt_suppressHistory) {
    this.updateHistory_();
  }
};

/**
 * Updates screen states (input focus/active toggle) based on the current stack.
 * @private
 */
gf.ui.ScreenManager.prototype.updateScreenStates_ = function() {
  // Walk all stacks in reverse - toggling state
  var activeAvailable = true;
  var inputAvailable = true;
  for (var n = this.stack_.length - 1; n >= 0; n--) {
    var screen = this.stack_[n];
    screen.setActive(activeAvailable);
    screen.setInputFocus(inputAvailable);
    if (screen.isCoveringDisplay()) {
      activeAvailable = false;
      inputAvailable = false;
    }
    if (screen.flags & gf.ui.Screen.Flags.MODAL_INPUT) {
      inputAvailable = false;
    }
  }
};

/**
 * Updates the current screen contents.
 * @param {!gf.UpdateFrame} frame Current update frame.
 */
gf.ui.ScreenManager.prototype.update = function(frame) {
  // Always update all screens
  for (var n = 0; n < this.stack_.length; n++) {
    var screen = this.stack_[n];
    screen.update(frame);
  }
};

/**
 * Renders the current screen contents.
 * @param {!gf.RenderFrame} frame Current render frame.
 */
gf.ui.ScreenManager.prototype.render = function(frame) {
  // Only render active screens
  for (var n = 0; n < this.stack_.length; n++) {
    var screen = this.stack_[n];
    if (screen.isActive()) {
      screen.render(frame);
    }
  }
};
<commit_msg>forcing include of currently disabled html5history<commit_after>/**
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @author benvanik@google.com (Ben Vanik)
 */

goog.provide('gf.ui.ScreenManager');

goog.require('gf.log');
goog.require('gf.ui.Screen');
goog.require('goog.Disposable');
goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.history.EventType');
/** @suppress {extraRequire} */
goog.require('goog.history.Html5History');

/**
 * Screen stack manager.
 * Enables multiple overlapping game screens to be added to a scene at once.
 * @constructor
 * @extends {goog.Disposable}
 * @param {!goog.dom.DomHelper} dom DOM helper.
 */
gf.ui.ScreenManager = function(dom) {
  goog.base(this);

  /**
   * DOM helper.
   * @type {!goog.dom.DomHelper}
   */
  this.dom = dom;

  /**
   * Screen stack, where the last item in the array top-most screen.
   * @private
   * @type {!Array.<!gf.ui.Screen>}
   */
  this.stack_ = [];

  /**
   * HTML5 history manager, used for navigation.
   * @private
   * @type {!goog.history.Html5History}
   */
  this.history_ = null;
  // TODO(benvanik): need to figure out issues with duplicate events/etc
  // if (goog.history.Html5History.isSupported()) {
  //   this.history_ = new goog.history.Html5History();
  //   goog.events.listen(this.history_, goog.history.EventType.NAVIGATE,
  //       this.historyNavigated_, false, this);
  //   this.history_.setEnabled(true);
  // }
};
goog.inherits(gf.ui.ScreenManager, goog.Disposable);

/**
 * @override
 */
gf.ui.ScreenManager.prototype.disposeInternal = function() {
  if (this.history_) {
    goog.events.unlisten(this.history_, goog.history.EventType.NAVIGATE,
        this.historyNavigated_, false, this);
    goog.dispose(this.history_);
    this.history_ = null;
  }

  while (this.stack_.length) {
    var screen = this.stack_.pop();
    screen.setScreenManager(null);
    goog.dispose(screen);
  }

  goog.base(this, 'disposeInternal');
};

/**
 * Handles HTML5 history change events.
 * @private
 * @param {!goog.history.Event} e Event.
 */
gf.ui.ScreenManager.prototype.historyNavigated_ = function(e) {
  gf.log.write('navigate: ', e.token, e.isNavigation);
};

/**
 * Updates the URL to the current stack.
 * @private
 */
gf.ui.ScreenManager.prototype.updateHistory_ = function() {
  if (!this.history_) {
    return;
  }

  var tokens = [];
  for (var n = 0; n < this.stack_.length; n++) {
    var screen = this.stack_[n];
    tokens.push(screen.getHashToken());
  }
  var token = tokens.join('/');

  this.history_.replaceToken(token);
};

/**
 * @return {gf.ui.Screen} The screen at the top of the stack, if any.
 */
gf.ui.ScreenManager.prototype.getTopScreen = function() {
  return this.stack_.length ? this.stack_[this.stack_.length - 1] : null;
};

/**
 * Enumerates all screens in stack order from bottom to top.
 * Do not modify the screen manager while enumerating.
 * @param {!function(!gf.ui.Screen):boolean|undefined} callback Function called
 *     once for each screen.
 * @param {Object=} opt_scope Scope to call the callback in.
 */
gf.ui.ScreenManager.prototype.forEachScreen = function(callback, opt_scope) {
  for (var n = 0; n < this.stack_.length; n++) {
    var screen = this.stack_[n];
    if (callback.call(opt_scope || goog.global, screen) === false) {
      break;
    }
  }
};

/**
 * Replaces the entire screen stack with the given screen.
 * @param {!gf.ui.Screen} screen Screen to display.
 * @param {boolean=} opt_suppressHistory Suppress history updates.
 */
gf.ui.ScreenManager.prototype.setScreen = function(
    screen, opt_suppressHistory) {
  this.popAllScreens(true);
  this.pushScreen(screen, true);

  if (!opt_suppressHistory) {
    this.updateHistory_();
  }
};

/**
 * Pushes a new screen on to the stack.
 * @param {!gf.ui.Screen} screen Screen to display.
 * @param {boolean=} opt_suppressHistory Suppress history updates.
 */
gf.ui.ScreenManager.prototype.pushScreen = function(
    screen, opt_suppressHistory) {
  goog.asserts.assert(!screen.getScreenManager());
  screen.setScreenManager(this);
  this.stack_.push(screen);
  this.updateScreenStates_();
  screen.enterDocument();

  if (!opt_suppressHistory) {
    this.updateHistory_();
  }
};

/**
 * Pops the screen at the top of the stack and disposes it.
 * @param {boolean=} opt_suppressHistory Suppress history updates.
 */
gf.ui.ScreenManager.prototype.popScreen = function(opt_suppressHistory) {
  goog.asserts.assert(this.stack_.length);
  var screen = this.stack_.pop();
  screen.setScreenManager(null);
  goog.dispose(screen);

  this.updateScreenStates_();

  if (!opt_suppressHistory) {
    this.updateHistory_();
  }
};

/**
 * Pops all screens and disposes them.
 * @param {boolean=} opt_suppressHistory Suppress history updates.
 */
gf.ui.ScreenManager.prototype.popAllScreens = function(opt_suppressHistory) {
  while (this.stack_.length) {
    this.popScreen(true);
  }
  if (!opt_suppressHistory) {
    this.updateHistory_();
  }
};

/**
 * Updates screen states (input focus/active toggle) based on the current stack.
 * @private
 */
gf.ui.ScreenManager.prototype.updateScreenStates_ = function() {
  // Walk all stacks in reverse - toggling state
  var activeAvailable = true;
  var inputAvailable = true;
  for (var n = this.stack_.length - 1; n >= 0; n--) {
    var screen = this.stack_[n];
    screen.setActive(activeAvailable);
    screen.setInputFocus(inputAvailable);
    if (screen.isCoveringDisplay()) {
      activeAvailable = false;
      inputAvailable = false;
    }
    if (screen.flags & gf.ui.Screen.Flags.MODAL_INPUT) {
      inputAvailable = false;
    }
  }
};

/**
 * Updates the current screen contents.
 * @param {!gf.UpdateFrame} frame Current update frame.
 */
gf.ui.ScreenManager.prototype.update = function(frame) {
  // Always update all screens
  for (var n = 0; n < this.stack_.length; n++) {
    var screen = this.stack_[n];
    screen.update(frame);
  }
};

/**
 * Renders the current screen contents.
 * @param {!gf.RenderFrame} frame Current render frame.
 */
gf.ui.ScreenManager.prototype.render = function(frame) {
  // Only render active screens
  for (var n = 0; n < this.stack_.length; n++) {
    var screen = this.stack_[n];
    if (screen.isActive()) {
      screen.render(frame);
    }
  }
};
<|endoftext|>


<commit_before>"use strict";

function gsuiTrack() {
	var root = this._clone();

	this.rootElement = root;
	this.rowElement = root.querySelector( ".gsui-row" );
	this.rowElement.remove();
	this.uiToggle = new gsuiToggle();
	this.uiSpan = new gsuiSpanEditable();
	root.append( this.uiToggle.rootElement );
	root.append( this.uiSpan.rootElement );

	this.data = {};
	this.uiToggle.onchange = this._evocToggle.bind( this );
	this.uiSpan.onchange = this._evocSpan.bind( this );
	this.toggle( true );
}

gsuiTrack.prototype = {
	remove() {
		this.rootElement.remove();
		this.rowElement.remove();
	},
	change( obj ) {
		"toggle" in obj && this.toggle( obj.toggle );
		"name" in obj && this.name( obj.name );
	},
	toggle( b ) {
		this._evocToggle( b, false );
	},
	name( n ) {
		this._evocSpan( n, false );
	},
	setPlaceholder( p ) {
		this.uiSpan.setPlaceholder( p );
	},

	// private:
	_clone() {
		var div = document.createElement( "div" );

		gsuiTrack.template = gsuiTrack.template || document.getElementById( "gsuiTrack" );
		div.appendChild( document.importNode( gsuiTrack.template.content, true ) );
		return div.removeChild( div.querySelector( "*" ) );
	},

	// events:
	_evocToggle( b, isUserAction ) {
		this.rootElement.classList.toggle( "gsui-mute", !b );
		this.rowElement.classList.toggle( "gsui-mute", !b );
		if ( isUserAction === false ) {
			this.uiToggle.toggle( b );
		} else {
			this.onchange( { redo: { toggle: b }, undo: { toggle: !b } } );
		}
		this.data.toggle = b;
	},
	_evocSpan( name, isUserAction ) {
		if ( isUserAction === false ) {
			this.uiSpan.setValue( name );
		} else {
			this.onchange( { redo: { name: name }, undo: { name: this.data.name } } );
		}
		this.data.name = name;
	}
};
<commit_msg>gsuiTrack: onchange, no more sending undo obj<commit_after>"use strict";

function gsuiTrack() {
	var root = this._clone();

	this.rootElement = root;
	this.rowElement = root.querySelector( ".gsui-row" );
	this.rowElement.remove();
	this.uiToggle = new gsuiToggle();
	this.uiSpan = new gsuiSpanEditable();
	root.append( this.uiToggle.rootElement );
	root.append( this.uiSpan.rootElement );

	this.data = {};
	this.uiToggle.onchange = this._evocToggle.bind( this );
	this.uiSpan.onchange = this._evocSpan.bind( this );
	this.toggle( true );
}

gsuiTrack.prototype = {
	remove() {
		this.rootElement.remove();
		this.rowElement.remove();
	},
	change( obj ) {
		"toggle" in obj && this.toggle( obj.toggle );
		"name" in obj && this.name( obj.name );
	},
	toggle( b ) {
		this._evocToggle( b, false );
	},
	name( n ) {
		this._evocSpan( n, false );
	},
	setPlaceholder( p ) {
		this.uiSpan.setPlaceholder( p );
	},

	// private:
	_clone() {
		var div = document.createElement( "div" );

		gsuiTrack.template = gsuiTrack.template || document.getElementById( "gsuiTrack" );
		div.appendChild( document.importNode( gsuiTrack.template.content, true ) );
		return div.removeChild( div.querySelector( "*" ) );
	},

	// events:
	_evocToggle( b, isUserAction ) {
		this.rootElement.classList.toggle( "gsui-mute", !b );
		this.rowElement.classList.toggle( "gsui-mute", !b );
		if ( isUserAction === false ) {
			this.uiToggle.toggle( b );
		} else {
			this.onchange( { toggle: b } );
		}
		this.data.toggle = b;
	},
	_evocSpan( name, isUserAction ) {
		if ( isUserAction === false ) {
			this.uiSpan.setValue( name );
		} else {
			this.onchange( { name: name } );
		}
		this.data.name = name;
	}
};
<|endoftext|>


<commit_before>var gulp = require('gulp'),
    del = require('del'),
    mainBowerFiles = require('main-bower-files'),
    rename = require("gulp-rename"),
    inject = require("gulp-inject"),
    less = require('gulp-less'),
    concat = require('gulp-concat'),
    html2js = require('gulp-html2js'),
    stylish = require('jshint-stylish'),
    jshint = require('gulp-jshint'),
    cache = require('gulp-cached'),
    watch = require('gulp-watch'),
    preprocess = require('gulp-preprocess'),
    gulpFilter = require('gulp-filter');
var debug = require('gulp-debug');
var changed = require('gulp-changed');

var config = require(__dirname+'/../../config');

module.exports = function(name) {
    var dependencies = require(process.cwd()+'/src/apps/'+name+'/dependencies.json');

    var cleanTask = 'clean@'+name,
        jsFiles = [
            'src/apps/'+name+'/**/*.js',
            'src/modules/**/'+name+'/**/*.js'
        ],
        commonJsFiles= [],
        commonJsFilesAll = ['src/common/frontend/**/*.js'];
    dependencies.common.forEach(function (dep) {
        commonJsFiles.push(dep+'/**/*.js')
    });

    var templatesFiles = [
            'src/apps/'+name+'/**/*.tpl.html',
            'src/common/frontend/**/*.tpl.html',
            'src/modules/**/'+name+'/**/*.tpl.html'
        ],
        htmlFile = 'src/apps/'+name+'/index.html',
        i18nFiles = [
            'src/common/i18n/*.json'
        ],
        lessFile = 'src/apps/'+name+'/main.less',
        lessFiles = [
            'src/apps/'+name+'/**/*.less',
            'src/common/**/*.less',
            'src/modules/**/'+name+'/**/*.less'
        ],
        sourcesIndex = [

            'dist/build/'+name+'/public/lib/jquery.js',
            'dist/build/'+name+'/public/lib/angular.js',
            'dist/build/'+name+'/public/lib/socket.io.js',

            'dist/build/'+name+'/public/bower_components/**/*.js',
            'dist/build/'+name+'/public/js/templates.js',
            'dist/build/'+name+'/public/js/**/*.js',
            'dist/build/'+name+'/public/css/main.css'
        ];

    var tasks = {
        jsFiles: function(){
            var dest = 'dist/build/'+name+'/public/js/modules';
            return gulp.src(jsFiles)
                .pipe(changed(dest))
                .pipe(gulp.dest(dest));
        },
        commonJsFiles: function(){
            var dest = 'dist/build/'+name+'/public/js/common';
            return gulp.src(commonJsFilesAll)
                .pipe(gulpFilter(commonJsFiles))
                .pipe(changed(dest))
                .pipe(gulp.dest(dest));
        },
        libJsFiles: function(){
            return gulp.src([
                    __dirname+'/../../../bower_components/jquery/dist/jquery.js',
                    __dirname+'/../../../bower_components/angular/angular.js',
                    __dirname+'/../../../bower_components/socket.io-client/socket.io.js'
                ])
                .pipe(gulp.dest('dist/build/'+name+'/public/lib'));
        },
        html2js: function() {
            return gulp.src(templatesFiles)
                .pipe(html2js({
                    outputModuleName: 'templates',
                    base: 'src/'
                }))
                .pipe(concat('templates.js'))
                .pipe(gulp.dest('./dist/build/'+name+'/public/js'));
        },
        i18n: function(){
            return gulp.src(i18nFiles)
                .pipe(gulp.dest('dist/build/'+name+'/public/i18n'));
        },
        bowerFiles: function(){
            return gulp.src(mainBowerFiles(), { base: 'bower_components' })
                .pipe(gulp.dest('dist/build/'+name+'/public/bower_components'))
        },
        frameworkFiles: function(){
            var env = process.env.NODE_ENV,
                envConfig = env;
            if(process.env.NODE_TEST!==undefined) {
                envConfig = 'test';
            }

            var appsUrl = "",
                apps = config.frontend.list();

            apps.forEach(function (app) {
                if(env=="production") {
                    appsUrl += "service.urls."+app+" = 'http://" + config.get(envConfig, app) + ":" + config.get(envConfig, 'main') + "';\n";
                } else if(env=="development") {
                    appsUrl += "service.urls."+app+" = 'http://" + config.get(envConfig, 'main') + ":" + config.get(envConfig, app) + "';\n";
                }

            });

            return gulp.src(__dirname+'/../../frontend/*.js')
                .pipe(preprocess({context: {
                    NODE_ENV: env,
                    socketConf: config.get(envConfig, 'socket'),
                    apiConf: config.get(envConfig, 'api'),
                    mainPort: config.get(envConfig, 'main'),
                    appsUrl: appsUrl
                }}))
                .pipe(gulp.dest('dist/build/'+name+'/public/js/bluestorm'))
        },
        less: function(){
            return gulp.src(lessFile)
                .pipe(less().on('error', function(e) {
                    console.log(e);
                }))
                .pipe(gulp.dest('./dist/build/'+name+'/public/css'));
        },
        indexHtml: function(){
            var sources = gulp.src(sourcesIndex, {
                read: false
            });

            return gulp.src(htmlFile)
                .pipe(rename(function (path) { path.basename = "main"; }))
                .pipe(inject(sources, { ignorePath: 'dist/build/'+name }))
                .pipe(gulp.dest('dist/build/'+name));
        },
        lint: function() {
            return gulp.src(jsFiles)
                .pipe(cache('linting'))
                .pipe(jshint())
                .pipe(jshint.reporter(stylish));
        }
    };

    gulp.task('lint@'+name, tasks.lint);

    gulp.task(cleanTask, function(cb) { del(['dist/build/'+name], cb); });

    gulp.task('bower-files@'+name, [cleanTask], tasks.bowerFiles);
    gulp.task('framework-files@'+name, [cleanTask], tasks.frameworkFiles);
    gulp.task('lib-js-files@'+name, [cleanTask], tasks.libJsFiles);

    gulp.task('js-files@'+name, [cleanTask], tasks.jsFiles);
    gulp.task('js-files-watch@'+name, tasks.jsFiles);
    gulp.task('js-file-added@'+name, ['js-files-watch@'+name], tasks.indexHtml);

    gulp.task('common-js-files@'+name, [cleanTask], tasks.commonJsFiles);
    gulp.task('common-js-files-watch@'+name, tasks.commonJsFiles);
    gulp.task('common-js-files-added@'+name, ['common-js-files-watch@'+name], tasks.indexHtml);

    gulp.task('html2js@'+name, [cleanTask], tasks.html2js);
    gulp.task('html2js-watch@'+name, tasks.html2js);

    gulp.task('i18n@'+name, [cleanTask], tasks.i18n);
    gulp.task('i18n-watch@'+name, tasks.i18n);

    gulp.task('less@'+name, [cleanTask], tasks.less);
    gulp.task('less-watch@'+name, tasks.less);

    gulp.task('assets@'+name, [cleanTask], function(){
        return gulp.src('src/common/assets/**/*')
            .pipe(gulp.dest('dist/build/'+name+'/public/assets'))
    });

    gulp.task('index.html@'+name, [
        'js-files@'+name,
        'common-js-files@'+name,
        'lib-js-files@'+name,
        'bower-files@'+name,
        'i18n@'+name,
        'less@'+name,
        'html2js@'+name,
        'framework-files@'+name
    ], tasks.indexHtml);
    gulp.task('index.html-watch@'+name, tasks.indexHtml);

    gulp.task('build@'+name, ['index.html@'+name,'assets@'+name,'lint@'+name], function() {
        if(process.env.NODE_ENV=='development') {
            gulp.watch(jsFiles, function(file) {
                gulpWatch.jsFiles(file, name);
            });
            gulp.watch(commonJsFilesAll, function(file) {
                gulpWatch.commonJsFilesAll(file, name);
            });
            gulp.watch(templatesFiles, ['html2js-watch@'+name]);
            gulp.watch(i18nFiles, ['i18n-watch@'+name]);
            gulp.watch(lessFiles, ['less-watch@'+name]);
            gulp.watch(htmlFile, ['index.html-watch@'+name]);
        }
    });
};

var gulpWatch = {
    jsFiles: function(file, name) {
        if(file.type=='changed') {
            gulp.start(['js-files-watch@'+name, 'lint@'+name]);
        }
        if(file.type=='added'||file.type=='renamed') {
            gulp.start(['js-file-added@'+name, 'lint@'+name]);
        }
        if(file.type=='deleted') {
            var pathToDelete = file.path.substring(file.path.indexOf('src/modules/')+12);
            del("dist/build/"+name+"/public/js/modules/"+pathToDelete, function(err) {
                gulp.start('index.html-watch@'+name);
            });

        }
    },
    commonJsFilesAll: function(file, name) {
        if(file.type=='changed') {
            gulp.start(['common-js-files-watch@'+name, 'lint@'+name]);
        }
        if(file.type=='added'||file.type=='renamed') {
            gulp.start(['common-js-files-added@'+name, 'lint@'+name]);
        }
        if(file.type=='deleted') {
            var pathToDelete = file.path.substring(file.path.indexOf('src/common/frontend')+20);
            console.log("dist/build/"+name+"/public/js/common/"+pathToDelete);
            del("dist/build/"+name+"/public/js/common/"+pathToDelete, function(err) {
                if(err) return console.error(err);
                gulp.start('index.html-watch@'+name);
            });

        }
    },
};<commit_msg>Templates full gulp support<commit_after>var gulp = require('gulp'),
    del = require('del'),
    mainBowerFiles = require('main-bower-files'),
    rename = require("gulp-rename"),
    inject = require("gulp-inject"),
    less = require('gulp-less'),
    concat = require('gulp-concat'),
    html2js = require('gulp-html2js'),
    stylish = require('jshint-stylish'),
    jshint = require('gulp-jshint'),
    cache = require('gulp-cached'),
    watch = require('gulp-watch'),
    preprocess = require('gulp-preprocess'),
    gulpFilter = require('gulp-filter');
var debug = require('gulp-debug');
var changed = require('gulp-changed');

var config = require(__dirname+'/../../config');

module.exports = function(name) {
    var dependencies = require(process.cwd()+'/src/apps/'+name+'/dependencies.json');

    var cleanTask = 'clean@'+name,
        jsFiles = [
            'src/apps/'+name+'/**/*.js',
            'src/modules/**/'+name+'/**/*.js'
        ],
        commonJsFiles= [],
        commonJsFilesAll = ['src/common/frontend/**/*.js'];
    dependencies.common.forEach(function (dep) {
        commonJsFiles.push(dep+'/**/*.js')
    });

    var templatesFiles = [
            'src/apps/'+name+'/**/*.tpl.html',
            'src/common/frontend/**/*.tpl.html',
            'src/modules/**/'+name+'/**/*.tpl.html'
        ],
        htmlFile = 'src/apps/'+name+'/index.html',
        i18nFiles = [
            'src/common/i18n/*.json'
        ],
        lessFile = 'src/apps/'+name+'/main.less',
        lessFiles = [
            'src/apps/'+name+'/**/*.less',
            'src/common/**/*.less',
            'src/modules/**/'+name+'/**/*.less'
        ],
        sourcesIndex = [

            'dist/build/'+name+'/public/lib/jquery.js',
            'dist/build/'+name+'/public/lib/angular.js',
            'dist/build/'+name+'/public/lib/socket.io.js',

            'dist/build/'+name+'/public/bower_components/**/*.js',
            'dist/build/'+name+'/public/js/templates.js',
            'dist/build/'+name+'/public/js/**/*.js',
            'dist/build/'+name+'/public/css/main.css'
        ];

    var tasks = {
        jsFiles: function(){
            var dest = 'dist/build/'+name+'/public/js/modules';
            return gulp.src(jsFiles)
                .pipe(changed(dest))
                .pipe(gulp.dest(dest));
        },
        commonJsFiles: function(){
            var dest = 'dist/build/'+name+'/public/js/common';
            return gulp.src(commonJsFilesAll)
                .pipe(gulpFilter(commonJsFiles))
                .pipe(changed(dest))
                .pipe(gulp.dest(dest));
        },
        libJsFiles: function(){
            return gulp.src([
                    __dirname+'/../../../bower_components/jquery/dist/jquery.js',
                    __dirname+'/../../../bower_components/angular/angular.js',
                    __dirname+'/../../../bower_components/socket.io-client/socket.io.js'
                ])
                .pipe(gulp.dest('dist/build/'+name+'/public/lib'));
        },
        html2js: function() {
            return gulp.src(templatesFiles)
                .pipe(html2js({
                    outputModuleName: 'templates',
                    base: 'src/'
                }))
                .pipe(concat('templates.js'))
                .pipe(gulp.dest('./dist/build/'+name+'/public/js'));
        },
        i18n: function(){
            return gulp.src(i18nFiles)
                .pipe(gulp.dest('dist/build/'+name+'/public/i18n'));
        },
        bowerFiles: function(){
            return gulp.src(mainBowerFiles(), { base: 'bower_components' })
                .pipe(gulp.dest('dist/build/'+name+'/public/bower_components'))
        },
        frameworkFiles: function(){
            var env = process.env.NODE_ENV,
                envConfig = env;
            if(process.env.NODE_TEST!==undefined) {
                envConfig = 'test';
            }

            var appsUrl = "",
                apps = config.frontend.list();

            apps.forEach(function (app) {
                if(env=="production") {
                    appsUrl += "service.urls."+app+" = 'http://" + config.get(envConfig, app) + ":" + config.get(envConfig, 'main') + "';\n";
                } else if(env=="development") {
                    appsUrl += "service.urls."+app+" = 'http://" + config.get(envConfig, 'main') + ":" + config.get(envConfig, app) + "';\n";
                }

            });

            return gulp.src(__dirname+'/../../frontend/*.js')
                .pipe(preprocess({context: {
                    NODE_ENV: env,
                    socketConf: config.get(envConfig, 'socket'),
                    apiConf: config.get(envConfig, 'api'),
                    mainPort: config.get(envConfig, 'main'),
                    appsUrl: appsUrl
                }}))
                .pipe(gulp.dest('dist/build/'+name+'/public/js/bluestorm'))
        },
        less: function(){
            return gulp.src(lessFile)
                .pipe(less().on('error', function(e) {
                    console.log(e);
                }))
                .pipe(gulp.dest('./dist/build/'+name+'/public/css'));
        },
        indexHtml: function(){
            var sources = gulp.src(sourcesIndex, {
                read: false
            });

            return gulp.src(htmlFile)
                .pipe(rename(function (path) { path.basename = "main"; }))
                .pipe(inject(sources, { ignorePath: 'dist/build/'+name }))
                .pipe(gulp.dest('dist/build/'+name));
        },
        lint: function() {
            return gulp.src(jsFiles)
                .pipe(cache('linting'))
                .pipe(jshint())
                .pipe(jshint.reporter(stylish));
        }
    };

    gulp.task('lint@'+name, tasks.lint);

    gulp.task(cleanTask, function(cb) { del(['dist/build/'+name], cb); });

    gulp.task('bower-files@'+name, [cleanTask], tasks.bowerFiles);
    gulp.task('framework-files@'+name, [cleanTask], tasks.frameworkFiles);
    gulp.task('lib-js-files@'+name, [cleanTask], tasks.libJsFiles);

    gulp.task('js-files@'+name, [cleanTask], tasks.jsFiles);
    gulp.task('js-files-watch@'+name, tasks.jsFiles);
    gulp.task('js-file-added@'+name, ['js-files-watch@'+name], tasks.indexHtml);

    gulp.task('common-js-files@'+name, [cleanTask], tasks.commonJsFiles);
    gulp.task('common-js-files-watch@'+name, tasks.commonJsFiles);
    gulp.task('common-js-files-added@'+name, ['common-js-files-watch@'+name], tasks.indexHtml);

    gulp.task('html2js@'+name, [cleanTask], tasks.html2js);
    gulp.task('html2js-watch@'+name, tasks.html2js);

    gulp.task('i18n@'+name, [cleanTask], tasks.i18n);
    gulp.task('i18n-watch@'+name, tasks.i18n);

    gulp.task('less@'+name, [cleanTask], tasks.less);
    gulp.task('less-watch@'+name, tasks.less);

    gulp.task('assets@'+name, [cleanTask], function(){
        return gulp.src('src/common/assets/**/*')
            .pipe(gulp.dest('dist/build/'+name+'/public/assets'))
    });

    gulp.task('index.html@'+name, [
        'js-files@'+name,
        'common-js-files@'+name,
        'lib-js-files@'+name,
        'bower-files@'+name,
        'i18n@'+name,
        'less@'+name,
        'html2js@'+name,
        'framework-files@'+name
    ], tasks.indexHtml);
    gulp.task('index.html-watch@'+name, tasks.indexHtml);

    gulp.task('build@'+name, ['index.html@'+name,'assets@'+name,'lint@'+name], function() {
        if(process.env.NODE_ENV=='development') {
            gulp.watch(jsFiles, function(file) {
                gulpWatch.jsFiles(file, name);
            });
            gulp.watch(commonJsFilesAll, function(file) {
                gulpWatch.commonJsFilesAll(file, name);
            });
            gulp.watch(templatesFiles, function(file) {
                gulp.start('html2js-watch@'+name);
            });
            gulp.watch(i18nFiles, ['i18n-watch@'+name]);
            gulp.watch(lessFiles, ['less-watch@'+name]);
            gulp.watch(htmlFile, ['index.html-watch@'+name]);
        }
    });
};

var gulpWatch = {
    jsFiles: function(file, name) {
        if(file.type=='changed') {
            gulp.start(['js-files-watch@'+name, 'lint@'+name]);
        }
        if(file.type=='added'||file.type=='renamed') {
            gulp.start(['js-file-added@'+name, 'lint@'+name]);
        }
        if(file.type=='deleted') {
            var pathToDelete = file.path.substring(file.path.indexOf('src/modules/')+12);
            del("dist/build/"+name+"/public/js/modules/"+pathToDelete, function(err) {
                gulp.start('index.html-watch@'+name);
            });

        }
    },
    commonJsFilesAll: function(file, name) {
        if(file.type=='changed') {
            gulp.start(['common-js-files-watch@'+name, 'lint@'+name]);
        }
        if(file.type=='added'||file.type=='renamed') {
            gulp.start(['common-js-files-added@'+name, 'lint@'+name]);
        }
        if(file.type=='deleted') {
            var pathToDelete = file.path.substring(file.path.indexOf('src/common/frontend')+20);
            console.log("dist/build/"+name+"/public/js/common/"+pathToDelete);
            del("dist/build/"+name+"/public/js/common/"+pathToDelete, function(err) {
                if(err) return console.error(err);
                gulp.start('index.html-watch@'+name);
            });

        }
    },
};<|endoftext|>


<commit_before>import { createElement, Component } from 'react';

class Retriever {
  constructor({ type, name, getter, publishData, publishError }) {
    this.type = type;
    this.name = name;
    this.getter = getter;
    this.publishData = publishData;
    this.publishError = publishError;
  }

  get(props) {
    const promise = this.getter(props);
    if (!promise || !promise.then) {
      throw new Error(`${this.type} for ${this.name} did not return a promise!`);
    }
    promise.then(this.publishData, this.publishError);
  }

  // eslint-disable-next-line class-methods-use-this
  mergeProps(props) {
    return props;
  }

  // eslint-disable-next-line class-methods-use-this
  onDestroy() {}
}

class ResolveRetriever extends Retriever {
  constructor({ name, getter, publishData, publishError }) {
    super({ type: 'resolve', name, getter, publishData, publishError });
  }
}

class ObserveRetriever extends Retriever {
  constructor({ name, getter, publishData, publishError }) {
    super({ type: 'observe', name, getter, publishData, publishError });

    this.subscription = null;
  }

  get(props) {
    const observable = this.getter(props);
    if (!observable || !observable) {
      throw new Error(`${this.type} for ${this.name} did not expose a subscribe function`);
    }
    this.subscription = observable.subscribe(this.publishData, this.publishError);
  }

  onDestroy() {
    if (this.subscription && this.subscription.unsubscribe) {
      this.subscription.unsubscribe();
    }
  }
}

class Container extends Component {
  constructor(props) {
    super(props);

    this.resolvedData = {};
    this.resolvedDataTargetSize = 0;

    this.retrievers = {};

    this.subscriptions = [];
    this.pagers = {};

    this.state = {
      pending: false,
      error: null,
      resolvedProps: null
    };
  }

  destroy() {
    Object.keys(this.retrievers).forEach((key) => {
      this.retrievers[key].onDestroy();
      delete this.retrievers[key];
    });
  }

  componentWillMount() {
    this.setupRetrievers(this.props);
    this.trigger(this.props);
  }

  componentWillReceiveProps(newProps) {
    this.destroy();
    this.setupRetrievers(newProps);
    this.trigger(newProps);
  }

  componentWillUnmount() {
    this.destroy();
  }

  addResolvedData(field, data) {
    this.resolvedData[field] = data;
    if (this.resolvedDataTargetSize === Object.keys(this.resolvedData).length) {
      this.setState({
        pending: false,
        resolvedProps: { ...this.resolvedData },
        error: null
      });
    }
  }

  setError(field, error) {
    this.setState({ pending: false, error });
  }

  setupRetrievers(props) {
    const { resolve = {}, observe = {} } = props;
    const resolveKeys = Object.keys(resolve);
    const observeKeys = Object.keys(observe);

    const publishData = (key) => (data) => this.addResolvedData(key, data);
    const publishError = (key) => (err) => this.setError(key, err);

    resolveKeys.forEach((key) => {
      this.retrievers[key] = new ResolveRetriever({
        name: key,
        publishData: publishData(key),
        publishError: publishError(key),
        getter: resolve[key]
      });
    });

    observeKeys.forEach((key) => {
      this.retrievers[key] = new ObserveRetriever({
        name: key,
        publishData: publishData(key),
        publishError: publishError(key),
        getter: observe[key]
      });
    });

    this.resolvedDataTargetSize = resolveKeys.length + observeKeys.length;
  }

  trigger(props) {
    this.setState({ pending: true, error: null });
    const { originalProps } = props;

    Object.keys(this.retrievers).forEach((key) => {
      this.retrievers[key].get(originalProps);
    });
  }

  render() {
    const { pending, error, resolvedProps } = this.state;
    const { originalProps, errorComponent, pendingComponent, component } = this.props;

    if (pending) {
      return pendingComponent ? createElement(pendingComponent, originalProps) : null;
    }

    if (error) {
      return errorComponent ? createElement(errorComponent, { ...originalProps, error }) : null;
    }

    return createElement(component, { ...originalProps, ...resolvedProps });
  }
}

export function withData(conf) {
  return component => {
    // make it pure again
    return (originalProps) => {
      const props = { ...conf, originalProps, component };
      return createElement(Container, props);
    };
  };
}

<commit_msg>feat(with-data) Implement pagination for resolve<commit_after>import { createElement, Component } from 'react';

const PAGINATION = {
  TYPE: {
    OFFSET_AND_LIMIT: 'offsetAndLimit'
  },
  MODE: {
    INFINITE: 'infinite'
  },
  PRESET: {
    infiniteOffsetAndLimit: (initialSize, nextSize = initialSize) => ({
      type: PAGINATION.TYPE.OFFSET_AND_LIMIT,
      mode: PAGINATION.MODE.INFINITE,
      getNextPage: ({ limit, offset }) => {
        if (offset === null) {
          return { offset: 0, limit: initialSize };
        }
        return { offset: offset + limit, limit: nextSize };
      }
    })
  }
};

class Retriever {
  constructor({ type, name, getter, getProps, publishData, publishError }) {
    this.type = type;
    this.name = name;
    this.getter = getter;
    this.getProps = getProps;
    this.publishData = publishData;
    this.publishError = publishError;
  }

  get() {
    const promise = this.getter(this.getProps());
    if (!promise || !promise.then) {
      throw new Error(`${this.type} for ${this.name} did not return a promise!`);
    }
    return promise.then(this.publishData, this.publishError);
  }

  // eslint-disable-next-line class-methods-use-this
  mergeProps(props) {
    return props;
  }

  // eslint-disable-next-line class-methods-use-this
  onDestroy() {}
}

class ResolveRetriever extends Retriever {
  constructor({ name, getter, getProps, publishData, publishError }) {
    super({ type: 'resolve', name, getter, getProps, publishData, publishError });
  }
}

class ObserveRetriever extends Retriever {
  constructor({ name, getter, getProps, publishData, publishError }) {
    super({ type: 'observe', name, getter, getProps, publishData, publishError });

    this.subscription = null;
  }

  get() {
    const observable = this.getter(this.getProps());
    if (!observable || !observable) {
      throw new Error(`${this.type} for ${this.name} did not expose a subscribe function`);
    }
    this.subscription = observable.subscribe(this.publishData, this.publishError);
    return Promise.resolve();
  }

  onDestroy() {
    if (this.subscription && this.subscription.unsubscribe) {
      this.subscription.unsubscribe();
    }
  }
}

class PaginatedInfiniteOffsetAndLimitResolveRetriever extends Retriever {
  constructor({ name, getter, getProps, publishData, publishError, pagerConfig }) {
    super({ type: 'resolve paginated', name, getter, getProps, publishData, publishError });
    this.pagerConfig = pagerConfig;

    this.pagers = [];

    this.queueNext();
  }

  get() {
    const props = this.getProps();
    return Promise.all(this.pagers.map((pager) => this.getter(props, pager))).then(
      (lists) => this.publishData(lists.reduce((mem, list) => [...mem, ...list], [])),
      this.publishError
    );
  }

  queueNext() {
    const prevPager = this.pagers[this.pagers.length - 1] || { limit: null, offset: null };
    const nextPager = this.pagerConfig.getNextPage(prevPager);
    this.pagers.push(nextPager);
  }

  mergeProps(props) {
    return {
      ...props,
      paginate: {
        ...props.paginate,
        [this.name]: {
          getNext: () => {
            this.queueNext();
            return this.get();
          }
        }
      }
    };
  }
}

class Container extends Component {
  constructor(props) {
    super(props);

    this.resolvedData = {};
    this.resolvedDataTargetSize = 0;

    this.retrievers = {};

    this.subscriptions = [];
    this.pagers = {};

    this.state = {
      pending: false,
      error: null,
      resolvedProps: null
    };
  }

  destroy() {
    Object.keys(this.retrievers).forEach((key) => {
      this.retrievers[key].onDestroy();
      delete this.retrievers[key];
    });
  }

  componentWillMount() {
    this.setupRetrievers(this.props);
    this.trigger();
  }

  componentWillReceiveProps(newProps) {
    this.destroy();
    this.setupRetrievers(newProps);
    this.trigger();
  }

  componentWillUnmount() {
    this.destroy();
  }

  addResolvedData(field, data) {
    this.resolvedData[field] = data;
    if (this.resolvedDataTargetSize === Object.keys(this.resolvedData).length) {
      this.setState({
        pending: false,
        resolvedProps: { ...this.resolvedData },
        error: null
      });
    }
  }

  setError(field, error) {
    this.setState({ pending: false, error });
  }

  setupRetrievers(props) {
    const { resolve = {}, observe = {}, paginate = {}, originalProps } = props;
    const getProps = () => originalProps;
    const resolveKeys = Object.keys(resolve);
    const observeKeys = Object.keys(observe);

    const publishData = (key) => (data) => this.addResolvedData(key, data);
    const publishError = (key) => (err) => this.setError(key, err);

    resolveKeys.forEach((key) => {
      if (paginate[key]) {
        const pagerConfig = paginate[key];
        const { mode, type } = pagerConfig;
        if (mode === PAGINATION.MODE.INFINITE && type === PAGINATION.TYPE.OFFSET_AND_LIMIT) {
          this.retrievers[key] = new PaginatedInfiniteOffsetAndLimitResolveRetriever({
            name: key,
            publishData: publishData(key),
            publishError: publishError(key),
            getProps,
            getter: resolve[key],
            pagerConfig
          });
        }
      } else {
        this.retrievers[key] = new ResolveRetriever({
          name: key,
          publishData: publishData(key),
          publishError: publishError(key),
          getProps,
          getter: resolve[key]
        });
      }
    });

    observeKeys.forEach((key) => {
      this.retrievers[key] = new ObserveRetriever({
        name: key,
        publishData: publishData(key),
        publishError: publishError(key),
        getProps,
        getter: observe[key]
      });
    });

    this.resolvedDataTargetSize = resolveKeys.length + observeKeys.length;
  }

  trigger() {
    this.setState({ pending: true, error: null });

    Object.keys(this.retrievers).forEach((key) => {
      this.retrievers[key].get();
    });
  }

  render() {
    const { pending, error, resolvedProps } = this.state;
    const { originalProps, errorComponent, pendingComponent, component } = this.props;

    if (pending) {
      return pendingComponent ? createElement(pendingComponent, originalProps) : null;
    }

    if (error) {
      return errorComponent ? createElement(errorComponent, { ...originalProps, error }) : null;
    }

    const nextProps = Object.keys(this.retrievers).reduce(
      (props, key) => this.retrievers[key].mergeProps(props),
      { ...originalProps, ...resolvedProps }
    );
    return createElement(component, nextProps);
  }
}

export function withData(conf) {
  return component => {
    // make it pure again
    return (originalProps) => {
      const props = { ...conf, originalProps, component };
      return createElement(Container, props);
    };
  };
}

withData.PAGINATION = PAGINATION;

<|endoftext|>


<commit_before>import React, { Component } from 'react';

const WhoMadeMe = () => (

Who Made Me

);

export default WhoMadeMe;
<commit_msg>Completed Who Made Me Page<commit_after>import React from 'react';

const WhoMadeMe = () => (

						 3

						Team Members

						Neil Lawrence

							Professor of Machine Learning and Computational Biology

							Appointed at the University of Sheffield's Departments of Neuroscience and Computer Science

						Mike Smith

							Post-Doctoral Research Associate

							Also at the University Of Sheffield in Neil Lawrence's Lab

Vasily Shelkov

							Developer, Traveller and Anime Lover

							University Of Sheffield Computer Science Graduate in 2016

);

export default WhoMadeMe;
<|endoftext|>


<commit_before>// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

(function () {

  ko.HUE_CHARTS = {
    TYPES: {
      LINECHART: "lines",
      BARCHART: "bars",
      TIMELINECHART: "timeline",
      POINTCHART: "points",
      PIECHART: "pie",
      MAP: "map",
      GRADIENTMAP: "gradientmap",
      SCATTERCHART: "scatter"
    }
  };

  ko.bindingHandlers.pieChart = {
    init: function (element, valueAccessor) {
      $(element).html('To-do.');
    },
    update: function (element, valueAccessor) {
      $(element).html('To-do.');
    }
  };

  ko.bindingHandlers.barChart = {
    init: function (element, valueAccessor) {
      $(element).html('To-do.');
    },
    update: function (element, valueAccessor) {
      $(element).html('To-do.');
    }
  };

  ko.bindingHandlers.timelineChart = {
    init: function (element, valueAccessor) {
      $(element).html('To-do.');
    },
    update: function (element, valueAccessor) {
      $(element).html('To-do.');
    }
  };

  ko.bindingHandlers.lineChart = {
    init: function (element, valueAccessor) {
      $(element).html('To-do.');
    },
    update: function (element, valueAccessor) {
      $(element).html('To-do.');
    }
  };

  ko.bindingHandlers.mapChart = {
    init: function (element, valueAccessor) {
      $(element).html('To-do.');
    },
    update: function (element, valueAccessor, allBindingsAccessor) {
      $(element).html('To-do.');
    }
  };

  ko.bindingHandlers.scatterChart = {
    update: function (element, valueAccessor) {
      $(element).html('To-do.');
    }
  };

  ko.bindingHandlers.partitionChart = {
    init: function (element, valueAccessor) {
      $(element).html('To-do.');
    },
    update: function (element, valueAccessor) {
      $(element).html('To-do.');
    }
  };

  window.chartsUpdatingState = function(){};
  window.chartsNormalState = function(){};

})();<commit_msg>HUE-6093 [frontend] Added support for basic Pie chart on Plotly<commit_after>// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

(function () {

  ko.HUE_CHARTS = {
    TYPES: {
      LINECHART: 'lines',
      BARCHART: 'bars',
      TIMELINECHART: 'timeline',
      POINTCHART: 'points',
      PIECHART: 'pie',
      MAP: 'map',
      GRADIENTMAP: 'gradientmap',
      SCATTERCHART: 'scatter'
    },
    PLOTLY_OPTIONS: {
      displaylogo: false,
      modeBarButtonsToRemove: ['sendDataToCloud', 'hoverCompareCartesian']
    }
  };

  ko.bindingHandlers.pieChart = {
    update: function (element, valueAccessor) {
      var _options = valueAccessor();
      var plotterTimeout = window.setTimeout(function () {
        window.clearTimeout(plotterTimeout);
        var _data = _options.transformer(_options.data);
        var chartData = {
          values: [],
          labels: [],
          type: 'pie'
        }
        _data.forEach(function (el) {
          chartData.values.push(el.value);
          chartData.labels.push(el.label);
        });
        var layout = {
          height: 400
        };
        Plotly.newPlot(element, [chartData], layout, ko.HUE_CHARTS.PLOTLY_OPTIONS);
      }, 10);
    }
  };

  ko.bindingHandlers.barChart = {
    init: function (element, valueAccessor) {
      $(element).html('To-do.');
    },
    update: function (element, valueAccessor) {
      $(element).html('To-do.');
    }
  };

  ko.bindingHandlers.timelineChart = {
    init: function (element, valueAccessor) {
      $(element).html('To-do.');
    },
    update: function (element, valueAccessor) {
      $(element).html('To-do.');
    }
  };

  ko.bindingHandlers.lineChart = {
    init: function (element, valueAccessor) {
      $(element).html('To-do.');
    },
    update: function (element, valueAccessor) {
      $(element).html('To-do.');
    }
  };

  ko.bindingHandlers.mapChart = {
    init: function (element, valueAccessor) {
      $(element).html('To-do.');
    },
    update: function (element, valueAccessor, allBindingsAccessor) {
      $(element).html('To-do.');
    }
  };

  ko.bindingHandlers.scatterChart = {
    update: function (element, valueAccessor) {
      $(element).html('To-do.');
    }
  };

  ko.bindingHandlers.partitionChart = {
    init: function (element, valueAccessor) {
      $(element).html('To-do.');
    },
    update: function (element, valueAccessor) {
      $(element).html('To-do.');
    }
  };

  window.chartsUpdatingState = function(){};
  window.chartsNormalState = function(){};

})();<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Internet of Protocols Alliance (IOPA)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const FreeList = require('../util/freelist.js').FreeList,
    Events = require('events'),
    URL = require('url'),
    util = require('util'),

    Cancellation = require('../util/cancellation').default,
    PrototypeExtend = require('./contextPrototypeExtend').default,

    constants = require('./constants'),
    IOPA = constants.IOPA,
    SERVER = constants.SERVER,

    mergeContext = require('../util/shallow').mergeContext;

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/* *********************************************************
 * IOPA CONTEXT
 * ********************************************************* */

/**
 * Represents IOPA Context object for any REST Request/Response
 * See http://iopa.io for further details
 *
 * @class IopaContext
 * @constructor
 */
function IopaContext() {
     return this;
}

/**
* Initialize blank IopaContext object
* Generic properties common to all server types included
*
* @method Init
*/
IopaContext.prototype.init = function init() {
    this[IOPA.Version] = "1.2";
    var _cancellationTokenSource = Cancellation();
    this[SERVER.CallCancelledSource] = _cancellationTokenSource;
    this[IOPA.CallCancelled] = _cancellationTokenSource.token;
    this[IOPA.Events] = new Events.EventEmitter();
    this[IOPA.Seq] = _nextSequence();
    this[SERVER.Logger] = console;
    this.log = this[SERVER.Logger];

    return this;
};

/**
 * Represents IopaContext Factory of up to 100 items
 *
 * @instance IopaContextFactory

 * @method alloc()  get new IopaContext from pool or by creation if none available; remember to call context.init();
 * @method free(context)   return IopaContext to the pool for reuse
 */
function IopaContextFactory() {
    _classCallCheck(this, IopaContextFactory);
    FreeList.call(this, 'IopaContext', 100, function () { return IopaContext.apply(Object.create(IopaContext.prototype)); });
 }

util.inherits(IopaContextFactory, FreeList);

/**
* Create a new barebones IOPA Request with or without a response record
*/
 IopaContextFactory.prototype._create = function _create(withoutResponse) {

    var context = this.alloc();

    context.init();

    if (!withoutResponse) {
        var response = this.alloc().init();
        context.response = response;
        context.response.parent = context;
    }

    return context;
};

/**
* Release the memory used by a given IOPA Context
*
* @param context the context to free
*/
IopaContextFactory.prototype.dispose = function dispose(context) {

    if (context.response) {
        //    console.log("Disposing " + context.response["iopa.Seq"]);

        var response = context.response;
        for (var prop in response) { if (response.hasOwnProperty(prop)) { response[prop] = null; } }
        this.free(response);
    }

    //   console.log("Disposing " + context["iopa.Seq"]);

    for (var prop in context) { if (context.hasOwnProperty(prop)) { context[prop] = null; } };

    this.free(context);
};

/*
* ES6 finally/dispose pattern for IOPA Context
* @param context Iopa
* @param appfunc function(context): Promise
* returns Promise that always ultimately resolves to callback's result or rejects
*/
IopaContextFactory.prototype.using = function using(context, appfunc) {

    var self = this;

    /**  bluebird version only -- not used:
    *  	 return Promise.using(Promise.resolve(context)
    *	 .disposer(function(context, promise){
    *		 self.dispose(context);
    *		 context = null;
    *	 }), cb);
    */

    return new Promise(function (resolve, reject) {
        var v = appfunc(context);
        if (typeof v === 'undefined')
            v = null;
        resolve(v);
    }).then(function (value) {
        return Promise.resolve(function () {
            self.dispose(context);
            context = null;
            return value;
        } ());
    },
        function (err) {
            context.log.error(err);
            self.dispose(context);
            context = null;
            throw err;
        });
};

/**
* Create a new IOPA Context, with default [iopa.*] values populated
*/
IopaContextFactory.prototype.createContext = function createContext() {
    var context = this._create();

    context[IOPA.Headers] = {};
    context[IOPA.Method] = "";
    context[IOPA.Host] = "";
    context[IOPA.Path] = "";
    context[IOPA.PathBase] = "";
    context[IOPA.Protocol] = "";
    context[IOPA.QueryString] = "";
    context[IOPA.Scheme] = "";
    context[IOPA.Body] = null;

    var response = context.response;
    response[IOPA.Headers] = {};
    response[IOPA.StatusCode] = null;
    response[IOPA.ReasonPhrase] = "";
    response[IOPA.Protocol] = "";
    response[IOPA.Body] = null;
    response[IOPA.Headers]["Content-Length"] = "-1";

    return context;
};

/**
* Create a new IOPA Context, with default [iopa.*] values populated
*/
IopaContextFactory.prototype.createRequest = function createRequest(urlStr, options) {

    if (typeof options === 'string' || options instanceof String)
       options = { "iopa.Method": options};

    options = options || {};

    var context = this._create(true);
    context[SERVER.IsLocalOrigin] = true;
    context[SERVER.OriginalUrl] = urlStr;
    context[IOPA.Method] = options[IOPA.Method] || IOPA.METHODS.GET;

    var urlParsed = URL.parse(urlStr);
    context[IOPA.PathBase] = "";
    context[IOPA.Path] = urlParsed.pathname || "";
    context[IOPA.QueryString] = urlParsed.query;
    context[IOPA.Scheme] = urlParsed.protocol;
    context[SERVER.RemoteAddress] = urlParsed.hostname;
    context[IOPA.Host] = urlParsed.hostname;
    context[IOPA.Headers] = {};

    const SCHEMES = IOPA.SCHEMES,
        PROTOCOLS = IOPA.PROTOCOLS,
        PORTS = IOPA.PORTS

    switch (urlParsed.protocol) {
        case SCHEMES.HTTP:
            context[IOPA.Protocol] = PROTOCOLS.HTTP;
            context[SERVER.TLS] = false;
            context[IOPA.Headers]["Host"] = context[IOPA.Host];
            context[SERVER.RemotePort] = urlParsed.port || PORTS.HTTP;
            break;
        case SCHEMES.HTTPS:
            context[IOPA.Protocol] = PROTOCOLS.HTTP;
            context[SERVER.TLS] = false;
            context[IOPA.Headers]["Host"] = context[IOPA.Host];
            context[SERVER.RemotePort] = urlParsed.port || PORTS.HTTPS;
            break;
        case SCHEMES.COAP:
            context[IOPA.Protocol] = PROTOCOLS.COAP;
            context[SERVER.TLS] = false;
            context[SERVER.RemotePort] = urlParsed.port || PORTS.COAP;
            break;
        case SCHEMES.COAPS:
            context[IOPA.Protocol] = PROTOCOLS.COAP;
            context[SERVER.TLS] = false;
            context[SERVER.RemotePort] = urlParsed.port || PORTS.COAPS;
            break;
        case SCHEMES.MQTT:
            context[IOPA.Protocol] = PROTOCOLS.MQTT;
            context[SERVER.TLS] = false;
            context[SERVER.RemotePort] = urlParsed.port || PORTS.MQTT;
            break;
        case SCHEMES.MQTTS:
            context[IOPA.Protocol] = PROTOCOLS.MQTT;
            context[SERVER.TLS] = false;
            context[SERVER.RemotePort] = urlParsed.port || PORTS.MQTTS;
            break;
        default:
            context[IOPA.Protocol] = urlParsed.protocol;
            context[SERVER.TLS] = false;
            context[SERVER.RemotePort] = urlParsed.port || 0;
    };

    mergeContext(context, options);

    return context;
};

function _disposable(context) {
    var that = this;
    var ctx = context

    return Promise.resolve(ctx)
      .disposer(function(ctx, promise){
          that.dispose(ctx);
          ctx = null;
          that = null;
      });
};

const maxSequence = Math.pow(2, 16);
var _lastSequence = Math.floor(Math.random() * (maxSequence - 1));

function _nextSequence() {
    if (++_lastSequence === maxSequence)
        _lastSequence = 1;

    return "#" + _lastSequence.toString();
};

var _factoryInstance = new IopaContextFactory();
exports.default = _factoryInstance;

/**
* DEFAULT EXPORT AND SELF INITIALIZATION
*/
var _factoryInstance = new IopaContextFactory();
exports.default = _factoryInstance;

function runonce(){
     var _context = _factoryInstance.createContext();   //  for adding prototype properties only
    PrototypeExtend(_context);
    _factoryInstance.free(_context);
    _context = null;
};
runonce();
<commit_msg>cleaned up slightly<commit_after>/*
 * Copyright (c) 2015 Internet of Protocols Alliance (IOPA)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const FreeList = require('../util/freelist.js').FreeList,
    Events = require('events'),
    URL = require('url'),
    util = require('util'),

    Cancellation = require('../util/cancellation').default,
    PrototypeExtend = require('./contextPrototypeExtend').default,

    constants = require('./constants'),
    IOPA = constants.IOPA,
    SERVER = constants.SERVER,

    mergeContext = require('../util/shallow').mergeContext;

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/* *********************************************************
 * IOPA CONTEXT
 * ********************************************************* */

/**
 * Represents IOPA Context object for any REST Request/Response
 * See http://iopa.io for further details
 *
 * @class IopaContext
 * @constructor
 */
function IopaContext() {
     return this;
}

/**
* Initialize blank IopaContext object
* Generic properties common to all server types included
*
* @method Init
*/
IopaContext.prototype.init = function init() {
    this[IOPA.Version] = "1.2";
    var _cancellationTokenSource = Cancellation();
    this[SERVER.CallCancelledSource] = _cancellationTokenSource;
    this[IOPA.CallCancelled] = _cancellationTokenSource.token;
    this[IOPA.Events] = new Events.EventEmitter();
    this[IOPA.Seq] = _nextSequence();
    this[SERVER.Logger] = console;
    this.log = this[SERVER.Logger];
    return this;
};

/**
 * Represents IopaContext Factory of up to 100 items
 *
 * @instance IopaContextFactory

 * @method alloc()  get new IopaContext from pool or by creation if none available; remember to call context.init();
 * @method free(context)   return IopaContext to the pool for reuse
 */
function IopaContextFactory() {
    _classCallCheck(this, IopaContextFactory);
    FreeList.call(this, 'IopaContext', 100, function () { return IopaContext.apply(Object.create(IopaContext.prototype)); });
 }

util.inherits(IopaContextFactory, FreeList);

/**
* Create a new barebones IOPA Request with or without a response record
*/
 IopaContextFactory.prototype._create = function _create(withoutResponse) {

    var context = this.alloc();

    context.init();

    if (!withoutResponse) {
        var response = this.alloc().init();
        context.response = response;
        context.response.parent = context;
    }

    return context;
};

/**
* Release the memory used by a given IOPA Context
*
* @param context the context to free
*/
IopaContextFactory.prototype.dispose = function dispose(context) {

    if (context.response) {

        var response = context.response;
        for (var prop in response) { if (response.hasOwnProperty(prop)) { response[prop] = null; } }
        this.free(response);
    }

    for (var prop in context) { if (context.hasOwnProperty(prop)) { context[prop] = null; } };

    this.free(context);
};

/*
* ES6 finally/dispose pattern for IOPA Context
* @param context Iopa
* @param appfunc function(context): Promise
* returns Promise that always ultimately resolves to callback's result or rejects
*/
IopaContextFactory.prototype.using = function using(context, appfunc) {

    var self = this;

    /**  bluebird version only -- not used:
    *  	 return Promise.using(Promise.resolve(context)
    *	 .disposer(function(context, promise){
    *		 self.dispose(context);
    *		 context = null;
    *	 }), cb);
    */

    return new Promise(function (resolve, reject) {
        var v = appfunc(context);
        if (typeof v === 'undefined')
            v = null;
        resolve(v);
    }).then(function (value) {
        return Promise.resolve(function () {
            self.dispose(context);
            context = null;
            return value;
        } ());
    },
        function (err) {
            context.log.error(err);
            self.dispose(context);
            context = null;
            throw err;
        });
};

/**
* Create a new IOPA Context, with default [iopa.*] values populated
*/
IopaContextFactory.prototype.createContext = function createContext() {
    var context = this._create();

    context[IOPA.Headers] = {};
    context[IOPA.Method] = "";
    context[IOPA.Host] = "";
    context[IOPA.Path] = "";
    context[IOPA.PathBase] = "";
    context[IOPA.Protocol] = "";
    context[IOPA.QueryString] = "";
    context[IOPA.Scheme] = "";
    context[IOPA.Body] = null;

    var response = context.response;
    response[IOPA.Headers] = {};
    response[IOPA.StatusCode] = null;
    response[IOPA.ReasonPhrase] = "";
    response[IOPA.Protocol] = "";
    response[IOPA.Body] = null;
    response[IOPA.Headers]["Content-Length"] = "-1";

    return context;
};

/**
* Create a new IOPA Context, with default [iopa.*] values populated
*/
IopaContextFactory.prototype.createRequest = function createRequest(urlStr, options) {

    if (typeof options === 'string' || options instanceof String)
       options = { "iopa.Method": options};

    options = options || {};

    var context = this._create(true);
    context[SERVER.IsLocalOrigin] = true;
    context[SERVER.OriginalUrl] = urlStr;
    context[IOPA.Method] = options[IOPA.Method] || IOPA.METHODS.GET;

    var urlParsed = URL.parse(urlStr);
    context[IOPA.PathBase] = "";
    context[IOPA.Path] = urlParsed.pathname || "";
    context[IOPA.QueryString] = urlParsed.query;
    context[IOPA.Scheme] = urlParsed.protocol;
    context[SERVER.RemoteAddress] = urlParsed.hostname;
    context[IOPA.Host] = urlParsed.hostname;
    context[IOPA.Headers] = {};

    const SCHEMES = IOPA.SCHEMES,
        PROTOCOLS = IOPA.PROTOCOLS,
        PORTS = IOPA.PORTS

    switch (urlParsed.protocol) {
        case SCHEMES.HTTP:
            context[IOPA.Protocol] = PROTOCOLS.HTTP;
            context[SERVER.TLS] = false;
            context[IOPA.Headers]["Host"] = context[IOPA.Host];
            context[SERVER.RemotePort] = urlParsed.port || PORTS.HTTP;
            break;
        case SCHEMES.HTTPS:
            context[IOPA.Protocol] = PROTOCOLS.HTTP;
            context[SERVER.TLS] = false;
            context[IOPA.Headers]["Host"] = context[IOPA.Host];
            context[SERVER.RemotePort] = urlParsed.port || PORTS.HTTPS;
            break;
        case SCHEMES.COAP:
            context[IOPA.Protocol] = PROTOCOLS.COAP;
            context[SERVER.TLS] = false;
            context[SERVER.RemotePort] = urlParsed.port || PORTS.COAP;
            break;
        case SCHEMES.COAPS:
            context[IOPA.Protocol] = PROTOCOLS.COAP;
            context[SERVER.TLS] = false;
            context[SERVER.RemotePort] = urlParsed.port || PORTS.COAPS;
            break;
        case SCHEMES.MQTT:
            context[IOPA.Protocol] = PROTOCOLS.MQTT;
            context[SERVER.TLS] = false;
            context[SERVER.RemotePort] = urlParsed.port || PORTS.MQTT;
            break;
        case SCHEMES.MQTTS:
            context[IOPA.Protocol] = PROTOCOLS.MQTT;
            context[SERVER.TLS] = false;
            context[SERVER.RemotePort] = urlParsed.port || PORTS.MQTTS;
            break;
        default:
            context[IOPA.Protocol] = urlParsed.protocol;
            context[SERVER.TLS] = false;
            context[SERVER.RemotePort] = urlParsed.port || 0;
    };

    mergeContext(context, options);

    return context;
};

function _disposable(context) {
    var that = this;
    var ctx = context

    return Promise.resolve(ctx)
      .disposer(function(ctx, promise){
          that.dispose(ctx);
          ctx = null;
          that = null;
      });
};

const maxSequence = Math.pow(2, 16);
var _lastSequence = Math.floor(Math.random() * (maxSequence - 1));

function _nextSequence() {
    if (++_lastSequence === maxSequence)
        _lastSequence = 1;

    return "#" + _lastSequence.toString();
};

var _factoryInstance = new IopaContextFactory();
exports.default = _factoryInstance;

/**
* DEFAULT EXPORT AND SELF INITIALIZATION
*/
var _factoryInstance = new IopaContextFactory();
exports.default = _factoryInstance;

function runonce(){
     var _context = _factoryInstance.createContext();   //  for adding prototype properties only
    PrototypeExtend(_context);
    _factoryInstance.free(_context);
    _context = null;
};
runonce();
<|endoftext|>