<commit_before>ig.module(
    'game.entities.player'
)
.requires(
    'impact.entity',
    'game.entities.projectiles.demonfang',
    'game.entities.projectiles.lightning',
    'game.entities.projectiles.fiercedemonfang'
)
.defines(function(){
    EntityPlayer = ig.Entity.extend({
        /* Collision Properties
         * type: What group does the player belong to?
         *  TYPE.A: Friendly
         *  TYPE.B: Enemy
         * checkAgainst: What entities do we check against?
         * collides: What happens if we collide with an entity?
        */
        type: ig.Entity.TYPE.A,
        checkAgainst: ig.Entity.TYPE.NONE,
        collides: ig.Entity.COLLIDES.ACTIVE,

        name: 'Kratos',

        /* Setup player properties */
        animSheet: new ig.AnimationSheet('media/kratos-d.png', 140, 100), // Animation sheet
        size: {x: 40, y: 50}, // Size of collision bounding box
        flip: true, // Set flip property to true
        accelGround: 200, // How fast we accelerate for movement on the ground
        accelAir: 310, // How fast we accelerate in the air
        jump: 360, // How high can we jump?
        friction: {x: 500, y: 0}, // Resistance against movement
        maxVel: {x: 100, y: 160}, // Cap our maximum velocity from acceleration
        attacking: false, // Boolean to control when we can attack
        startPosition: null, // Our starting position in the game world, used for respawning
        offset: {x: 50, y: 30},
        running: false,
        arte: null, // Which arte are we using?

        /* Player stats */
        // Just temporary for now
        stats : {
            str: 10,
            mag: 5,
            def: 9,
            spd: 10,
            totalExp: 0,
            nextExp: 10,
            level: 1,
            hp: 150,
            tp: 100,
            maxHP: 150,
            maxTP: 100,
        },

        skillPoints: 10, // How many skill points we have to allocate
        health: 150, // Override base health value
        tp: 100, // Technical Points

        init: function(x, y, settings){
            this.parent(x, y, settings);
            /* Set up player animations */

            /* this.addAnim(name, speed, frames)
             * name: string
             *  - the identifier for this animation
             * speed: number
             *  - how fast to iterate through frame cycle
             * frames: array
             *  - array of what frames to animate
            */

            this.addAnim('idle', 1, [1]);
            this.addAnim('walk', 0.10, [14, 15, 16, 17, 18, 19, 20]);
            this.addAnim('run', 0.10, [28, 29, 30, 31, 32, 33]);
            this.addAnim('jump', 0.10, [48]);
            this.addAnim('fall', 0.10, [48]);
            this.addAnim('lightningBlade', 0.10, [57, 58, 59, 60]);

            this.atkTimer = new ig.Timer(1.5);
            this.startPosition = {x:x, y:y};
            this.parent(x, y, settings);
        },

        update: function(){
            // Set up movement cases
            var accel = this.standing ? this.accelGround : this.accelAir;
            if(ig.input.state('left') && !ig.game.menuVisible){
                this.accel.x = -accel;
                this.flip = false;
                /*
                 *  Lightning blade framework
                 *  -------------------------
                 * Pressing left/right in combination with 'a' will trigger
                 * the lightning blade attack.
                 *
                 * Implementation
                 * --------------
                 * 1. Put timer on attack. This is to:
                 *      - Prevent spamming of arte (cooldown)
                 *      - Allow animations to finish
                 *      - Lock player into specific animation
                 * 2. If player has not attacked (!this.attacking):
                 *      - Initiate attack. Reset timer.
                 * 3. Until timer expires, we set attacking = true, preventing
                 *    additional triggers of Lightning Blade.
                 * 4. Once the timer expires, we reset the attacking boolean flag.
                 *
                 * TODO
                 * ----
                 * 1. Setup animation frames for Lightning blade
                */
                // Trigger Lightning blade facing left
                if(ig.input.state('attack') && !this.attacking){
                    this.atkTimer.reset();
                     ig.game.spawnEntity(EntityDemonFang, this.pos.x - 20, this.pos.y + 7, {flip: !this.flip});
                     this.tp -= 5;
                     this.currentAnim = this.anims.lightningBlade;
                    // ig.game.spawnEntity(EntityFierceDemonFang, this.pos.x - 30, this.pos.y + 4, {flip: !this.flip});
                    console.log('Lightning blade');
                    if(this.atkTimer.delta() < 0){
                        this.attacking = true;
                    }
                }
            } else if(ig.input.state('right') && !ig.game.menuVisible){
                this.accel.x = accel;
                this.flip = true;
                // Trigger lightning blade facing right
                if(ig.input.state('attack') && !this.attacking){
                    this.atkTimer.reset();
                    ig.game.spawnEntity(EntityDemonFang, this.pos.x + 40, this.pos.y + 7, {flip: !this.flip});
                    // ig.game.spawnEntity(EntityFierceDemonFang, this.pos.x + 20, this.pos.y + 4, {flip: !this.flip});
                    console.log('Lightning blade');
                    if(this.atkTimer.delta() < 0){
                        this.attacking = true;
                        this.arte = 'lightning_blade';
                    }
                }
            } else if(ig.input.state('down') && !ig.game.menuVisible){
                if(ig.input.state('attack') && !this.attacking){
                    this.atkTimer.reset();
                    console.log('Casting Spell');
                    ig.game.spawnEntity(EntityLightning, this.pos.x + 40, this.pos.y - 40, {flip: !this.flip});
                    ig.game.spawnEntity(EntityLightning, this.pos.x + 30, this.pos.y - 40, {flip: !this.flip});
                    ig.game.spawnEntity(EntityLightning, this.pos.x + 20, this.pos.y - 40, {flip: !this.flip});
                    if(this.atkTimer.delta() < 0){
                        this.attacking = true;
                    }
                }

             } else if(ig.input.state('up') && !ig.game.menuVisible){
                // Stop the player
                this.accel.x = 0;
                if(ig.input.state('attack') && !this.attacking){
                    this.atkTimer.reset();
                    console.log('Hell Pyre');
                    if(this.atkTimer.delta() < 0){
                        this.attacking = true;
                    }
                }

             } else {
                // If we aren't moving in any direction, we must
                // be standing still. Therefore, accel = 0
                this.accel.x = 0;
            }

            // Used to reset attack timer after time has elasped.
            // Once the timer has expired, we can attack again
            if(this.atkTimer.delta() > 0){
                this.attacking = false;
            }

            // If the player is using an arte, stop them in place
            // The player will be stopped based on this.atkTimer
            // NOTE: this is also useful for spell casting cooldowns
            if(this.attacking){
                // Stop the player
                this.accel.x = 0;
            }

            // Jumping logic: CASE 1
            if(this.standing && ig.input.state('jump') && !ig.game.menuVisible) {
                if(this.vel.y == 0) {
                    this.vel.y = -this.jump;
                    this.falling = false;
                }
            }

            // Jumping logic: CASE 2
            else if(!this.standing && !ig.input.state('jump') && !this.falling && !ig.game.menuVisible){
                this.vel.y = Math.floor(this.vel.y/3);
                this.falling = true;
            }

            // Flip the player based on left/right movement
            this.currentAnim.flip.x = this.flip;

            this.parent();

            if(this.attacking === true && this.arte === 'lightning_blade'){
                console.log('should display animation');
                this.currentAnim = this.anims.lightningBlade;
                // TODO: Lock animation to repeat frame
            }
            // Animate player based on velocity
            // This may be refactored later

            // CASE 1: Y-velocity is negative and we aren't standing...
            //         therefore we are jumping.
            if(this.vel.y < 0 && !this.standing && !this.attacking)
                this.currentAnim = this.anims.jump;
            // CASE 2: Y-velocity is positive and we aren't standing...
            //         Y-velocity is only positive when falling
            else if(this.vel.y > 0 && !this.standing && !this.attacking)
                this.currentAnim = this.anims.fall;
            // CASE 3: X-velocity is not zero, we must be moving
            else if(this.vel.x > 0 && this.vel.x < 100 && !this.attacking || this.vel.x < 0 && this.vel.x > -100 && !this.attacking) {
                this.currentAnim = this.anims.walk;
            }
            else if(this.vel.x >= 100 && !this.attacking || this.vel.x <= -100 && !this.attacking) {
                this.currentAnim = this.anims.run;
            }
            // CASE 4: We are not moving, play idle animation
            else if (this.vel.y === 0 && this.vel.x == 0 && !this.attacking) {
                this.currentAnim = this.anims.idle;

            }

        },

        // This method is called on player's death
        kill: function() {
            this.parent();
            ig.game.respawnPlayerAtLastCheckpoint(this.pos.x, this.pos.y);
        },

        // On a player's death, this method checks # of lives and displays the proper screen
        // If lives > 0, respawn the player, else show game over screen
        onDeath: function() {
            ig.game.lives --;
            if(ig.game.lives < 0)
                ig.game.gameOver();
        },

    });
});
<commit_msg>Setting up lightning blade animation<commit_after>ig.module(
    'game.entities.player'
)
.requires(
    'impact.entity',
    'game.entities.projectiles.demonfang',
    'game.entities.projectiles.lightning',
    'game.entities.projectiles.fiercedemonfang'
)
.defines(function(){
    EntityPlayer = ig.Entity.extend({
        /* Collision Properties
         * type: What group does the player belong to?
         *  TYPE.A: Friendly
         *  TYPE.B: Enemy
         * checkAgainst: What entities do we check against?
         * collides: What happens if we collide with an entity?
        */
        type: ig.Entity.TYPE.A,
        checkAgainst: ig.Entity.TYPE.NONE,
        collides: ig.Entity.COLLIDES.ACTIVE,

        name: 'Kratos',

        /* Setup player properties */
        animSheet: new ig.AnimationSheet('media/kratos-d.png', 140, 100), // Animation sheet
        size: {x: 40, y: 50}, // Size of collision bounding box
        flip: true, // Set flip property to true
        accelGround: 200, // How fast we accelerate for movement on the ground
        accelAir: 310, // How fast we accelerate in the air
        jump: 360, // How high can we jump?
        friction: {x: 500, y: 0}, // Resistance against movement
        maxVel: {x: 100, y: 160}, // Cap our maximum velocity from acceleration
        attacking: false, // Boolean to control when we can attack
        startPosition: null, // Our starting position in the game world, used for respawning
        offset: {x: 50, y: 30},
        running: false,
        arte: null, // Which arte are we using?

        /* Player stats */
        // Just temporary for now
        stats : {
            str: 10,
            mag: 5,
            def: 9,
            spd: 10,
            totalExp: 0,
            nextExp: 10,
            level: 1,
            hp: 150,
            tp: 100,
            maxHP: 150,
            maxTP: 100,
        },

        skillPoints: 10, // How many skill points we have to allocate
        health: 150, // Override base health value
        tp: 100, // Technical Points

        init: function(x, y, settings){
            this.parent(x, y, settings);
            /* Set up player animations */

            /* this.addAnim(name, speed, frames)
             * name: string
             *  - the identifier for this animation
             * speed: number
             *  - how fast to iterate through frame cycle
             * frames: array
             *  - array of what frames to animate
            */

            this.addAnim('idle', 1, [1]);
            this.addAnim('walk', 0.10, [14, 15, 16, 17, 18, 19, 20]);
            this.addAnim('run', 0.10, [28, 29, 30, 31, 32, 33]);
            this.addAnim('jump', 0.10, [48]);
            this.addAnim('fall', 0.10, [48]);
            this.addAnim('lightningBlade', 0.10, [57, 58, 59, 60], true);

            this.atkTimer = new ig.Timer(1.5);
            this.startPosition = {x:x, y:y};
            this.parent(x, y, settings);
        },

        update: function(){
            // Set up movement cases
            var accel = this.standing ? this.accelGround : this.accelAir;
            if(ig.input.state('left') && !ig.game.menuVisible){
                this.accel.x = -accel;
                this.flip = false;
                /*
                 *  Lightning blade framework
                 *  -------------------------
                 * Pressing left/right in combination with 'a' will trigger
                 * the lightning blade attack.
                 *
                 * Implementation
                 * --------------
                 * 1. Put timer on attack. This is to:
                 *      - Prevent spamming of arte (cooldown)
                 *      - Allow animations to finish
                 *      - Lock player into specific animation
                 * 2. If player has not attacked (!this.attacking):
                 *      - Initiate attack. Reset timer.
                 * 3. Until timer expires, we set attacking = true, preventing
                 *    additional triggers of Lightning Blade.
                 * 4. Once the timer expires, we reset the attacking boolean flag.
                 *
                 * TODO
                 * ----
                 * 1. Setup animation frames for Lightning blade
                */
                // Trigger Lightning blade facing left
                if(ig.input.state('attack') && !this.attacking){
                    this.atkTimer.reset();
                    ig.game.spawnEntity(EntityDemonFang, this.pos.x - 20, this.pos.y + 7, {flip: !this.flip});
                    this.tp -= 5;
                    this.currentAnim = this.anims.lightningBlade;
                    // ig.game.spawnEntity(EntityFierceDemonFang, this.pos.x - 30, this.pos.y + 4, {flip: !this.flip});
                    console.log('Lightning blade');
                    if(this.atkTimer.delta() < 0){
                        this.attacking = true;
                    }
                }
            } else if(ig.input.state('right') && !ig.game.menuVisible){
                this.accel.x = accel;
                this.flip = true;
                // Trigger lightning blade facing right
                if(ig.input.state('attack') && !this.attacking){
                    this.atkTimer.reset();
                    ig.game.spawnEntity(EntityDemonFang, this.pos.x + 40, this.pos.y + 7, {flip: !this.flip});
                    // ig.game.spawnEntity(EntityFierceDemonFang, this.pos.x + 20, this.pos.y + 4, {flip: !this.flip});
                    console.log('Lightning blade');
                    if(this.atkTimer.delta() < 0){
                        this.attacking = true;
                        this.arte = 'lightning_blade';
                        console.log(this.currentAnim.frame);
                    }
                }
            } else if(ig.input.state('down') && !ig.game.menuVisible){
                if(ig.input.state('attack') && !this.attacking){
                    this.atkTimer.reset();
                    console.log('Casting Spell');
                    ig.game.spawnEntity(EntityLightning, this.pos.x + 40, this.pos.y - 40, {flip: !this.flip});
                    ig.game.spawnEntity(EntityLightning, this.pos.x + 30, this.pos.y - 40, {flip: !this.flip});
                    ig.game.spawnEntity(EntityLightning, this.pos.x + 20, this.pos.y - 40, {flip: !this.flip});
                    if(this.atkTimer.delta() < 0){
                        this.attacking = true;
                    }
                }

             } else if(ig.input.state('up') && !ig.game.menuVisible){
                // Stop the player
                this.accel.x = 0;
                if(ig.input.state('attack') && !this.attacking){
                    this.atkTimer.reset();
                    console.log('Hell Pyre');
                    if(this.atkTimer.delta() < 0){
                        this.attacking = true;
                    }
                }

             } else {
                // If we aren't moving in any direction, we must
                // be standing still. Therefore, accel = 0
                this.accel.x = 0;
            }

            // Used to reset attack timer after time has elasped.
            // Once the timer has expired, we can attack again
            if(this.atkTimer.delta() > 0){
                this.attacking = false;
            }

            // If the player is using an arte, stop them in place
            // The player will be stopped based on this.atkTimer
            // NOTE: this is also useful for spell casting cooldowns
            if(this.attacking){
                // Stop the player
                this.accel.x = 0;
            }

            // Jumping logic: CASE 1
            if(this.standing && ig.input.state('jump') && !ig.game.menuVisible) {
                if(this.vel.y == 0) {
                    this.vel.y = -this.jump;
                    this.falling = false;
                }
            }

            // Jumping logic: CASE 2
            else if(!this.standing && !ig.input.state('jump') && !this.falling && !ig.game.menuVisible){
                this.vel.y = Math.floor(this.vel.y/3);
                this.falling = true;
            }

            // Flip the player based on left/right movement
            this.currentAnim.flip.x = this.flip;

            this.parent();

            if(this.attacking === true && this.arte === 'lightning_blade'){
                console.log('should display animation');
                this.currentAnim = this.anims.lightningBlade;
            }
            // Animate player based on velocity
            // This may be refactored later

            // CASE 1: Y-velocity is negative and we aren't standing...
            //         therefore we are jumping.
            if(this.vel.y < 0 && !this.standing && !this.attacking)
                this.currentAnim = this.anims.jump;
            // CASE 2: Y-velocity is positive and we aren't standing...
            //         Y-velocity is only positive when falling
            else if(this.vel.y > 0 && !this.standing && !this.attacking)
                this.currentAnim = this.anims.fall;
            // CASE 3: X-velocity is not zero, we must be moving
            else if(this.vel.x > 0 && this.vel.x < 100 && !this.attacking || this.vel.x < 0 && this.vel.x > -100 && !this.attacking) {
                this.currentAnim = this.anims.walk;
            }
            else if(this.vel.x >= 100 && !this.attacking || this.vel.x <= -100 && !this.attacking) {
                this.currentAnim = this.anims.run;
            }
            // CASE 4: We are not moving, play idle animation
            else if (this.vel.y === 0 && this.vel.x == 0 && !this.attacking) {
                this.currentAnim = this.anims.idle;

            }

        },

        // This method is called on player's death
        kill: function() {
            this.parent();
            ig.game.respawnPlayerAtLastCheckpoint(this.pos.x, this.pos.y);
        },

        // On a player's death, this method checks # of lives and displays the proper screen
        // If lives > 0, respawn the player, else show game over screen
        onDeath: function() {
            ig.game.lives --;
            if(ig.game.lives < 0)
                ig.game.gameOver();
        },

    });
});
<|endoftext|>


<commit_before>/* Namespace for core functionality related to modal dialogs.
 *
 * Modals in Horizon are treated as a "stack", e.g new ones are added to the
 * top of the stack, and they are always removed in a last-in-first-out
 * order. This allows for things like swapping between modals as part of a
 * workflow, for confirmations, etc.
 *
 * When a new modal is loaded into the DOM, it fires a "new_modal" event which
 * event handlers can listen for. However, for consistency, it is better to
 * add methods which should be run on instantiation of any new modal to be
 * applied via the horizon.modals.addModalInitFunction method.
 */
horizon.modals = {
  // Storage for our current jqXHR object.
  _request: null,
  spinner: null,
  _init_functions: []
};

horizon.modals.addModalInitFunction = function (f) {
  horizon.modals._init_functions.push(f);
};

horizon.modals.initModal = function (modal) {
  $(horizon.modals._init_functions).each(function (index, f) {
    f(modal);
  });
};

/* Creates a modal dialog from the client-side template. */
horizon.modals.create = function (title, body, confirm, cancel) {
  if (!cancel) {
    cancel = gettext("Cancel");
  }
  var template = horizon.templates.compiled_templates["#modal_template"],
    params = {
      title: title, body: body, confirm: confirm, cancel: cancel,
      modal_backdrop: horizon.modals.MODAL_BACKDROP
    };
  return $(template.render(params)).appendTo("#modal_wrapper");
};

horizon.modals.success = function (data, textStatus, jqXHR) {
  var modal;
  $('#modal_wrapper').append(data);
  modal = $('.modal:last');
  modal.modal();
  $(modal).trigger("new_modal", modal);
  return modal;
};

horizon.modals.modal_spinner = function (text) {
  // Adds a spinner with the desired text in a modal window.
  var template = horizon.templates.compiled_templates["#spinner-modal"];
  horizon.modals.spinner = $(template.render({text: text}));
  horizon.modals.spinner.appendTo("#modal_wrapper");
  horizon.modals.spinner.modal({backdrop: 'static'});
  horizon.modals.spinner.find(".modal-body").spin(horizon.conf.spinner_options.modal);
};

horizon.modals.init_wizard = function () {
  // If workflow is in wizard mode, initialize wizard.
  var _max_visited_step = 0;
  var _validate_steps = function (start, end) {
    var $form = $('.workflow > form'),
      response = {};

    if (typeof end === 'undefined') {
      end = start;
    }

    // Clear old errors.
    $form.find('td.actions div.alert-danger').remove();
    $form.find('.form-group.error').each(function () {
      var $group = $(this);
      $group.removeClass('error');
      $group.find('span.help-block.error').remove();
    });

    // Send the data for validation.
    $.ajax({
      type: 'POST',
      url: $form.attr('action'),
      headers: {
        'X-Horizon-Validate-Step-Start': start,
        'X-Horizon-Validate-Step-End': end
      },
      data: $form.serialize(),
      dataType: 'json',
      async: false,
      success: function (data) { response = data; }
    });

    // Handle errors.
    if (response.has_errors) {
      var first_field = true;

      $.each(response.errors, function (step_slug, step_errors) {
        var step_id = response.workflow_slug + '__' + step_slug,
          $fieldset = $form.find('#' + step_id);
        $.each(step_errors, function (field, errors) {
          var $field;
          if (field === '__all__') {
            // Add global errors.
            $.each(errors, function (index, error) {
              $fieldset.find('td.actions').prepend(
                '
' +
                error + '
');
            });
            $fieldset.find('input,  select, textarea').first().focus();
            return;
          }
          // Add field errors.
          $field = $fieldset.find('[name="' + field + '"]');
          $field.closest('.form-group').addClass('error');
          $.each(errors, function (index, error) {
            $field.before(
              '' +
              error + '');
          });
          // Focus the first invalid field.
          if (first_field) {
            $field.focus();
            first_field = false;
          }
        });
      });

      return false;
    }
  };

  $('.workflow.wizard').bootstrapWizard({
    tabClass: 'wizard-tabs',
    nextSelector: '.button-next',
    previousSelector: '.button-previous',
    onTabShow: function (tab, navigation, index) {
      var $navs = navigation.find('li');
      var total = $navs.length;
      var current = index;
      var $footer = $('.modal-footer');
      _max_visited_step = Math.max(_max_visited_step, current);
      if (current + 1 >= total) {
        $footer.find('.button-next').hide();
        $footer.find('.button-final').show();
      } else {
        $footer.find('.button-next').show();
        $footer.find('.button-final').hide();
      }
      $navs.each(function(i) {
        $this = $(this);
        if (i <= _max_visited_step) {
          $this.addClass('done');
        } else {
          $this.removeClass('done');
        }
      });
    },
    onNext: function ($tab, $nav, index) {
      return _validate_steps(index - 1);
    },
    onTabClick: function ($tab, $nav, current, index) {
      // Validate if moving forward, but move backwards without validation
      return (index <= current ||
              _validate_steps(current, index - 1) !== false);
    }
  });
};

horizon.addInitFunction(horizon.modals.init = function() {

  var $document = $(document);

  // Bind handler for initializing new modals.
  $('#modal_wrapper').on('new_modal', function (evt, modal) {
    horizon.modals.initModal(modal);
  });

  // Bind "cancel" button handler.
  $document.on('click', '.modal .cancel', function (evt) {
    $(this).closest('.modal').modal('hide');
    evt.preventDefault();
  });

  // AJAX form submissions from modals. Makes validation happen in-modal.
  $document.on('submit', '.modal form', function (evt) {
    var $form = $(this),
      form = this,
      $button = $form.find(".modal-footer .btn-primary"),
      update_field_id = $form.attr("data-add-to-field"),
      headers = {},
      modalFileUpload = $form.attr("enctype") === "multipart/form-data",
      formData, ajaxOpts, featureFileList, featureFormData;

    if (modalFileUpload) {
      featureFileList = $("<input type='file'/>").get(0).files !== undefined;
      featureFormData = window.FormData !== undefined;

      if (!featureFileList || !featureFormData) {
        // Test whether browser supports HTML5 FileList and FormData interfaces,
        // which make XHR file upload possible. If not, it doesn't
        // support setting custom headers in AJAX requests either, so
        // modal forms won't work in them (namely, IE9).
        return;
      } else {
        formData = new window.FormData(form);
      }
    } else {
      formData = $form.serialize();
    }
    evt.preventDefault();

    // Prevent duplicate form POSTs
    $button.prop("disabled", true);

    if (update_field_id) {
      headers["X-Horizon-Add-To-Field"] = update_field_id;
    }

    ajaxOpts = {
      type: "POST",
      url: $form.attr('action'),
      headers: headers,
      data: formData,
      beforeSend: function () {
        $("#modal_wrapper .modal").last().modal("hide");
        $('.ajax-modal, .dropdown-toggle').attr('disabled', true);
        horizon.modals.modal_spinner(gettext("Working"));
      },
      complete: function (jqXHR) {
        var redirect_header = jqXHR.getResponseHeader("X-Horizon-Location");
        if (redirect_header === null) {
          horizon.modals.spinner.modal('hide');
        }
        $("#modal_wrapper .modal").last().modal("show");
        $button.prop("disabled", false);
      },
      success: function (data, textStatus, jqXHR) {
        var redirect_header = jqXHR.getResponseHeader("X-Horizon-Location"),
          add_to_field_header = jqXHR.getResponseHeader("X-Horizon-Add-To-Field"),
          json_data, field_to_update;
        if (redirect_header === null) {
          $('.ajax-modal, .dropdown-toggle').removeAttr("disabled");
        }

        var compile = function (content) {
           var $injector = angular.injector(['ng', 'hz']);
           $injector.invoke(function($rootScope, $compile) {
             $compile(content)($rootScope);
           });
        }

        // custom update handling
        if (data.hasOwnProperty('id')) {
          if (data.hasOwnProperty('content')) {
              // create
              if (data.hasOwnProperty('region')) {
                // prepend first
                if (data.ordering === 0) {
                  $('.' + data.region).prepend(data.content);
                  window.location.replace('#' + data.id);
                } else {
                  // append before region tools
                  $(data.content).insertBefore('.' + data.region + ' > .region-tools');
                }
              } else {
                // update
                $('#' + data.id).replaceWith(data.content);
              }
              // compile content
              compile($('#' + data.id));

          } else {
              // remove
              $('#' + data.id).remove();
          }

          // reinit angular
          //angular.bootstrap(document,['hz']);
          $form.closest(".modal").modal("hide");

        } else {
          $form.closest(".modal").modal("hide");
          if (redirect_header) {
            location.href = redirect_header;
          }
          else if (add_to_field_header) {
            json_data = $.parseJSON(data);
            field_to_update = $("#" + add_to_field_header);
            field_to_update.append("<option value='" + json_data[0] + "'>" + json_data[1] + "</option>");
            field_to_update.change();
            field_to_update.val(json_data[0]);
          } else {
            horizon.modals.success(data, textStatus, jqXHR);
          }
        }
      },
      error: function (jqXHR, status, errorThrown) {
        if (jqXHR.getResponseHeader('logout')) {
          location.href = jqXHR.getResponseHeader("X-Horizon-Location");
        } else {
          $('.ajax-modal, .dropdown-toggle').removeAttr("disabled");
          $form.closest(".modal").modal("hide");
          horizon.alert("danger", gettext("There was an error submitting the form. Please try again."));
        }
      }
    };

    if (modalFileUpload) {
      ajaxOpts.contentType = false;  // tell jQuery not to process the data
      ajaxOpts.processData = false;  // tell jQuery not to set contentType
    }
    $.ajax(ajaxOpts);
  });

  // Position modal so it's in-view even when scrolled down.
  $document.on('show.bs.modal', '.modal', function (evt) {
    // Filter out indirect triggers of "show" from (for example) tabs.
    if ($(evt.target).hasClass("modal")) {
      var scrollShift = $('body').scrollTop() || $('html').scrollTop(),
        $this = $(this),
        topVal = $this.css('top');
      $this.css('top', scrollShift + parseInt(topVal, 10));
    }
    // avoid closing the modal when escape is pressed on a select input
    $("select", evt.target).keyup(function (e) {
      if (e.keyCode === 27) {
        // remove the focus on the select, so double escape close the modal
        e.target.blur();
        e.stopPropagation();
      }
    });
  });

  // Focus the first usable form field in the modal for accessibility.
  horizon.modals.addModalInitFunction(function (modal) {
    $(modal).find(":text, select, textarea").filter(":visible:first").focus();
  });

  horizon.modals.addModalInitFunction(function(modal) {
    horizon.datatables.validate_button($(modal).find(".table_wrapper > form"));
  });
  horizon.modals.addModalInitFunction(horizon.utils.loadAngular);

  // Load modals for ajax-modal links.
  $document.on('click', '.ajax-modal', function (evt) {
    var $this = $(this);

    // If there's an existing modal request open, cancel it out.
    if (horizon.modals._request && typeof(horizon.modals._request.abort) !== undefined) {
      horizon.modals._request.abort();
    }

    horizon.modals._request = $.ajax($this.attr('href'), {
      beforeSend: function () {
        horizon.modals.modal_spinner(gettext("Loading"));
      },
      complete: function () {
        // Clear the global storage;
        horizon.modals._request = null;
        horizon.modals.spinner.modal('hide');
      },
      error: function(jqXHR, status, errorThrown) {
        if (jqXHR.status === 401){
          var redir_url = jqXHR.getResponseHeader("X-Horizon-Location");
          if (redir_url){
            location.href = redir_url;
          } else {
            location.reload(true);
          }
        }
        else {
          if (!horizon.ajax.get_messages(jqXHR)) {
            // Generic error handler. Really generic.
            horizon.alert("danger", gettext("An error occurred. Please try again later."));
          }
        }
      },
      success: function (data, textStatus, jqXHR) {
        var update_field_id = $this.attr('data-add-to-field'),
          modal,
          form;
        modal = horizon.modals.success(data, textStatus, jqXHR);
        if (update_field_id) {
          form = modal.find("form");
          if (form.length) {
            form.attr("data-add-to-field", update_field_id);
          }
        }
      }
    });
    evt.preventDefault();
  });

  /* Manage the modal "stack" */

  // After a modal has been shown, hide any other modals that are already in
  // the stack. Only one modal can be visible at the same time.
  $document.on("show.bs.modal", ".modal", function () {
    var modal_stack = $("#modal_wrapper .modal");
    modal_stack.splice(modal_stack.length - 1, 1);
    modal_stack.modal("hide");
  });

  // After a modal has been fully hidden, remove it to avoid confusion.
  // Note: the modal should only be removed if it is the "top" of the stack of
  // modals, e.g. it's the one currently being interacted with and isn't just
  // temporarily being hidden.
  $document.on('hidden.bs.modal', '.modal', function () {
    var $this = $(this),
      modal_stack = $("#modal_wrapper .modal");
    if ($this[0] === modal_stack.last()[0] || $this.hasClass("loading")) {
      $this.remove();
      if (!$this.hasClass("loading")) {
        $("#modal_wrapper .modal").last().modal("show");
      }
    }
  });

  // Make modals draggable
  $document.on("show.bs.modal", ".modal", function () {
    $(".modal-content").draggable({
      handle: ".modal-header"
    });
  });
});<commit_msg>Fix ajax update.<commit_after>/* Namespace for core functionality related to modal dialogs.
 *
 * Modals in Horizon are treated as a "stack", e.g new ones are added to the
 * top of the stack, and they are always removed in a last-in-first-out
 * order. This allows for things like swapping between modals as part of a
 * workflow, for confirmations, etc.
 *
 * When a new modal is loaded into the DOM, it fires a "new_modal" event which
 * event handlers can listen for. However, for consistency, it is better to
 * add methods which should be run on instantiation of any new modal to be
 * applied via the horizon.modals.addModalInitFunction method.
 */
horizon.modals = {
  // Storage for our current jqXHR object.
  _request: null,
  spinner: null,
  _init_functions: []
};

horizon.modals.addModalInitFunction = function (f) {
  horizon.modals._init_functions.push(f);
};

horizon.modals.initModal = function (modal) {
  $(horizon.modals._init_functions).each(function (index, f) {
    f(modal);
  });
};

/* Creates a modal dialog from the client-side template. */
horizon.modals.create = function (title, body, confirm, cancel) {
  if (!cancel) {
    cancel = gettext("Cancel");
  }
  var template = horizon.templates.compiled_templates["#modal_template"],
    params = {
      title: title, body: body, confirm: confirm, cancel: cancel,
      modal_backdrop: horizon.modals.MODAL_BACKDROP
    };
  return $(template.render(params)).appendTo("#modal_wrapper");
};

horizon.modals.success = function (data, textStatus, jqXHR) {
  var modal;
  $('#modal_wrapper').append(data);
  modal = $('.modal:last');
  modal.modal();
  $(modal).trigger("new_modal", modal);
  return modal;
};

horizon.modals.modal_spinner = function (text) {
  // Adds a spinner with the desired text in a modal window.
  var template = horizon.templates.compiled_templates["#spinner-modal"];
  horizon.modals.spinner = $(template.render({text: text}));
  horizon.modals.spinner.appendTo("#modal_wrapper");
  horizon.modals.spinner.modal({backdrop: 'static'});
  horizon.modals.spinner.find(".modal-body").spin(horizon.conf.spinner_options.modal);
};

horizon.modals.init_wizard = function () {
  // If workflow is in wizard mode, initialize wizard.
  var _max_visited_step = 0;
  var _validate_steps = function (start, end) {
    var $form = $('.workflow > form'),
      response = {};

    if (typeof end === 'undefined') {
      end = start;
    }

    // Clear old errors.
    $form.find('td.actions div.alert-danger').remove();
    $form.find('.form-group.error').each(function () {
      var $group = $(this);
      $group.removeClass('error');
      $group.find('span.help-block.error').remove();
    });

    // Send the data for validation.
    $.ajax({
      type: 'POST',
      url: $form.attr('action'),
      headers: {
        'X-Horizon-Validate-Step-Start': start,
        'X-Horizon-Validate-Step-End': end
      },
      data: $form.serialize(),
      dataType: 'json',
      async: false,
      success: function (data) { response = data; }
    });

    // Handle errors.
    if (response.has_errors) {
      var first_field = true;

      $.each(response.errors, function (step_slug, step_errors) {
        var step_id = response.workflow_slug + '__' + step_slug,
          $fieldset = $form.find('#' + step_id);
        $.each(step_errors, function (field, errors) {
          var $field;
          if (field === '__all__') {
            // Add global errors.
            $.each(errors, function (index, error) {
              $fieldset.find('td.actions').prepend(
                '
' +
                error + '
');
            });
            $fieldset.find('input,  select, textarea').first().focus();
            return;
          }
          // Add field errors.
          $field = $fieldset.find('[name="' + field + '"]');
          $field.closest('.form-group').addClass('error');
          $.each(errors, function (index, error) {
            $field.before(
              '' +
              error + '');
          });
          // Focus the first invalid field.
          if (first_field) {
            $field.focus();
            first_field = false;
          }
        });
      });

      return false;
    }
  };

  $('.workflow.wizard').bootstrapWizard({
    tabClass: 'wizard-tabs',
    nextSelector: '.button-next',
    previousSelector: '.button-previous',
    onTabShow: function (tab, navigation, index) {
      var $navs = navigation.find('li');
      var total = $navs.length;
      var current = index;
      var $footer = $('.modal-footer');
      _max_visited_step = Math.max(_max_visited_step, current);
      if (current + 1 >= total) {
        $footer.find('.button-next').hide();
        $footer.find('.button-final').show();
      } else {
        $footer.find('.button-next').show();
        $footer.find('.button-final').hide();
      }
      $navs.each(function(i) {
        $this = $(this);
        if (i <= _max_visited_step) {
          $this.addClass('done');
        } else {
          $this.removeClass('done');
        }
      });
    },
    onNext: function ($tab, $nav, index) {
      return _validate_steps(index - 1);
    },
    onTabClick: function ($tab, $nav, current, index) {
      // Validate if moving forward, but move backwards without validation
      return (index <= current ||
              _validate_steps(current, index - 1) !== false);
    }
  });
};

horizon.addInitFunction(horizon.modals.init = function() {

  var $document = $(document);

  // Bind handler for initializing new modals.
  $('#modal_wrapper').on('new_modal', function (evt, modal) {
    horizon.modals.initModal(modal);
  });

  // Bind "cancel" button handler.
  $document.on('click', '.modal .cancel', function (evt) {
    $(this).closest('.modal').modal('hide');
    evt.preventDefault();
  });

  // AJAX form submissions from modals. Makes validation happen in-modal.
  $document.on('submit', '.modal form', function (evt) {
    var $form = $(this),
      form = this,
      $button = $form.find(".modal-footer .btn-primary"),
      update_field_id = $form.attr("data-add-to-field"),
      headers = {},
      modalFileUpload = $form.attr("enctype") === "multipart/form-data",
      formData, ajaxOpts, featureFileList, featureFormData;

    if (modalFileUpload) {
      featureFileList = $("<input type='file'/>").get(0).files !== undefined;
      featureFormData = window.FormData !== undefined;

      if (!featureFileList || !featureFormData) {
        // Test whether browser supports HTML5 FileList and FormData interfaces,
        // which make XHR file upload possible. If not, it doesn't
        // support setting custom headers in AJAX requests either, so
        // modal forms won't work in them (namely, IE9).
        return;
      } else {
        formData = new window.FormData(form);
      }
    } else {
      formData = $form.serialize();
    }
    evt.preventDefault();

    // Prevent duplicate form POSTs
    $button.prop("disabled", true);

    if (update_field_id) {
      headers["X-Horizon-Add-To-Field"] = update_field_id;
    }

    ajaxOpts = {
      type: "POST",
      url: $form.attr('action'),
      headers: headers,
      data: formData,
      beforeSend: function () {
        $("#modal_wrapper .modal").last().modal("hide");
        $('.ajax-modal, .dropdown-toggle').attr('disabled', true);
        horizon.modals.modal_spinner(gettext("Working"));
      },
      complete: function (jqXHR) {
        var redirect_header = jqXHR.getResponseHeader("X-Horizon-Location");
        if (redirect_header === null) {
          horizon.modals.spinner.modal('hide');
        }
        $("#modal_wrapper .modal").last().modal("show");
        $button.prop("disabled", false);
      },
      success: function (data, textStatus, jqXHR) {
        var redirect_header = jqXHR.getResponseHeader("X-Horizon-Location"),
          add_to_field_header = jqXHR.getResponseHeader("X-Horizon-Add-To-Field"),
          json_data, field_to_update;
        if (redirect_header === null) {
          $('.ajax-modal, .dropdown-toggle').removeAttr("disabled");
        }

        var compile = function (content) {
           var $injector = angular.injector(['ng', 'horizon.app']);
           $injector.invoke(function($rootScope, $compile) {
             $compile(content)($rootScope);
           });
        }

        // custom update handling
        if (data.hasOwnProperty('id')) {
          if (data.hasOwnProperty('content')) {
              // create
              if (data.hasOwnProperty('region')) {
                // prepend first
                if (data.ordering === 0) {
                  $('.' + data.region).prepend(data.content);
                  window.location.replace('#' + data.id);
                } else {
                  // append before region tools
                  $(data.content).insertBefore('.' + data.region + ' > .region-tools');
                }
              } else {
                // update
                $('#' + data.id).replaceWith(data.content);
              }
              // compile content
              compile($('#' + data.id));

          } else {
              // remove
              $('#' + data.id).remove();
          }

          // reinit angular
          //angular.bootstrap(document,['hz']);
          $form.closest(".modal").modal("hide");

        } else {
          $form.closest(".modal").modal("hide");
          if (redirect_header) {
            location.href = redirect_header;
          }
          else if (add_to_field_header) {
            json_data = $.parseJSON(data);
            field_to_update = $("#" + add_to_field_header);
            field_to_update.append("<option value='" + json_data[0] + "'>" + json_data[1] + "</option>");
            field_to_update.change();
            field_to_update.val(json_data[0]);
          } else {
            horizon.modals.success(data, textStatus, jqXHR);
          }
        }
      },
      error: function (jqXHR, status, errorThrown) {
        if (jqXHR.getResponseHeader('logout')) {
          location.href = jqXHR.getResponseHeader("X-Horizon-Location");
        } else {
          $('.ajax-modal, .dropdown-toggle').removeAttr("disabled");
          $form.closest(".modal").modal("hide");
          horizon.alert("danger", gettext("There was an error submitting the form. Please try again."));
        }
      }
    };

    if (modalFileUpload) {
      ajaxOpts.contentType = false;  // tell jQuery not to process the data
      ajaxOpts.processData = false;  // tell jQuery not to set contentType
    }
    $.ajax(ajaxOpts);
  });

  // Position modal so it's in-view even when scrolled down.
  $document.on('show.bs.modal', '.modal', function (evt) {
    // Filter out indirect triggers of "show" from (for example) tabs.
    if ($(evt.target).hasClass("modal")) {
      var scrollShift = $('body').scrollTop() || $('html').scrollTop(),
        $this = $(this),
        topVal = $this.css('top');
      $this.css('top', scrollShift + parseInt(topVal, 10));
    }
    // avoid closing the modal when escape is pressed on a select input
    $("select", evt.target).keyup(function (e) {
      if (e.keyCode === 27) {
        // remove the focus on the select, so double escape close the modal
        e.target.blur();
        e.stopPropagation();
      }
    });
  });

  // Focus the first usable form field in the modal for accessibility.
  horizon.modals.addModalInitFunction(function (modal) {
    $(modal).find(":text, select, textarea").filter(":visible:first").focus();
  });

  horizon.modals.addModalInitFunction(function(modal) {
    horizon.datatables.validate_button($(modal).find(".table_wrapper > form"));
  });
  horizon.modals.addModalInitFunction(horizon.utils.loadAngular);

  // Load modals for ajax-modal links.
  $document.on('click', '.ajax-modal', function (evt) {
    var $this = $(this);

    // If there's an existing modal request open, cancel it out.
    if (horizon.modals._request && typeof(horizon.modals._request.abort) !== undefined) {
      horizon.modals._request.abort();
    }

    horizon.modals._request = $.ajax($this.attr('href'), {
      beforeSend: function () {
        horizon.modals.modal_spinner(gettext("Loading"));
      },
      complete: function () {
        // Clear the global storage;
        horizon.modals._request = null;
        horizon.modals.spinner.modal('hide');
      },
      error: function(jqXHR, status, errorThrown) {
        if (jqXHR.status === 401){
          var redir_url = jqXHR.getResponseHeader("X-Horizon-Location");
          if (redir_url){
            location.href = redir_url;
          } else {
            location.reload(true);
          }
        }
        else {
          if (!horizon.ajax.get_messages(jqXHR)) {
            // Generic error handler. Really generic.
            horizon.alert("danger", gettext("An error occurred. Please try again later."));
          }
        }
      },
      success: function (data, textStatus, jqXHR) {
        var update_field_id = $this.attr('data-add-to-field'),
          modal,
          form;
        modal = horizon.modals.success(data, textStatus, jqXHR);
        if (update_field_id) {
          form = modal.find("form");
          if (form.length) {
            form.attr("data-add-to-field", update_field_id);
          }
        }
      }
    });
    evt.preventDefault();
  });

  /* Manage the modal "stack" */

  // After a modal has been shown, hide any other modals that are already in
  // the stack. Only one modal can be visible at the same time.
  $document.on("show.bs.modal", ".modal", function () {
    var modal_stack = $("#modal_wrapper .modal");
    modal_stack.splice(modal_stack.length - 1, 1);
    modal_stack.modal("hide");
  });

  // After a modal has been fully hidden, remove it to avoid confusion.
  // Note: the modal should only be removed if it is the "top" of the stack of
  // modals, e.g. it's the one currently being interacted with and isn't just
  // temporarily being hidden.
  $document.on('hidden.bs.modal', '.modal', function () {
    var $this = $(this),
      modal_stack = $("#modal_wrapper .modal");
    if ($this[0] === modal_stack.last()[0] || $this.hasClass("loading")) {
      $this.remove();
      if (!$this.hasClass("loading")) {
        $("#modal_wrapper .modal").last().modal("show");
      }
    }
  });

  // Make modals draggable
  $document.on("show.bs.modal", ".modal", function () {
    $(".modal-content").draggable({
      handle: ".modal-header"
    });
  });
});<|endoftext|>


<commit_before>fb_app_ecosol_store = {

  addJS: function(url) {
    var script = document.createElement('script'); script.type = 'text/javascript'; script.src = url;
    document.getElementsByTagName('head')[0].appendChild(script);
  },

  admin: {

    init: function() {
      if (jQuery('#fb_store_admin_page').length > 0) {
        this.init_integration_type_selection();
        this.init_autocomplete();
        this.redraw_tabela_empreendimentos();
        //init commit button
        jQuery('#fb_ecosol_admin_save_button').on('click',this.commit.bind(this));
      }
    },

    close: function() {
      jQuery.colorbox.close();
      window.location.reload();
    },

    cancel: function() {
      jQuery.colorbox.close();
    },

    selected_empreendimento: null,

    init_autocomplete: function() {

      var self = this;

      var profilesSearch = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        remote: {
          url: '/plugin/fb_app_ecosol_store/search?query=%QUERY',
          ajax: {
            beforeSend: function() {
              jQuery('[name=fb_store]').addClass('small-loading');
            },
            complete: function() {
              jQuery('[name=fb_store]').removeClass('small-loading');
            }
          }
        }
      });

      profilesSearch.initialize();

      var input = jQuery('[name=fb_store]');

      input.typeahead(null, {
        name: 'fb_search_store',
        displayKey: 'name',
        source: profilesSearch.ttAdapter()
      });

      input.on('typeahead:selected typeahead:autocompleted', function(object, datum){
        self.selected_empreendimento = datum
        self.add_empreendimento()
      });

      input.on('keydown', function() {
        self.selected_empreendimento = null
      });

      jQuery('#fb_store_add_profile').on('click',this.add_empreendimento.bind(this));
    },

    add_empreendimento: function(evt) {
      if (evt != null && evt != void 0) { evt.preventDefault(); evt.stopPropagation();}
      if (this.selected_empreendimento != null) {
        empreendimentos.push(this.selected_empreendimento);
        this.selected_empreendimento = null;
        jQuery('[name=fb_store]').val('');
        this.redraw_tabela_empreendimentos();
      }
    },

    init_integration_type_selection: function() {
      var func_on_radio_change;

      func_on_radio_change = function(evt) {
        var radio_elements = jQuery('[name=fb_integration_type]');

        radio_elements.each(function(key,elm) {
          if (elm.checked) {
            jQuery('#fb_integration_type_'+elm.value).show();
          } else {
            jQuery('#fb_integration_type_'+elm.value).hide();
          }
        })
      };

      jQuery('[name=fb_integration_type]').each(function(key,radio_elm) {
        var $radio_elm = jQuery(radio_elm);
        $radio_elm.on('change',func_on_radio_change);
        $radio_elm.trigger('change');
      })

      if (empreendimentos.length > 0) {
        jQuery('[name=fb_integration_type][value=profiles]').click()
      } else {
        jQuery('[name=fb_integration_type][value=query]').click()

      }
    },

    redraw_tabela_empreendimentos: function() {
      var i, tbody, tr_html, tr, remove_button, self;
      self = this;
      tbody = jQuery('#fb_tabela_empreendimentos');
      tbody.empty();
      for (i=0;i<empreendimentos.length;i++) {
        tr_html  = '
';
        tr_html += ''+empreendimentos[i].name+'	';
        tr_html += '	';
        tr_html += '
';
        tr = jQuery(tr_html);
        tbody.append(tr);
        remove_button = jQuery('<button data-profile-pos="'+i+'">Remover</button>');
        remove_button.on('click',function(evt) {
          var pos = parseInt(jQuery(evt.target).data('profile-pos'));
          empreendimentos.splice(pos,1);
          self.redraw_tabela_empreendimentos();
        });
        tr.find('.remove-btn-holder').append(remove_button);
      }
    },

    commit: function(evt) {
      if (evt != null && evt != void 0) { evt.preventDefault(); evt.stopPropagation();}

      var profile_ids = []
      for (var i=0;i<empreendimentos.length;i++) {
        profile_ids.push(empreendimentos[i].id)
      }

      var data = {
        integration_type: jQuery( "[name=fb_integration_type]:checked" ).val(),
        keyword: jQuery('[name=fb_keyword]').val(),
        profile_ids: profile_ids,
        page_id: window.page_id,
      }

      jQuery.ajax({
        url: '/plugin/fb_app_ecosol_store/admin',
        type: 'post',
        dataType: 'script', /* json */
        data: data,
        /*success: function(data) {
          display_notice('Aba instalada!');
        }, */
        error: function() {
          alert('Erro!')
        }
      });

    },

  },

  fb: {
    id: '',
    page_tab_next: '',

    init: function(id, next, asyncInit) {
      this.id = id;
      this.page_tab_next = next;

      window.fbAsyncInit = function() {
        FB.init({
          appId: id,
          status: true,
          cookie: true,
          xfbml: true
        });

        fb_app_ecosol_store.fb.size_change();
        jQuery(document).on('DOMNodeInserted', fb_app_ecosol_store.fb.size_change);

        if (asyncInit)
          jQuery.globalEval(asyncInit)
      };
    },

    size_change: function() {
      FB.Canvas.setSize({height: jQuery('body').height()+100});
    },

    redirect_to_tab: function(pageID) {
      FB.api('/'+pageID, function(response) {
        window.location.href = response.link + '?sk=app_' + fb_app_ecosol_store.fb.id;
      });
    },

    add_tab: function () {
      window.location.href = 'https://www.facebook.com/dialog/pagetab?' + jQuery.param({app_id: fb_app_ecosol_store.fb.id, next: fb_app_ecosol_store.base_url});
    },

    login: function() {
      FB.getLoginStatus(function(response) {
        if (response.status === 'connected') {
          fb_app_ecosol_store.fb.add_tab();
        } else {
          window.location.href = 'https://www.facebook.com/dialog/oauth?' + jQuery.param({client_id: fb_app_ecosol_store.fb.id, redirect_uri: fb_app_ecosol_store.base_url })
        }
      });
    },
  },
};

<commit_msg>correção para mudança do nome da variável para fb_integration_type<commit_after>fb_app_ecosol_store = {

  addJS: function(url) {
    var script = document.createElement('script'); script.type = 'text/javascript'; script.src = url;
    document.getElementsByTagName('head')[0].appendChild(script);
  },

  admin: {

    init: function() {
      if (jQuery('#fb_store_admin_page').length > 0) {
        this.init_integration_type_selection();
        this.init_autocomplete();
        this.redraw_tabela_empreendimentos();
        //init commit button
        jQuery('#fb_ecosol_admin_save_button').on('click',this.commit.bind(this));
      }
    },

    close: function() {
      jQuery.colorbox.close();
      window.location.reload();
    },

    cancel: function() {
      jQuery.colorbox.close();
    },

    selected_empreendimento: null,

    init_autocomplete: function() {

      var self = this;

      var profilesSearch = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        remote: {
          url: '/plugin/fb_app_ecosol_store/search?query=%QUERY',
          ajax: {
            beforeSend: function() {
              jQuery('[name=fb_store]').addClass('small-loading');
            },
            complete: function() {
              jQuery('[name=fb_store]').removeClass('small-loading');
            }
          }
        }
      });

      profilesSearch.initialize();

      var input = jQuery('[name=fb_store]');

      input.typeahead(null, {
        name: 'fb_search_store',
        displayKey: 'name',
        source: profilesSearch.ttAdapter()
      });

      input.on('typeahead:selected typeahead:autocompleted', function(object, datum){
        self.selected_empreendimento = datum
        self.add_empreendimento()
      });

      input.on('keydown', function() {
        self.selected_empreendimento = null
      });

      jQuery('#fb_store_add_profile').on('click',this.add_empreendimento.bind(this));
    },

    add_empreendimento: function(evt) {
      if (evt != null && evt != void 0) { evt.preventDefault(); evt.stopPropagation();}
      if (this.selected_empreendimento != null) {
        empreendimentos.push(this.selected_empreendimento);
        this.selected_empreendimento = null;
        jQuery('[name=fb_store]').val('');
        this.redraw_tabela_empreendimentos();
      }
    },

    init_integration_type_selection: function() {
      var func_on_radio_change;

      func_on_radio_change = function(evt) {
        var radio_elements = jQuery('[name=fb_integration_type]');

        radio_elements.each(function(key,elm) {
          if (elm.checked) {
            jQuery('#fb_integration_type_'+elm.value).show();
          } else {
            jQuery('#fb_integration_type_'+elm.value).hide();
          }
        })
      };

      jQuery('[name=fb_integration_type]').each(function(key,radio_elm) {
        var $radio_elm = jQuery(radio_elm);
        $radio_elm.on('change',func_on_radio_change);
        $radio_elm.trigger('change');
      })

      if (empreendimentos.length > 0) {
        jQuery('[name=fb_integration_type][value=profiles]').click()
      } else {
        jQuery('[name=fb_integration_type][value=query]').click()

      }
    },

    redraw_tabela_empreendimentos: function() {
      var i, tbody, tr_html, tr, remove_button, self;
      self = this;
      tbody = jQuery('#fb_tabela_empreendimentos');
      tbody.empty();
      for (i=0;i<empreendimentos.length;i++) {
        tr_html  = '
';
        tr_html += ''+empreendimentos[i].name+'	';
        tr_html += '	';
        tr_html += '
';
        tr = jQuery(tr_html);
        tbody.append(tr);
        remove_button = jQuery('<button data-profile-pos="'+i+'">Remover</button>');
        remove_button.on('click',function(evt) {
          var pos = parseInt(jQuery(evt.target).data('profile-pos'));
          empreendimentos.splice(pos,1);
          self.redraw_tabela_empreendimentos();
        });
        tr.find('.remove-btn-holder').append(remove_button);
      }
    },

    commit: function(evt) {
      if (evt != null && evt != void 0) { evt.preventDefault(); evt.stopPropagation();}

      var profile_ids = []
      for (var i=0;i<empreendimentos.length;i++) {
        profile_ids.push(empreendimentos[i].id)
      }

      var data = {
        fb_integration_type: jQuery( "[name=fb_integration_type]:checked" ).val(),
        keyword: jQuery('[name=fb_keyword]').val(),
        profile_ids: profile_ids,
        page_id: window.page_id,
      }

      jQuery.ajax({
        url: '/plugin/fb_app_ecosol_store/admin',
        type: 'post',
        dataType: 'script', /* json */
        data: data,
        /*success: function(data) {
          display_notice('Aba instalada!');
        }, */
        error: function() {
          alert('Erro!')
        }
      });

    },

  },

  fb: {
    id: '',
    page_tab_next: '',

    init: function(id, next, asyncInit) {
      this.id = id;
      this.page_tab_next = next;

      window.fbAsyncInit = function() {
        FB.init({
          appId: id,
          status: true,
          cookie: true,
          xfbml: true
        });

        fb_app_ecosol_store.fb.size_change();
        jQuery(document).on('DOMNodeInserted', fb_app_ecosol_store.fb.size_change);

        if (asyncInit)
          jQuery.globalEval(asyncInit)
      };
    },

    size_change: function() {
      FB.Canvas.setSize({height: jQuery('body').height()+100});
    },

    redirect_to_tab: function(pageID) {
      FB.api('/'+pageID, function(response) {
        window.location.href = response.link + '?sk=app_' + fb_app_ecosol_store.fb.id;
      });
    },

    add_tab: function () {
      window.location.href = 'https://www.facebook.com/dialog/pagetab?' + jQuery.param({app_id: fb_app_ecosol_store.fb.id, next: fb_app_ecosol_store.base_url});
    },

    login: function() {
      FB.getLoginStatus(function(response) {
        if (response.status === 'connected') {
          fb_app_ecosol_store.fb.add_tab();
        } else {
          window.location.href = 'https://www.facebook.com/dialog/oauth?' + jQuery.param({client_id: fb_app_ecosol_store.fb.id, redirect_uri: fb_app_ecosol_store.base_url })
        }
      });
    },
  },
};

<|endoftext|>


<commit_before>import AdvancedCollapsible from './components/advancedCollapsible';
import Avatar, { AvatarStack } from './components/avatar';
import Badge from './components/badge';
import Banner from './components/banner';
import Box from './components/box';
import Button from './components/button';
import ButtonGroup from './components/buttonGroup';
import {
  Heading1,
  Heading2,
  Heading3,
  Heading4,
  Heading5,
  Marker,
  Monospaced,
  TextBody,
  TextBodyCompact,
  TextDisplay,
  TextSmall,
  UITextDisplay,
  UITextBody,
  UITextSmall,
} from './components/typography';
import Bullet from './components/bullet';
import Checkbox from './components/checkbox';
import Container from './components/container';
import Counter from './components/counter';
import DataGrid from './components/datagrid';
import { DatePicker, DatePickerRange, DatePickerInput, DatePickerInputRange } from './components/datepicker';
import DetailPage, { DetailPageBody, DetailPageHeader } from './components/detailPage';
import Dialog, { DialogBase } from './components/dialog';
import EmptyState from './components/emptyState';
import FilterSelection from './components/filterSelection';
import Icon from './components/icon';
import IconButton from './components/iconButton';
import Input, { InputBase, NumericInput, Textarea, TimeInput, DurationInput } from './components/input';
import Menu, { IconMenu, MenuItem, MenuDivider, MenuTitle } from './components/menu';
import Link from './components/link';
import MarketingButton from './components/marketingButton';
import MarketingLink from './components/marketingLink';
import MarketingLockBadge from './components/marketingLockBadge';
import MarketingMarker from './components/marketingMarker';
import MarketingStatusLabel from './components/marketingStatusLabel';
import MarketingTab from './components/marketingTab';
import { MarketingHeading1, MarketingHeading2 } from './components/marketingTypography';
import Message from './components/message';
import Overlay from './components/overlay';
import OverviewPage, { OverviewPageBody, OverviewPageHeader } from './components/overviewPage';
import { LabelValuePair, LabelValuePairGroup } from './components/labelValuePair';
import LoadingBar from './components/loadingBar';
import LoadingMolecule from './components/loadingMolecule';
import LoadingSpinner from './components/loadingSpinner';
import Pagination from './components/pagination';
import Passport, { EmptyPassport } from './components/passport';
import Popover from './components/popover';
import { RadioButton, RadioGroup } from './components/radio';
import ScrollContainer from './components/scrollContainer';
import Section from './components/section';
import Select, { AsyncSelect } from './components/select';
import { Island, IslandGroup } from './components/island';
import SplitButton from './components/splitButton';
import StatusBullet from './components/statusBullet';
import StatusLabel from './components/statusLabel';
import { TitleTab, TabGroup } from './components/tab';
import Tag from './components/tag';
import Timer from './components/timer';
import TimerPulser from './components/timerPulser';
import { Toast, ToastContainer } from './components/toast';
import Toggle from './components/toggle';
import ValidationText, { ErrorText, HelpText } from './components/validationText';
import Label from './components/label';
import Tooltip from './components/tooltip';
import ProgressTracker from './components/progressTracker';
import Widget from './components/widget';
import WysiwygEditor from './components/wysiwygEditor';

import {
  COLOR,
  COLORS,
  TINTS,
  colorsWithout,
  tintsWithout,
  SIZES,
  sizesWithout,
  TINY,
  SMALL,
  MEDIUM,
  LARGE,
  FULLSCREEN,
} from './constants';

export {
  AdvancedCollapsible,
  Avatar,
  AvatarStack,
  AsyncSelect,
  Badge,
  Banner,
  InputBase,
  Box,
  Bullet,
  Button,
  ButtonGroup,
  Checkbox,
  Container,
  Counter,
  DataGrid,
  DatePicker,
  DatePickerInput,
  DatePickerRange,
  DatePickerInputRange,
  DetailPage,
  DetailPageBody,
  DetailPageHeader,
  Dialog,
  DialogBase,
  EmptyPassport,
  EmptyState,
  ErrorText,
  FilterSelection,
  Heading1,
  Heading2,
  Heading3,
  Heading4,
  Heading5,
  HelpText,
  Icon,
  IconButton,
  IconMenu,
  Input,
  Island,
  IslandGroup,
  Label,
  LabelValuePair,
  LabelValuePairGroup,
  Link,
  LoadingBar,
  LoadingMolecule,
  LoadingSpinner,
  Marker,
  MarketingButton,
  MarketingLink,
  MarketingLockBadge,
  MarketingMarker,
  MarketingStatusLabel,
  MarketingHeading1,
  MarketingHeading2,
  MarketingTab,
  Menu,
  MenuItem,
  MenuDivider,
  MenuTitle,
  Message,
  Monospaced,
  NumericInput,
  Overlay,
  OverviewPage,
  OverviewPageBody,
  OverviewPageHeader,
  Passport,
  Pagination,
  Popover,
  ProgressTracker,
  RadioButton,
  RadioGroup,
  ScrollContainer,
  Section,
  Select,
  SplitButton,
  StatusBullet,
  StatusLabel,
  TextBody,
  TextBodyCompact,
  TextDisplay,
  TextSmall,
  TabGroup,
  Tag,
  Textarea,
  TimeInput,
  DurationInput,
  Timer,
  TimerPulser,
  TitleTab,
  Toast,
  ToastContainer,
  Toggle,
  Tooltip,
  UITextDisplay,
  UITextBody,
  UITextSmall,
  ValidationText,
  Widget,
  WysiwygEditor,
  COLOR,
  COLORS,
  TINTS,
  colorsWithout,
  tintsWithout,
  SIZES,
  sizesWithout,
  TINY,
  SMALL,
  MEDIUM,
  LARGE,
  FULLSCREEN,
};
<commit_msg>Expose powered by button<commit_after>import AdvancedCollapsible from './components/advancedCollapsible';
import Avatar, { AvatarStack } from './components/avatar';
import Badge from './components/badge';
import Banner from './components/banner';
import Box from './components/box';
import Button from './components/button';
import ButtonGroup from './components/buttonGroup';
import {
  Heading1,
  Heading2,
  Heading3,
  Heading4,
  Heading5,
  Marker,
  Monospaced,
  TextBody,
  TextBodyCompact,
  TextDisplay,
  TextSmall,
  UITextDisplay,
  UITextBody,
  UITextSmall,
} from './components/typography';
import Bullet from './components/bullet';
import Checkbox from './components/checkbox';
import Container from './components/container';
import Counter from './components/counter';
import DataGrid from './components/datagrid';
import { DatePicker, DatePickerRange, DatePickerInput, DatePickerInputRange } from './components/datepicker';
import DetailPage, { DetailPageBody, DetailPageHeader } from './components/detailPage';
import Dialog, { DialogBase } from './components/dialog';
import EmptyState from './components/emptyState';
import FilterSelection from './components/filterSelection';
import Icon from './components/icon';
import IconButton from './components/iconButton';
import Input, { InputBase, NumericInput, Textarea, TimeInput, DurationInput } from './components/input';
import Menu, { IconMenu, MenuItem, MenuDivider, MenuTitle } from './components/menu';
import Link from './components/link';
import MarketingButton from './components/marketingButton';
import MarketingLink from './components/marketingLink';
import MarketingLockBadge from './components/marketingLockBadge';
import MarketingMarker from './components/marketingMarker';
import MarketingStatusLabel from './components/marketingStatusLabel';
import MarketingTab from './components/marketingTab';
import { MarketingHeading1, MarketingHeading2 } from './components/marketingTypography';
import Message from './components/message';
import Overlay from './components/overlay';
import OverviewPage, { OverviewPageBody, OverviewPageHeader } from './components/overviewPage';
import { LabelValuePair, LabelValuePairGroup } from './components/labelValuePair';
import LoadingBar from './components/loadingBar';
import LoadingMolecule from './components/loadingMolecule';
import LoadingSpinner from './components/loadingSpinner';
import Pagination from './components/pagination';
import Passport, { EmptyPassport } from './components/passport';
import Popover from './components/popover';
import PoweredByButton from './components/poweredByButton';
import { RadioButton, RadioGroup } from './components/radio';
import ScrollContainer from './components/scrollContainer';
import Section from './components/section';
import Select, { AsyncSelect } from './components/select';
import { Island, IslandGroup } from './components/island';
import SplitButton from './components/splitButton';
import StatusBullet from './components/statusBullet';
import StatusLabel from './components/statusLabel';
import { TitleTab, TabGroup } from './components/tab';
import Tag from './components/tag';
import Timer from './components/timer';
import TimerPulser from './components/timerPulser';
import { Toast, ToastContainer } from './components/toast';
import Toggle from './components/toggle';
import ValidationText, { ErrorText, HelpText } from './components/validationText';
import Label from './components/label';
import Tooltip from './components/tooltip';
import ProgressTracker from './components/progressTracker';
import Widget from './components/widget';
import WysiwygEditor from './components/wysiwygEditor';

import {
  COLOR,
  COLORS,
  TINTS,
  colorsWithout,
  tintsWithout,
  SIZES,
  sizesWithout,
  TINY,
  SMALL,
  MEDIUM,
  LARGE,
  FULLSCREEN,
} from './constants';

export {
  AdvancedCollapsible,
  Avatar,
  AvatarStack,
  AsyncSelect,
  Badge,
  Banner,
  InputBase,
  Box,
  Bullet,
  Button,
  ButtonGroup,
  Checkbox,
  Container,
  Counter,
  DataGrid,
  DatePicker,
  DatePickerInput,
  DatePickerRange,
  DatePickerInputRange,
  DetailPage,
  DetailPageBody,
  DetailPageHeader,
  Dialog,
  DialogBase,
  EmptyPassport,
  EmptyState,
  ErrorText,
  FilterSelection,
  Heading1,
  Heading2,
  Heading3,
  Heading4,
  Heading5,
  HelpText,
  Icon,
  IconButton,
  IconMenu,
  Input,
  Island,
  IslandGroup,
  Label,
  LabelValuePair,
  LabelValuePairGroup,
  Link,
  LoadingBar,
  LoadingMolecule,
  LoadingSpinner,
  Marker,
  MarketingButton,
  MarketingLink,
  MarketingLockBadge,
  MarketingMarker,
  MarketingStatusLabel,
  MarketingHeading1,
  MarketingHeading2,
  MarketingTab,
  Menu,
  MenuItem,
  MenuDivider,
  MenuTitle,
  Message,
  Monospaced,
  NumericInput,
  Overlay,
  OverviewPage,
  OverviewPageBody,
  OverviewPageHeader,
  Passport,
  Pagination,
  Popover,
  ProgressTracker,
  PoweredByButton,
  RadioButton,
  RadioGroup,
  ScrollContainer,
  Section,
  Select,
  SplitButton,
  StatusBullet,
  StatusLabel,
  TextBody,
  TextBodyCompact,
  TextDisplay,
  TextSmall,
  TabGroup,
  Tag,
  Textarea,
  TimeInput,
  DurationInput,
  Timer,
  TimerPulser,
  TitleTab,
  Toast,
  ToastContainer,
  Toggle,
  Tooltip,
  UITextDisplay,
  UITextBody,
  UITextSmall,
  ValidationText,
  Widget,
  WysiwygEditor,
  COLOR,
  COLORS,
  TINTS,
  colorsWithout,
  tintsWithout,
  SIZES,
  sizesWithout,
  TINY,
  SMALL,
  MEDIUM,
  LARGE,
  FULLSCREEN,
};
<|endoftext|>


<commit_before>import {
  isNone,
  isPresent
} from '@ember/utils';
import {
  A
} from '@ember/array';
import Service from '@ember/service';
import NotificationMessage from '../objects/notification-message';
import configuration from '../configuration';

export default Service.extend({

  messages: A([]),

  _getPropertyOrDefault(options, propertyName) {
    //first try to obtain property value from per-message definition
    let value = options[propertyName];

    //if not available, use global (default) settings
    if (isNone(value)) {
      value = configuration.getDefaultSettingForProperty(options.type, propertyName);
    }

    return value;
  },

  getAllMessages() {
    return this.get('messages');
  },

  addMessage(options) {

    //first make sure, message has "some" type
    options.type = options.type || 'info';

    let timeout = this._getPropertyOrDefault(options, 'timeout');
    let sticky = this._getPropertyOrDefault(options, 'sticky');
    if (timeout < 0) {
      sticky = true;
    }

    let messageObject = NotificationMessage.create({
      message: options.message,
      type: options.type,
      timeout: timeout,
      sticky,
      onClick: options.onClick || function() {},
      onClose: options.onClose || function() {},
      htmlContent: options.htmlContent,
      onCloseTimeout: options.onCloseTimeout || function() {},
      closeOnClick: options.closeOnClick,
      icon: options.icon,
      id: options.id,
      data: options.data || {}
    });

    this.get('messages').addObject(messageObject);

    if (!this.get('message.sticky')) {
      this.startMessageTimer(messageObject);
    }

    return messageObject;
  },

  error(message, options) {
    options = options || {};
    options.type = 'error';
    options.message = message;
    this.addMessage(options);
  },

  info(message, options) {
    options = options || {};
    options.message = message;
    options.type = 'info';
    this.addMessage(options);
  },

  success(message, options) {
    options = options || {};
    options.message = message;
    options.type = 'success';
    this.addMessage(options);
  },

  removeMessageFromList(message) {
    this.get('messages').removeObject(message);
  },

  removeMessage(message, force = false) {
    clearTimeout(message.get('closeTimer'));
    if (force === true) {
      this.removeMessageFromList(message);
    } else {
      message.set('removeMe', true);
    }
  },

  removeMessageById(messageId, force = false) {
    let message = this.get('messages').find((msg) => {
      return msg.get('id') === messageId;
    });

    if (isPresent(message)) {
      this.removeMessage(message, force);
    }
  },

  removeAll(exceptIdsArray, force = false) {
    while (this.get('messages.length') > 0){
      let msg = this.get('messages').objectAt(0);
      if (isNone(exceptIdsArray) || !exceptIdsArray.includes(msg.id)) {
        this.removeMessage(msg, force);
      }
    }
  },

  startMessageTimer(message) {
    if (message.get('sticky')) {
      return;
    }
    message.set('startTimeoutTime', Date.now());

    let timer = setTimeout(() => {
      this.removeMessage(message);

      let onCloseTimeout = message.get('onCloseTimeout');
      onCloseTimeout(message);
    }, message.get('timeout'));

    message.set('closeTimer', timer);
  },

  pauseMessageTimeout(message) {
    if (message.get('sticky')) {
      return;
    }

    clearTimeout(message.get('closeTimer'));

    let remainingTimeout = message.get('timeout') - (Date.now() - message.get('startTimeoutTime'));
    message.set('timeout', remainingTimeout);
  }

});
<commit_msg>fix infinite loop in removeAll<commit_after>import {
  isNone,
  isPresent
} from '@ember/utils';
import {
  A
} from '@ember/array';
import Service from '@ember/service';
import NotificationMessage from '../objects/notification-message';
import configuration from '../configuration';

export default Service.extend({

  messages: A([]),

  _getPropertyOrDefault(options, propertyName) {
    //first try to obtain property value from per-message definition
    let value = options[propertyName];

    //if not available, use global (default) settings
    if (isNone(value)) {
      value = configuration.getDefaultSettingForProperty(options.type, propertyName);
    }

    return value;
  },

  getAllMessages() {
    return this.get('messages');
  },

  addMessage(options) {

    //first make sure, message has "some" type
    options.type = options.type || 'info';

    let timeout = this._getPropertyOrDefault(options, 'timeout');
    let sticky = this._getPropertyOrDefault(options, 'sticky');
    if (timeout < 0) {
      sticky = true;
    }

    let messageObject = NotificationMessage.create({
      message: options.message,
      type: options.type,
      timeout: timeout,
      sticky,
      onClick: options.onClick || function() {},
      onClose: options.onClose || function() {},
      htmlContent: options.htmlContent,
      onCloseTimeout: options.onCloseTimeout || function() {},
      closeOnClick: options.closeOnClick,
      icon: options.icon,
      id: options.id,
      data: options.data || {}
    });

    this.get('messages').addObject(messageObject);

    if (!this.get('message.sticky')) {
      this.startMessageTimer(messageObject);
    }

    return messageObject;
  },

  error(message, options) {
    options = options || {};
    options.type = 'error';
    options.message = message;
    this.addMessage(options);
  },

  info(message, options) {
    options = options || {};
    options.message = message;
    options.type = 'info';
    this.addMessage(options);
  },

  success(message, options) {
    options = options || {};
    options.message = message;
    options.type = 'success';
    this.addMessage(options);
  },

  removeMessageFromList(message) {
    this.get('messages').removeObject(message);
  },

  removeMessage(message, force = false) {
    clearTimeout(message.get('closeTimer'));
    if (force === true) {
      this.removeMessageFromList(message);
    } else {
      message.set('removeMe', true);
    }
  },

  removeMessageById(messageId, force = false) {
    let message = this.get('messages').find((msg) => {
      return msg.get('id') === messageId;
    });

    if (isPresent(message)) {
      this.removeMessage(message, force);
    }
  },

  removeAll(exceptIdsArray, force = false) {
    for (let i = this.get('messages.length') - 1; i >= 0; i--) {
      let msg = this.get('messages').objectAt(i);
      if (isNone(exceptIdsArray) || !exceptIdsArray.includes(msg.id)) {
        this.removeMessage(msg, force);
      }
    }
  },

  startMessageTimer(message) {
    if (message.get('sticky')) {
      return;
    }
    message.set('startTimeoutTime', Date.now());

    let timer = setTimeout(() => {
      this.removeMessage(message);

      let onCloseTimeout = message.get('onCloseTimeout');
      onCloseTimeout(message);
    }, message.get('timeout'));

    message.set('closeTimer', timer);
  },

  pauseMessageTimeout(message) {
    if (message.get('sticky')) {
      return;
    }

    clearTimeout(message.get('closeTimer'));

    let remainingTimeout = message.get('timeout') - (Date.now() - message.get('startTimeoutTime'));
    message.set('timeout', remainingTimeout);
  }

});
<|endoftext|>


<commit_before>module.exports = install;

install.usage = "rappidjs install <pkg>"
    + "\nrappidjs install <pkg> <version>"
    + "\nInstalls rAppidjs dependencies from ./package.json.";

var npm = require("npm.js"),
    fs = require("fs"),
    path = require("path"),
    readJson = require("npm/utils/read-json.js"),
    flow = require("flow.js").flow;

var dir;

function install(args, callback){
    if(args.length  === 0){
        callback("No args defined");
    }
    var packageName = args.shift();
    var what = packageName;
    if(args.length > 0){
        what += "@"+args.shift();
    }

    // try to install package
    npm.commands.install(what, function(err, installed){
        if(!err){
            if(installed){

                dir = dir || process.cwd();

                var publicDir = path.join(dir,"Public");
                var where = path.resolve(npm.dir, "..");
                var packageDir = path.join(dir,"node_modules",packageName);
                readJson(path.join(packageDir,"package.json"),function(er, data){
                    if (er) data = null;

                    fs.symlinkSync(path.join(publicDir, data.lib), path.join(packageDir, data.lib));

                    var dependencies = data.rAppidDependencies;
                    var f = flow();
                    for(let key in dependencies){
                        if(dependencies.hasOwnProperty(key)){
                            f.seq(function (cb) {
                                install([key,dependencies[key]].join("@"), cb);
                            });
                        }
                    }
                    f.exec(callback);
                });

            }else{
                callback("Installation failed");
            }
        }else{
            callback("Error while installing " + packageName);
        }
    });
}<commit_msg>changed<commit_after>module.exports = install;

install.usage = "rappidjs install <pkg>"
    + "\nrappidjs install <pkg> <version>"
    + "\nInstalls rAppidjs dependencies from ./package.json.";

var npm = require("npm.js"),
    fs = require("fs"),
    path = require("path"),
    readJson = require("npm/utils/read-json.js"),
    flow = require("flow.js").flow;

var dir;

function install(args, callback){
    if(args.length  === 0){
        callback("No args defined");
    }
    var packageName = args.shift();
    var what = packageName;
    if(args.length > 0){
        what += "@"+args.shift();
    }

    // try to install package
    npm.commands.install(what, function(err, installed){
        if(!err){
            if(installed){

                dir = dir || process.cwd();

                var publicDir = path.join(dir,"Public");
                var where = path.resolve(npm.dir, "..");
                var packageDir = path.join(dir,"node_modules",packageName);
                readJson(path.join(packageDir,"package.json"),function(er, data){
                    if (er) data = null;

                    fs.symlinkSync(path.join(publicDir, data.lib), path.join(packageDir, data.lib));

                    var dependencies = data.rAppidDependencies;
                    var f = flow();
                    function doInstall(dName,dVersion, cb){
                        install([dName, dVersion].join("@"), cb);
                    }
                    for(var key in dependencies){
                        if(dependencies.hasOwnProperty(key)){
                            f.seq(function (cb) {
                                doInstall(key,dependencies[key],cb);
                            });
                        }
                    }
                    f.exec(callback);
                });

            }else{
                callback("Installation failed");
            }
        }else{
            callback("Error while installing " + packageName);
        }
    });
}<|endoftext|>


<commit_before>import React, {Component, Fragment} from 'react';
import round from 'lodash/round';

import Table from 'src/Table';
import Switcher from 'src/Switcher';
import IconButton from 'src/IconButton';
import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';
import RaisedButton from 'src/RaisedButton';

import PropTypeDescTable from 'components/PropTypeDescTable';
import doc from 'assets/propTypes/Table.json';

import 'scss/containers/app/modules/layout/TableExamples.scss';

class TableExamples extends Component {

    constructor(props) {

        super(props);

        this.state = {
            data: this.generateData(),
            sort: null
        };

        this.columns = [{
            fixed: Table.Fixed.LEFT,
            headRenderer: 'ID',
            bodyRenderer: 'id',
            footRenderer: 'Total',
            footSpan: 2,
            sortable: true,
            sortingProp: 'id'
        }, {
            fixed: Table.Fixed.LEFT,
            width: 300,
            headRenderer: 'Name',
            bodyRenderer: '${firstName} ${lastName}',
            sortable: true,
            sortingProp: 'firstName'
        }, {
            headRenderer: 'Age',
            headAlign: Table.Align.RIGHT,
            bodyRenderer: 'age',
            bodyAlign: Table.Align.RIGHT,
            footRenderer: () => {
                const {data} = this.state;
                return (
                    <Fragment>

Average

{data.reduce((a, b) => a + b.age, 0) / data.length}

                    </Fragment>
                );
            },
            footAlign: Table.Align.RIGHT,
            sortable: true,
            sortingProp: 'age'
        }, {
            headRenderer: 'Deposit',
            headAlign: Table.Align.RIGHT,
            bodyRenderer: '$${deposit}',
            bodyAlign: Table.Align.RIGHT,
            footRenderer: () =>
                <Fragment>

Sum

${this.state.data.reduce((a, b) => round(a + b.deposit, 2), 0)}

                </Fragment>,
            footAlign: Table.Align.RIGHT,
            sortable: true,
            sortingProp: 'deposit'
        }, {
            fixed: Table.Fixed.RIGHT,
            headRenderer: 'Status',
            bodyRenderer: rowData =>
                <Switcher value={!rowData.disabled}
                          size="small"
                          onClick={e => e.stopPropagation()}/>
        }];

        this.pageSizes = [{
            value: 10,
            text: '10 / page'
        }, {
            value: 20,
            text: '20 / page'
        }, {
            value: 30,
            text: '30 / page'
        }, {
            value: 40,
            text: '40 / page'
        }, {
            value: 50,
            text: '50 / page'
        }];

    }

    generateData = (size = 100) => {

        let data = [];
        for (let i = 0; i < size; i++) {
            data.push({
                id: i,
                firstName: `firstName${i}`,
                lastName: `lastName${i}`,
                age: Math.floor(Math.random() * 100),
                deposit: round(Math.random() * 1000000, 2),
                childrenNum: i === 0 ? 9 : 0
            });
        }

        return data;

    };

    deleteRow = id => {

        const {data} = this.state,
            newData = data.filter(item => item.id !== id);

        this.setState({
            data: newData
        });

    };

    sortHandler = sort => {
        this.setState({
            sort
        });
        console.log('Sort Change Value: ', sort);
    };

    pageChangeHandler = (page, pageSize) => {
        console.log(`page: ${page}, pageSize: ${pageSize}`);
    };

    dataUpdateHandler = currentPageData => {
        console.log('Data Update Value: ', currentPageData);
    };

    selectHandler = (rowData, rowIndex, value) => {
        console.log('Select Value: ', rowData);
    };

    deselectHandler = (rowData, rowIndex, value) => {
        console.log('Deselect Value: ', rowData);
    };

    selectAllHandler = value => {
        console.log('Select All Value: ', value);
    };

    deselectAllHandler = value => {
        console.log('Deselect All Value: ', value);
    };

    changeHandler = value => {
        console.log('Changed Value: ', value);
    };

    clearSort = () => {
        this.setState({
            sort: null
        });
    };

    render() {

        const {data, sort} = this.state;

        return (

Table

                    Tables
                    are used to display data and to organize it.

Examples

                <Widget>

                    <WidgetHeader className="example-header" title="With isPagging"/>

A simple Table example.

                            <RaisedButton className="table-action"
                                          theme={RaisedButton.Theme.PRIMARY}
                                          value="Clear Table Sort"
                                          onClick={this.clearSort}/>

                                           <IconButton iconCls="fas fa-trash-alt"
                                                       onClick={() => this.deleteRow(rowData.id)}/>
                                   }]}
                                   sort={sort}
                                   isHeadFixed={true}
                                   isFootFixed={true}
                                   scroll={{
                                       width: 800,
                                       height: 400
                                   }}
                                   paggingCountRenderer={count => Self Defined Total Count: {count}}
                                   onSortChange={this.sortHandler}
                                   onPageChange={this.pageChangeHandler}
                                   onDataUpdate={this.dataUpdateHandler}/>

                </Widget>

                {/*<Widget>*/}

                {/*<WidgetHeader className="example-header" title="With hasLineNumber and isMultiSelect"/>*/}

                {/*
*/}
                {/*
*/}

                {/*
A more complex example.Set the hasLineNumber and isMultiSelect*/}
                {/*to true for showLineNumber and checkbox.
*/}

                {/*<Table data={data}*/}
                {/*columns={this.columns}*/}
                {/*selectMode={Table.SelectMode.MULTI_SELECT}*/}
                {/*selectAllMode={Table.SelectAllMode.CURRENT_PAGE}*/}
                {/*paggingSelectedCountVisible={true}*/}
                {/*defaultPageSize={20}*/}
                {/*pageSizes={this.pageSizes}*/}
                {/*useFullPagging={true}*/}
                {/*sortingAscIconCls="fas fa-caret-up"*/}
                {/*sortingDescIconCls="fas fa-caret-down"*/}
                {/*onPageChange={this.pageChangeHandler}*/}
                {/*onSelect={this.selectHandler}*/}
                {/*onDeselect={this.deselectHandler}*/}
                {/*onSelectAll={this.selectAllHandler}*/}
                {/*onDeselectAll={this.deselectAllHandler}*/}
                {/*onChange={this.changeHandler}/>*/}

                {/*
*/}
                {/*
*/}

                {/*</Widget>*/}

                {/*<Widget>*/}

                {/*<WidgetHeader className="example-header" title="Empty"/>*/}

                {/*
*/}
                {/*
*/}
                {/*
*/}
                {/*
*/}
                {/*
*/}

                {/*</Widget>*/}

Properties

                {/*<PropTypeDescTable data={doc}/>*/}

        );
    }
}

export default TableExamples;
<commit_msg>update TableExamples<commit_after>import React, {Component, Fragment} from 'react';
import round from 'lodash/round';

import Table from 'src/Table';
import Switcher from 'src/Switcher';
import IconButton from 'src/IconButton';
import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';
import RaisedButton from 'src/RaisedButton';

import PropTypeDescTable from 'components/PropTypeDescTable';
import doc from 'assets/propTypes/Table.json';

import 'scss/containers/app/modules/layout/TableExamples.scss';

class TableExamples extends Component {

    constructor(props) {

        super(props);

        this.state = {
            data: this.generateData(),
            sort: null
        };

        this.columns = [{
            fixed: Table.Fixed.LEFT,
            headRenderer: 'ID',
            bodyRenderer: 'id',
            footRenderer: 'Total',
            footSpan: 2,
            sortable: true,
            sortingProp: 'id'
        }, {
            fixed: Table.Fixed.LEFT,
            width: 300,
            headRenderer: 'Name',
            bodyRenderer: '${firstName} ${lastName}',
            sortable: true,
            sortingProp: 'firstName'
        }, {
            headRenderer: 'Age',
            headAlign: Table.Align.RIGHT,
            bodyRenderer: 'age',
            bodyAlign: Table.Align.RIGHT,
            footRenderer: () => {
                const {data} = this.state;
                return (
                    <Fragment>

Average

{data.reduce((a, b) => a + b.age, 0) / data.length}

                    </Fragment>
                );
            },
            footAlign: Table.Align.RIGHT,
            sortable: true,
            sortingProp: 'age'
        }, {
            headRenderer: 'Deposit',
            headAlign: Table.Align.RIGHT,
            bodyRenderer: '$${deposit}',
            bodyAlign: Table.Align.RIGHT,
            footRenderer: () =>
                <Fragment>

Sum

${this.state.data.reduce((a, b) => round(a + b.deposit, 2), 0)}

                </Fragment>,
            footAlign: Table.Align.RIGHT,
            sortable: true,
            sortingProp: 'deposit'
        }, {
            headRenderer: 'Other Column 1'
        }, {
            headRenderer: 'Other Column 2'
        }, {
            headRenderer: 'Other Column 3'
        }, {
            headRenderer: 'Other Column 4'
        }, {
            fixed: Table.Fixed.RIGHT,
            headRenderer: 'Status',
            bodyRenderer: rowData =>
                <Switcher value={!rowData.disabled}
                          size="small"
                          onClick={e => e.stopPropagation()}/>
        }];

        this.pageSizes = [{
            value: 10,
            text: '10 / page'
        }, {
            value: 20,
            text: '20 / page'
        }, {
            value: 30,
            text: '30 / page'
        }, {
            value: 40,
            text: '40 / page'
        }, {
            value: 50,
            text: '50 / page'
        }];

    }

    generateData = (size = 100) => {

        let data = [];
        for (let i = 0; i < size; i++) {
            data.push({
                id: i,
                firstName: `firstName${i}`,
                lastName: `lastName${i}`,
                age: Math.floor(Math.random() * 100),
                deposit: round(Math.random() * 1000000, 2),
                childrenNum: i === 0 ? 9 : 0
            });
        }

        return data;

    };

    deleteRow = id => {

        const {data} = this.state,
            newData = data.filter(item => item.id !== id);

        this.setState({
            data: newData
        });

    };

    sortHandler = sort => {
        this.setState({
            sort
        });
        console.log('Sort Change Value: ', sort);
    };

    pageChangeHandler = (page, pageSize) => {
        console.log(`page: ${page}, pageSize: ${pageSize}`);
    };

    dataUpdateHandler = currentPageData => {
        console.log('Data Update Value: ', currentPageData);
    };

    selectHandler = (rowData, rowIndex, value) => {
        console.log('Select Value: ', rowData);
    };

    deselectHandler = (rowData, rowIndex, value) => {
        console.log('Deselect Value: ', rowData);
    };

    selectAllHandler = value => {
        console.log('Select All Value: ', value);
    };

    deselectAllHandler = value => {
        console.log('Deselect All Value: ', value);
    };

    changeHandler = value => {
        console.log('Changed Value: ', value);
    };

    clearSort = () => {
        this.setState({
            sort: null
        });
    };

    render() {

        const {data, sort} = this.state;

        return (

Table

                    Tables
                    are used to display data and to organize it.

Examples

                <Widget>

                    <WidgetHeader className="example-header" title="With isPagging"/>

A simple Table example.

                            <RaisedButton className="table-action"
                                          theme={RaisedButton.Theme.PRIMARY}
                                          value="Clear Table Sort"
                                          onClick={this.clearSort}/>

                                           <IconButton iconCls="fas fa-trash-alt"
                                                       onClick={() => this.deleteRow(rowData.id)}/>
                                   }]}
                                   sort={sort}
                                   isHeadFixed={true}
                                   isFootFixed={true}
                                   scroll={{
                                       width: 800,
                                       height: 400
                                   }}
                                   paggingCountRenderer={count => Self Defined Total Count: {count}}
                                   onSortChange={this.sortHandler}
                                   onPageChange={this.pageChangeHandler}
                                   onDataUpdate={this.dataUpdateHandler}/>

                </Widget>

                {/*<Widget>*/}

                {/*<WidgetHeader className="example-header" title="With hasLineNumber and isMultiSelect"/>*/}

                {/*
*/}
                {/*
*/}

                {/*
A more complex example.Set the hasLineNumber and isMultiSelect*/}
                {/*to true for showLineNumber and checkbox.
*/}

                {/*<Table data={data}*/}
                {/*columns={this.columns}*/}
                {/*selectMode={Table.SelectMode.MULTI_SELECT}*/}
                {/*selectAllMode={Table.SelectAllMode.CURRENT_PAGE}*/}
                {/*paggingSelectedCountVisible={true}*/}
                {/*defaultPageSize={20}*/}
                {/*pageSizes={this.pageSizes}*/}
                {/*useFullPagging={true}*/}
                {/*sortingAscIconCls="fas fa-caret-up"*/}
                {/*sortingDescIconCls="fas fa-caret-down"*/}
                {/*onPageChange={this.pageChangeHandler}*/}
                {/*onSelect={this.selectHandler}*/}
                {/*onDeselect={this.deselectHandler}*/}
                {/*onSelectAll={this.selectAllHandler}*/}
                {/*onDeselectAll={this.deselectAllHandler}*/}
                {/*onChange={this.changeHandler}/>*/}

                {/*
*/}
                {/*
*/}

                {/*</Widget>*/}

                {/*<Widget>*/}

                {/*<WidgetHeader className="example-header" title="Empty"/>*/}

                {/*
*/}
                {/*
*/}
                {/*
*/}
                {/*
*/}
                {/*
*/}

                {/*</Widget>*/}

Properties

                {/*<PropTypeDescTable data={doc}/>*/}

        );
    }
}

export default TableExamples;
<|endoftext|>