<commit_before>
//parses a single line of assembly
function parseLine(line){
  line = line.replace(/^\s+/,''); //eliminate leading whitespace

  var parts = line.split(/\s+/);
  var int   = parts.shift();
  if(int.startsWith('.')){
    return parseConfig(line);
  }else if(int.contains(':')){
    return parseLabel(line);
  }
  int = genInt(int.toLowerCase());

  line = parts.join(' ').toLowerCase();
  line = line.replace(/;.*$/,'');  //eliminate comments

  var rd = parsers.rn(line);
  line = rd[0];
  rd = rd[1];

  console.log(line,int, rd);
}

function parseConfig(line){
  return line;
}
function parseLabel(line){
  return {label:line};
}

var parsers = {};
parsers.rn = function(line){ //parse
  var rn, tmp = line;
  line = line.replace(/^\s+/,''); //eliminate leading whitespace

  for(var i = 0; i < line.length; i++){
    if(line[i] === ' ' || line[i] === ','){
      rn = line.slice(0,i);
      line = line.slice(i+1);
      break;
    }
  }
  if(!rn){
    rn = line;
  }
  if(rn && (registers.indexOf(rn) >= 0 ||
     rn.startsWith('#'))){
    return [line,rn];
  }
  return [tmp];
};
parsers.op = function(line){

  return [line,op];
};
parsers.generic = function(line,parser){
  var tmp, out = [];
  for(var i = 0; i < parser.length; i++){
    tmp = parsers[parser[i]](line);
    if(tmp.length === 2){
      out.push(tmp[1]);
    }else if(parser[i].startsWith('?')){
      out.push('');
    }else{
      console.log(line,tmp);
      throw "Could not fill argument "+ (i+1);
    }
    line = tmp[0];
  }
  return out;
};

/* generates an array [instruction, conditional, additional] from str
 * str: imput string to first whitespace
 * instruction: add, sub, etc
 * conditional: eq, al, etc
 * additional: s, ia, x, b, etc                                        */
function genInt(str){
  for(var int in stdlib.instructions){
    if(str.startsWith(int)){
      if(int.length === str.length){
        return [int];
      }
      for(var suffix in stdlib.suffixes){
        if(str.startsWith(int + suffix)){
          if(int.length + suffix.length === str.length){
            return [int,suffix];
          }
          if(stdlib.instructions[int].additional){
            for(var add in stdlib.instructions[int].additional){
              if(str.startsWith(int + suffix + add)){
                if(int.length + suffix.length + add.length === str.length){
                  return [int,suffix,add];
                }
              }
            }
          }
        }
      }
      if(stdlib.instructions[int].additional){
        for(var add in stdlib.instructions[int].additional){
          if(str.startsWith(int + add)){
            if(int.length + add.length === str.length){
              return [int,'',add];
            }
          }
        }
      }
    }
  }
  throw "Unsupporting Instruction: " + str;
}

registers = ['r0','r1','r2','r3','r4','r5','r6','r7','r8','r9','r10','r11','r12','r13','r14','r15',
             'a1','a2','a3','a4','v1','v2','v3','v4','v5','v6','sb' ,'sl' , 'fp','sp' ,'lr' , 'pc']

pattern = '<operation><cond><flags> Rd,Rn,Operand2'

operand2 = "value" | "<shift>" +  "value" | "register"<commit_msg>operand2 setup<commit_after>
//parses a single line of assembly
function parseLine(line){
  line = line.replace(/^\s+/,''); //eliminate leading whitespace

  var parts = line.split(/\s+/);
  var int   = parts.shift();
  if(int.startsWith('.')){
    return parseConfig(line);
  }else if(int.contains(':')){
    return parseLabel(line);
  }
  int = genInt(int.toLowerCase());

  line = parts.join(' ').toLowerCase();
  line = line.replace(/;.*$/,'');  //eliminate comments

  var rd = parsers.rn(line);
  line = rd[0];
  rd = rd[1];

  console.log(line,int, rd);
}

function parseConfig(line){
  return line;
}
function parseLabel(line){
  return {label:line};
}

var parsers = {};
parsers.rn = function(line){ //parse
  var rn, tmp = line;
  line = line.replace(/^\s+/,''); //eliminate leading whitespace

  for(var i = 0; i < line.length; i++){
    if(line[i] === ' ' || line[i] === ','){
      rn = line.slice(0,i);
      line = line.slice(i+1);
      break;
    }
  }
  if(!rn){
    rn = line;
    line = '';
  }
  if(rn && (registers.indexOf(rn) >= 0 ||
     rn.startsWith('#'))){
    return [line,rn];
  }
  return [tmp];
};
parsers.op = function(line){
  var op, tmp = line;
  line = parsers.rn(line);
  op = line[1];
  line = line[0];
  //Barrel shift

  return ['',op,line];
};
parsers.generic = function(line,parser){
  var tmp,temp, out = [];
  for(var i = 0; i < parser.length; i++){
    temp = parser[i].startsWith('?');
    if(temp){
      tmp = parsers[parser[i].slice(1)](line);
    }else{
      tmp = parsers[parser[i]](line);
    }
    if(tmp[1]){
      if(tmp.length === 2){
        out.push(tmp[1]);
      }else{
        out.push(tmp.slice(1));
      }
    }else if(temp){
      out.push('');
    }else{
      console.log(line,tmp);
      throw "Could not fill argument "+ (i+1);
    }
    line = tmp[0];
  }
  return out;
};

/* generates an array [instruction, conditional, additional] from str
 * str: imput string to first whitespace
 * instruction: add, sub, etc
 * conditional: eq, al, etc
 * additional: s, ia, x, b, etc                                        */
function genInt(str){
  for(var int in stdlib.instructions){
    if(str.startsWith(int)){
      if(int.length === str.length){
        return [int];
      }
      for(var suffix in stdlib.suffixes){
        if(str.startsWith(int + suffix)){
          if(int.length + suffix.length === str.length){
            return [int,suffix];
          }
          if(stdlib.instructions[int].additional){
            for(var add in stdlib.instructions[int].additional){
              if(str.startsWith(int + suffix + add)){
                if(int.length + suffix.length + add.length === str.length){
                  return [int,suffix,add];
                }
              }
            }
          }
        }
      }
      if(stdlib.instructions[int].additional){
        for(var add in stdlib.instructions[int].additional){
          if(str.startsWith(int + add)){
            if(int.length + add.length === str.length){
              return [int,'',add];
            }
          }
        }
      }
    }
  }
  throw "Unsupporting Instruction: " + str;
}

registers = ['r0','r1','r2','r3','r4','r5','r6','r7','r8','r9','r10','r11','r12','r13','r14','r15',
             'a1','a2','a3','a4','v1','v2','v3','v4','v5','v6','sb' ,'sl' , 'fp','sp' ,'lr' , 'pc']

pattern = '<operation><cond><flags> Rd,Rn,Operand2'

operand2 = "value" | "<shift>" +  "value" | "register"<|endoftext|>


<commit_before>/**
 *  {@link Ext.ux.slidenavigation.View} is a subclass of {@link Ext.Container}
 *  that provides a sliding main view with an underlying navigation list.  The
 *  concept was inspired by Facebook's mobile app.
 *
 *  @author Weston Nielson <wnielson@github>
 */
Ext.define('Ext.ux.slidenavigation.View', {
    extend: 'Ext.Container',

    requires: [
        'Ext.Button',
        'Ext.Container',
        'Ext.Function',
        'Ext.ModelManager',
        'Ext.Toolbar',
        'Ext.data.Model',
        'Ext.data.Store',
        'Ext.dataview.List',
    ],

    xtype: 'slidenavigationview',

    config: {
        /**
         * @cfg {Object} list Configuration for the navigation list
         */
        list: {
            width: 250,
            maxDrag: null,
            itemTpl: '{title}',
            grouped: true,
            items: [{
                xtype: 'toolbar',
                docked: 'top',
                ui: 'light'
            }]
        },

        /**
         * @cfg {Object} container Configuration for the container
         */
        container: {},

        /**
         * @cfg {Array} items An array of items to put into the navigation list.
         * The items can either be Ext components or special objects with a "handler"
         * key, which should be a function to execute when selected.  Additionally, you
         * can define the order of the items by defining an 'order' parameter.
         */
        items: [],

        /**
         * @cfg {Object} groups Mapping of group name to order.  For example,
         * say you have defined two groups; "Group 1" and "Group 2".  By default
         * these will be presented in the list in that order, since
         * 'Group 1' > 'Group 2'.  This option allows you to change the ordering,
         * like so:
         *
         *  groups: {
         *    'Group 1': 2
         *    'Group 2': 1
         *  }
         *
         *  You should use integers, starting with 1, as the ordering value.
         *  By default groups are ordered by their name.
         */
        groups: {},

        /**
         * @cfg {Object} defaults An object of default values to apply to any Ext
         * components created from those listed in ``items``.
         */
        defaults: {
            layout: 'card'
        },

        /**
         * @cfg {String} slideSelector Class selector of object (or parent)
         * of which dragging should be allowed.  Defaults to the entire container.
         * For example, this could be set to something like 'x-toolbar' to restrict
         * dragging only to a toolbar.
         */
        slideSelector: '',

        /**
         * @cfg {Integer} slideDuration Number of miliseconds to animate the sliding
         * of the container when "flicked".  By default the animation is disable on
         * Android.
         */
        slideDuration: Ext.os.is.Android ? 0 : 100,

        /**
         * @cfg {Integer} selectSlideDuration Number of miliseconds to animate the sliding
         * of the container when list item is selected (if closeOnSelect = true). The default
         * value here of 300 gives a much nicer feel.  By default the animation is disable on
         * Android.
         */
        selectSlideDuration: Ext.os.is.Android ? 0 : 300,

        /**
         * @cfg {Boolean} closeOnSelect Whether or not to automatically close the container
         * when an item in the list is selected.  Default is true.
         */
        closeOnSelect: true
    },

    initConfig: function() {
        var me = this;

        me._indexCount = 0;

        /**
         *  Create the store.
         */
        me.store = Ext.create('Ext.data.Store', {
            model: me.getModel(),
            sorters: 'order',
            grouper: {
                property: 'group',
                sortProperty: 'groupOrder'
            }
        });

        /**
         *  Add the items into the list.
         */
        me.addItems(me.config.items || []);
        delete me.config.items;

        me.callParent(arguments);

        /**
         *  This stores the instances of the components created.
         *  TODO: Support 'autoDestroy'.
         *  @private
         */
        me._cache = {};

        /**
         *  Default config values used for creating a slideButton.
         */
        me.slideButtonDefaults = {
            xtype: 'button',
            iconMask: true,
            iconCls: 'more',
            name: 'slidebutton',
            listeners: {
                release: me.toggleContainer,
                scope: me
            },
            /**
             *  To add the button into a toolbar, you can add the following
             *  to any item in your navigation list.
             */
            //selector: ['toolbar']
        };

        //me.config = Ext.merge({}, me.config, config || {});
        //return me.callParent(arguments);
    },

    initialize: function() {
        this.callParent();

        this.addCls('x-slidenavigation');

        this.list = this.createNavigationList();
        this.container = this.createContainer();

        this.add([
            this.list,
            this.container
        ]);

        // TODO: Make this optional, perhaps by defining
        // "selected: true" in the items list
        this.list.select(0);
    },

    /**
     *  Adds an array of items (or a single item) into the list.
     */
    addItems: function(items) {
        var me = this,
            items = Ext.isArray(items) ? items : [items],
            groups = me.config.groups;

        Ext.each(items, function(item, index) {
            if (!Ext.isDefined(item.index)) {
                item.index = me._indexCount;
                me._indexCount++;
            }
            me.store.add(item);
        });
    },

    /**
     *  Creates a button that can toggle the navigation menu.  For an example
     *  config, see ``slideButtonDefaults``.
     */
    createSlideButton: function(el, config) {
        var me = this,
            parent = el.down(config.selector);

        if (parent) {
            return parent.add(Ext.merge(me.slideButtonDefaults, config));
        }

        return false;
    },

    /**
     * Called when an item in the list is tapped.
     */
    onSelect: function(list, item, eOpts) {
        var me = this,
            store = list.getStore(),
            index = item.raw.index,
            container = me.container;

        if (me._cache[index] == undefined) {
            //container = this.down('container[cls="x-slidenavigation-container"]');

            // If the object has a handler defined, then we don't need to
            // create an Ext object
            if (Ext.isFunction(item.raw.handler)) {
                me._cache[index] = item.raw.handler;
            } else {
                me._cache[index] = container.add(Ext.merge(me.config.defaults, item.raw));

                // Add a button for controlling the slide, if desired
                if ((item.raw.slideButton || false)) {
                    me.createSlideButton(me._cache[index], item.raw.slideButton);
                }
            }
        }

        if (Ext.isFunction(this._cache[index])) {
            this._cache[index]();
        } else {
            container.setActiveItem(this._cache[index]);
        }

        if (this.config.closeOnSelect) {
            this.closeContainer(this.config.selectSlideDuration);
        }
    },

    onContainerDrag: function(draggable, e, offset, eOpts) {
        if (offset.x < 1) {
            this.setClosed(true);
        } else {
            this.setClosed(false);
        }
    },

    onContainerDragstart: function(draggable, e, offset, eOpts) {
        if (this.config.slideSelector == false) {
            return false;
        }

        if (this.config.slideSelector) {
            node = e.target;
            while (node = node.parentNode) {
                if (node.className && node.className.indexOf(this.config.slideSelector) > -1) {
                    return true;
                }
            }
            return false;
        }
        return false;
    },

    onContainerDragend: function(draggable, e, eOpts) {
        var velocity  = Math.abs(e.deltaX / e.deltaTime),
            direction = (e.deltaX > 0) ? "right" : "left",
            offset    = Ext.clone(draggable.offset),
            threshold = parseInt(this.config.list.width * .70);

        switch (direction) {
            case "right":
                offset.x = (velocity > 0.75 || offset.x > threshold) ? this.config.list.width : 0;
                break;
            case "left":
                offset.x = (velocity > 0.75 || offset.x < threshold) ? 0 : this.config.list.width;
                break;
        }

        this.moveContainer(offset.x);
    },

    /**
     * Registers the model with Ext.ModelManager, if it hasn't been
     * already, and returns the name of the model for use in the store.
     */
    getModel: function() {
        var model = 'SlideNavigationPanelItem',
            groups = this.config.groups;

        if (!Ext.ModelManager.get(model)) {
            Ext.define(model, {
                extend: 'Ext.data.Model',
                config: {
                    idProperty: 'index',
                    fields: [
                        'index', 'title', 'group',
                        {
                            name: 'order',
                            defaultValue: 1
                        },{
                            name: 'groupOrder',
                            convert: function(value, record) {
                                // By default we group and order by group name.
                                group = record.get('group');
                                return groups[group] || group;
                            }
                        }
                    ]
                }
            });
        }

        return model;
    },

    /**
     *  Closes the container.  See ``moveContainer`` for more details.
     */
    closeContainer: function(duration) {
        var duration = duration || this.config.slideDuration;
        this.moveContainer(0, duration);
    },

    /**
     *  Opens the container.  See ``moveContainer`` for more details.
     */
    openContainer: function(duration) {
        var duration = duration || this.config.slideDuration;
        this.container.addCls('open');
        this.moveContainer(this.config.list.width, duration);
    },

    toggleContainer: function(duration) {
        var duration = Ext.isNumber(duration) ? duration : this.config.slideDuration;
        if (this.isClosed()) {
            this.openContainer(duration);
        } else {
            this.closeContainer(duration);
        }
    },

    /**
     *  Moves the container to a specified ``offsetX`` pixels.  Positive
     *  integer values move the container that many pixels from the left edge
     *  of the window.  If ``duration`` is provided, it should be an integer
     *  number of milliseconds to animate the slide effect.  If no duration is
     *  provided, the default in ``config.slideDuration`` is used.
     */
    moveContainer: function(offsetX, duration) {
        var duration = duration || this.config.slideDuration,
            draggable = this.container.draggableBehavior.draggable;

        draggable.setOffset(offsetX, 0, {
            duration: duration
        });
    },

    /**
     *  Returns true if the container is closed, false otherwise.  This is a
     *  computed value based off the current offset position of the container.
     */
    isClosed: function() {
        return (this.container.draggableBehavior.draggable.offset.x == 0);
    },

    /**
     *  Sets the container as being closed.  This shouldn't ever be called
     *  directly as it is automatically called by the ``translatable``
     *  "animationend" event after the container has stopped moving.  All this
     *  really does is set the CSS class for the container.
     */
    setClosed: function(closed) {
        /**
         *  TODO: Consider some way to mask/disable certain elements when
         *        the container is opened.  The code commented-out below
         *        'works' but I think there is a better way to approach this.
         */

        if (closed) {
            this.container.removeCls('open');

            /*
            Ext.each(this.container.getActiveItem().getItems().items, function(item) {
                if (item.maskOnSlide) {
                    item.setMasked(false);
                }
            });
            */
        } else {
            this.container.addCls('open');
            /*
            Ext.each(this.container.getActiveItem().getItems().items, function(item) {
                if (item.maskOnSlide) {
                    item.setMasked(true);
                }
            });
            */
        }
    },

    /**
     * Generates a new Ext.dataview.List object to be used for displaying
     * the navigation items.
     */
    createNavigationList: function(store) {
        return Ext.create('Ext.dataview.List', Ext.merge({}, this.config.list, {
            store: this.store,
            docked: 'left',
            cls: 'x-slidenavigation-list',
            style: 'position: absolute; top: 0; left: 0; height: 100%;' +
                   'width: 100% !important; z-index: 2',
            listeners: {
                select: this.onSelect,
                scope: this
            }
        }));
    },

    /**
     *  Generates and returns the Ext.Container to be used for displaying
     *  content.  This is the "slideable" container that is positioned above
     *  the navigation list.
     */
    createContainer: function() {
        return Ext.create('Ext.Container', Ext.merge({}, this.config.container, {
            docked: 'left',
            cls: 'x-slidenavigation-container',
            style: 'width: 100%; height: 100%; position: absolute; opacity: 1; z-index: 5',
            layout: 'card',
            draggable: {
                direction: 'horizontal',
                constraint: {
                    min: { x: 0, y: 0 },
                    max: { x: this.config.list.maxDrag || Math.max(screen.width, screen.height), y: 0 }
                },
                listeners: {
                    dragstart: {
                        fn: this.onContainerDragstart,
                        order: 'before',
                        scope: this
                    },
                    drag: Ext.Function.createThrottled(this.onContainerDrag, 100, this),
                    dragend: this.onContainerDragend,
                    scope: this
                },
                translatable: {
                    listeners: {
                        animationend: function(translatable, b, c) {
                            // Remove the class when the animation is finished, but only
                            // if we're "closed"
                            this.setClosed(this.isClosed());
                        },
                        scope: this // The "x-slidenavigation" container
                    }
                }
            }
        }));
    },

    /**
     *  Override the default method so that we actually return the active item in the list,
     *  otherwise this will always return the same thing (the main container, not the
     *  selected item).
     *
     */
    getActiveItem: function() {
        var selection = this.list.getSelection();
        if (selection) {
            return selection[0];
        }
    }
});<commit_msg>Fixed config issue; thanks andrew.archer for the fix.<commit_after>/**
 *  {@link Ext.ux.slidenavigation.View} is a subclass of {@link Ext.Container}
 *  that provides a sliding main view with an underlying navigation list.  The
 *  concept was inspired by Facebook's mobile app.
 *
 *  @author Weston Nielson <wnielson@github>
 */
Ext.define('Ext.ux.slidenavigation.View', {
    extend: 'Ext.Container',

    requires: [
        'Ext.Button',
        'Ext.Container',
        'Ext.Function',
        'Ext.ModelManager',
        'Ext.Toolbar',
        'Ext.data.Model',
        'Ext.data.Store',
        'Ext.dataview.List',
    ],

    xtype: 'slidenavigationview',

    config: {
        /**
         * @cfg {Object} list Configuration for the navigation list
         */
        list: {
            width: 250,
            maxDrag: null,
            itemTpl: '{title}',
            grouped: true,
            items: [{
                xtype: 'toolbar',
                docked: 'top',
                ui: 'light'
            }]
        },

        /**
         * @cfg {Object} container Configuration for the container
         */
        container: {},

        /**
         * @cfg {Array} items An array of items to put into the navigation list.
         * The items can either be Ext components or special objects with a "handler"
         * key, which should be a function to execute when selected.  Additionally, you
         * can define the order of the items by defining an 'order' parameter.
         */
        items: [],

        /**
         * @cfg {Object} groups Mapping of group name to order.  For example,
         * say you have defined two groups; "Group 1" and "Group 2".  By default
         * these will be presented in the list in that order, since
         * 'Group 1' > 'Group 2'.  This option allows you to change the ordering,
         * like so:
         *
         *  groups: {
         *    'Group 1': 2
         *    'Group 2': 1
         *  }
         *
         *  You should use integers, starting with 1, as the ordering value.
         *  By default groups are ordered by their name.
         */
        groups: {},

        /**
         * @cfg {Object} defaults An object of default values to apply to any Ext
         * components created from those listed in ``items``.
         */
        defaults: {
            layout: 'card'
        },

        /**
         * @cfg {String} slideSelector Class selector of object (or parent)
         * of which dragging should be allowed.  Defaults to the entire container.
         * For example, this could be set to something like 'x-toolbar' to restrict
         * dragging only to a toolbar.
         */
        slideSelector: '',

        /**
         * @cfg {Integer} slideDuration Number of miliseconds to animate the sliding
         * of the container when "flicked".  By default the animation is disable on
         * Android.
         */
        slideDuration: Ext.os.is.Android ? 0 : 100,

        /**
         * @cfg {Integer} selectSlideDuration Number of miliseconds to animate the sliding
         * of the container when list item is selected (if closeOnSelect = true). The default
         * value here of 300 gives a much nicer feel.  By default the animation is disable on
         * Android.
         */
        selectSlideDuration: Ext.os.is.Android ? 0 : 300,

        /**
         * @cfg {Boolean} closeOnSelect Whether or not to automatically close the container
         * when an item in the list is selected.  Default is true.
         */
        closeOnSelect: true
    },

    initConfig: function() {
        var me = this;

        me._indexCount = 0;

        /**
         *  Create the store.
         */
        me.store = Ext.create('Ext.data.Store', {
            model: me.getModel(),
            sorters: 'order',
            grouper: {
                property: 'group',
                sortProperty: 'groupOrder'
            }
        });

        /**
         *  Add the items into the list.
         */
        me.addItems(me.config.items || []);
        delete me.config.items;

        me.callParent(arguments);

        /**
         *  This stores the instances of the components created.
         *  TODO: Support 'autoDestroy'.
         *  @private
         */
        me._cache = {};

        /**
         *  Default config values used for creating a slideButton.
         */
        me.slideButtonDefaults = {
            xtype: 'button',
            iconMask: true,
            iconCls: 'more',
            name: 'slidebutton',
            listeners: {
                release: me.toggleContainer,
                scope: me
            },
            /**
             *  To add the button into a toolbar, you can add the following
             *  to any item in your navigation list.
             */
            //selector: ['toolbar']
        };

        //me.config = Ext.merge({}, me.config, config || {});
        //return me.callParent(arguments);
    },

    initialize: function() {
        this.callParent();

        this.addCls('x-slidenavigation');

        this.list = this.createNavigationList();
        this.container = this.createContainer();

        this.add([
            this.list,
            this.container
        ]);

        // TODO: Make this optional, perhaps by defining
        // "selected: true" in the items list
        this.list.select(0);
    },

    /**
     *  Adds an array of items (or a single item) into the list.
     */
    addItems: function(items) {
        var me = this,
            items = Ext.isArray(items) ? items : [items],
            groups = me.config.groups;

        Ext.each(items, function(item, index) {
            if (!Ext.isDefined(item.index)) {
                item.index = me._indexCount;
                me._indexCount++;
            }
            me.store.add(item);
        });
    },

    /**
     *  Creates a button that can toggle the navigation menu.  For an example
     *  config, see ``slideButtonDefaults``.
     */
    createSlideButton: function(el, config) {
        var me = this,
            parent = el.down(config.selector);

        if (parent) {
            return parent.add(Ext.merge(me.slideButtonDefaults, config));
        }

        return false;
    },

    /**
     * Called when an item in the list is tapped.
     */
    onSelect: function(list, item, eOpts) {
        var me = this,
            store = list.getStore(),
            index = item.raw.index,
            container = me.container;

        if (me._cache[index] == undefined) {
            //container = this.down('container[cls="x-slidenavigation-container"]');

            // If the object has a handler defined, then we don't need to
            // create an Ext object
            if (Ext.isFunction(item.raw.handler)) {
                me._cache[index] = item.raw.handler;
            } else {
                me._cache[index] = container.add(Ext.merge({}, me.config.defaults, item.raw));

                // Add a button for controlling the slide, if desired
                if ((item.raw.slideButton || false)) {
                    me.createSlideButton(me._cache[index], item.raw.slideButton);
                }
            }
        }

        if (Ext.isFunction(this._cache[index])) {
            this._cache[index]();
        } else {
            container.setActiveItem(this._cache[index]);
        }

        if (this.config.closeOnSelect) {
            this.closeContainer(this.config.selectSlideDuration);
        }
    },

    onContainerDrag: function(draggable, e, offset, eOpts) {
        if (offset.x < 1) {
            this.setClosed(true);
        } else {
            this.setClosed(false);
        }
    },

    onContainerDragstart: function(draggable, e, offset, eOpts) {
        if (this.config.slideSelector == false) {
            return false;
        }

        if (this.config.slideSelector) {
            node = e.target;
            while (node = node.parentNode) {
                if (node.className && node.className.indexOf(this.config.slideSelector) > -1) {
                    return true;
                }
            }
            return false;
        }
        return false;
    },

    onContainerDragend: function(draggable, e, eOpts) {
        var velocity  = Math.abs(e.deltaX / e.deltaTime),
            direction = (e.deltaX > 0) ? "right" : "left",
            offset    = Ext.clone(draggable.offset),
            threshold = parseInt(this.config.list.width * .70);

        switch (direction) {
            case "right":
                offset.x = (velocity > 0.75 || offset.x > threshold) ? this.config.list.width : 0;
                break;
            case "left":
                offset.x = (velocity > 0.75 || offset.x < threshold) ? 0 : this.config.list.width;
                break;
        }

        this.moveContainer(offset.x);
    },

    /**
     * Registers the model with Ext.ModelManager, if it hasn't been
     * already, and returns the name of the model for use in the store.
     */
    getModel: function() {
        var model = 'SlideNavigationPanelItem',
            groups = this.config.groups;

        if (!Ext.ModelManager.get(model)) {
            Ext.define(model, {
                extend: 'Ext.data.Model',
                config: {
                    idProperty: 'index',
                    fields: [
                        'index', 'title', 'group',
                        {
                            name: 'order',
                            defaultValue: 1
                        },{
                            name: 'groupOrder',
                            convert: function(value, record) {
                                // By default we group and order by group name.
                                group = record.get('group');
                                return groups[group] || group;
                            }
                        }
                    ]
                }
            });
        }

        return model;
    },

    /**
     *  Closes the container.  See ``moveContainer`` for more details.
     */
    closeContainer: function(duration) {
        var duration = duration || this.config.slideDuration;
        this.moveContainer(0, duration);
    },

    /**
     *  Opens the container.  See ``moveContainer`` for more details.
     */
    openContainer: function(duration) {
        var duration = duration || this.config.slideDuration;
        this.container.addCls('open');
        this.moveContainer(this.config.list.width, duration);
    },

    toggleContainer: function(duration) {
        var duration = Ext.isNumber(duration) ? duration : this.config.slideDuration;
        if (this.isClosed()) {
            this.openContainer(duration);
        } else {
            this.closeContainer(duration);
        }
    },

    /**
     *  Moves the container to a specified ``offsetX`` pixels.  Positive
     *  integer values move the container that many pixels from the left edge
     *  of the window.  If ``duration`` is provided, it should be an integer
     *  number of milliseconds to animate the slide effect.  If no duration is
     *  provided, the default in ``config.slideDuration`` is used.
     */
    moveContainer: function(offsetX, duration) {
        var duration = duration || this.config.slideDuration,
            draggable = this.container.draggableBehavior.draggable;

        draggable.setOffset(offsetX, 0, {
            duration: duration
        });
    },

    /**
     *  Returns true if the container is closed, false otherwise.  This is a
     *  computed value based off the current offset position of the container.
     */
    isClosed: function() {
        return (this.container.draggableBehavior.draggable.offset.x == 0);
    },

    /**
     *  Sets the container as being closed.  This shouldn't ever be called
     *  directly as it is automatically called by the ``translatable``
     *  "animationend" event after the container has stopped moving.  All this
     *  really does is set the CSS class for the container.
     */
    setClosed: function(closed) {
        /**
         *  TODO: Consider some way to mask/disable certain elements when
         *        the container is opened.  The code commented-out below
         *        'works' but I think there is a better way to approach this.
         */

        if (closed) {
            this.container.removeCls('open');

            /*
            Ext.each(this.container.getActiveItem().getItems().items, function(item) {
                if (item.maskOnSlide) {
                    item.setMasked(false);
                }
            });
            */
        } else {
            this.container.addCls('open');
            /*
            Ext.each(this.container.getActiveItem().getItems().items, function(item) {
                if (item.maskOnSlide) {
                    item.setMasked(true);
                }
            });
            */
        }
    },

    /**
     * Generates a new Ext.dataview.List object to be used for displaying
     * the navigation items.
     */
    createNavigationList: function(store) {
        return Ext.create('Ext.dataview.List', Ext.merge({}, this.config.list, {
            store: this.store,
            docked: 'left',
            cls: 'x-slidenavigation-list',
            style: 'position: absolute; top: 0; left: 0; height: 100%;' +
                   'width: 100% !important; z-index: 2',
            listeners: {
                select: this.onSelect,
                scope: this
            }
        }));
    },

    /**
     *  Generates and returns the Ext.Container to be used for displaying
     *  content.  This is the "slideable" container that is positioned above
     *  the navigation list.
     */
    createContainer: function() {
        return Ext.create('Ext.Container', Ext.merge({}, this.config.container, {
            docked: 'left',
            cls: 'x-slidenavigation-container',
            style: 'width: 100%; height: 100%; position: absolute; opacity: 1; z-index: 5',
            layout: 'card',
            draggable: {
                direction: 'horizontal',
                constraint: {
                    min: { x: 0, y: 0 },
                    max: { x: this.config.list.maxDrag || Math.max(screen.width, screen.height), y: 0 }
                },
                listeners: {
                    dragstart: {
                        fn: this.onContainerDragstart,
                        order: 'before',
                        scope: this
                    },
                    drag: Ext.Function.createThrottled(this.onContainerDrag, 100, this),
                    dragend: this.onContainerDragend,
                    scope: this
                },
                translatable: {
                    listeners: {
                        animationend: function(translatable, b, c) {
                            // Remove the class when the animation is finished, but only
                            // if we're "closed"
                            this.setClosed(this.isClosed());
                        },
                        scope: this // The "x-slidenavigation" container
                    }
                }
            }
        }));
    },

    /**
     *  Override the default method so that we actually return the active item in the list,
     *  otherwise this will always return the same thing (the main container, not the
     *  selected item).
     *
     */
    getActiveItem: function() {
        var selection = this.list.getSelection();
        if (selection) {
            return selection[0];
        }
    }
});<|endoftext|>


<commit_before>goog.provide('utilities.Topping');

var toppingData = {
  //PEPPERONI//
  pepperoni: {
    image: 'assets/toppings_pepperoni.png',
    chaining: function(levelData, wedge, row, column,resultsObject){
      //nothing happens here!
    },
    powerUp: function(levelData, wedge, row, column, strength){
      //nuttin here either
    }
  },

  //MUSHROOM//
  mushroom: {
    image: 'assets/toppings_mushroom.png',
    chaining: function(levelData, wedge, row, column, resultsObject){
        //turn into a pepperoni and ATTACK!!
        levelData.get(wedge, row, column).toppingType = 'pepperoni';
        levelData.get(wedge, row, column).sprite.setFill(toppingData.pepperoni.image);
        resultsObject.mushroom++;
        attackNeighbors(levelData, wedge, row, column, resultsObject);
    },

    //STACKING power-up
    powerUp: function(levelData, wedge, row, column, strength){
      if(strength >= 4){

        if(strength <6) {
          levelData.get(wedge, row, column).toppingType = 'doublePepperoni';
          levelData.get(wedge, row, column).sprite.setFill(toppingData.doublePepperoni.image);
        }
        else if (strength >=6) {
          levelData.get(wedge, row, column).toppingType = 'triplePepperoni';
          levelData.get(wedge, row, column).sprite.setFill(toppingData.triplePepperoni.image);
        }
        console.log(levelData.get(wedge, row, column).toppingType);
        return true;
      }

      levelData.get(wedge,row,column).toppingType.stack = 1;
      return false;
    }
  },

  //OLIVES//
  olive: {
    image: 'assets/toppings_olive.png',
    chaining: function(levelData, wedge, row, column, resultsObject){
      var neighborTypes = checkNeighbors(levelData,wedge,row,column);
      var pprCount = 0;

      for (var i = neighborTypes.length - 1; i >= 0; i--) {
        if(neighborTypes[i] == 'pepperoni')
          pprCount++;
        else if(neighborTypes[i] == 'doublePepperoni' || neighborTypes[i] == 'triplePepperoni'){
          pprCount +=2; //don't need 3 anywho
        }
      }

      if(pprCount >= 2){
        //turn into a pepperoni and ATTACK!!
        levelData.get(wedge, row, column).toppingType = 'pepperoni';
        levelData.get(wedge, row, column).sprite.setFill(toppingData.pepperoni.image);
        resultsObject.olive++;
        return attackNeighbors(levelData, wedge, row, column, resultsObject);
      }
    },

    //AOE power-up
    powerUp: function(levelData, wedge, row, column, strength){
      if(strength >= 2){
        var neighborList = levelData.neighbors(wedge,row,column);
        console.log('AOE ENABLED');

        for (var i = neighborList.length - 1; i >= 0; i--) {
          var neighborData = levelData.get(neighborList[i].wedge, neighborList[i].row, neighborList[i].column);

          if(!neighborData.isOccupied){
            neighborData.toppingType = 'littlePepperoni';
            neighborData.sprite.setFill(utilities.Topping('pepperoni').image)
            neighborData.isOccupied = true;
          }
        }
        return true;
      }
      return false;
    }
  },

  //ANCHOVY//
  anchovy: {
    image: 'assets/toppings_anchovy.png',
    chaining: function(levelData, wedge, row, column, resultsObject, levelTimer){
      var neighborTypes = checkNeighbors(levelData,wedge,row,column);
      var pprCount = 0;

      for (var i = neighborTypes.length - 1; i >= 0; i--) {
        if(neighborTypes[i] == 'pepperoni')
          pprCount ++;
        else if(neighborTypes[i] == 'doublePepperoni')
          pprCount +=2; //don't need 3 anywho
        else if(neighborTypes[i] == 'triplePepperoni')
          pprCount +=3;
      }

      if(pprCount >= 3){
        //turn into a pepperoni and ATTACK!!
        levelData.get(wedge, row, column).toppingType = 'pepperoni';
        levelData.get(wedge, row, column).sprite.setFill(toppingData.pepperoni.image);
        resultsObject.anchovy++;
        return attackNeighbors(levelData, wedge, row, column, resultsObject);
      }
    },
    powerUp: function(levelData, wedge, row, column, strength){
      if(strength >= 1){
        return true;
      }
      return false;
    }
  },

  // bacon: 4,
  // buffaloChicken: 5,

  doublePepperoni: {
    image: 'assets/toppings_pepperoni_double.png',
    chaining: function(levelData, wedge, row, column,resultsObject){
      //nothing happens here!
    },
    powerUp: function(levelData, wedge, row, column, strength){
      //nuttin here either
    }
  },

  triplePepperoni: {
    image: 'assets/toppings_pepperoni_triple.png',
    chaining: function(levelData, wedge, row, column,resultsObject){
      //nothing happens here!
    },
    powerUp: function(levelData, wedge, row, column, strength){
      //nuttin here either
    }
  },

  littlePepperoni: {
    image: 'assets/toppings_pepperoni.png',
    chaining: function(levelData, wedge, row, column,resultsObject){
      //turn into a pepperoni and ATTACK!!
      levelData.get(wedge, row, column).toppingType = 'pepperoni';
      levelData.get(wedge, row, column).sprite.setFill(toppingData.pepperoni.image);
      resultsObject.mushroom++;
      attackNeighbors(levelData, wedge, row, column, resultsObject);
    },
    powerUp: function(levelData, wedge, row, column, strength){
      //nuttin here either
    }
  }

};

utilities.Topping = function(type)
{
    return toppingData[type];
};

//dat local neighbor check
function attackNeighbors(levelData, wedge,row,column, resultsObject)
{
  //TALLYING
  levelData.get(wedge,row,column).toppingType;

  var neighborList = levelData.neighbors(wedge,row,column);

  for (var i = neighborList.length - 1; i >= 0; i--) {
    var target = levelData.get(neighborList[i].wedge, neighborList[i].row, neighborList[i].column);

    if(target.isOccupied && target.toppingType != 'pepperoni')
      toppingData[target.toppingType].chaining(levelData,neighborList[i].wedge, neighborList[i].row, neighborList[i].column, resultsObject);
  }
}

function checkNeighbors(levelData, wedge,row,column)
{
  var neighborList = levelData.neighbors(wedge,row,column);
  var neighborTypes = [];

  for (var i = neighborList.length - 1; i >= 0; i--) {
    var target = levelData.get(neighborList[i].wedge, neighborList[i].row, neighborList[i].column);

    if(target.isOccupied)
      neighborTypes.push(target.toppingType);
  }

  return neighborTypes;
}

goog.exportSymbol('utilities.Topping',utilities.Topping);

/*
var attackNeighbors = function(wedge,row,column)
            {
                var neighborList = levelData.neighbors(wedge,row,column);

                for(i=0; i<neighborList.length; i++){
                  console.log(neighborList);
                  var target= levelData.get(neighborList[i].wedge,, neighborList[i].row, neighborList[i].column);

                  if(!target.isOccupied)
                    return;

                  if(target.toppingType == 'mushroom'){
                    target.toppingType = 'pepperoni';
                    target.sprite.setFill(utilities.Topping('pepperoni').image);
                    attackNeighbors(neighborList[i].wedge,, neighborList[i].row, neighborList[i].column);
                  }
                }
            }

attackNeighbors(wedge,row,column);
*/<commit_msg>stuff<commit_after>goog.provide('utilities.Topping');

var toppingData = {
  //PEPPERONI//
  pepperoni: {
    image: 'assets/toppings_pepperoni.png',
    chaining: function(levelData, wedge, row, column,resultsObject){
      //nothing happens here!
    },
    powerUp: function(levelData, wedge, row, column, strength){
      //nuttin here either
    }
  },

  //MUSHROOM//
  mushroom: {
    image: 'assets/toppings_mushroom.png',
    chaining: function(levelData, wedge, row, column, resultsObject){
        //turn into a pepperoni and ATTACK!!
        levelData.get(wedge, row, column).toppingType = 'pepperoni';
        levelData.get(wedge, row, column).sprite.setFill(toppingData.pepperoni.image);
        resultsObject.mushroom++;
        attackNeighbors(levelData, wedge, row, column, resultsObject);
    },

    //STACKING power-up
    powerUp: function(levelData, wedge, row, column, strength){
      if(strength >= 4){

        if(strength <6) {
          levelData.get(wedge, row, column).toppingType = 'doublePepperoni';
          levelData.get(wedge, row, column).sprite.setFill(toppingData.doublePepperoni.image);
        }
        else if (strength >=6) {
          levelData.get(wedge, row, column).toppingType = 'triplePepperoni';
          levelData.get(wedge, row, column).sprite.setFill(toppingData.triplePepperoni.image);
        }
        console.log(levelData.get(wedge, row, column).toppingType);
        return true;
      }

      levelData.get(wedge,row,column).toppingType.stack = 1;
      return false;
    }
  },

  //OLIVES//
  olive: {
    image: 'assets/toppings_olive.png',
    chaining: function(levelData, wedge, row, column, resultsObject){
      var neighborTypes = checkNeighbors(levelData,wedge,row,column);
      var pprCount = 0;

      for (var i = neighborTypes.length - 1; i >= 0; i--) {
        if(neighborTypes[i] == 'pepperoni')
          pprCount++;
        else if(neighborTypes[i] == 'doublePepperoni' || neighborTypes[i] == 'triplePepperoni'){
          pprCount +=2; //don't need 3 anywho
        }
      }

      if(pprCount >= 2){
        //turn into a pepperoni and ATTACK!!
        levelData.get(wedge, row, column).toppingType = 'pepperoni';
        levelData.get(wedge, row, column).sprite.setFill(toppingData.pepperoni.image);
        resultsObject.olive++;
        return attackNeighbors(levelData, wedge, row, column, resultsObject);
      }
    },

    //AOE power-up
    powerUp: function(levelData, wedge, row, column, strength){
      if(strength >= 3){
        var neighborList = levelData.neighbors(wedge,row,column);
        console.log('AOE ENABLED');

        for (var i = neighborList.length - 1; i >= 0; i--) {
          var neighborData = levelData.get(neighborList[i].wedge, neighborList[i].row, neighborList[i].column);

          if(!neighborData.isOccupied){
            neighborData.toppingType = 'littlePepperoni';
            neighborData.sprite.setFill(utilities.Topping('pepperoni').image)
            neighborData.isOccupied = true;
          }
        }
        return true;
      }
      return false;
    }
  },

  //ANCHOVY//
  anchovy: {
    image: 'assets/toppings_anchovy.png',
    chaining: function(levelData, wedge, row, column, resultsObject){
      var neighborTypes = checkNeighbors(levelData,wedge,row,column);
      var pprCount = 0;

      for (var i = neighborTypes.length - 1; i >= 0; i--) {
        if(neighborTypes[i] == 'pepperoni')
          pprCount ++;
        else if(neighborTypes[i] == 'doublePepperoni')
          pprCount +=2; //don't need 3 anywho
        else if(neighborTypes[i] == 'triplePepperoni')
          pprCount +=3;
      }

      if(pprCount >= 3){
        //turn into a pepperoni and ATTACK!!
        levelData.get(wedge, row, column).toppingType = 'pepperoni';
        levelData.get(wedge, row, column).sprite.setFill(toppingData.pepperoni.image);
        resultsObject.anchovy++;
        return attackNeighbors(levelData, wedge, row, column, resultsObject);
      }
    },

    //SLOW TIME
    powerUp: function(levelData, wedge, row, column, strength, levelTimer){
      if(strength >= 2){

        return true;
      }
      return false;
    }
  },

  // bacon: 4,
  // buffaloChicken: 5,

  doublePepperoni: {
    image: 'assets/toppings_pepperoni_double.png',
    chaining: function(levelData, wedge, row, column,resultsObject){
      //nothing happens here!
    },
    powerUp: function(levelData, wedge, row, column, strength){
      //nuttin here either
    }
  },

  triplePepperoni: {
    image: 'assets/toppings_pepperoni_triple.png',
    chaining: function(levelData, wedge, row, column,resultsObject){
      //nothing happens here!
    },
    powerUp: function(levelData, wedge, row, column, strength){
      //nuttin here either
    }
  },

  littlePepperoni: {
    image: 'assets/toppings_pepperoni.png',
    chaining: function(levelData, wedge, row, column,resultsObject){
      //turn into a pepperoni and ATTACK!!
      levelData.get(wedge, row, column).toppingType = 'pepperoni';
      levelData.get(wedge, row, column).sprite.setFill(toppingData.pepperoni.image);
      resultsObject.mushroom++;
      attackNeighbors(levelData, wedge, row, column, resultsObject);
    },
    powerUp: function(levelData, wedge, row, column, strength){
      //nuttin here either
    }
  }

};

utilities.Topping = function(type)
{
    return toppingData[type];
};

//dat local neighbor check
function attackNeighbors(levelData, wedge,row,column, resultsObject)
{
  //TALLYING
  levelData.get(wedge,row,column).toppingType;

  var neighborList = levelData.neighbors(wedge,row,column);

  for (var i = neighborList.length - 1; i >= 0; i--) {
    var target = levelData.get(neighborList[i].wedge, neighborList[i].row, neighborList[i].column);

    if(target.isOccupied && target.toppingType != 'pepperoni')
      toppingData[target.toppingType].chaining(levelData,neighborList[i].wedge, neighborList[i].row, neighborList[i].column, resultsObject);
  }
}

function checkNeighbors(levelData, wedge,row,column)
{
  var neighborList = levelData.neighbors(wedge,row,column);
  var neighborTypes = [];

  for (var i = neighborList.length - 1; i >= 0; i--) {
    var target = levelData.get(neighborList[i].wedge, neighborList[i].row, neighborList[i].column);

    if(target.isOccupied)
      neighborTypes.push(target.toppingType);
  }

  return neighborTypes;
}

goog.exportSymbol('utilities.Topping',utilities.Topping);

/*
var attackNeighbors = function(wedge,row,column)
            {
                var neighborList = levelData.neighbors(wedge,row,column);

                for(i=0; i<neighborList.length; i++){
                  console.log(neighborList);
                  var target= levelData.get(neighborList[i].wedge,, neighborList[i].row, neighborList[i].column);

                  if(!target.isOccupied)
                    return;

                  if(target.toppingType == 'mushroom'){
                    target.toppingType = 'pepperoni';
                    target.sprite.setFill(utilities.Topping('pepperoni').image);
                    attackNeighbors(neighborList[i].wedge,, neighborList[i].row, neighborList[i].column);
                  }
                }
            }

attackNeighbors(wedge,row,column);
*/<|endoftext|>


<commit_before>/*
 *   Copyright 2011 Marco Martin <mart@kde.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as
 *   published by the Free Software Foundation; either version 2, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

.pragma library

var positions = new Array()

var cellSize = new Object()
cellSize.width = 178
cellSize.height = 158

var resultsFlow

var itemsConfig

//bookkeeping for the item groups
var itemGroups = new Object()

function restore()
{
    itemsConfig = new Object()
    var configString = String(plasmoid.readConfig("ItemsGeometries"))

    //array, a cell for encoded item geometry
    var itemsStrings = configString.split(";")
    for (var i=0; i<itemsStrings.length; i++) {
        //[id, encoded geometry]
        var idConfig = itemsStrings[i].split(":")
        if (idConfig.length < 2) {
            continue
        }

        //array [x, y, width, height]
        var rect = idConfig[1].split(",")
        if (rect.length < 4) {
            continue
        }
        var geomObject = new Object()
        geomObject.x = rect[0]
        geomObject.y = rect[1]
        geomObject.width = rect[2]
        geomObject.height = rect[3]
        itemsConfig[idConfig[0]] = geomObject
    }

}

function save()
{
    var configString = String()

    for (id in itemsConfig) {
        var rect = itemsConfig[id]
        configString += id + ":" + rect.x + "," + rect.y + "," + rect.width + "," + rect.height + ";"
    }

    print("saving "+configString)
    plasmoid.writeConfig("ItemsGeometries", configString)
}

function resetPositions()
{
    positions = new Array()
}

//returns the available size at a given position
function availableSpace(x, y, width, height)
{
    var row = Math.round(x/cellSize.width)
    var column = Math.round(y/cellSize.height)
    var rowsWidth = Math.ceil(width/cellSize.width)
    var columnsHeight = Math.ceil(height/cellSize.height)

    var availableSize = new Object
    availableSize.width = 0
    availableSize.height = 0

    if (x < 0 || y < 0) {
        return availableSize;
    } else if (positions[row] == undefined) {
        availableSize.width = width
        availableSize.height = height
        return availableSize;
    } else if (!positions[row][column]) {

        for (var w=0; w<rowsWidth; w++) {
            //occupied?
            if (!positions[row+w] || !positions[row+w][column]) {
                availableSize.width = w+1
            } else {
                break;
            }
        }

        for (var h=0; h<columnsHeight; h++) {
            //occupied?
            if (positions[row][column+h]) {
                //print("occupied"+row+" "+column+" "+h+" "+positions[row][column+h]+" "+availableSize.height)
                break;
            } else {
                availableSize.height = h+1
            }
        }
    }

    availableSize.width *= cellSize.width
    availableSize.height *= cellSize.height

    //don't make it overflow
    availableSize.width = Math.min(availableSize.width,
                                   (resultsFlow.width-row*cellSize.width))

    return availableSize
}

function setSpaceAvailable(x, y, width, height, available)
{
    var row = Math.round(x/cellSize.width)
    var column = Math.round(y/cellSize.height)
    var rowsWidth = Math.round(width/cellSize.width)
    var columnsHeight = Math.round(height/cellSize.height)

    for (var i = row; i<row+rowsWidth; ++i) {
        if (!positions[i]) {
            positions[i] = new Array()
        }
        for (var j = column; j<column+columnsHeight; ++j) {
            positions[i][j] = !available
            print("set "+i+" "+j+" "+!available)
        }
    }
}

function normalizeItemPosition(item)
{
    var x = Math.max(0, Math.round(item.x/cellSize.width)*cellSize.width)
    var y = Math.max(0, Math.round(item.y/cellSize.height)*cellSize.height)

    var width = Math.max(cellSize.width, Math.round(item.width/cellSize.width)*cellSize.width)
    var height = Math.max(cellSize.height, Math.round(item.height/cellSize.height)*cellSize.height)

    item.x = x
    item.y = y
    /*item.width = width
    item.height = height*/
}

function positionItem(item)
{
    var x = Math.max(0, Math.round(item.x/cellSize.width)*cellSize.width)
    var y = Math.max(0, Math.round(item.y/cellSize.height)*cellSize.height)

    var forwardX = x
    var forwardY = y
    var backX = x - cellSize.width
    var backY = y
    var avail

    while (1) {
        //look forward
        var forwardAvail = availableSpace(forwardX, forwardY,
                                          Math.max(item.minimumWidth, item.width),
                                          Math.max(item.minimumHeight, item.height))
        print("checking forward "+forwardX/cellSize.width+" "+forwardY/cellSize.height+" "+forwardAvail.width/cellSize.width+" "+forwardAvail.height/cellSize.height)

        if (forwardAvail.width >= item.minimumWidth &&
            forwardAvail.height >= item.minimumHeight) {
            x = forwardX
            y = forwardY
            avail = forwardAvail
            break
        }
        forwardX += cellSize.width
        //new line
        if (forwardX+item.width > resultsFlow.width) {
            forwardX = 0
            forwardY += cellSize.height
            //forward positions exausted
            //scrolling now
            /*if (forwardY > resultsFlow.height) {
                break;
            }*/
        }

        //backwards positions exausted
        if (backY < 0) {
            continue
        }

        //look backwards
        var backAvail = availableSpace(backX, backY,
                                       Math.max(item.minimumWidth, item.width),
                                       Math.max(item.minimumHeight, item.height))
        print("checking backwards "+backX/cellSize.width+" "+backY/cellSize.height+" "+backAvail.width/cellSize.width+" "+backAvail.height/cellSize.height)

        if (backAvail.width >= item.minimumWidth &&
            backAvail.height >= item.minimumHeight) {
            x = backX
            y = backY
            avail = backAvail
            break
        }
        backX -= cellSize.width
        if (backX < 0) {
            backX = resultsFlow.width - item.width
            backY -= cellSize.height
        }
    }

    var width = Math.max(cellSize.width*Math.max(1, Math.ceil(item.minimumWidth/cellSize.width)),
                         Math.round(Math.min(avail.width, item.width)/cellSize.width)*cellSize.width)
    var height = Math.max(cellSize.height*Math.max(1, Math.ceil(item.minimumHeight/cellSize.height)),
                          Math.round(Math.min(avail.height, item.height)/cellSize.height)*cellSize.height)

    setSpaceAvailable(x, y, width, height, false)
    item.x = x
    item.y = y
    //resultsFlow.height = Math.max(resultsFlow.height, y+cellSize.height)

    item.width = width
    item.height = height

    var rect = new Object()
    rect.x = item.x
    rect.y = item.y
    rect.width = item.width
    rect.height = item.height
    itemsConfig[item.category] = rect
    save()
}

<commit_msg>don't overlap plasmoids over boxes<commit_after>/*
 *   Copyright 2011 Marco Martin <mart@kde.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License as
 *   published by the Free Software Foundation; either version 2, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

.pragma library

var positions = new Array()

var cellSize = new Object()
cellSize.width = 178
cellSize.height = 158

var resultsFlow

var itemsConfig

//bookkeeping for the item groups
var itemGroups = new Object()

function restore()
{
    itemsConfig = new Object()
    var configString = String(plasmoid.readConfig("ItemsGeometries"))

    //array, a cell for encoded item geometry
    var itemsStrings = configString.split(";")
    for (var i=0; i<itemsStrings.length; i++) {
        //[id, encoded geometry]
        var idConfig = itemsStrings[i].split(":")
        if (idConfig.length < 2) {
            continue
        }

        //array [x, y, width, height]
        var rect = idConfig[1].split(",")
        if (rect.length < 4) {
            continue
        }
        var geomObject = new Object()
        geomObject.x = rect[0]
        geomObject.y = rect[1]
        geomObject.width = rect[2]
        geomObject.height = rect[3]
        itemsConfig[idConfig[0]] = geomObject
    }

}

function save()
{
    var configString = String()

    for (id in itemsConfig) {
        var rect = itemsConfig[id]
        configString += id + ":" + rect.x + "," + rect.y + "," + rect.width + "," + rect.height + ";"
    }

    print("saving "+configString)
    plasmoid.writeConfig("ItemsGeometries", configString)
}

function resetPositions()
{
    positions = new Array()
}

//returns the available size at a given position
function availableSpace(x, y, width, height)
{
    var row = Math.round(x/cellSize.width)
    var column = Math.round(y/cellSize.height)
    var rowsWidth = Math.ceil(width/cellSize.width)
    var columnsHeight = Math.ceil(height/cellSize.height)

    var availableSize = new Object
    availableSize.width = 0
    availableSize.height = 0

    if (x < 0 || y < 0) {
        return availableSize;
    } else if (positions[row] == undefined) {
        availableSize.width = width
        availableSize.height = height
        return availableSize;
    } else if (!positions[row][column]) {

        for (var w=0; w<rowsWidth; w++) {
            //occupied?
            var free = true;
            for (var i = column; i < column+columnsHeight; ++i) {
                if (positions[row+w] && positions[row+w][i]) {
                    free = false;
                    break;
                }
            }
            if (free) {
                availableSize.width = w+1
            } else {
                break;
            }
        }

        for (var h=0; h<columnsHeight; h++) {
            //occupied?
            if (positions[row][column+h]) {
                //print("occupied"+row+" "+column+" "+h+" "+positions[row][column+h]+" "+availableSize.height)
                break;
            } else {
                availableSize.height = h+1
            }
        }
    }

    availableSize.width *= cellSize.width
    availableSize.height *= cellSize.height

    //don't make it overflow
    availableSize.width = Math.min(availableSize.width,
                                   (resultsFlow.width-row*cellSize.width))

    return availableSize
}

function setSpaceAvailable(x, y, width, height, available)
{
    var row = Math.round(x/cellSize.width)
    var column = Math.round(y/cellSize.height)
    var rowsWidth = Math.round(width/cellSize.width)
    var columnsHeight = Math.round(height/cellSize.height)

    for (var i = row; i<row+rowsWidth; ++i) {
        if (!positions[i]) {
            positions[i] = new Array()
        }
        for (var j = column; j<column+columnsHeight; ++j) {
            positions[i][j] = !available
            print("set "+i+" "+j+" "+!available)
        }
    }
}

function normalizeItemPosition(item)
{
    var x = Math.max(0, Math.round(item.x/cellSize.width)*cellSize.width)
    var y = Math.max(0, Math.round(item.y/cellSize.height)*cellSize.height)

    var width = Math.max(cellSize.width, Math.round(item.width/cellSize.width)*cellSize.width)
    var height = Math.max(cellSize.height, Math.round(item.height/cellSize.height)*cellSize.height)

    item.x = x
    item.y = y
    /*item.width = width
    item.height = height*/
}

function positionItem(item)
{
    var x = Math.max(0, Math.round(item.x/cellSize.width)*cellSize.width)
    var y = Math.max(0, Math.round(item.y/cellSize.height)*cellSize.height)

    var forwardX = x
    var forwardY = y
    var backX = x - cellSize.width
    var backY = y
    var avail

    while (1) {
        //look forward
        var forwardAvail = availableSpace(forwardX, forwardY,
                                          Math.max(item.minimumWidth, item.width),
                                          Math.max(item.minimumHeight, item.height))
        print("checking forward "+forwardX/cellSize.width+" "+forwardY/cellSize.height+" "+forwardAvail.width/cellSize.width+" "+forwardAvail.height/cellSize.height)

        if (forwardAvail.width >= item.minimumWidth &&
            forwardAvail.height >= item.minimumHeight) {
            x = forwardX
            y = forwardY
            avail = forwardAvail
            break
        }
        forwardX += cellSize.width
        //new line
        if (forwardX+item.width > resultsFlow.width) {
            forwardX = 0
            forwardY += cellSize.height
            //forward positions exausted
            //scrolling now
            /*if (forwardY > resultsFlow.height) {
                break;
            }*/
        }

        //backwards positions exausted
        if (backY < 0) {
            continue
        }

        //look backwards
        var backAvail = availableSpace(backX, backY,
                                       Math.max(item.minimumWidth, item.width),
                                       Math.max(item.minimumHeight, item.height))
        print("checking backwards "+backX/cellSize.width+" "+backY/cellSize.height+" "+backAvail.width/cellSize.width+" "+backAvail.height/cellSize.height)

        if (backAvail.width >= item.minimumWidth &&
            backAvail.height >= item.minimumHeight) {
            x = backX
            y = backY
            avail = backAvail
            break
        }
        backX -= cellSize.width
        if (backX < 0) {
            backX = resultsFlow.width - item.width
            backY -= cellSize.height
        }
    }

    var width = Math.max(cellSize.width*Math.max(1, Math.ceil(item.minimumWidth/cellSize.width)),
                         Math.round(Math.min(avail.width, item.width)/cellSize.width)*cellSize.width)
    var height = Math.max(cellSize.height*Math.max(1, Math.ceil(item.minimumHeight/cellSize.height)),
                          Math.round(Math.min(avail.height, item.height)/cellSize.height)*cellSize.height)

    setSpaceAvailable(x, y, width, height, false)
    item.x = x
    item.y = y
    //resultsFlow.height = Math.max(resultsFlow.height, y+cellSize.height)

    item.width = width
    item.height = height

    var rect = new Object()
    rect.x = item.x
    rect.y = item.y
    rect.width = item.width
    rect.height = item.height
    itemsConfig[item.category] = rect
    save()
}

<|endoftext|>


<commit_before>(function () {
	'use strict';
//Global variables.
var configured = false;
var userloc, res_upkeep, res_production, amount_max, amount_min, buy_price, sell_price, time, amount;

function configure() {
	if (!configured) {
		document.defaultView.addEventListener( 'message', onGameMessage );
		var script = document.createElement( 'script' );
		script.type = 'text/javascript';
		script.textContent = "(function() {var fn=function(){window.postMessage({pardus_copilot:1,\
		loc:typeof(userloc)=='undefined'?null:userloc,\
		res_upkeep:typeof(res_upkeep)=='undefined'?null:res_upkeep,\
		res_production:typeof(res_production)=='undefined'?null:res_production,\
		amount_max:typeof(amount_max)=='undefined'?null:amount_max,\
		amount_min:typeof(amount_min)=='undefined'?null:amount_min,\
		player_buy_price:typeof(player_buy_price)=='undefined'?null:player_buy_price,\
		player_sell_price:typeof(player_sell_price)=='undefined'?null:player_sell_price,\
		time:typeof(milliTime)=='undefined'?null:milliTime,\
		amount:typeof(amount)=='undefined'?null:amount,\
		},window.location.origin);};if(typeof(addUserFunction)=='function')addUserFunction(fn);fn();})();";
		document.body.appendChild( script );
		configured = true;
		}
	}

// Arrival of a message means the page contents were updated.  The
// message contains the value of our variables, too.
function onGameMessage( event ) {
	var data = event.data;

	if ( !data || data.pardus_copilot != 1 ) {
		return;
	}

	userloc = parseInt( data.loc );
	res_upkeep = data.res_upkeep;
	res_production = data.res_production;
	amount_max = data.amount_max;
	amount_min = data.amount_min;
	buy_price = data.player_buy_price;
	sell_price = data.player_sell_price;
	time = data.time;
	amount = data.amount;
}

function Building(loc,owner,res_upkeep,res_production,amount,amount_max,amount_min,buy_price, sell_price,time) {
	this.loc = loc;
	this.owner = "tbd";
	this.res_upkeep = res_upkeep;
	this.res_production = res_production;
	this.amount = amount;
	this.amount_max = amount_max;
	this.amount_min = amount_min;
	this.buy_price = buy_price;
	this.sell_price = sell_price;
	this.time = time;
  /*this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };*/

}

function addTrackerButtons() {
	// We add track/untrack buttons on the trade screen.
	var transferButton = findTransferButton();

	function addButton(name,listener) {
		//Adds button below the quickbuttons.
		//Initially there were two, I decided a single track/untrack button was more elegant.
		var new_button = document.createElement("input");
		new_button.setAttribute('style','width: 175px; height: 35px; margin-left: 3px; margin-right: 3px;');
		new_button.setAttribute('type','button');
		new_button.setAttribute('value',name);
		new_button.setAttribute('id',name+'Button');
		new_button.addEventListener('click',listener);
		transferButton.parentNode.appendChild(document.createElement('br'));
		transferButton.parentNode.appendChild(document.createElement('br'));
		transferButton.parentNode.appendChild(new_button);
	}

	addButton('Clear',clear);
	chrome.storage.local.get("buildingList",addTracker)
	function addTracker(data) {
		if (checkBuildingSaved(data)[0]) {
			saveBuilding();
			addButton('Untrack',buildingTracker);
		} else {
			addButton('Track',buildingTracker);
		}
	}

}

function clear() {
	chrome.storage.local.clear();
}

function checkBuildingSaved(data) {
	var index;
	var saved = false;
	if (!!data.buildingList) {
		for (var i = 0; i < data.buildingList.length; i++) {
			if (data.buildingList[i] === userloc) {
				saved = true;
				index = i;
			}
		}

	}
	// Returns true if we have data of the building.
	console.log(saved);
	return [saved, index];
}

function toggleButton(btn) {
	if (btn.getAttribute('value') === 'Track') {
		btn.setAttribute('value','Untrack');
	}
	else {
		btn.setAttribute('value','Track');
	}
}

function buildingTracker() {
	if (this.value === "Track") {
		chrome.storage.local.get("buildingList",addBuilding)

		function addBuilding(data) {
			//We're adding a building to the tracker here.
			//So first check if we have a list at all. Not sure if this is really required.
			if (!data.buildingList) {
				var list = [];
				list[0] = userloc;
				chrome.storage.local.set({"buildingList":list})
			} //If we have a list, we add the building if it's not there yet.
			else {
				if (!checkBuildingSaved(data)[0]) {
					data.buildingList.push(userloc);
					chrome.storage.local.set({"buildingList":data.buildingList});
				}

			}
			// You pressed track so you get all the stuffz saved. Owner is not yet there, saving some space anyway.
			saveBuilding();
		}
	}

	else {
		chrome.storage.local.get("buildingList",removeBuilding);
		function removeBuilding(data) {
			data.buildingList.splice(checkBuildingSaved(data)[1],1);
			chrome.storage.local.remove("building"+userloc.toString())
			chrome.storage.local.set({"buildingList":data.buildingList});
		}
	}
	toggleButton(this);
}

function findTransferButton() {
	// Function finds the transfer button since Pardus sadly gave it
	// neither ID nor name, so we have to check all input elements for
	// the value '<- Transfer ->'
	var inputs = document.getElementsByTagName("input");
	var transferButton;
	for (var i = 0; i < inputs.length ; i++) {
		if (inputs[i].value === "<- Transfer ->"){
			transferButton = inputs[i];
		}
	}
	return transferButton;
}

function saveBuilding() {
	var buildingData = new Building(userloc,"",res_upkeep,res_production,amount,amount_max,amount_min,buy_price, sell_price,time);
	var buildingId = "building" + userloc.toString();
	var items = new Object();
	items[buildingId] = JSON.stringify(buildingData);
	console.log('saveBuilding', items);
	chrome.storage.local.set(items);
}

configure();
addTrackerButtons();

})();
<commit_msg>Removing debugging options.<commit_after>(function () {
	'use strict';
//Global variables.
var configured = false;
var userloc, res_upkeep, res_production, amount_max, amount_min, buy_price, sell_price, time, amount;

function configure() {
	if (!configured) {
		document.defaultView.addEventListener( 'message', onGameMessage );
		var script = document.createElement( 'script' );
		script.type = 'text/javascript';
		script.textContent = "(function() {var fn=function(){window.postMessage({pardus_copilot:1,\
		loc:typeof(userloc)=='undefined'?null:userloc,\
		res_upkeep:typeof(res_upkeep)=='undefined'?null:res_upkeep,\
		res_production:typeof(res_production)=='undefined'?null:res_production,\
		amount_max:typeof(amount_max)=='undefined'?null:amount_max,\
		amount_min:typeof(amount_min)=='undefined'?null:amount_min,\
		player_buy_price:typeof(player_buy_price)=='undefined'?null:player_buy_price,\
		player_sell_price:typeof(player_sell_price)=='undefined'?null:player_sell_price,\
		time:typeof(milliTime)=='undefined'?null:milliTime,\
		amount:typeof(amount)=='undefined'?null:amount,\
		},window.location.origin);};if(typeof(addUserFunction)=='function')addUserFunction(fn);fn();})();";
		document.body.appendChild( script );
		configured = true;
		}
	}

// Arrival of a message means the page contents were updated.  The
// message contains the value of our variables, too.
function onGameMessage( event ) {
	var data = event.data;

	if ( !data || data.pardus_copilot != 1 ) {
		return;
	}

	userloc = parseInt( data.loc );
	res_upkeep = data.res_upkeep;
	res_production = data.res_production;
	amount_max = data.amount_max;
	amount_min = data.amount_min;
	buy_price = data.player_buy_price;
	sell_price = data.player_sell_price;
	time = data.time;
	amount = data.amount;
}

function Building(loc,owner,res_upkeep,res_production,amount,amount_max,amount_min,buy_price, sell_price,time) {
	this.loc = loc;
	this.owner = "tbd";
	this.res_upkeep = res_upkeep;
	this.res_production = res_production;
	this.amount = amount;
	this.amount_max = amount_max;
	this.amount_min = amount_min;
	this.buy_price = buy_price;
	this.sell_price = sell_price;
	this.time = time;
  /*this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };*/

}

function addTrackerButtons() {
	// We add track/untrack buttons on the trade screen.
	var transferButton = findTransferButton();

	function addButton(name,listener) {
		//Adds button below the quickbuttons.
		//Initially there were two, I decided a single track/untrack button was more elegant.
		var new_button = document.createElement("input");
		new_button.setAttribute('style','width: 175px; height: 35px; margin-left: 3px; margin-right: 3px;');
		new_button.setAttribute('type','button');
		new_button.setAttribute('value',name);
		new_button.setAttribute('id',name+'Button');
		new_button.addEventListener('click',listener);
		transferButton.parentNode.appendChild(document.createElement('br'));
		transferButton.parentNode.appendChild(document.createElement('br'));
		transferButton.parentNode.appendChild(new_button);
	}

	//addButton('Clear',clear);
	chrome.storage.local.get("buildingList",addTracker)
	function addTracker(data) {
		if (checkBuildingSaved(data)[0]) {
			saveBuilding();
			addButton('Untrack',buildingTracker);
		} else {
			addButton('Track',buildingTracker);
		}
	}

}
/*
function clear() {
	chrome.storage.local.clear();
}*/

function checkBuildingSaved(data) {
	var index;
	var saved = false;
	if (!!data.buildingList) {
		for (var i = 0; i < data.buildingList.length; i++) {
			if (data.buildingList[i] === userloc) {
				saved = true;
				index = i;
			}
		}

	}
	// Returns true if we have data of the building.
	//console.log(saved);
	return [saved, index];
}

function toggleButton(btn) {
	if (btn.getAttribute('value') === 'Track') {
		btn.setAttribute('value','Untrack');
	}
	else {
		btn.setAttribute('value','Track');
	}
}

function buildingTracker() {
	if (this.value === "Track") {
		chrome.storage.local.get("buildingList",addBuilding)

		function addBuilding(data) {
			//We're adding a building to the tracker here.
			//So first check if we have a list at all. Not sure if this is really required.
			if (!data.buildingList) {
				var list = [];
				list[0] = userloc;
				chrome.storage.local.set({"buildingList":list})
			} //If we have a list, we add the building if it's not there yet.
			else {
				if (!checkBuildingSaved(data)[0]) {
					data.buildingList.push(userloc);
					chrome.storage.local.set({"buildingList":data.buildingList});
				}

			}
			// You pressed track so you get all the stuffz saved. Owner is not yet there, saving some space anyway.
			saveBuilding();
		}
	}

	else {
		chrome.storage.local.get("buildingList",removeBuilding);
		function removeBuilding(data) {
			data.buildingList.splice(checkBuildingSaved(data)[1],1);
			chrome.storage.local.remove("building"+userloc.toString())
			chrome.storage.local.set({"buildingList":data.buildingList});
		}
	}
	toggleButton(this);
}

function findTransferButton() {
	// Function finds the transfer button since Pardus sadly gave it
	// neither ID nor name, so we have to check all input elements for
	// the value '<- Transfer ->'
	var inputs = document.getElementsByTagName("input");
	var transferButton;
	for (var i = 0; i < inputs.length ; i++) {
		if (inputs[i].value === "<- Transfer ->"){
			transferButton = inputs[i];
		}
	}
	return transferButton;
}

function saveBuilding() {
	var buildingData = new Building(userloc,"",res_upkeep,res_production,amount,amount_max,amount_min,buy_price, sell_price,time);
	var buildingId = "building" + userloc.toString();
	var items = new Object();
	items[buildingId] = JSON.stringify(buildingData);
	//console.log('saveBuilding', items);
	chrome.storage.local.set(items);
}

configure();
addTrackerButtons();

})();
<|endoftext|>


<commit_before>'use strict';

angular.module('ui.utils.masks.global.number', [
	'ui.utils.masks.helpers'
])
.directive('uiNumberMask',
	['$locale', '$parse', 'PreFormatters', 'NumberMasks', 'NumberValidators',
	function ($locale, $parse, PreFormatters, NumberMasks, NumberValidators) {
		return {
			restrict: 'A',
			require: 'ngModel',
			link: function (scope, element, attrs, ctrl) {
				var decimalDelimiter = $locale.NUMBER_FORMATS.DECIMAL_SEP,
					thousandsDelimiter = $locale.NUMBER_FORMATS.GROUP_SEP,
					decimals = $parse(attrs.uiNumberMask)(scope);

				if (angular.isDefined(attrs.uiHideGroupSep)){
					thousandsDelimiter = '';
				}

				if(isNaN(decimals)) {
					decimals = 2;
				}

				var viewMask = NumberMasks.viewMask(decimals, decimalDelimiter, thousandsDelimiter),
					modelMask = NumberMasks.modelMask(decimals);

				function parse(value) {
					if(!value) {
						return value;
					}

					var valueToFormat = PreFormatters.clearDelimitersAndLeadingZeros(value) || '0';
					var formatedValue = viewMask.apply(valueToFormat);
					var actualNumber = parseFloat(modelMask.apply(valueToFormat));

					if(angular.isDefined(attrs.uiNegativeNumber)){
						var isNegative = (value[0] === '-'),
							needsToInvertSign = (value.slice(-1) === '-');

						//only apply the minus sign if it is negative or(exclusive)
						//needs to be negative and the number is different from zero
						if(needsToInvertSign ^ isNegative && !!actualNumber) {
							actualNumber *= -1;
							formatedValue = '-' + formatedValue;
						}
					}

					if (ctrl.$viewValue !== formatedValue) {
						ctrl.$setViewValue(formatedValue);
						ctrl.$render();
					}

					return actualNumber;
				}

				ctrl.$formatters.push(function(value) {
					var prefix = '';
					if(angular.isDefined(attrs.uiNegativeNumber) && value < 0){
						prefix = '-';
					}

					if(!value) {
						return value;
					}

					var valueToFormat = PreFormatters.prepareNumberToFormatter(value, decimals);
					return prefix + viewMask.apply(valueToFormat);
				});

				ctrl.$parsers.push(parse);

				if (attrs.uiNumberMask) {
					scope.$watch(attrs.uiNumberMask, function(decimals) {
						if(isNaN(decimals)) {
							decimals = 2;
						}
						viewMask = NumberMasks.viewMask(decimals, decimalDelimiter, thousandsDelimiter);
						modelMask = NumberMasks.modelMask(decimals);

						parse(ctrl.$viewValue || '');
					});
				}

				if(attrs.min){
					ctrl.$parsers.push(function(value) {
						var min = $parse(attrs.min)(scope);
						return NumberValidators.minNumber(ctrl, value, min);
					});

					scope.$watch(attrs.min, function(value) {
						NumberValidators.minNumber(ctrl, ctrl.$modelValue, value);
					});
				}

				if(attrs.max) {
					ctrl.$parsers.push(function(value) {
						var max = $parse(attrs.max)(scope);
						return NumberValidators.maxNumber(ctrl, value, max);
					});

					scope.$watch(attrs.max, function(value) {
						NumberValidators.maxNumber(ctrl, ctrl.$modelValue, value);
					});
				}
			}
		};
	}
]);
<commit_msg>fix(number): fix the result for 0 and other edge cases<commit_after>'use strict';

angular.module('ui.utils.masks.global.number', [
	'ui.utils.masks.helpers'
])
.directive('uiNumberMask',
	['$locale', '$parse', 'PreFormatters', 'NumberMasks', 'NumberValidators',
	function ($locale, $parse, PreFormatters, NumberMasks, NumberValidators) {
		return {
			restrict: 'A',
			require: 'ngModel',
			link: function (scope, element, attrs, ctrl) {
				var decimalDelimiter = $locale.NUMBER_FORMATS.DECIMAL_SEP,
					thousandsDelimiter = $locale.NUMBER_FORMATS.GROUP_SEP,
					decimals = $parse(attrs.uiNumberMask)(scope);

				if (angular.isDefined(attrs.uiHideGroupSep)){
					thousandsDelimiter = '';
				}

				if(isNaN(decimals)) {
					decimals = 2;
				}

				var viewMask = NumberMasks.viewMask(decimals, decimalDelimiter, thousandsDelimiter),
					modelMask = NumberMasks.modelMask(decimals);

				function parser(value) {
					if(ctrl.$isEmpty(value)) {
						return value;
					}

					var valueToFormat = PreFormatters.clearDelimitersAndLeadingZeros(value) || '0';
					var formatedValue = viewMask.apply(valueToFormat);
					var actualNumber = parseFloat(modelMask.apply(valueToFormat));

					if(angular.isDefined(attrs.uiNegativeNumber)){
						var isNegative = (value[0] === '-'),
							needsToInvertSign = (value.slice(-1) === '-');

						//only apply the minus sign if it is negative or(exclusive)
						//needs to be negative and the number is different from zero
						if(needsToInvertSign ^ isNegative && !!actualNumber) {
							actualNumber *= -1;
							formatedValue = '-' + formatedValue;
						}
					}

					if (ctrl.$viewValue !== formatedValue) {
						ctrl.$setViewValue(formatedValue);
						ctrl.$render();
					}

					return actualNumber;
				}

				function formatter(value) {
					if(ctrl.$isEmpty(value)) {
						return value;
					}

					var prefix = '';
					if(angular.isDefined(attrs.uiNegativeNumber) && value < 0){
						prefix = '-';
					}

					var valueToFormat = PreFormatters.prepareNumberToFormatter(value, decimals);
					return prefix + viewMask.apply(valueToFormat);
				}

				ctrl.$formatters.push(formatter);
				ctrl.$parsers.push(parser);

				if (attrs.uiNumberMask) {
					scope.$watch(attrs.uiNumberMask, function(decimals) {
						if(isNaN(decimals)) {
							decimals = 2;
						}
						viewMask = NumberMasks.viewMask(decimals, decimalDelimiter, thousandsDelimiter);
						modelMask = NumberMasks.modelMask(decimals);

						parser(ctrl.$viewValue);
					});
				}

				if(attrs.min){
					ctrl.$parsers.push(function(value) {
						var min = $parse(attrs.min)(scope);
						return NumberValidators.minNumber(ctrl, value, min);
					});

					scope.$watch(attrs.min, function(value) {
						NumberValidators.minNumber(ctrl, ctrl.$modelValue, value);
					});
				}

				if(attrs.max) {
					ctrl.$parsers.push(function(value) {
						var max = $parse(attrs.max)(scope);
						return NumberValidators.maxNumber(ctrl, value, max);
					});

					scope.$watch(attrs.max, function(value) {
						NumberValidators.maxNumber(ctrl, ctrl.$modelValue, value);
					});
				}
			}
		};
	}
]);
<|endoftext|>


<commit_before>/**
 * @fileOverview Locale module for restartless addons
 * @author       SHIMODA "Piro" Hiroshi
 * @version      3
 *
 * @license
 *   The MIT License, Copyright (c) 2010-2011 SHIMODA "Piro" Hiroshi.
 *   https://github.com/piroor/restartless/blob/master/license.txt
 * @url http://github.com/piroor/restartless
 */

const EXPORTED_SYMBOLS = ['get'];

const DEFAULT_LOCALE = 'en-US';

var gCache = {}
var get = function(aPath, aBaseURI) {
		if (/^\w+:/.test(aPath))
			aBaseURI = aPath;

		var locale = DEFAULT_LOCALE;
		try {
			let prefs = Cc['@mozilla.org/preferences;1'].getService(Ci.nsIPrefBranch);
			locale = prefs.getCharPref('general.useragent.locale');
			if (/\w+:/.test(locale))
				locale = prefs.getComplexValue('general.useragent.locale', Ci.nsIPrefLocalizedString).data;
			locale = locale || DEFAULT_LOCALE;
		}
		catch(e) {
		dump(e+'\n');
		}
		var uri = aPath;
		[
			aPath+'.'+locale,
			aPath+'.'+(locale.split('-')[0]),
			aPath+'.'+DEFAULT_LOCALE,
			aPath+'.'+(DEFAULT_LOCALE.split('-')[0])
		].some(function(aURI) {
			var resolved = exists(aURI, aBaseURI);
			if (resolved) {
				uri = resolved;
				return true;
			}
			return false;
		});

		if (!(uri in gCache)) {
			gCache[uri] = new StringBundle(uri);
		}
		return gCache[uri];
	};
exports.get = get;

const Service = Cc['@mozilla.org/intl/stringbundle;1']
					.getService(Ci.nsIStringBundleService);

function StringBundle(aURI)
{
	this._bundle = Service.createBundle(aURI);
}
StringBundle.prototype = {
	getString : function(aKey) {
		try {
			return this._bundle.GetStringFromName(aKey);
		}
		catch(e) {
		}
		return '';
	},
	getFormattedString : function(aKey, aArray) {
		try {
			return this._bundle.formatStringFromName(aKey, aArray, aArray.length);
		}
		catch(e) {
		}
		return '';
	},
	get strings() {
		return this._bundle.getSimpleEnumeration();
	}
};

/** A handler for bootstrap.js */
function shutdown()
{
	gCache = {};
	Service.flushBundles();
}
<commit_msg>locale should export the object "locale" instead of the function "get".<commit_after>/**
 * @fileOverview Locale module for restartless addons
 * @author       SHIMODA "Piro" Hiroshi
 * @version      4
 *
 * @license
 *   The MIT License, Copyright (c) 2010-2011 SHIMODA "Piro" Hiroshi.
 *   https://github.com/piroor/restartless/blob/master/license.txt
 * @url http://github.com/piroor/restartless
 */

const EXPORTED_SYMBOLS = ['locale'];

const DEFAULT_LOCALE = 'en-US';

var gCache = {}
var get = function(aPath, aBaseURI) {
		if (/^\w+:/.test(aPath))
			aBaseURI = aPath;

		var locale = DEFAULT_LOCALE;
		try {
			let prefs = Cc['@mozilla.org/preferences;1'].getService(Ci.nsIPrefBranch);
			locale = prefs.getCharPref('general.useragent.locale');
			if (/\w+:/.test(locale))
				locale = prefs.getComplexValue('general.useragent.locale', Ci.nsIPrefLocalizedString).data;
			locale = locale || DEFAULT_LOCALE;
		}
		catch(e) {
		dump(e+'\n');
		}
		var uri = aPath;
		[
			aPath+'.'+locale,
			aPath+'.'+(locale.split('-')[0]),
			aPath+'.'+DEFAULT_LOCALE,
			aPath+'.'+(DEFAULT_LOCALE.split('-')[0])
		].some(function(aURI) {
			var resolved = exists(aURI, aBaseURI);
			if (resolved) {
				uri = resolved;
				return true;
			}
			return false;
		});

		if (!(uri in gCache)) {
			gCache[uri] = new StringBundle(uri);
		}
		return gCache[uri];
	};
exports.get = get;

var locale = { 'get' : get };

const Service = Cc['@mozilla.org/intl/stringbundle;1']
					.getService(Ci.nsIStringBundleService);

function StringBundle(aURI)
{
	this._bundle = Service.createBundle(aURI);
}
StringBundle.prototype = {
	getString : function(aKey) {
		try {
			return this._bundle.GetStringFromName(aKey);
		}
		catch(e) {
		}
		return '';
	},
	getFormattedString : function(aKey, aArray) {
		try {
			return this._bundle.formatStringFromName(aKey, aArray, aArray.length);
		}
		catch(e) {
		}
		return '';
	},
	get strings() {
		return this._bundle.getSimpleEnumeration();
	}
};

/** A handler for bootstrap.js */
function shutdown()
{
	gCache = {};
	Service.flushBundles();
}
<|endoftext|>