<commit_before>// http://jon.haslett.id.au/post/37391562488/fixing-the-hover-problem-on-touch-screens-with-feature
if (!("ontouchstart" in document.documentElement)) {
  document.documentElement.className += " no-touch";
}

if ($("#ractive-allocations").length) {
  var Allocations = Ractive.extend({
    el: "ractive-allocations",
    template: "#allocationsTemplate",
    data: {
      plan: gon.plan.plan,
      events: gon.plan.events,
      kits: gon.plan.kits,
      owner: gon.plan.owner,
      plural: function(count) { return (count === 1) ? "" : "s"; }
    },
    init: function() {
      var self = this;

      self.set("selectedEvent", self.get("events.0"));
      self.set("newTask", "");

      self.on("select-event", function(event) {
        self.set("selectedEvent", event.context);
        $.scrollTo(".main-page", 750);
      });

      self.on("key", function(event) {
        if (event.original.keyCode === 13) {
          self.addTask(event.context.newTask, self);
        }
      });

      self.on("add-task", function(event) {
        self.addTask(event.context.newTask, self);
      });

      self.on("remove-task", function(event) {
        self.removeTask(event.context, event.index.i, self);
      });

      self.on("move-task", function(event) {
        self.moveTask(event.context, self);
      });

      var update_plan_endpoint = '/plans/private/' + self.get("plan.private_guid") + '/update';
      $('.plan-name .edit').editable(update_plan_endpoint, {
        indicator : 'Saving...',
        name      : 'name'
      });

      $('.plan-postcode .edit').editable(update_plan_endpoint, {
        indicator : 'Saving...',
        name      : 'postcode'
      });
    },

    addTask: function(name, self) {
      if (name.trim() !== "") {
        $.ajax({
          type: "POST",
          url: "/tasks/",
          data: {
            name: name,
            event_id: this.get("selectedEvent.event.id"),
            owner_id: this.get("owner.id")
          },
          success: function(data) {
            self.get("selectedEvent.custom_tasks").push(data);
            self.set("newTask", "");
            self.update();
            self.get("selectedEvent.custom_tasks").last().effect( "bounce", "slow" );
          }
        });
      }
    },

    removeTask: function(task, index, self) {
      $.ajax({
        type: "POST",
        url: "/tasks/" + task.id,
        data: { "_method": "delete" },
        success: function() {
          var tasks = self.get("selectedEvent.custom_tasks");
          tasks.splice(index, 1);
          self.update();
        }
      });
    },

    moveTask: function(task, self) {
      $.ajax({
        type: "POST",
        url: "/tasks/",
        data: { task_id: task.id, owner_id: self.get("owner.id") },
        success: function(data) {
          self.get("selectedEvent.custom_tasks").push(data);
          self.update();
        }
      });
    }

  });

  var allocations = new Allocations();
}

//function createAllocation(task_id, person_id) {
  //var xhr = new XMLHttpRequest();
  //xhr.open('POST', '/allocations', true);
  //xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
  //xhr.onload = function(e) {
    //if (this.status == 200) {
      //var resp = JSON.parse(this.responseText);
      //var position = $('table#allocations tbody > tr').length;
      //var html = ""
        //html +="
";
        //html +=  "
"+paddedPosition(position)+"
	"
        //html +=  ""+resp.task_name+"	";
        //html +=  "	"
        //html +="
"
      //$( html ).appendTo( $( "table#allocations") );

      //$('table#allocations').find('tr#add-row').appendTo('table#allocations'); // move the Add to the end of the list..
      //$('td#add').text('Click here to add your own task'); // work-around bad binding

      //$("td.allocation-delete[data-id='"+resp.allocation_id+"']").bind('click', deleteAllocation);
    //}
  //};
  //current_event_id = $('dl.sub-nav dd.active').attr('data-id');
  //xhr.send(JSON.stringify({id: current_event_id, allocation: {task_id: task_id, person_id: person_id}}));
//}

//function deleteAllocation(e){
  //var elem = this;
  //if(confirm("Are you sure you want to delete this task?")){
    //$.ajax({
      //url: '/allocations/' + elem.getAttribute('data-id'),
      //type: 'post',
      //dataType: 'script',
      //data: { '_method': 'delete' },
      //success: function() {
        //$(elem.parentNode).remove();
        //updateTaskNumbering();
      //}
    //});
    //return false;
  //} else {
    //return false;
  //}
//}

//function paddedPosition(position) {
  //return position.toString().length === 1 ? '0' + position : position;
//}

//function updateTaskNumbering() {
  //$('td.allocation-signature h4').each(function( index ) {
    //$( this ).text(paddedPosition(index + 1));
  //});
//}

//$(function($) { // document ready

   //START: http://www.appelsiini.net/projects/jeditable
  //plan_private_guid = $( "span#private-guid" ).attr('data-id');
  //var update_plan_endpoint = '/plans/private/'+plan_private_guid+'/update';
  //$('.edit#name').editable(update_plan_endpoint, {
    //indicator : 'Saving...',
    //name      : 'name'
  //});

  //$('.edit#postcode').editable(update_plan_endpoint, {
    //indicator : 'Saving...',
    //name      : 'postcode'
  //});

  //$('.edit#add').editable('/allocations', {
    //indicator  : 'Saving...',
    //name       : 'name',
    //data       : ' ', // empty string doesn't work unfortunately
    //submitdata : function(value, settings) {
      //var person_id = $('span#person-id').attr('data-id');
      //var event_id  = $('dl.sub-nav dd.active').attr('data-id');
      //return {person_id: person_id, event_id: event_id};
    //},
    //callback : function(value, settings) {
      //var resp = JSON.parse(value);

      //var position = $('table#allocations tbody > tr').length.toString();
      //var padded_position = position.length === 1 ? '0' + position : position;
      //var html = ""
        //html +="
";
        //html +=  "
"+padded_position+"
	"
        //html +=  ""+resp.task_name+"	";
        //html +=  "	"
        //html +="
"
      //$( html ).appendTo( $( "table#allocations") );

      //$('table#allocations').find('tr#add-row').appendTo('table#allocations'); // move the Add to the end of the list..
      //$('td#add').text('Click here to add your own task'); // work-around bad binding

      //$("td.allocation-delete[data-id='"+resp.allocation_id+"']").bind('click', deleteAllocation);
     //}
  //});
   //END

  //$('td.allocation-delete').bind('click', deleteAllocation);

  //$('table#tasks td.red-margin').draggable({
    //opacity: 0.7,
    //cursor: "pointer",
    //cursorAt: { top: 0, left: 0 },
    //helper: function() { return $(this.parentElement).find('td.suggested').clone()[0]; }
  //});

  //$( "table#allocations" ).droppable({
    //activeClass: "ui-state-highlight",
    //hoverClass: "ui-state-hover",
    //accept: "table#tasks td.red-margin",
    //tolerance: 'pointer',
    //drop: function( event, ui ) {
      //task_id = ui.helper.attr("data-id");
      //person_id = $( "span#person-id" ).attr('data-id');
      //createAllocation(task_id, person_id);
    //}
  //});
//});
<commit_msg>could be time to call it a night..<commit_after>// http://jon.haslett.id.au/post/37391562488/fixing-the-hover-problem-on-touch-screens-with-feature
if (!("ontouchstart" in document.documentElement)) {
  document.documentElement.className += " no-touch";
}

if ($("#ractive-allocations").length) {
  var Allocations = Ractive.extend({
    el: "ractive-allocations",
    template: "#allocationsTemplate",
    data: {
      plan: gon.plan.plan,
      events: gon.plan.events,
      kits: gon.plan.kits,
      owner: gon.plan.owner,
      plural: function(count) { return (count === 1) ? "" : "s"; }
    },
    init: function() {
      var self = this;

      self.set("selectedEvent", self.get("events.0"));
      self.set("newTask", "");

      self.on("select-event", function(event) {
        self.set("selectedEvent", event.context);
        $.scrollTo(".main-page", 750);
      });

      self.on("key", function(event) {
        if (event.original.keyCode === 13) {
          self.addTask(event.context.newTask, self);
        }
      });

      self.on("add-task", function(event) {
        self.addTask(event.context.newTask, self);
      });

      self.on("remove-task", function(event) {
        self.removeTask(event.context, event.index.i, self);
      });

      self.on("move-task", function(event) {
        self.moveTask(event.context, self);
      });

      var update_plan_endpoint = '/plans/private/' + self.get("plan.private_guid") + '/update';
      $('.plan-name .edit').editable(update_plan_endpoint, {
        indicator : 'Saving...',
        name      : 'name'
      });

      $('.plan-postcode .edit').editable(update_plan_endpoint, {
        indicator : 'Saving...',
        name      : 'postcode'
      });
    },

    addTask: function(name, self) {
      if (name.trim() !== "") {
        $.ajax({
          type: "POST",
          url: "/tasks/",
          data: {
            name: name,
            event_id: this.get("selectedEvent.event.id"),
            owner_id: this.get("owner.id")
          },
          success: function(data) {
            self.get("selectedEvent.custom_tasks").push(data);
            self.set("newTask", "");
            self.update();
          }
        });
      }
    },

    removeTask: function(task, index, self) {
      $.ajax({
        type: "POST",
        url: "/tasks/" + task.id,
        data: { "_method": "delete" },
        success: function() {
          var tasks = self.get("selectedEvent.custom_tasks");
          tasks.splice(index, 1);
          self.update();
        }
      });
    },

    moveTask: function(task, self) {
      $.ajax({
        type: "POST",
        url: "/tasks/",
        data: { task_id: task.id, owner_id: self.get("owner.id") },
        success: function(data) {
          self.get("selectedEvent.custom_tasks").push(data);
          self.update();
        }
      });
    }

  });

  var allocations = new Allocations();
}

//function createAllocation(task_id, person_id) {
  //var xhr = new XMLHttpRequest();
  //xhr.open('POST', '/allocations', true);
  //xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
  //xhr.onload = function(e) {
    //if (this.status == 200) {
      //var resp = JSON.parse(this.responseText);
      //var position = $('table#allocations tbody > tr').length;
      //var html = ""
        //html +="
";
        //html +=  "
"+paddedPosition(position)+"
	"
        //html +=  ""+resp.task_name+"	";
        //html +=  "	"
        //html +="
"
      //$( html ).appendTo( $( "table#allocations") );

      //$('table#allocations').find('tr#add-row').appendTo('table#allocations'); // move the Add to the end of the list..
      //$('td#add').text('Click here to add your own task'); // work-around bad binding

      //$("td.allocation-delete[data-id='"+resp.allocation_id+"']").bind('click', deleteAllocation);
    //}
  //};
  //current_event_id = $('dl.sub-nav dd.active').attr('data-id');
  //xhr.send(JSON.stringify({id: current_event_id, allocation: {task_id: task_id, person_id: person_id}}));
//}

//function deleteAllocation(e){
  //var elem = this;
  //if(confirm("Are you sure you want to delete this task?")){
    //$.ajax({
      //url: '/allocations/' + elem.getAttribute('data-id'),
      //type: 'post',
      //dataType: 'script',
      //data: { '_method': 'delete' },
      //success: function() {
        //$(elem.parentNode).remove();
        //updateTaskNumbering();
      //}
    //});
    //return false;
  //} else {
    //return false;
  //}
//}

//function paddedPosition(position) {
  //return position.toString().length === 1 ? '0' + position : position;
//}

//function updateTaskNumbering() {
  //$('td.allocation-signature h4').each(function( index ) {
    //$( this ).text(paddedPosition(index + 1));
  //});
//}

//$(function($) { // document ready

   //START: http://www.appelsiini.net/projects/jeditable
  //plan_private_guid = $( "span#private-guid" ).attr('data-id');
  //var update_plan_endpoint = '/plans/private/'+plan_private_guid+'/update';
  //$('.edit#name').editable(update_plan_endpoint, {
    //indicator : 'Saving...',
    //name      : 'name'
  //});

  //$('.edit#postcode').editable(update_plan_endpoint, {
    //indicator : 'Saving...',
    //name      : 'postcode'
  //});

  //$('.edit#add').editable('/allocations', {
    //indicator  : 'Saving...',
    //name       : 'name',
    //data       : ' ', // empty string doesn't work unfortunately
    //submitdata : function(value, settings) {
      //var person_id = $('span#person-id').attr('data-id');
      //var event_id  = $('dl.sub-nav dd.active').attr('data-id');
      //return {person_id: person_id, event_id: event_id};
    //},
    //callback : function(value, settings) {
      //var resp = JSON.parse(value);

      //var position = $('table#allocations tbody > tr').length.toString();
      //var padded_position = position.length === 1 ? '0' + position : position;
      //var html = ""
        //html +="
";
        //html +=  "
"+padded_position+"
	"
        //html +=  ""+resp.task_name+"	";
        //html +=  "	"
        //html +="
"
      //$( html ).appendTo( $( "table#allocations") );

      //$('table#allocations').find('tr#add-row').appendTo('table#allocations'); // move the Add to the end of the list..
      //$('td#add').text('Click here to add your own task'); // work-around bad binding

      //$("td.allocation-delete[data-id='"+resp.allocation_id+"']").bind('click', deleteAllocation);
     //}
  //});
   //END

  //$('td.allocation-delete').bind('click', deleteAllocation);

  //$('table#tasks td.red-margin').draggable({
    //opacity: 0.7,
    //cursor: "pointer",
    //cursorAt: { top: 0, left: 0 },
    //helper: function() { return $(this.parentElement).find('td.suggested').clone()[0]; }
  //});

  //$( "table#allocations" ).droppable({
    //activeClass: "ui-state-highlight",
    //hoverClass: "ui-state-hover",
    //accept: "table#tasks td.red-margin",
    //tolerance: 'pointer',
    //drop: function( event, ui ) {
      //task_id = ui.helper.attr("data-id");
      //person_id = $( "span#person-id" ).attr('data-id');
      //createAllocation(task_id, person_id);
    //}
  //});
//});
<|endoftext|>


<commit_before>
define(['jquery', 'common'], function ($, MAS) {
  'use strict';

  var defaults = {
    name: 'not set',

    // Setup
    triggerEl: '.collapsible',
    targetEl: '.collapsible-section',
    targetType: 'class', // class / href / data-attr
    activeClass: 'is-on',
    inactiveClass: 'is-off',
    closeOffFocus: false,
    parentWrapper: false,
    accordion: false,
    showOnlyFirst: false,

    // Display options
    showText: true,
    showIcon: false,
    headingIcon: '',
    headingText: '{{txt}}',
    useButton: false,

    // Localised text strings
    textString: {
      showThisSection: MAS.text.show || 'Show',
      hideThisSection: MAS.text.hide || 'Hide'
    },

    // Callbacks
    onSelect: false,
    onFocusout: false
  };

  var _isHidden = function(target, opts){
    if( target.hasClass(opts.inactiveClass) ) return true;
    if( target.hasClass(opts.activeClass) ) return false;
    return target.is(':hidden');
  };

  var _getTarget = function($el, opts){
    switch(opts.targetType){
    case 'class':
      return $el.next(opts.targetEl);
    case 'href':
      var href = $el.attr('href'),
        $t = $(href);
      return ($t.length)? $t : false;
    default:
      return false;
    }
  };

  var Collapsible = function(opts){
    this.o = $.extend({}, defaults, opts);
    this.sections = [];
    this.selected = false;

    var _this = this,
        triggers = $(this.o.triggerEl),
        l = triggers.length,
        i = 0;

    if(l === 0){
      return MAS.warn('mas_collapsible => no trigger elements in page: ' + this.o.triggerEl);
    }

    for(i; i<l; i++){
      this._setupEach.call(this, i, triggers[i]);
    }

    if(this.o.closeOffFocus){
      this.$parent = $(this.o.parentWrapper);

      if(!this.o.parentWrapper || !this.$parent.length) {
        MAS.warn('options.parentWrapper should be set & valid for closeOffFocus to work properly');
        return;
      }

      this.$parent.on('focusout', $.proxy(_this._delayDomCheck, _this));
    }
  };

  Collapsible.prototype._delayDomCheck = function(){
    setTimeout( $.proxy(function(){
      if( this.$parent.find(document.activeElement).length === 0 && this.selected !== false){
        // Callback
        if(typeof this.o.onFocusout === 'function') this.o.onFocusout(this);
        // Action
        this.hide(this.selected);
      }
    },this),300);
  };

  Collapsible.prototype._modifyButtonHTML = function(i){
    var trigger = this.sections[i].trigger,
        txt = (this.o.showText) ?
          this.o.headingText.replace('{{txt}}', this.o.textString.showThisSection) :
          '',
        icon = (this.o.showIcon)? this.o.headingIcon : '';

    if(this.o.useButton){
      var buttonTitle = trigger.text();

      if(trigger[0].nodeName === 'A'){
        // Anchor => replace elemnt
        var newEl = $('')
          .addClass(trigger[0].className)
          .attr('id', trigger[0])
          .text(icon + txt + buttonTitle);
        // add new
        trigger.after(newEl);
        // remove old
        trigger.remove();
        trigger = newEl;
      }else{
        // Anything else => insert button inside
        trigger.html('<button class="unstyled-button">' + icon + txt + buttonTitle  + '</button>');
      }
    }else{
      // Use aria-role
      trigger.attr('aria-role','button');
      trigger.attr('tabindex', '0');
      trigger.prepend(icon);
      trigger.prepend(txt);
    }

    if(this.o.showIcon) this.sections[i].icon = trigger.find('.icon');
    if(this.o.showText) this.sections[i].txt = trigger.find('.visually-hidden');
  };

  Collapsible.prototype._setupEach = function(i,el){
    var $el = $(el),
      _this = this,
      _target = _getTarget($el, _this.o);

    this.sections[i] = {
      index: i,
      trigger: $el,
      target: _target,
      hidden: _isHidden(_target, _this.o)
    };

    // Dont modify or bind events if no target element
    if(!this.sections[i].target.length) return;

    // Set show / hide states based on options
    if(this.o.showOnlyFirst){
      this.sections[i].hidden = (i === 0)? false : true;
    }

    // For accordions, if there is a selected item, hide other items
    if(this.o.accordion && this.selected !== false && this.sections[i].hidden){
      this.sections[i].hidden = true;
    }

    // Update Button HTML to make accessible
    this._modifyButtonHTML(i);

    // Set initial state
    this.setVisibility(!this.sections[i].hidden,i);

    // Bind events
    this.sections[i].trigger.on('click', i, function(e){
      e.preventDefault();
      // Check for callbacks
      if(typeof _this.o.onSelect === 'function') _this.o.onSelect(_this.sections[i]);
      _this.setVisibility(_this.sections[i].hidden, i);
    });

    // Accessibility support for spacebar
    this.sections[i].trigger.on('keypress', function(e){
      if(e.which === 32 && _this.sections[i].trigger[0].nodeName !== 'BUTTON' &&
          !_this.o.useButton) {
        e.preventDefault();
        _this.sections[i].trigger.trigger('click');
      }
    });
    return this;
  };

  Collapsible.prototype.setVisibility = function(show,i){
    var method = (show)? 'show' : 'hide';
    this[method](i);
    return this;
  };

  function publishEvent(userInitiated, data){
    if(userInitiated){
      data.module = 'collapsable';
      MAS.publish('collapsable', data);
      MAS.publish('analytics:trigger', data);
    }
  }

  Collapsible.prototype.show = function(i, userInitiated){
    publishEvent(userInitiated, {
      name: this.o.name,
      index: i,
      action: 'show'
    });

    var item = this.sections[i];
    item.trigger.removeClass(this.o.inactiveClass).addClass(this.o.activeClass);
    item.target.removeClass(this.o.inactiveClass).addClass(this.o.activeClass);
    item.target.attr('aria-hidden', 'false');
    item.hidden = false;
    if(this.o.showText) item.txt.text(this.o.textString.hideThisSection);
    if(this.o.accordion && (this.selected !== false && this.selected !== i)) {
      this.hide(this.selected, false);
    }
    this.selected = i;
    return this;
  };

  Collapsible.prototype.hide = function(i, userInitiated){
    publishEvent(userInitiated, {
      name: this.o.name,
      index: i,
      action: 'hide'
    });

    var item = this.sections[i];
    item.trigger.removeClass(this.o.activeClass).addClass(this.o.inactiveClass);
    item.target.removeClass(this.o.activeClass).addClass(this.o.inactiveClass);
    item.target.attr('aria-hidden', 'true');
    item.hidden = true;
    if(this.o.showText) item.txt.text(this.o.textString.showThisSection);
    return this;
  };

  return Collapsible;
});
<commit_msg>fix #1396 collapsable accessibility<commit_after>
define(['jquery', 'common'], function ($, MAS) {
  'use strict';

  var defaults = {
    name: 'not set',

    // Setup
    triggerEl: '.collapsible',
    targetEl: '.collapsible-section',
    targetType: 'class', // class / href / data-attr
    activeClass: 'is-on',
    inactiveClass: 'is-off',
    closeOffFocus: false,
    parentWrapper: false,
    accordion: false,
    showOnlyFirst: false,

    // Display options
    showText: true,
    showIcon: false,
    headingIcon: '',
    headingText: '{{txt}}',
    useButton: false,

    // Localised text strings
    textString: {
      showThisSection: MAS.text.show || 'Show',
      hideThisSection: MAS.text.hide || 'Hide'
    },

    // Callbacks
    onSelect: false,
    onFocusout: false
  };

  var _isHidden = function(target, opts){
    if( target.hasClass(opts.inactiveClass) ) return true;
    if( target.hasClass(opts.activeClass) ) return false;
    return target.is(':hidden');
  };

  var _getTarget = function($el, opts){
    switch(opts.targetType){
    case 'class':
      return $el.next(opts.targetEl);
    case 'href':
      var href = $el.attr('href'),
        $t = $(href);
      return ($t.length)? $t : false;
    default:
      return false;
    }
  };

  var Collapsible = function(opts){
    this.o = $.extend({}, defaults, opts);
    this.sections = [];
    this.selected = false;

    var _this = this,
        triggers = $(this.o.triggerEl),
        l = triggers.length,
        i = 0;

    if(l === 0){
      return MAS.warn('mas_collapsible => no trigger elements in page: ' + this.o.triggerEl);
    }

    for(i; i<l; i++){
      this._setupEach.call(this, i, triggers[i]);
    }

    if(this.o.closeOffFocus){
      this.$parent = $(this.o.parentWrapper);

      if(!this.o.parentWrapper || !this.$parent.length) {
        MAS.warn('options.parentWrapper should be set & valid for closeOffFocus to work properly');
        return;
      }

      this.$parent.on('focusout', $.proxy(_this._delayDomCheck, _this));
    }
  };

  Collapsible.prototype._delayDomCheck = function(){
    setTimeout( $.proxy(function(){
      if( this.$parent.find(document.activeElement).length === 0 && this.selected !== false){
        // Callback
        if(typeof this.o.onFocusout === 'function') this.o.onFocusout(this);
        // Action
        this.hide(this.selected);
      }
    },this),300);
  };

  Collapsible.prototype._modifyButtonHTML = function(i){
    var trigger = this.sections[i].trigger,
        txt = (this.o.showText) ?
          this.o.headingText.replace('{{txt}}', this.o.textString.showThisSection) :
          '',
        icon = (this.o.showIcon)? this.o.headingIcon : '';

    if(this.o.useButton){
      var buttonTitle = trigger.text();

      if(trigger[0].nodeName === 'A'){
        // Anchor => replace elemnt
        var newEl = $('')
          .addClass(trigger[0].className)
          .attr('id', trigger[0])
          .text(icon + txt + buttonTitle);
        // add new
        trigger.after(newEl);
        // remove old
        trigger.remove();
        trigger = newEl;
      }else{
        // Anything else => insert button inside
        trigger.html('<button class="unstyled-button">' + icon + txt + buttonTitle  + '</button>');
      }
    }else{
      // Use aria-role
      trigger.attr('aria-role','button');
      trigger.attr('tabindex', '0');
      trigger.prepend(icon);
      trigger.prepend(txt);
    }

    if(this.o.showIcon) this.sections[i].icon = trigger.find('.icon');
    if(this.o.showText) this.sections[i].txt = trigger.find('.collapsable-hidden');
  };

  Collapsible.prototype._setupEach = function(i,el){
    var $el = $(el),
      _this = this,
      _target = _getTarget($el, _this.o);

    this.sections[i] = {
      index: i,
      trigger: $el,
      target: _target,
      hidden: _isHidden(_target, _this.o)
    };

    // Dont modify or bind events if no target element
    if(!this.sections[i].target.length) return;

    // Set show / hide states based on options
    if(this.o.showOnlyFirst){
      this.sections[i].hidden = (i === 0)? false : true;
    }

    // For accordions, if there is a selected item, hide other items
    if(this.o.accordion && this.selected !== false && this.sections[i].hidden){
      this.sections[i].hidden = true;
    }

    // Update Button HTML to make accessible
    this._modifyButtonHTML(i);

    // Set initial state
    this.setVisibility(!this.sections[i].hidden,i);

    // Bind events
    this.sections[i].trigger.on('click', i, function(e){
      e.preventDefault();
      // Check for callbacks
      if(typeof _this.o.onSelect === 'function') _this.o.onSelect(_this.sections[i]);
      _this.setVisibility(_this.sections[i].hidden, i);
    });

    // Accessibility support for spacebar
    this.sections[i].trigger.on('keypress', function(e){
      if(e.which === 32 && _this.sections[i].trigger[0].nodeName !== 'BUTTON' &&
          !_this.o.useButton) {
        e.preventDefault();
        _this.sections[i].trigger.trigger('click');
      }
    });
    return this;
  };

  Collapsible.prototype.setVisibility = function(show,i){
    var method = (show)? 'show' : 'hide';
    this[method](i);
    return this;
  };

  function publishEvent(userInitiated, data){
    if(userInitiated){
      data.module = 'collapsable';
      MAS.publish('collapsable', data);
      MAS.publish('analytics:trigger', data);
    }
  }

  Collapsible.prototype.show = function(i, userInitiated){
    publishEvent(userInitiated, {
      name: this.o.name,
      index: i,
      action: 'show'
    });

    var item = this.sections[i];
    item.trigger.removeClass(this.o.inactiveClass).addClass(this.o.activeClass);
    item.target.removeClass(this.o.inactiveClass).addClass(this.o.activeClass);
    item.target.attr('aria-hidden', 'false');
    item.hidden = false;
    if(this.o.showText) item.txt.text(this.o.textString.hideThisSection + ' ');
    if(this.o.accordion && (this.selected !== false && this.selected !== i)) {
      this.hide(this.selected, false);
    }
    this.selected = i;
    return this;
  };

  Collapsible.prototype.hide = function(i, userInitiated){
    publishEvent(userInitiated, {
      name: this.o.name,
      index: i,
      action: 'hide'
    });

    var item = this.sections[i];
    item.trigger.removeClass(this.o.activeClass).addClass(this.o.inactiveClass);
    item.target.removeClass(this.o.activeClass).addClass(this.o.inactiveClass);
    item.target.attr('aria-hidden', 'true');
    item.hidden = true;
    if(this.o.showText) item.txt.text(this.o.textString.showThisSection + ' ');
    return this;
  };

  return Collapsible;
});
<|endoftext|>


<commit_before>import Utils from "libs/utils";
import constants from "../constants";

// This is a class with static methods dealing with dimensions and
// conversions between them.

const Dimensions = {

  PLANE_XY: constants.PLANE_XY,
  PLANE_YZ: constants.PLANE_YZ,
  PLANE_XZ: constants.PLANE_XZ,
  TDView: constants.TDView,

  getIndices(planeID) {
    // Returns a ordered 3-tuple [x, y, z] which represents the dimensions from the viewpoint

    switch (planeID) {
      case constants.PLANE_XY: return [0, 1, 2];  // of each plane. For example, moving along the
      case constants.PLANE_YZ: return [2, 1, 0];  // X-Axis of the YZ-Plane is equivalent to moving
      case constants.PLANE_XZ: return [0, 2, 1];  // along the Z axis in the cube -> ind[0]=2
      default: throw new Error(`Unrecognized plane ID: ${planeID}`);
    }
  },

  transDim(array, planeID) {
    // Translate Dimension: Helper method to translate arrays with three elements

    const ind = this.getIndices(planeID);
    return [array[ind[0]], array[ind[1]], array[ind[2]]];
  },

  planeForThirdDimension(dim) {
    // Return the plane in which dim is always the same

    switch (dim) {
      case 2: return this.PLANE_XY;
      case 0: return this.PLANE_YZ;
      case 1: return this.PLANE_XZ;
      default: throw new Error(`Unrecognized dimension: ${dim}`);
    }
  },

  thirdDimensionForPlane(planeID) {
    // Opposite of planeForThirdDimension

    switch (planeID) {
      case this.PLANE_XY: return 2;
      case this.PLANE_YZ: return 0;
      case this.PLANE_XZ: return 1;
      default: throw new Error(`Unrecognized plane ID: ${planeID}`);
    }
  },

  round(number) {
    // Floor number, as done at texture rendering

    return ~~number;
  },

  roundCoordinate(coordinate) {
    const res = coordinate.slice();
    for (const i of Utils.__range__(0, res.length, false)) {
      res[i] = this.round(res[i]);
    }
    return res;
  },

  distance(pos1, pos2) {
    let sumOfSquares = 0;
    for (const i of Utils.__range__(0, pos1.length, false)) {
      const diff = pos1[i] - pos2[i];
      sumOfSquares += diff * diff;
    }
    return Math.sqrt(sumOfSquares);
  },
};

export default Dimensions;
<commit_msg>fix node selection on 3d-view<commit_after>import Utils from "libs/utils";
import constants from "../constants";

// This is a class with static methods dealing with dimensions and
// conversions between them.

const Dimensions = {

  PLANE_XY: constants.PLANE_XY,
  PLANE_YZ: constants.PLANE_YZ,
  PLANE_XZ: constants.PLANE_XZ,
  TDView: constants.TDView,

  getIndices(planeID) {
    // Returns a ordered 3-tuple [x, y, z] which represents the dimensions from the viewpoint

    switch (planeID) {
      case constants.PLANE_XY: return [0, 1, 2];  // of each plane. For example, moving along the
      case constants.PLANE_YZ: return [2, 1, 0];  // X-Axis of the YZ-Plane is equivalent to moving
      case constants.PLANE_XZ: return [0, 2, 1];  // along the Z axis in the cube -> ind[0]=2
      default: return null;
    }
  },

  transDim(array, planeID) {
    // Translate Dimension: Helper method to translate arrays with three elements

    const ind = this.getIndices(planeID);
    return [array[ind[0]], array[ind[1]], array[ind[2]]];
  },

  planeForThirdDimension(dim) {
    // Return the plane in which dim is always the same

    switch (dim) {
      case 2: return this.PLANE_XY;
      case 0: return this.PLANE_YZ;
      case 1: return this.PLANE_XZ;
      default: throw new Error(`Unrecognized dimension: ${dim}`);
    }
  },

  thirdDimensionForPlane(planeID) {
    // Opposite of planeForThirdDimension

    switch (planeID) {
      case this.PLANE_XY: return 2;
      case this.PLANE_YZ: return 0;
      case this.PLANE_XZ: return 1;
      default: throw new Error(`Unrecognized plane ID: ${planeID}`);
    }
  },

  round(number) {
    // Floor number, as done at texture rendering

    return ~~number;
  },

  roundCoordinate(coordinate) {
    const res = coordinate.slice();
    for (const i of Utils.__range__(0, res.length, false)) {
      res[i] = this.round(res[i]);
    }
    return res;
  },

  distance(pos1, pos2) {
    let sumOfSquares = 0;
    for (const i of Utils.__range__(0, pos1.length, false)) {
      const diff = pos1[i] - pos2[i];
      sumOfSquares += diff * diff;
    }
    return Math.sqrt(sumOfSquares);
  },
};

export default Dimensions;
<|endoftext|>


<commit_before>var disassemblerOptions = systemOptions.register(new OptionSet("Disassembler Options"));

var filter = disassemblerOptions.register(new Option("f", "filter", "string", "SpciMsm", "[S]ource, constant[p]ool, [c]lasses, [i]nstances, [M]etadata, [s]cripts, [m]ethods, multi[N]ames"));

function traceArray(writer, name, array, abc) {
  if (array.length === 0) {
    return;
  }
  writer.enter(name + " {");
  array.forEach(function (a, idx) {
    a.trace(writer, abc);
  });
  writer.leave("}");
}

AbcFile.prototype.trace = function trace(writer) {
  if (filter.value.indexOf("p") >= 0) {
    this.constantPool.trace(writer);
  }
  if (filter.value.indexOf("N") >= 0) {
    this.constantPool.traceMultinamesOnly(writer);
  }
  if (filter.value.indexOf("c") >= 0) {
    traceArray(writer, "classes", this.classes);
  }
  if (filter.value.indexOf("i") >= 0) {
    traceArray(writer, "instances", this.instances);
  }
  if (filter.value.indexOf("M") >= 0) {
    traceArray(writer, "metadata", this.metadata);
  }
  if (filter.value.indexOf("s") >= 0) {
    traceArray(writer, "scripts", this.scripts);
  }
  if (filter.value.indexOf("m") >= 0) {
    traceArray(writer, "methods", this.methods, this);
  }
  if (filter.value.indexOf("S") >= 0) {
    traceSource(writer, this);
  }
};

ConstantPool.prototype.trace = function (writer) {
  writer.enter("constantPool {");
  for (var key in this) {
    /* Special-case namespaces to print out full names. */
    if (key === "namespaces") {
      writer.enter("namespaces {");
      this.namespaces.forEach(function (ns, i) {
        writer.writeLn(("" + i).padRight(' ', 3) +
                 (ns ? ns.toString() : "*"));
      });
      writer.leave("}");
    } else if (this[key] instanceof Array) {
      writer.enter(key + " " + this[key].length + " {");
      writer.writeArray(this[key]);
      writer.leave("}");
    }
  }
  writer.leave("}");
};

ConstantPool.prototype.traceMultinamesOnly = function (writer) {
  writer.writeArray(this.multinames, null, true);
};

Traits.prototype.trace = function (writer) {
  traceArray(writer, "traits", this.traits);
};

ClassInfo.prototype.trace = function (writer) {
  writer.enter("class " + this + " {");
  this.traits.trace(writer);
  writer.leave("}");
};

MetaDataInfo.prototype.trace = function (writer) {
  writer.enter(this + " {");
  this.items.forEach(function (item) {
    writer.writeLn((item.key ? item.key + ": " : "") + "\"" + item.value + "\"");
  });
  writer.leave("}");
};

InstanceInfo.prototype.trace = function (writer) {
  writer.enter("instance " + this + " {");
  this.traits.trace(writer);
  writer.leave("}");
};

ScriptInfo.prototype.trace = function (writer) {
  writer.enter("script " + this + " {");
  this.traits.trace(writer);
  writer.leave("}");
};

Trait.prototype.trace = function (writer) {
  if (this.metadata) {
    for (var key in this.metadata) {
      if (this.metadata.hasOwnProperty(key)) {
        this.metadata[key].trace(writer);
      }
    }
  }
  writer.writeLn(this);
};

function traceAbc(writer, abc) {
  abc.trace(writer);
}

function traceOperand(operand, abc, code) {
  var value = 0;
  switch(operand.size) {
    case "s08": value = code.readS8(); break;
    case "u08": value = code.readU8(); break;
    case "s16": value = code.readS16(); break;
    case "s24": value = code.readS24(); break;
    case "u30": value = code.readU30(); break;
    case "u32": value = code.readU32(); break;
    default: assert (false); break;
  }
  var description = "";
  switch(operand.type) {
    case "": break;
    case "I": description = abc.constantPool.ints[value]; break;
    case "U": description = abc.constantPool.uints[value]; break;
    case "D": description = abc.constantPool.doubles[value]; break;
    case "S": description = abc.constantPool.strings[value]; break;
    case "N": description = abc.constantPool.namespaces[value]; break;
    case "CI": description = abc.classes[value]; break;
    case "M":
      return abc.constantPool.multinames[value];
    default: description = "?"; break;
  }
  return operand.name + ":" + value + (description === "" ? "" : " (" + description + ")");
}

function traceOperands(opcode, abc, code, rewind) {
  rewind = rewind || false;
  var old = code.position;
  var str = "";
  if (opcode.operands === null) {
    str = "null";
  } else {
    opcode.operands.forEach(function (op, i) {
      str += traceOperand(op, abc, code);
      if (i < opcode.operands.length - 1) {
        str += ", ";
      }
    });
  }
  if (rewind) {
    code.seek(old);
  }
  return str;
}

MethodInfo.prototype.trace = function trace(writer, abc) {
  writer.enter("method" + (this.name ? " " + this.name : "") + " {");
  writer.writeLn("flags: " + getFlags(this.flags, "NEED_ARGUMENTS|NEED_ACTIVATION|NEED_REST|HAS_OPTIONAL||NATIVE|SET_DXN|HAS_PARAM_NAMES".split("|")));

  if (!this.code) {
    writer.leave("}");
    return;
  }

  var code = new AbcStream(this.code);

  this.traits.trace(writer);

  writer.enter("code {");
  while (code.remaining() > 0) {
    var bc = code.readU8();
    var opcode = opcodeTable[bc];
    var str, defaultOffset, offset, count;
    str = ("" + code.position).padRight(' ', 6);
    switch (bc) {
      case OP_lookupswitch:
        str += opcode.name + ": defaultOffset: " + code.readS24();
        var caseCount = code.readU30();
        str += ", caseCount: " + caseCount;
        for (var i = 0; i < caseCount + 1; i++) {
          str += " offset: " + code.readS24();
        }
        writer.writeLn(str);
        break;
      default:
        if (opcode) {
          str += opcode.name.padRight(' ', 20);
          if (!opcode.operands) {
            assert(false, "Opcode: " + opcode.name + " has undefined operands.");
          } else {
            if (opcode.operands.length > 0) {
              str += traceOperands(opcode, abc, code);
            }
            writer.writeLn(str);
          }
        } else {
          assert(false, "Opcode: " + bc + " is not implemented.");
        }
        break;
    }
  }
  writer.leave("}");
  writer.leave("}");
}

var SourceTracer = (function () {
  function literal(value) {
    if (value === undefined) {
      return "undefined";
    } else if (value === null) {
      return "null";
    } else if (typeof (value) === "string") {
      return "\"" + value + "\"";
    } else {
      return String(value);
    }
  }

  function getSignature(mi, excludeTypesAndDefaultValues) {
    return mi.parameters.map(function (x) {
      var str = x.name;
      if (!excludeTypesAndDefaultValues) {
        if (x.type) {
          str += ":" + x.type.getName();
        }
        if (x.value !== undefined) {
          str += "=" + literal(x.value);
        }
      }
      return str;
    }).join(", ");
  }

  function SourceTracer(writer) {
    this.writer = writer;
  }

  SourceTracer.prototype = {
    traceTraits: function traceTraits(traits, isStatic, inInterfaceNamespace) {
      const writer = this.writer;
      const tracer = this;

      traits.traits.forEach(function (trait) {
        var str;
        var accessModifier = trait.name.getAccessModifier();
        var namespaceName = trait.name.namespaces[0].originalURI;
        if (namespaceName) {
          if (namespaceName === "http://adobe.com/AS3/2006/builtin") {
            namespaceName = "AS3";
          }
          if (accessModifier === "public") {
            str = inInterfaceNamespace === namespaceName ? "" : namespaceName;
          } else {
            str = accessModifier;
          }
        } else {
          str = accessModifier;
        }
        if (isStatic) {
          str += " static";
        }
        if (trait.isSlot() || trait.isConst()) {
          tracer.traceMetadata(trait.metadata);
          if (trait.isConst()) {
            str += " const";
          } else {
            str += " var";
          }
          str += " " + trait.name.getName();
          if (trait.typeName) {
            str += ":" + trait.typeName.getName();
          }
          if (trait.value) {
            str += " = " + literal(trait.value);
          }
          writer.writeLn(str + ";");
        } else if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
          tracer.traceMetadata(trait.metadata);
          var mi = trait.methodInfo;
          if (trait.attributes & ATTR_Override) {
            str += " override";
          }
          if (mi.isNative()) {
            str += " native";
          }
          str += " function";
          str += trait.isGetter() ? " get" : (trait.isSetter() ? " set" : "");
          str += " " + trait.name.getName();
          str += "(" + getSignature(mi) + ")";
          str += mi.returnType ? ":" + mi.returnType.getName() : "";
          if (mi.isNative()) {
            writer.writeLn(str + ";");
          } else {
            if (inInterfaceNamespace) {
              writer.writeLn(str + ";");
            } else {
              writer.writeLn(str + " { notImplemented(\"" + trait.name.getName() + "\"); }");
            }
          }
        } else if (trait.isClass()) {
          var className = trait.classInfo.instanceInfo.name;
          writer.enter("package " + className.namespaces[0].originalURI + " {\n");
          tracer.traceMetadata(trait.metadata);
          tracer.traceClass(trait.classInfo);
          writer.leave("\n}");
          tracer.traceClassStub(trait);
        } else {
          notImplemented();
        }
      });
    },

    traceClassStub: function traceClassStub(trait) {
      const writer = this.writer;

      var ci = trait.classInfo;
      var ii = ci.instanceInfo;
      var name = ii.name.getName();
      var native = trait.metadata ? trait.metadata.native : null;
      if (!native) {
        return;
      }
      writer.enter("Shumway Stub {");
      writer.enter("natives." + native.cls + " = function " + native.cls + "(scope, instance, baseClass) {");
      writer.writeLn("// Signature: " + getSignature(ii.init));
      var initSignature = getSignature(ii.init, true);
      writer.writeLn("function " + name + "(" + initSignature + ") {");
      writer.writeLn("  instance.call(this" + (initSignature ? ", " + initSignature : "") + ")");
      writer.writeLn("};");
      writer.writeLn("var c = new Class(\"" + name + "\", " + name +
                     ", Class.passthroughCallable(" + name + "));");
      writer.writeLn("//");
      writer.writeLn("// WARNING! This sets:")
      writer.writeLn("//   " + name + ".prototype = " +
                     "Object.create(baseClass.instance.prototype)");
      writer.writeLn("//");
      writer.writeLn("// If you want to manage prototypes manually, do this instead:");
      writer.writeLn("//   c.baseClass = baseClass");
      writer.writeLn("//");
      writer.writeLn("c.extend(baseClass);");

      function traceTraits(traits, isStatic) {
        traits.traits.forEach(function (trait) {
          var traitName = trait.name.getName();
          if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
            var mi = trait.methodInfo;
            if (mi.isNative()) {
              var str = isStatic ? "s" : "m";
              if (mi.parameters.length) {
                var returnTypeStr = "";
                if (mi.returnType) {
                  returnTypeStr = " -> " + mi.returnType.getName();
                }
                writer.writeLn("// Signature: " + getSignature(mi) + returnTypeStr);
              }
              var prop;
              if (trait.isGetter()) {
                prop = "[\"get " + traitName + "\"]";
              } else if (trait.isSetter()) {
                prop = "[\"set " + traitName + "\"]";
              } else {
                prop = "." + traitName;
              }
              str += prop + " = function " + traitName + "(" + getSignature(mi, true) + ")";
              writer.writeLn(str + " {");
              writer.writeLn("  notImplemented(\"" + name + "." + traitName + "\"); };");
              writer.writeLn("}");
            }
          }
        });
      }

      writer.writeLn("var m = " + name + ".prototype;");
      writer.writeLn("var s = {};");

      traceTraits(ci.traits, true);
      traceTraits(ii.traits);

      writer.writeLn("c.nativeMethods = m;");
      writer.writeLn("c.nativeStatics = s;");

      writer.writeLn("return c;");
      writer.leave("};");
      writer.leave("}");
    },

    traceClass: function traceClass(ci) {
      const writer = this.writer;

      var ii = ci.instanceInfo;
      var name = ii.name;
      var str = name.getAccessModifier();
      if (ii.isFinal()) {
        str += " final";
      }
      if (!ii.isSealed()) {
        str += " dynamic";
      }
      str += ii.isInterface() ? " interface " : " class ";
      str += name.getName();
      if (ii.superName && ii.superName.getName() !== "Object") {
        str += " extends " + ii.superName.getName();
      }
      if (ii.interfaces.length) {
        str += " implements " + ii.interfaces.map(function (x) {
          return x.getName();
        }).join(", ");
      }
      writer.enter(str + " {");
      if (!ii.isInterface()) {
        writer.writeLn("public function " + name.getName() + "(" + getSignature(ii.init) + ") {}");
      }
      var interfaceNamespace;
      if (ii.isInterface()) {
        interfaceNamespace = name.namespaces[0].originalURI + ":" + name.name;
      }
      this.traceTraits(ci.traits, true, interfaceNamespace);
      this.traceTraits(ii.traits, false, interfaceNamespace);
      writer.leave("}");
    },

    traceMetadata: function traceMetadata(metadata) {
      const writer = this.writer;

      for (var key in metadata) {
        if (metadata.hasOwnProperty(key)) {
          if (key.indexOf("__") === 0) {
            continue;
          }
          writer.writeLn("[" + key + "(" + metadata[key].items.map(function (m) {
            var str = m.key ? m.key + "=" : "";
            return str + "\"" + m.value + "\"";
          }).join(", ") + ")]");
        }
      }
    }
  };

  return SourceTracer;
})();

function traceSource(writer, abc) {
  var tracer = new SourceTracer(writer);
  abc.scripts.forEach(function (script) {
    tracer.traceTraits(script.traits);
  });
}
<commit_msg>Disassembler bug fix.<commit_after>var disassemblerOptions = systemOptions.register(new OptionSet("Disassembler Options"));

var filter = disassemblerOptions.register(new Option("f", "filter", "string", "SpciMsm", "[S]ource, constant[p]ool, [c]lasses, [i]nstances, [M]etadata, [s]cripts, [m]ethods, multi[N]ames"));

function traceArray(writer, name, array, abc) {
  if (array.length === 0) {
    return;
  }
  writer.enter(name + " {");
  array.forEach(function (a, idx) {
    a.trace(writer, abc);
  });
  writer.leave("}");
}

AbcFile.prototype.trace = function trace(writer) {
  if (filter.value.indexOf("p") >= 0) {
    this.constantPool.trace(writer);
  }
  if (filter.value.indexOf("N") >= 0) {
    this.constantPool.traceMultinamesOnly(writer);
  }
  if (filter.value.indexOf("c") >= 0) {
    traceArray(writer, "classes", this.classes);
  }
  if (filter.value.indexOf("i") >= 0) {
    traceArray(writer, "instances", this.instances);
  }
  if (filter.value.indexOf("M") >= 0) {
    traceArray(writer, "metadata", this.metadata);
  }
  if (filter.value.indexOf("s") >= 0) {
    traceArray(writer, "scripts", this.scripts);
  }
  if (filter.value.indexOf("m") >= 0) {
    traceArray(writer, "methods", this.methods, this);
  }
  if (filter.value.indexOf("S") >= 0) {
    traceSource(writer, this);
  }
};

ConstantPool.prototype.trace = function (writer) {
  writer.enter("constantPool {");
  for (var key in this) {
    /* Special-case namespaces to print out full names. */
    if (key === "namespaces") {
      writer.enter("namespaces {");
      this.namespaces.forEach(function (ns, i) {
        writer.writeLn(("" + i).padRight(' ', 3) +
                 (ns ? ns.toString() : "*"));
      });
      writer.leave("}");
    } else if (this[key] instanceof Array) {
      writer.enter(key + " " + this[key].length + " {");
      writer.writeArray(this[key]);
      writer.leave("}");
    }
  }
  writer.leave("}");
};

ConstantPool.prototype.traceMultinamesOnly = function (writer) {
  writer.writeArray(this.multinames, null, true);
};

Traits.prototype.trace = function (writer) {
  traceArray(writer, "traits", this.traits);
};

ClassInfo.prototype.trace = function (writer) {
  writer.enter("class " + this + " {");
  this.traits.trace(writer);
  writer.leave("}");
};

MetaDataInfo.prototype.trace = function (writer) {
  writer.enter(this + " {");
  this.items.forEach(function (item) {
    writer.writeLn((item.key ? item.key + ": " : "") + "\"" + item.value + "\"");
  });
  writer.leave("}");
};

InstanceInfo.prototype.trace = function (writer) {
  writer.enter("instance " + this + " {");
  this.traits.trace(writer);
  writer.leave("}");
};

ScriptInfo.prototype.trace = function (writer) {
  writer.enter("script " + this + " {");
  this.traits.trace(writer);
  writer.leave("}");
};

Trait.prototype.trace = function (writer) {
  if (this.metadata) {
    for (var key in this.metadata) {
      if (this.metadata.hasOwnProperty(key)) {
        this.metadata[key].trace(writer);
      }
    }
  }
  writer.writeLn(this);
};

function traceAbc(writer, abc) {
  abc.trace(writer);
}

function traceOperand(operand, abc, code) {
  var value = 0;
  switch(operand.size) {
    case "s08": value = code.readS8(); break;
    case "u08": value = code.readU8(); break;
    case "s16": value = code.readS16(); break;
    case "s24": value = code.readS24(); break;
    case "u30": value = code.readU30(); break;
    case "u32": value = code.readU32(); break;
    default: assert (false); break;
  }
  var description = "";
  switch(operand.type) {
    case "": break;
    case "I": description = abc.constantPool.ints[value]; break;
    case "U": description = abc.constantPool.uints[value]; break;
    case "D": description = abc.constantPool.doubles[value]; break;
    case "S": description = abc.constantPool.strings[value]; break;
    case "N": description = abc.constantPool.namespaces[value]; break;
    case "CI": description = abc.classes[value]; break;
    case "M":
      return abc.constantPool.multinames[value];
    default: description = "?"; break;
  }
  return operand.name + ":" + value + (description === "" ? "" : " (" + description + ")");
}

function traceOperands(opcode, abc, code, rewind) {
  rewind = rewind || false;
  var old = code.position;
  var str = "";
  if (opcode.operands === null) {
    str = "null";
  } else {
    opcode.operands.forEach(function (op, i) {
      str += traceOperand(op, abc, code);
      if (i < opcode.operands.length - 1) {
        str += ", ";
      }
    });
  }
  if (rewind) {
    code.seek(old);
  }
  return str;
}

MethodInfo.prototype.trace = function trace(writer, abc) {
  writer.enter("method" + (this.name ? " " + this.name : "") + " {");
  writer.writeLn("flags: " + getFlags(this.flags, "NEED_ARGUMENTS|NEED_ACTIVATION|NEED_REST|HAS_OPTIONAL||NATIVE|SET_DXN|HAS_PARAM_NAMES".split("|")));

  if (!this.code) {
    writer.leave("}");
    return;
  }

  var code = new AbcStream(this.code);

  this.traits.trace(writer);

  writer.enter("code {");
  while (code.remaining() > 0) {
    var bc = code.readU8();
    var opcode = opcodeTable[bc];
    var str, defaultOffset, offset, count;
    str = ("" + code.position).padRight(' ', 6);
    switch (bc) {
      case OP_lookupswitch:
        str += opcode.name + ": defaultOffset: " + code.readS24();
        var caseCount = code.readU30();
        str += ", caseCount: " + caseCount;
        for (var i = 0; i < caseCount + 1; i++) {
          str += " offset: " + code.readS24();
        }
        writer.writeLn(str);
        break;
      default:
        if (opcode) {
          str += opcode.name.padRight(' ', 20);
          if (!opcode.operands) {
            assert(false, "Opcode: " + opcode.name + " has undefined operands.");
          } else {
            if (opcode.operands.length > 0) {
              str += traceOperands(opcode, abc, code);
            }
            writer.writeLn(str);
          }
        } else {
          assert(false, "Opcode: " + bc + " is not implemented.");
        }
        break;
    }
  }
  writer.leave("}");
  writer.leave("}");
}

var SourceTracer = (function () {
  function literal(value) {
    if (value === undefined) {
      return "undefined";
    } else if (value === null) {
      return "null";
    } else if (typeof (value) === "string") {
      return "\"" + value + "\"";
    } else {
      return String(value);
    }
  }

  function getSignature(mi, excludeTypesAndDefaultValues) {
    return mi.parameters.map(function (x) {
      var str = x.name;
      if (!excludeTypesAndDefaultValues) {
        if (x.type) {
          str += ":" + x.type.getName();
        }
        if (x.value !== undefined) {
          str += "=" + literal(x.value);
        }
      }
      return str;
    }).join(", ");
  }

  function SourceTracer(writer) {
    this.writer = writer;
  }

  SourceTracer.prototype = {
    traceTraits: function traceTraits(traits, isStatic, inInterfaceNamespace) {
      const writer = this.writer;
      const tracer = this;

      traits.traits.forEach(function (trait) {
        var str;
        var accessModifier = trait.name.getAccessModifier();
        var namespaceName = trait.name.namespaces[0].originalURI;
        if (namespaceName) {
          if (namespaceName === "http://adobe.com/AS3/2006/builtin") {
            namespaceName = "AS3";
          }
          if (accessModifier === "public") {
            str = inInterfaceNamespace === namespaceName ? "" : namespaceName;
          } else {
            str = accessModifier;
          }
        } else {
          str = accessModifier;
        }
        if (isStatic) {
          str += " static";
        }
        if (trait.isSlot() || trait.isConst()) {
          tracer.traceMetadata(trait.metadata);
          if (trait.isConst()) {
            str += " const";
          } else {
            str += " var";
          }
          str += " " + trait.name.getName();
          if (trait.typeName) {
            str += ":" + trait.typeName.getName();
          }
          if (trait.value) {
            str += " = " + literal(trait.value);
          }
          writer.writeLn(str + ";");
        } else if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
          tracer.traceMetadata(trait.metadata);
          var mi = trait.methodInfo;
          if (trait.attributes & ATTR_Override) {
            str += " override";
          }
          if (mi.isNative()) {
            str += " native";
          }
          str += " function";
          str += trait.isGetter() ? " get" : (trait.isSetter() ? " set" : "");
          str += " " + trait.name.getName();
          str += "(" + getSignature(mi) + ")";
          str += mi.returnType ? ":" + mi.returnType.getName() : "";
          if (mi.isNative()) {
            writer.writeLn(str + ";");
          } else {
            if (inInterfaceNamespace) {
              writer.writeLn(str + ";");
            } else {
              writer.writeLn(str + " { notImplemented(\"" + trait.name.getName() + "\"); }");
            }
          }
        } else if (trait.isClass()) {
          var className = trait.classInfo.instanceInfo.name;
          writer.enter("package " + className.namespaces[0].originalURI + " {\n");
          tracer.traceMetadata(trait.metadata);
          tracer.traceClass(trait.classInfo);
          writer.leave("\n}");
          tracer.traceClassStub(trait);
        } else {
          notImplemented();
        }
      });
    },

    traceClassStub: function traceClassStub(trait) {
      const writer = this.writer;

      var ci = trait.classInfo;
      var ii = ci.instanceInfo;
      var name = ii.name.getName();
      var native = trait.metadata ? trait.metadata.native : null;
      if (!native) {
        return;
      }
      writer.enter("Shumway Stub {");
      writer.enter("natives." + native.cls + " = function " + native.cls + "(scope, instance, baseClass) {");
      writer.writeLn("// Signature: " + getSignature(ii.init));
      var initSignature = getSignature(ii.init, true);
      writer.writeLn("function " + name + "(" + initSignature + ") {");
      writer.writeLn("  instance.call(this" + (initSignature ? ", " + initSignature : "") + ");");
      writer.writeLn("}");
      writer.writeLn("var c = new Class(\"" + name + "\", " + name +
                     ", Class.passthroughCallable(" + name + "));");
      writer.writeLn("//");
      writer.writeLn("// WARNING! This sets:")
      writer.writeLn("//   " + name + ".prototype = " +
                     "Object.create(baseClass.instance.prototype)");
      writer.writeLn("//");
      writer.writeLn("// If you want to manage prototypes manually, do this instead:");
      writer.writeLn("//   c.baseClass = baseClass");
      writer.writeLn("//");
      writer.writeLn("c.extend(baseClass);");

      function traceTraits(traits, isStatic) {
        traits.traits.forEach(function (trait) {
          var traitName = trait.name.getName();
          if (trait.isMethod() || trait.isGetter() || trait.isSetter()) {
            var mi = trait.methodInfo;
            if (mi.isNative()) {
              var str = isStatic ? "s" : "m";
              if (mi.parameters.length) {
                var returnTypeStr = "";
                if (mi.returnType) {
                  returnTypeStr = " -> " + mi.returnType.getName();
                }
                writer.writeLn("// Signature: " + getSignature(mi) + returnTypeStr);
              }
              var prop;
              if (trait.isGetter()) {
                prop = "[\"get " + traitName + "\"]";
              } else if (trait.isSetter()) {
                prop = "[\"set " + traitName + "\"]";
              } else {
                prop = "." + traitName;
              }
              str += prop + " = function " + traitName + "(" + getSignature(mi, true) + ")";
              writer.writeLn(str + " {");
              writer.writeLn("  notImplemented(\"" + name + "." + traitName + "\");");
              writer.writeLn("};");
            }
          }
        });
      }

      writer.writeLn("var m = " + name + ".prototype;");
      writer.writeLn("var s = {};");

      traceTraits(ci.traits, true);
      traceTraits(ii.traits);

      writer.writeLn("c.nativeMethods = m;");
      writer.writeLn("c.nativeStatics = s;");

      writer.writeLn("return c;");
      writer.leave("};");
      writer.leave("}");
    },

    traceClass: function traceClass(ci) {
      const writer = this.writer;

      var ii = ci.instanceInfo;
      var name = ii.name;
      var str = name.getAccessModifier();
      if (ii.isFinal()) {
        str += " final";
      }
      if (!ii.isSealed()) {
        str += " dynamic";
      }
      str += ii.isInterface() ? " interface " : " class ";
      str += name.getName();
      if (ii.superName && ii.superName.getName() !== "Object") {
        str += " extends " + ii.superName.getName();
      }
      if (ii.interfaces.length) {
        str += " implements " + ii.interfaces.map(function (x) {
          return x.getName();
        }).join(", ");
      }
      writer.enter(str + " {");
      if (!ii.isInterface()) {
        writer.writeLn("public function " + name.getName() + "(" + getSignature(ii.init) + ") {}");
      }
      var interfaceNamespace;
      if (ii.isInterface()) {
        interfaceNamespace = name.namespaces[0].originalURI + ":" + name.name;
      }
      this.traceTraits(ci.traits, true, interfaceNamespace);
      this.traceTraits(ii.traits, false, interfaceNamespace);
      writer.leave("}");
    },

    traceMetadata: function traceMetadata(metadata) {
      const writer = this.writer;

      for (var key in metadata) {
        if (metadata.hasOwnProperty(key)) {
          if (key.indexOf("__") === 0) {
            continue;
          }
          writer.writeLn("[" + key + "(" + metadata[key].items.map(function (m) {
            var str = m.key ? m.key + "=" : "";
            return str + "\"" + m.value + "\"";
          }).join(", ") + ")]");
        }
      }
    }
  };

  return SourceTracer;
})();

function traceSource(writer, abc) {
  var tracer = new SourceTracer(writer);
  abc.scripts.forEach(function (script) {
    tracer.traceTraits(script.traits);
  });
}
<|endoftext|>


<commit_before>define("dojox/socket", ["dojo", "dojo/cookie"], function(dojo) {

var WebSocket = window.WebSocket;

dojox.socket = Socket;
function Socket(/*dojo.__XhrArgs*/ argsOrUrl){
	// summary:
	//		Provides a simple socket connection using WebSocket, or alternate
	// 		communication mechanisms in legacy browsers for comet-style communication. This is based
	//		on the WebSocket API and returns an object that implements the WebSocket interface:
	//		http://dev.w3.org/html5/websockets/#websocket
	//	description:
	//		Provides socket connections. This can be used with virtually any Comet protocol.
	//	argsOrUrl:
	//		This uses the same arguments as the other I/O functions in Dojo, or a
	// 		URL to connect to. The URL should be a relative URL in order to properly
	//		work with WebSockets (it can still be host relative, like //other-site.org/endpoint)
	// returns:
	// 		An object that implements the WebSocket API
	// example:
	//		| dojo.require("dojox.socket");
	//		| var socket = dojox.socket({"//comet-server/comet");
	//		| // we could also add auto-reconnect support
	//		| // now we can connect to standard HTML5 WebSocket-style events
	//		| dojo.connect(socket, "onmessage", function(event){
	//		|    var message = event.data;
	//		|    // do something with the message
	//		| });
	//		| // send something
	//		| socket.send("hi there");
	//		| whenDone(function(){
	//		|   socket.close();
	//		| });
	//		You can also use the Reconnect module:
	//		| dojo.require("dojox.socket");
	//		| dojo.require("dojox.socket.Reconnect");
	//		| var socket = dojox.socket({url:"/comet"});
	//		| // add auto-reconnect support
	//		| socket = dojox.socket.Reconnect(socket);
	if(typeof argsOrUrl == "string"){
		argsOrUrl = {url: argsOrUrl};
	}
	return WebSocket ? dojox.socket.WebSocket(argsOrUrl) : dojox.socket.LongPoll(argsOrUrl);
};

Socket.WebSocket = function(args){
	// summary:
	//		A wrapper for WebSocket, than handles standard args and relative URLs
	var ws = new WebSocket(new dojo._Url(document.baseURI.replace(/^http/i,'ws'), args.url));
	ws.on = ws.addEventListener;
	var opened;
	dojo.connect(ws, "onopen", function(event){
		opened = true;
	});
	dojo.connect(ws, "onclose", function(event){
		if(opened){
			return;
		}
		WebSocket = null;
		Socket.replace(ws, dojox.socket(args), true);
	});
	return ws;
};
Socket.replace = function(socket, newSocket, listenForOpen){
	// make the original socket a proxy for the new socket
	socket.send = dojo.hitch(newSocket, "send");
	socket.close = dojo.hitch(newSocket, "close");
	if(listenForOpen){
		proxyEvent("open");
	}
	// redirect the events as well
	dojo.forEach(["message", "close", "error"], proxyEvent);
	function proxyEvent(type){
		(newSocket.addEventListener || newSocket.on).call(newSocket, type, function(event){
			socket.dispatchEvent(event);
		});
	}
};
Socket.LongPoll = function(/*dojo.__XhrArgs*/ args){
	// summary:
	//		Provides a simple long-poll based comet-style socket/connection to a server and returns an
	// 		object implementing the WebSocket interface:
	//		http://dev.w3.org/html5/websockets/#websocket
	//	args:
	//		This uses the same arguments as the other I/O functions in Dojo, with this addition:
	//	args.interval:
	//		Indicates the amount of time (in milliseconds) after a response was received
	//		before another request is made. By default, a request is made immediately
	//		after getting a response. The interval can be increased to reduce load on the
	//		server or to do simple time-based polling where the server always responds
	// 		immediately.
	//	args.transport:
	//		Provide an alternate transport like dojo.io.script.get
	// returns:
	// 		An object that implements the WebSocket API
	// example:
	//		| dojo.require("dojox.socket.LongPoll");
	//		| var socket = dojox.socket.LongPoll({url:"/comet"});
	//		or:
	//		| dojo.require("dojox.socket.LongPoll");
	//		| dojox.socket.LongPoll.add();
	//		| var socket = dojox.socket({url:"/comet"});

var cancelled = false,
		first = true,
		timeoutId,
		connections = [];

	// create the socket object
	var socket = {
		send: function(data){
			// summary:
			// 		Send some data using XHR or provided transport
			var sendArgs = dojo.delegate(args);
			sendArgs.rawBody = data;
			clearTimeout(timeoutId);
			var deferred = first ? (first = false) || socket.firstRequest(sendArgs) :
				socket.transport(sendArgs);
			connections.push(deferred);
			deferred.then(function(response){
				// got a response
				socket.readyState = 1;
				// remove the current connection
				connections.splice(dojo.indexOf(connections, deferred), 1);
				// reconnect to listen for the next message if there are no active connections,
				// we queue it up in case one of the onmessage handlers has a message to send
				if(!connections.length){
					timeoutId = setTimeout(connect, args.interval);
				}
				if(response){
					// now send the message along to listeners
					fire("message", {data: response}, deferred);
				}
			}, function(error){
				connections.splice(dojo.indexOf(connections, deferred), 1);
				// an error occurred, fire the appropriate event listeners
				if(!cancelled){
					fire("error", {error:error}, deferred);
					if(!connections.length){
						socket.readyState = 3;
						fire("close", {wasClean:false}, deferred);
					}
				}
			});
			return deferred;
		},
		close: function(){
			// summary:
			// 		Close the connection
			socket.readyState = 2;
			cancelled = true;
			for(var i = 0; i < connections.length; i++){
				connections[i].cancel();
			}
			socket.readyState = 3;
			fire("close", {wasClean:true});
		},
		transport: args.transport || dojo.xhrPost,
		args: args,
		url: args.url,
		readyState: 0,
		CONNECTING: 0,
		OPEN: 1,
		CLOSING: 2,
		CLOSED: 3,
		dispatchEvent: function(event){
			fire(event.type, event);
		},
		on: function(type, callback){
			return dojo.connect(this, "on" + type, callback);
		},
		firstRequest: function(args){
			// summary:
			// 		This allows for special handling for the first request. This is useful for
			//		providing information to disambiguate between the first request and
			//		subsequent long-poll requests so the server can properly setup a
			// 		connection on the first connection or reject a request for an expired
			// 		connection if the request is not expecting to be the first for a connection.
			//		This method can be overriden. The default behavior is to include a Pragma
			//		header with a value of "start-long-poll"
			var headers = (args.headers || (args.headers = {}));
			headers.Pragma = "start-long-poll";
			try{
				return this.transport(args);
			}finally{
				// cleanup the header so it is not used on subsequent requests
				delete headers.Pragma;
			}
		}
	};
	function connect(){
		if(socket.readyState == 0){
			// we fire the open event now because we really don't know when the "socket"
			// is truly open, and this gives us a to do a send() and get it included in the
			// HTTP request
			fire("open",{});
		}
		// make the long-poll connection, to wait for response from the server
		if(!connections.length){
			socket.send();
		}
	}
	function fire(type, object, deferred){
		if(socket["on" + type]){
			var event = document.createEvent("HTMLEvents");
			event.initEvent(type);
			dojo.mixin(event, object);
			event.ioArgs = deferred && deferred.ioArgs;
			socket["on" + type](event);
		}
	}
	// provide an alias for Dojo's connect method
	socket.connect = socket.on;
	// do the initial connection
	setTimeout(connect);
	return socket;
};
return Socket;
});<commit_msg>Call initEvent properly, fixes #12621 !strict<commit_after>define("dojox/socket", ["dojo", "dojo/cookie"], function(dojo) {

var WebSocket = window.WebSocket;

dojox.socket = Socket;
function Socket(/*dojo.__XhrArgs*/ argsOrUrl){
	// summary:
	//		Provides a simple socket connection using WebSocket, or alternate
	// 		communication mechanisms in legacy browsers for comet-style communication. This is based
	//		on the WebSocket API and returns an object that implements the WebSocket interface:
	//		http://dev.w3.org/html5/websockets/#websocket
	//	description:
	//		Provides socket connections. This can be used with virtually any Comet protocol.
	//	argsOrUrl:
	//		This uses the same arguments as the other I/O functions in Dojo, or a
	// 		URL to connect to. The URL should be a relative URL in order to properly
	//		work with WebSockets (it can still be host relative, like //other-site.org/endpoint)
	// returns:
	// 		An object that implements the WebSocket API
	// example:
	//		| dojo.require("dojox.socket");
	//		| var socket = dojox.socket({"//comet-server/comet");
	//		| // we could also add auto-reconnect support
	//		| // now we can connect to standard HTML5 WebSocket-style events
	//		| dojo.connect(socket, "onmessage", function(event){
	//		|    var message = event.data;
	//		|    // do something with the message
	//		| });
	//		| // send something
	//		| socket.send("hi there");
	//		| whenDone(function(){
	//		|   socket.close();
	//		| });
	//		You can also use the Reconnect module:
	//		| dojo.require("dojox.socket");
	//		| dojo.require("dojox.socket.Reconnect");
	//		| var socket = dojox.socket({url:"/comet"});
	//		| // add auto-reconnect support
	//		| socket = dojox.socket.Reconnect(socket);
	if(typeof argsOrUrl == "string"){
		argsOrUrl = {url: argsOrUrl};
	}
	return WebSocket ? dojox.socket.WebSocket(argsOrUrl) : dojox.socket.LongPoll(argsOrUrl);
};

Socket.WebSocket = function(args){
	// summary:
	//		A wrapper for WebSocket, than handles standard args and relative URLs
	var ws = new WebSocket(new dojo._Url(document.baseURI.replace(/^http/i,'ws'), args.url));
	ws.on = ws.addEventListener;
	var opened;
	dojo.connect(ws, "onopen", function(event){
		opened = true;
	});
	dojo.connect(ws, "onclose", function(event){
		if(opened){
			return;
		}
		WebSocket = null;
		Socket.replace(ws, dojox.socket(args), true);
	});
	return ws;
};
Socket.replace = function(socket, newSocket, listenForOpen){
	// make the original socket a proxy for the new socket
	socket.send = dojo.hitch(newSocket, "send");
	socket.close = dojo.hitch(newSocket, "close");
	if(listenForOpen){
		proxyEvent("open");
	}
	// redirect the events as well
	dojo.forEach(["message", "close", "error"], proxyEvent);
	function proxyEvent(type){
		(newSocket.addEventListener || newSocket.on).call(newSocket, type, function(event){
			socket.dispatchEvent(event);
		});
	}
};
Socket.LongPoll = function(/*dojo.__XhrArgs*/ args){
	// summary:
	//		Provides a simple long-poll based comet-style socket/connection to a server and returns an
	// 		object implementing the WebSocket interface:
	//		http://dev.w3.org/html5/websockets/#websocket
	//	args:
	//		This uses the same arguments as the other I/O functions in Dojo, with this addition:
	//	args.interval:
	//		Indicates the amount of time (in milliseconds) after a response was received
	//		before another request is made. By default, a request is made immediately
	//		after getting a response. The interval can be increased to reduce load on the
	//		server or to do simple time-based polling where the server always responds
	// 		immediately.
	//	args.transport:
	//		Provide an alternate transport like dojo.io.script.get
	// returns:
	// 		An object that implements the WebSocket API
	// example:
	//		| dojo.require("dojox.socket.LongPoll");
	//		| var socket = dojox.socket.LongPoll({url:"/comet"});
	//		or:
	//		| dojo.require("dojox.socket.LongPoll");
	//		| dojox.socket.LongPoll.add();
	//		| var socket = dojox.socket({url:"/comet"});

var cancelled = false,
		first = true,
		timeoutId,
		connections = [];

	// create the socket object
	var socket = {
		send: function(data){
			// summary:
			// 		Send some data using XHR or provided transport
			var sendArgs = dojo.delegate(args);
			sendArgs.rawBody = data;
			clearTimeout(timeoutId);
			var deferred = first ? (first = false) || socket.firstRequest(sendArgs) :
				socket.transport(sendArgs);
			connections.push(deferred);
			deferred.then(function(response){
				// got a response
				socket.readyState = 1;
				// remove the current connection
				connections.splice(dojo.indexOf(connections, deferred), 1);
				// reconnect to listen for the next message if there are no active connections,
				// we queue it up in case one of the onmessage handlers has a message to send
				if(!connections.length){
					timeoutId = setTimeout(connect, args.interval);
				}
				if(response){
					// now send the message along to listeners
					fire("message", {data: response}, deferred);
				}
			}, function(error){
				connections.splice(dojo.indexOf(connections, deferred), 1);
				// an error occurred, fire the appropriate event listeners
				if(!cancelled){
					fire("error", {error:error}, deferred);
					if(!connections.length){
						socket.readyState = 3;
						fire("close", {wasClean:false}, deferred);
					}
				}
			});
			return deferred;
		},
		close: function(){
			// summary:
			// 		Close the connection
			socket.readyState = 2;
			cancelled = true;
			for(var i = 0; i < connections.length; i++){
				connections[i].cancel();
			}
			socket.readyState = 3;
			fire("close", {wasClean:true});
		},
		transport: args.transport || dojo.xhrPost,
		args: args,
		url: args.url,
		readyState: 0,
		CONNECTING: 0,
		OPEN: 1,
		CLOSING: 2,
		CLOSED: 3,
		dispatchEvent: function(event){
			fire(event.type, event);
		},
		on: function(type, callback){
			return dojo.connect(this, "on" + type, callback);
		},
		firstRequest: function(args){
			// summary:
			// 		This allows for special handling for the first request. This is useful for
			//		providing information to disambiguate between the first request and
			//		subsequent long-poll requests so the server can properly setup a
			// 		connection on the first connection or reject a request for an expired
			// 		connection if the request is not expecting to be the first for a connection.
			//		This method can be overriden. The default behavior is to include a Pragma
			//		header with a value of "start-long-poll"
			var headers = (args.headers || (args.headers = {}));
			headers.Pragma = "start-long-poll";
			try{
				return this.transport(args);
			}finally{
				// cleanup the header so it is not used on subsequent requests
				delete headers.Pragma;
			}
		}
	};
	function connect(){
		if(socket.readyState == 0){
			// we fire the open event now because we really don't know when the "socket"
			// is truly open, and this gives us a to do a send() and get it included in the
			// HTTP request
			fire("open",{});
		}
		// make the long-poll connection, to wait for response from the server
		if(!connections.length){
			socket.send();
		}
	}
	function fire(type, object, deferred){
		if(socket["on" + type]){
			var event = document.createEvent("HTMLEvents");
			event.initEvent(type, false, false);
			dojo.mixin(event, object);
			event.ioArgs = deferred && deferred.ioArgs;
			socket["on" + type](event);
		}
	}
	// provide an alias for Dojo's connect method
	socket.connect = socket.on;
	// do the initial connection
	setTimeout(connect);
	return socket;
};
return Socket;
});<|endoftext|>


<commit_before>(function() {

  describe('google suggest like', function() {
    beforeEach(function() {
      return setFixtures('<input type="text" id="suggest" value="a" />');
    });
    it('1. should call function when key press in my marvelous input', function() {
      $('#suggest').on('keyup', function() {});
      return expect($('#suggest')).toHandle('keyup');
    });
    it('2. should display ul element when user press "a" key', function() {
      SUGGEST.suggest();
      $('#suggest').keyup();
      return expect($('#suggest + ul > li')).toHaveText("a");
    });
    it('3. should display only one ul element when user press "a" key twice', function() {
      SUGGEST.suggest();
      $('#suggest').keyup();
      $('#suggest').keyup();
      return expect('
a

a
').toEqual($('#suggest + ul').html());
    });
    it('4. should delete ul element when marvelous input loose focus', function() {
      setFixtures('<input type="text" id="suggest" value="a" />\n

a

');
      SUGGEST.deleteSuggest();
      $('#suggest').blur();
      return expect($('#suggest + ul').length).toEqual(0);
    });
    it("5. should display links when user write search word", function() {
      var expectedGoogleCalendarLinkPrefix, expectedGoogleCalendarLinkSuffix, expectedWebcalLinkPrefix, expectedWebcalLinkSuffix;
      setFixtures('<input type="text" id="suggest" value="a" />\n

\n
\n  \n  \n  \n
');
      SUGGEST.displaySubscription('A');
      expectedGoogleCalendarLinkPrefix = "http://www.google.com/calendar/render?cid=";
      expectedGoogleCalendarLinkSuffix = "%2Fevents%2FA";
      expectedWebcalLinkPrefix = "webcal://";
      expectedWebcalLinkSuffix = "/events/A";
      expect($('#subscription').css('display')).toEqual('block');
      expect($('#subscription a.ical')).toHaveAttr('href', '/events/A');
      expect($('#subscription a.gcal').attr('href')).toContain(expectedGoogleCalendarLinkPrefix);
      expect($('#subscription a.gcal').attr('href')).toContain(expectedGoogleCalendarLinkSuffix);
      expect($('#subscription a.webcal').attr('href')).toContain(expectedWebcalLinkPrefix);
      return expect($('#subscription a.webcal').attr('href')).toContain(expectedWebcalLinkSuffix);
    });
    it("6. if user don't write search should not display links", function() {
      setFixtures('<input type="text" id="suggest" value="" />\n

\n
\n  \n  \n  \n
');
      SUGGEST.displaySubscription('');
      return expect($('#subscription').css('display')).toEqual('none');
    });
    it("7. should add devoxx url in link for devoxx section", function() {
      setFixtures('
\n  \n  \n  \n
');
      SUGGEST.loadUrlDevoxxSection();
      expect($("#devoxx a.gcal").attr("href")).toContain('%2Fevents%2FDEVOXX');
      return expect($("#devoxx a.webcal").attr("href")).toContain('/events/DEVOXX');
    });
    it("8. should call rest controller to retrieve preview result when user click on search", function() {
      var callbackData, urlServer;
      setFixtures('<form method="get" id="events" >\n  <input type="text" id="suggest" value="a" />\n</form>\n
\n  \n  \n  \n
');
      urlServer = 'http://serveur';
      callbackData = {
        "key": "value"
      };
      SUGGEST.retrievePreviewResults({
        url: urlServer
      });
      spyOn(SUGGEST, 'displaySubscription').andCallThrough;
      spyOn(SUGGEST, 'displayPreviewResult').andCallThrough;
      spyOn($, 'ajax').andCallFake(function(params) {
        return params.success(function() {
          return callbackData;
        });
      });
      $("#events").submit();
      expect($.ajax).toHaveBeenCalled();
      expect(SUGGEST.displayPreviewResult).toHaveBeenCalled();
      return expect(SUGGEST.displaySubscription).toHaveBeenCalledWith('A');
    });
    it("9. should call displayNoResult method when callback is error", function() {
      var callbackData, urlServer;
      setFixtures('<form method="get" id="events" >\n  <input type="text" id="suggest" value="a" />\n</form>\n
\n  \n  \n  \n
');
      urlServer = 'http://serveur';
      callbackData = {
        "key": "value"
      };
      SUGGEST.retrievePreviewResults({
        url: urlServer
      });
      spyOn(SUGGEST, 'displayNoResult').andCallThrough;
      spyOn($, 'ajax').andCallFake(function(params) {
        return params.error(function() {
          return "";
        });
      });
      $("#events").submit();
      expect($.ajax).toHaveBeenCalled();
      return expect(SUGGEST.displayNoResult).toHaveBeenCalledWith('a');
    });
    it("10. should display preview", function() {
      var callbackResponse, previewElement;
      setFixtures('
\n

\n

\n

\n

\n  \n  \n  \n
\n

');
      callbackResponse = {
        "size": "5",
        "eventList": [
          {
            "event": {
              "date": "2012-04-19T15:35:00.000+02:00",
              "title": "title 1",
              "location": "location 1"
            }
          }, {
            "event": {
              "date": "2012-04-19T15:35:00.000+02:00",
              "title": "title 2",
              "location": "location 2"
            }
          }, {
            "event": {
              "date": "2012-04-19T15:35:00.000+02:00",
              "title": "title 3",
              "location": "location 3"
            }
          }
        ]
      };
      SUGGEST.displayPreviewResult(callbackResponse);
      expect($('#resultSize')).toHaveText("nombre d'évènement(s) trouvé(s): 5");
      expect($('#callbackNoResult').css('display')).toEqual('none');
      previewElement = $('#subscription .preview');
      expect($(previewElement[0]).text()).toContain("title 1");
      expect($(previewElement[0]).text()).toContain("19 04 2012 - 15:35 - GMT+02");
      expect($(previewElement[0]).text()).toContain("location 1");
      expect($(previewElement[1]).text()).toContain("title 2");
      expect($(previewElement[1]).text()).toContain("19 04 2012 - 15:35 - GMT+02");
      expect($(previewElement[1]).text()).toContain("location 2");
      expect($(previewElement[2]).text()).toContain("title 3");
      expect($(previewElement[2]).text()).toContain("19 04 2012 - 15:35 - GMT+02");
      return expect($(previewElement[2]).text()).toContain("location 3");
    });
    it("11. should display fail", function() {
      setFixtures('

');
      SUGGEST.displayNoResult("toto");
      expect($('#callbackNoResult').css('display')).toEqual('block');
      return expect($('#callbackNoResult')).toHaveText("Le mot clé 'toto' ne donne aucun résultat dans la base OneCalendar");
    });
    it("12. should hide subscription div", function() {
      setFixtures('

');
      SUGGEST.displayNoResult("toto");
      return expect($('#subscription').css('display')).toEqual('none');
    });
    it("13. should hide subscription & callbackNoResult div if user dont write anything when he click", function() {
      setFixtures('<form method="get" id="events" >\n  <input type="text" id="suggest" value="" />\n</form>\n
\n  \n  \n  \n
\n

');
      SUGGEST.retrievePreviewResults({
        url: ""
      });
      $("#events").submit();
      expect($("#subscription").css('display')).toEqual("none");
      return expect($("#callbackNoResult").css('display')).toEqual("none");
    });
    return it("14. shoud format icalendar date format", function() {
      return expect(SUGGEST.formatIcalDate("2012-04-19T14:30:00.000+02:00")).toEqual("19 04 2012 - 14:30 - GMT+02");
    });
  });

}).call(this);
<commit_msg>fix: recompile coffee to make tests ok<commit_after>// Generated by CoffeeScript 1.3.1
(function() {

  describe('google suggest like', function() {
    beforeEach(function() {
      return setFixtures('<input type="text" id="suggest" value="a" />');
    });
    it('1. should call function when key press in my marvelous input', function() {
      $('#suggest').on('keyup', function() {});
      return expect($('#suggest')).toHandle('keyup');
    });
    it('2. should display ul element when user press "a" key', function() {
      SUGGEST.suggest();
      $('#suggest').keyup();
      return expect($('#suggest + ul > li')).toHaveText("a");
    });
    it('3. should display only one ul element when user press "a" key twice', function() {
      SUGGEST.suggest();
      $('#suggest').keyup();
      $('#suggest').keyup();
      return expect('
a

a
').toEqual($('#suggest + ul').html());
    });
    it('4. should delete ul element when marvelous input loose focus', function() {
      setFixtures('<input type="text" id="suggest" value="a" />\n

a

');
      SUGGEST.deleteSuggest();
      $('#suggest').blur();
      return expect($('#suggest + ul').length).toEqual(0);
    });
    it("5. should display links when user write search word", function() {
      var expectedGoogleCalendarLinkPrefix, expectedGoogleCalendarLinkSuffix, expectedWebcalLinkPrefix, expectedWebcalLinkSuffix;
      setFixtures('<input type="text" id="suggest" value="a" />\n

\n
\n  \n  \n  \n
');
      SUGGEST.displaySubscription('A');
      expectedGoogleCalendarLinkPrefix = "http://www.google.com/calendar/render?cid=";
      expectedGoogleCalendarLinkSuffix = "%2Fevents%2FA";
      expectedWebcalLinkPrefix = "webcal://";
      expectedWebcalLinkSuffix = "/events/A";
      expect($('#subscription').css('display')).toEqual('block');
      expect($('#subscription a.ical')).toHaveAttr('href', '/events/A');
      expect($('#subscription a.gcal').attr('href')).toContain(expectedGoogleCalendarLinkPrefix);
      expect($('#subscription a.gcal').attr('href')).toContain(expectedGoogleCalendarLinkSuffix);
      expect($('#subscription a.webcal').attr('href')).toContain(expectedWebcalLinkPrefix);
      return expect($('#subscription a.webcal').attr('href')).toContain(expectedWebcalLinkSuffix);
    });
    it("6. if user don't write search should not display links", function() {
      setFixtures('<input type="text" id="suggest" value="" />\n

\n
\n  \n  \n  \n
');
      SUGGEST.displaySubscription('');
      return expect($('#subscription').css('display')).toEqual('none');
    });
    it("7. should add devoxx url in link for devoxx section", function() {
      setFixtures('
\n  \n  \n  \n
');
      SUGGEST.loadUrlDevoxxSection();
      expect($("#devoxx a.gcal").attr("href")).toContain('%2Fevents%2FDEVOXX');
      return expect($("#devoxx a.webcal").attr("href")).toContain('/events/DEVOXX');
    });
    it("8. should call rest controller to retrieve preview result when user click on search", function() {
      var callbackData, urlServer;
      setFixtures('<form method="get" id="events" >\n  <input type="text" id="suggest" value="a" />\n</form>\n
\n  \n  \n  \n
');
      urlServer = 'http://serveur';
      callbackData = {
        "key": "value"
      };
      SUGGEST.retrievePreviewResults({
        url: urlServer
      });
      spyOn(SUGGEST, 'displaySubscription').andCallThrough;
      spyOn(SUGGEST, 'displayPreviewResult').andCallThrough;
      spyOn($, 'ajax').andCallFake(function(params) {
        return params.success(function() {
          return callbackData;
        });
      });
      $("#events").submit();
      expect($.ajax).toHaveBeenCalled();
      expect(SUGGEST.displayPreviewResult).toHaveBeenCalled();
      return expect(SUGGEST.displaySubscription).toHaveBeenCalledWith('A');
    });
    it("9. should call displayNoResult method when callback is error", function() {
      var callbackData, urlServer;
      setFixtures('<form method="get" id="events" >\n  <input type="text" id="suggest" value="a" />\n</form>\n
\n  \n  \n  \n
');
      urlServer = 'http://serveur';
      callbackData = {
        "key": "value"
      };
      SUGGEST.retrievePreviewResults({
        url: urlServer
      });
      spyOn(SUGGEST, 'displayNoResult').andCallThrough;
      spyOn($, 'ajax').andCallFake(function(params) {
        return params.error(function() {
          return "";
        });
      });
      $("#events").submit();
      expect($.ajax).toHaveBeenCalled();
      return expect(SUGGEST.displayNoResult).toHaveBeenCalledWith('a');
    });
    it("10. should display preview", function() {
      var callbackResponse, previewElement;
      setFixtures('
\n

\n

\n

\n

\n  \n  \n  \n
\n

');
      callbackResponse = {
        "size": "5",
        "eventList": [
          {
            "event": {
              "date": "2012-04-19T15:35:00.000+02:00",
              "title": "title 1",
              "location": "location 1"
            }
          }, {
            "event": {
              "date": "2012-04-19T15:35:00.000+02:00",
              "title": "title 2",
              "location": "location 2"
            }
          }, {
            "event": {
              "date": "2012-04-19T15:35:00.000+02:00",
              "title": "title 3",
              "location": "location 3"
            }
          }
        ]
      };
      SUGGEST.displayPreviewResult(callbackResponse);
      expect($('#resultSize')).toHaveText("2 autres évènements trouvés");
      expect($('#callbackNoResult').css('display')).toEqual('none');
      previewElement = $('#subscription .preview');
      expect($(previewElement[0]).text()).toContain("title 1");
      expect($(previewElement[0]).text()).toContain("19 04 2012 - 15:35");
      expect($(previewElement[0]).text()).toContain("location 1");
      expect($(previewElement[1]).text()).toContain("title 2");
      expect($(previewElement[1]).text()).toContain("19 04 2012 - 15:35");
      expect($(previewElement[1]).text()).toContain("location 2");
      expect($(previewElement[2]).text()).toContain("title 3");
      expect($(previewElement[2]).text()).toContain("19 04 2012 - 15:35");
      return expect($(previewElement[2]).text()).toContain("location 3");
    });
    it("11. should display fail", function() {
      setFixtures('

');
      SUGGEST.displayNoResult("toto");
      expect($('#callbackNoResult').css('display')).toEqual('block');
      return expect($('#callbackNoResult')).toHaveText("Le mot clé 'toto' ne donne aucun résultat dans la base OneCalendar");
    });
    it("12. should hide subscription div", function() {
      setFixtures('

');
      SUGGEST.displayNoResult("toto");
      return expect($('#subscription').css('display')).toEqual('none');
    });
    it("13. should hide subscription & callbackNoResult div if user dont write anything when he click", function() {
      setFixtures('<form method="get" id="events" >\n  <input type="text" id="suggest" value="" />\n</form>\n
\n  \n  \n  \n
\n

');
      SUGGEST.retrievePreviewResults({
        url: ""
      });
      $("#events").submit();
      expect($("#subscription").css('display')).toEqual("none");
      return expect($("#callbackNoResult").css('display')).toEqual("none");
    });
    return it("14. shoud format icalendar date format", function() {
      return expect(SUGGEST.formatIcalDate("2012-04-19T14:30:00.000+02:00")).toEqual("19 04 2012 - 14:30");
    });
  });

}).call(this);
<|endoftext|>