<commit_before>// ======================================
// Form buttons: shortcuts, AJAX improvements and form validation
// To be completed.
if (typeof(XWiki) == 'undefined') {
  XWiki = new Object();
}
if (typeof(XWiki.actionButtons) == 'undefined') {
  XWiki.actionButtons = new Object();
}

XWiki.actionButtons.EditActions = Class.create({
  initialize : function() {
    this.addListeners();
    this.addShortcuts();
  },
  addListeners : function() {
    $$('input[name=action_cancel]').each(function(item) {
      item.observe('click', this.onCancel.bindAsEventListener(this));
    }.bind(this));
    $$('input[name=action_preview]').each(function(item) {
      item.observe('click', this.onPreview.bindAsEventListener(this));
    }.bind(this));
    $$('input[name=action_save]').each(function(item) {
      item.observe('click', this.onSaveAndView.bindAsEventListener(this));
    }.bind(this));
    $$('input[name=action_saveandcontinue]').each(function(item) {
      item.observe('click', this.onSaveAndContinue.bindAsEventListener(this));
    }.bind(this));
  },
  addShortcuts : function() {
    var shortcuts = {
      'action_cancel' : "$msg.get('core.shortcuts.edit.cancel')",
      'action_preview' : "$msg.get('core.shortcuts.edit.preview')",
      // The following 2 are both "Back to edit" in the preview mode, depending on the used editor
      'action_edit' : "$msg.get('core.shortcuts.edit.backtoedit')",
      'action_inline' : "$msg.get('core.shortcuts.edit.backtoedit')",
      'action_save' : "$msg.get('core.shortcuts.edit.saveandview')",
      'action_propupdate' : "$msg.get('core.shortcuts.edit.saveandview')",
      'action_saveandcontinue' : "$msg.get('core.shortcuts.edit.saveandcontinue')"
    }
    for (var key in shortcuts) {
      var targetButtons = $$("input[name=" + key + "]");
      if (targetButtons.size() > 0) {
        shortcut.add(shortcuts[key], function() {
          this.click();
        }.bind(targetButtons.first()), {'propagate' : false} );
      }
    }
  },
  validateForm : function(form) {
    #if($xwiki.isEditCommentMandatory())
      var commentField = form.comment
      while (commentField.value == "") {
        var response = prompt("${msg.get('core.comment.prompt')}");
        if (response === null) {
          return false;
        }
        commentField.value = response;
      }
    #elseif($xwiki.isEditCommentSuggested())
      var commentField = form.comment
      if (commentField.value == "") {
        var response = prompt("${msg.get('core.comment.prompt')}");
        if (response === null) {
          return false;
        }
        commentField.value = response;
      }
    #end
    return true;
  },
  onCancel : function(event) {
    event.stop();

    // Notify others we are going to cancel
    this.notify(event, "cancel");

    var location = event.element().form.action;
    if (typeof location != "string") {
       location = event.element().form.attributes.getNamedItem("action");
       if (location) {
         location = location.nodeValue;
       } else {
         location = window.self.location.href;
       }
    }
    if (location.indexOf('?') == -1) {
      location += '?';
    }
    window.location = location + '&action_cancel=true';
  },
  onPreview : function(event) {
    if (!this.validateForm(event.element().form)) {
      event.stop();
    } else {
      // Notify others
      this.notify(event, "preview");
    }
  },
  onSaveAndView : function(event) {
    if (!this.validateForm(event.element().form)) {
      event.stop();
    } else {
      this.notify(event, "save", {"continue" : false});
    }
  },
  onSaveAndContinue : function(event) {
    if (!this.validateForm(event.element().form)) {
      event.stop();
    } else {
      this.notify(event, "save", {"continue" : true});
    }
  },
  notify : function(event, action, params) {
    document.fire("xwiki:actions:" + action, Object.extend({originalEvent : event, form: event.element().form}, params || { }));
    // In IE, events can't be stopped from another event's handler, so we must call stop() again here
    if (event.stopped) {
      event.stop();
    }
  }
});

// ======================================
// Save and continue button: Ajax improvements
XWiki.actionButtons.AjaxSaveAndContinue = Class.create({
  effectDuration : 1.0,
  initialize : function() {
    this.createMessages();
    this.addListeners();
  },
  createMessages : function() {
    this.container = new Element('div').setStyle({
      'fontWeight' : 'bold',
      position : 'fixed',
      bottom: '8px',
      left: '0%',
      width: '100%',
      'textAlign': 'center',
      zIndex: 1200
    }).hide();
    var innerContainer = new Element('div');
    this.savingBox = new Element('span', { 'class' : 'plainmessage' }).setStyle({
      background: "#000 url($xwiki.getSkinFile('icons/xwiki/ajax-loader-white.gif')) 8px center no-repeat",
      margin: 'auto',
      padding: '8px 32px',
      color: '#FFF'
    }).update('Saving...').hide();
    this.savedBox = new Element('span').setStyle({
      background: "#000 url($xwiki.getSkinFile('icons/silk/tick.gif')) 8px center no-repeat",
      margin: 'auto',
      padding: '8px 32px',
      color: '#FFF'
    }).update('Saved').hide();
    this.failedBox = new Element('span').setStyle({
      background: "#DDD url($xwiki.getSkinFile('icons/msgerror.png')) 8px center no-repeat",
      margin: 'auto',
      padding: '6px 32px 4px',
      color: '#F00',
      border: '2px solid #F00'
    }).update('Failed to save the document. Reason: ').hide();
    innerContainer.appendChild(this.savingBox);
    innerContainer.appendChild(this.savedBox);
    innerContainer.appendChild(this.failedBox);
    this.container.appendChild(innerContainer);
    document.body.appendChild(this.container);
  },
  addListeners : function() {
    document.observe("xwiki:actions:save", this.onSave.bindAsEventListener(this));
  },
  onSave : function(event) {
    if (event.memo["continue"]) {
      if (typeof (event.memo.originalEvent) != 'undefined') {
        event.memo.originalEvent.stop();
      }
      this.savedBox.hide();
      this.failedBox.hide();
      this.savingBox.show();
      this.showMessage();
      var formData = new Hash(event.memo.form.serialize({hash: true, submit: 'action_saveandcontinue'}));
      if (!Prototype.Browser.Opera) {
        // Opera can't handle properly 204 responses.
        formData.set('ajax', 'true');
      }
      new Ajax.Request(event.memo.form.action, {
        method : 'post',
        parameters : formData.toQueryString(),
        onSuccess : this.onSuccess.bindAsEventListener(this),
        on1223 : this.on1223.bindAsEventListener(this),
        on0 : this.on0.bindAsEventListener(this),
        onFailure : this.onFailure.bind(this)
      });
    }
  },
  // IE converts 204 status code into 1223...
  on1223 : function(response) {
    response.request.options.onSuccess(response);
  },
  // 0 is returned for network failures, except on IE where a strange large number (12031) is returned.
  on0 : function(response) {
    response.request.options.onFailure(response);
  },
  onSuccess : function(response) {
    this.savingBox.hide();
    this.savedBox.show();
    this.hideMessage();
  },
  onFailure : function(response) {
    if (response.statusText == '' /* No response */ || response.status == 12031 /* In IE */) {
      $('ajaxRequestFailureReason').update('Server not responding');
    } else {
      $('ajaxRequestFailureReason').update(response.statusText);
    }
    this.savingBox.hide();
    this.failedBox.show();
    this.hideMessage();
  },
  showMessage : function() {
    if (this.hideEffect) {
      this.hideEffect.cancel();
      delete this.hideEffect;
    }
    if (Prototype.Browser.IE) {
      this.container.setStyle({position : 'absolute', 'bottom': '0px'});
    }
    if (!this.showEffect && !this.container.visible()) {
      this.showEffect = new Effect.Appear(this.container, {duration: 0.2, afterFinish: function() {
        delete this.showEffect;
      }.bind(this)});
    }
  },
  hideMessage : function() {
    this.hideEffect = new Effect.Fade(this.container, {duration: this.effectDuration, delay: 2, afterFinish: function() {
      this.savedBox.hide();
      this.failedBox.hide();
      delete this.hideEffect;
    }.bind(this)});
  }
});
document.observe('dom:loaded', function() {
  new XWiki.actionButtons.EditActions();
  new XWiki.actionButtons.AjaxSaveAndContinue();
});
<commit_msg>XWIKI-3701: Faster save and continue using AJAX Fixed problem with documents created from templates: When attempting to save more than once,  the error message "This document already exists" appears and the document cannot be saved. The fix consists of simply disabeling the template field after the save, so that it is ignored the next time.<commit_after>// ======================================
// Form buttons: shortcuts, AJAX improvements and form validation
// To be completed.
if (typeof(XWiki) == 'undefined') {
  XWiki = new Object();
}
if (typeof(XWiki.actionButtons) == 'undefined') {
  XWiki.actionButtons = new Object();
}

XWiki.actionButtons.EditActions = Class.create({
  initialize : function() {
    this.addListeners();
    this.addShortcuts();
  },
  addListeners : function() {
    $$('input[name=action_cancel]').each(function(item) {
      item.observe('click', this.onCancel.bindAsEventListener(this));
    }.bind(this));
    $$('input[name=action_preview]').each(function(item) {
      item.observe('click', this.onPreview.bindAsEventListener(this));
    }.bind(this));
    $$('input[name=action_save]').each(function(item) {
      item.observe('click', this.onSaveAndView.bindAsEventListener(this));
    }.bind(this));
    $$('input[name=action_saveandcontinue]').each(function(item) {
      item.observe('click', this.onSaveAndContinue.bindAsEventListener(this));
    }.bind(this));
  },
  addShortcuts : function() {
    var shortcuts = {
      'action_cancel' : "$msg.get('core.shortcuts.edit.cancel')",
      'action_preview' : "$msg.get('core.shortcuts.edit.preview')",
      // The following 2 are both "Back to edit" in the preview mode, depending on the used editor
      'action_edit' : "$msg.get('core.shortcuts.edit.backtoedit')",
      'action_inline' : "$msg.get('core.shortcuts.edit.backtoedit')",
      'action_save' : "$msg.get('core.shortcuts.edit.saveandview')",
      'action_propupdate' : "$msg.get('core.shortcuts.edit.saveandview')",
      'action_saveandcontinue' : "$msg.get('core.shortcuts.edit.saveandcontinue')"
    }
    for (var key in shortcuts) {
      var targetButtons = $$("input[name=" + key + "]");
      if (targetButtons.size() > 0) {
        shortcut.add(shortcuts[key], function() {
          this.click();
        }.bind(targetButtons.first()), {'propagate' : false} );
      }
    }
  },
  validateForm : function(form) {
    #if($xwiki.isEditCommentMandatory())
      var commentField = form.comment
      while (commentField.value == "") {
        var response = prompt("${msg.get('core.comment.prompt')}");
        if (response === null) {
          return false;
        }
        commentField.value = response;
      }
    #elseif($xwiki.isEditCommentSuggested())
      var commentField = form.comment
      if (commentField.value == "") {
        var response = prompt("${msg.get('core.comment.prompt')}");
        if (response === null) {
          return false;
        }
        commentField.value = response;
      }
    #end
    return true;
  },
  onCancel : function(event) {
    event.stop();

    // Notify others we are going to cancel
    this.notify(event, "cancel");

    var location = event.element().form.action;
    if (typeof location != "string") {
       location = event.element().form.attributes.getNamedItem("action");
       if (location) {
         location = location.nodeValue;
       } else {
         location = window.self.location.href;
       }
    }
    if (location.indexOf('?') == -1) {
      location += '?';
    }
    window.location = location + '&action_cancel=true';
  },
  onPreview : function(event) {
    if (!this.validateForm(event.element().form)) {
      event.stop();
    } else {
      // Notify others
      this.notify(event, "preview");
    }
  },
  onSaveAndView : function(event) {
    if (!this.validateForm(event.element().form)) {
      event.stop();
    } else {
      this.notify(event, "save", {"continue" : false});
    }
  },
  onSaveAndContinue : function(event) {
    if (!this.validateForm(event.element().form)) {
      event.stop();
    } else {
      this.notify(event, "save", {"continue" : true});
    }
  },
  notify : function(event, action, params) {
    document.fire("xwiki:actions:" + action, Object.extend({originalEvent : event, form: event.element().form}, params || { }));
    // In IE, events can't be stopped from another event's handler, so we must call stop() again here
    if (event.stopped) {
      event.stop();
    }
  }
});

// ======================================
// Save and continue button: Ajax improvements
XWiki.actionButtons.AjaxSaveAndContinue = Class.create({
  effectDuration : 1.0,
  initialize : function() {
    this.createMessages();
    this.addListeners();
  },
  createMessages : function() {
    this.container = new Element('div').setStyle({
      'fontWeight' : 'bold',
      position : 'fixed',
      bottom: '8px',
      left: '0%',
      width: '100%',
      'textAlign': 'center',
      zIndex: 1200
    }).hide();
    var innerContainer = new Element('div');
    this.savingBox = new Element('span', { 'class' : 'plainmessage' }).setStyle({
      background: "#000 url($xwiki.getSkinFile('icons/xwiki/ajax-loader-white.gif')) 8px center no-repeat",
      margin: 'auto',
      padding: '8px 32px',
      color: '#FFF'
    }).update('Saving...').hide();
    this.savedBox = new Element('span').setStyle({
      background: "#000 url($xwiki.getSkinFile('icons/silk/tick.gif')) 8px center no-repeat",
      margin: 'auto',
      padding: '8px 32px',
      color: '#FFF'
    }).update('Saved').hide();
    this.failedBox = new Element('span').setStyle({
      background: "#DDD url($xwiki.getSkinFile('icons/msgerror.png')) 8px center no-repeat",
      margin: 'auto',
      padding: '6px 32px 4px',
      color: '#F00',
      border: '2px solid #F00'
    }).update('Failed to save the document. Reason: ').hide();
    innerContainer.appendChild(this.savingBox);
    innerContainer.appendChild(this.savedBox);
    innerContainer.appendChild(this.failedBox);
    this.container.appendChild(innerContainer);
    document.body.appendChild(this.container);
  },
  addListeners : function() {
    document.observe("xwiki:actions:save", this.onSave.bindAsEventListener(this));
  },
  onSave : function(event) {
    if (event.memo["continue"]) {
      if (typeof (event.memo.originalEvent) != 'undefined') {
        event.memo.originalEvent.stop();
      }
      this.form = event.memo.form;
      this.savedBox.hide();
      this.failedBox.hide();
      this.savingBox.show();
      this.showMessage();
      var formData = new Hash(event.memo.form.serialize({hash: true, submit: 'action_saveandcontinue'}));
      if (!Prototype.Browser.Opera) {
        // Opera can't handle properly 204 responses.
        formData.set('ajax', 'true');
      }
      new Ajax.Request(event.memo.form.action, {
        method : 'post',
        parameters : formData.toQueryString(),
        onSuccess : this.onSuccess.bindAsEventListener(this),
        on1223 : this.on1223.bindAsEventListener(this),
        on0 : this.on0.bindAsEventListener(this),
        onFailure : this.onFailure.bind(this)
      });
    }
  },
  // IE converts 204 status code into 1223...
  on1223 : function(response) {
    response.request.options.onSuccess(response);
  },
  // 0 is returned for network failures, except on IE where a strange large number (12031) is returned.
  on0 : function(response) {
    response.request.options.onFailure(response);
  },
  onSuccess : function(response) {
    // If there was a 'template' field in the form, disable it to avoid 'This document already exists' errors.
    if (this.form && this.form.template) {
      this.form.template.disabled = true;
      this.form.template.value = "";
    }
    this.savingBox.hide();
    this.savedBox.show();
    this.hideMessage();
  },
  onFailure : function(response) {
    if (response.statusText == '' /* No response */ || response.status == 12031 /* In IE */) {
      $('ajaxRequestFailureReason').update('Server not responding');
    } else {
      $('ajaxRequestFailureReason').update(response.statusText);
    }
    this.savingBox.hide();
    this.failedBox.show();
    this.hideMessage();
  },
  showMessage : function() {
    if (this.hideEffect) {
      this.hideEffect.cancel();
      delete this.hideEffect;
    }
    if (Prototype.Browser.IE) {
      this.container.setStyle({position : 'absolute', 'bottom': '0px'});
    }
    if (!this.showEffect && !this.container.visible()) {
      this.showEffect = new Effect.Appear(this.container, {duration: 0.2, afterFinish: function() {
        delete this.showEffect;
      }.bind(this)});
    }
  },
  hideMessage : function() {
    this.hideEffect = new Effect.Fade(this.container, {duration: this.effectDuration, delay: 2, afterFinish: function() {
      this.savedBox.hide();
      this.failedBox.hide();
      delete this.hideEffect;
    }.bind(this)});
  }
});
document.observe('dom:loaded', function() {
  new XWiki.actionButtons.EditActions();
  new XWiki.actionButtons.AjaxSaveAndContinue();
});
<|endoftext|>


<commit_before>// ======================================
// Form buttons: shortcuts, AJAX improvements and form validation
// To be completed.

// Make sure the XWiki 'namespace' exists.
if (typeof(XWiki) == 'undefined') {
  XWiki = new Object();
}
// Make sure the actionButtons 'namespace' exists.
if (typeof(XWiki.actionButtons) == 'undefined') {
  XWiki.actionButtons = new Object();
}

XWiki.actionButtons.EditActions = Class.create({
  initialize : function() {
    this.addListeners();
    this.addShortcuts();
  },
  addListeners : function() {
    $$('input[name=action_cancel]').each(function(item) {
      item.observe('click', this.onCancel.bindAsEventListener(this));
    }.bind(this));
    $$('input[name=action_preview]').each(function(item) {
      item.observe('click', this.onPreview.bindAsEventListener(this));
    }.bind(this));
    $$('input[name=action_save]').each(function(item) {
      item.observe('click', this.onSaveAndView.bindAsEventListener(this));
    }.bind(this));
    $$('input[name=action_saveandcontinue]').each(function(item) {
      item.observe('click', this.onSaveAndContinue.bindAsEventListener(this));
    }.bind(this));
  },
  addShortcuts : function() {
    var shortcuts = {
      'action_cancel' : "$msg.get('core.shortcuts.edit.cancel')",
      'action_preview' : "$msg.get('core.shortcuts.edit.preview')",
      // The following 2 are both "Back to edit" in the preview mode, depending on the used editor
      'action_edit' : "$msg.get('core.shortcuts.edit.backtoedit')",
      'action_inline' : "$msg.get('core.shortcuts.edit.backtoedit')",
      'action_save' : "$msg.get('core.shortcuts.edit.saveandview')",
      'action_propupdate' : "$msg.get('core.shortcuts.edit.saveandview')",
      'action_saveandcontinue' : "$msg.get('core.shortcuts.edit.saveandcontinue')"
    }
    for (var key in shortcuts) {
      var targetButtons = $$("input[name=" + key + "]");
      if (targetButtons.size() > 0) {
        shortcut.add(shortcuts[key], function() {
          this.click();
        }.bind(targetButtons.first()), {'propagate' : false} );
      }
    }
  },
  validateForm : function(form) {
    #if($xwiki.isEditCommentMandatory())
      var commentField = form.comment
      while (commentField.value == "") {
        var response = prompt("${msg.get('core.comment.prompt')}");
        if (response === null) {
          return false;
        }
        commentField.value = response;
      }
    #elseif($xwiki.isEditCommentSuggested())
      var commentField = form.comment
      if (commentField.value == "") {
        var response = prompt("${msg.get('core.comment.prompt')}");
        if (response === null) {
          return false;
        }
        commentField.value = response;
      }
    #end
    return true;
  },
  onCancel : function(event) {
    event.stop();

    // Notify others we are going to cancel
    this.notify(event, "cancel");

    var location = event.element().form.action;
    if (typeof location != "string") {
       location = event.element().form.attributes.getNamedItem("action");
       if (location) {
         location = location.nodeValue;
       } else {
         location = window.self.location.href;
       }
    }
    if (location.indexOf('?') == -1) {
      location += '?';
    }
    window.location = location + '&action_cancel=true';
  },
  onPreview : function(event) {
    if (!this.validateForm(event.element().form)) {
      event.stop();
    } else {
      // Notify others
      this.notify(event, "preview");
    }
  },
  onSaveAndView : function(event) {
    if (!this.validateForm(event.element().form)) {
      event.stop();
    } else {
      this.notify(event, "save", {"continue" : false});
    }
  },
  onSaveAndContinue : function(event) {
    if (!this.validateForm(event.element().form)) {
      event.stop();
    } else {
      this.notify(event, "save", {"continue" : true});
    }
  },
  notify : function(event, action, params) {
    document.fire("xwiki:actions:" + action, Object.extend({originalEvent : event, form: event.element().form}, params || { }));
    // In IE, events can't be stopped from another event's handler, so we must call stop() again here
    if (event.stopped) {
      event.stop();
    }
  }
});

// ======================================
// Save and continue button: Ajax improvements
XWiki.actionButtons.AjaxSaveAndContinue = Class.create({
  initialize : function() {
    this.createMessages();
    this.addListeners();
  },
  createMessages : function() {
    this.savingBox = new XWiki.widgets.Notification("Saving...", "inprogress", {inactive: true});
    this.savedBox = new XWiki.widgets.Notification("Saved", "done", {inactive: true});
    this.failedBox = new XWiki.widgets.Notification("Failed to save the document. Reason: ", "error", {inactive: true});
  },
  addListeners : function() {
    document.observe("xwiki:actions:save", this.onSave.bindAsEventListener(this));
  },
  onSave : function(event) {
    if (event.memo["continue"]) {
      if (typeof (event.memo.originalEvent) != 'undefined') {
        event.memo.originalEvent.stop();
      }
      this.form = event.memo.form;
      this.savedBox.hide();
      this.failedBox.hide();
      this.savingBox.show();
      var formData = new Hash(event.memo.form.serialize({hash: true, submit: 'action_saveandcontinue'}));
      if (!Prototype.Browser.Opera) {
        // Opera can't handle properly 204 responses.
        formData.set('ajax', 'true');
      }
      new Ajax.Request(event.memo.form.action, {
        method : 'post',
        parameters : formData.toQueryString(),
        onSuccess : this.onSuccess.bindAsEventListener(this),
        on1223 : this.on1223.bindAsEventListener(this),
        on0 : this.on0.bindAsEventListener(this),
        onFailure : this.onFailure.bind(this)
      });
    }
  },
  // IE converts 204 status code into 1223...
  on1223 : function(response) {
    response.request.options.onSuccess(response);
  },
  // 0 is returned for network failures, except on IE where a strange large number (12031) is returned.
  on0 : function(response) {
    response.request.options.onFailure(response);
  },
  onSuccess : function(response) {
    // If there was a 'template' field in the form, disable it to avoid 'This document already exists' errors.
    if (this.form && this.form.template) {
      this.form.template.disabled = true;
      this.form.template.value = "";
    }
    this.savingBox.replace(this.savedBox);
    // Announce that the document has been saved
    // TODO: We should send the new version as a memo field
    document.fire("xwiki:document:saved");
  },
  onFailure : function(response) {
    this.savingBox.replace(this.failedBox);
    if (response.statusText == '' /* No response */ || response.status == 12031 /* In IE */) {
      $('ajaxRequestFailureReason').update('Server not responding');
    } else {
      $('ajaxRequestFailureReason').update(response.statusText);
    }
    // Announce that a document save attempt has failed
    document.fire("xwiki:document:saveFailed", {'response' : response});
  }
});
document.observe('dom:loaded', function() {
  new XWiki.actionButtons.EditActions();
  new XWiki.actionButtons.AjaxSaveAndContinue();
});
<commit_msg>XWIKI-5021: "Save and Continue" doesn't work in Preview mode only with IE7 Fixed.<commit_after>// ======================================
// Form buttons: shortcuts, AJAX improvements and form validation
// To be completed.

// Make sure the XWiki 'namespace' exists.
if (typeof(XWiki) == 'undefined') {
  XWiki = new Object();
}
// Make sure the actionButtons 'namespace' exists.
if (typeof(XWiki.actionButtons) == 'undefined') {
  XWiki.actionButtons = new Object();
}

XWiki.actionButtons.EditActions = Class.create({
  initialize : function() {
    this.addListeners();
    this.addShortcuts();
  },
  addListeners : function() {
    $$('input[name=action_cancel]').each(function(item) {
      item.observe('click', this.onCancel.bindAsEventListener(this));
    }.bind(this));
    $$('input[name=action_preview]').each(function(item) {
      item.observe('click', this.onPreview.bindAsEventListener(this));
    }.bind(this));
    $$('input[name=action_save]').each(function(item) {
      item.observe('click', this.onSaveAndView.bindAsEventListener(this));
    }.bind(this));
    $$('input[name=action_saveandcontinue]').each(function(item) {
      item.observe('click', this.onSaveAndContinue.bindAsEventListener(this));
    }.bind(this));
  },
  addShortcuts : function() {
    var shortcuts = {
      'action_cancel' : "$msg.get('core.shortcuts.edit.cancel')",
      'action_preview' : "$msg.get('core.shortcuts.edit.preview')",
      // The following 2 are both "Back to edit" in the preview mode, depending on the used editor
      'action_edit' : "$msg.get('core.shortcuts.edit.backtoedit')",
      'action_inline' : "$msg.get('core.shortcuts.edit.backtoedit')",
      'action_save' : "$msg.get('core.shortcuts.edit.saveandview')",
      'action_propupdate' : "$msg.get('core.shortcuts.edit.saveandview')",
      'action_saveandcontinue' : "$msg.get('core.shortcuts.edit.saveandcontinue')"
    }
    for (var key in shortcuts) {
      var targetButtons = $$("input[name=" + key + "]");
      if (targetButtons.size() > 0) {
        shortcut.add(shortcuts[key], function() {
          this.click();
        }.bind(targetButtons.first()), {'propagate' : false} );
      }
    }
  },
  validateForm : function(form) {
    #if($xwiki.isEditCommentMandatory())
      var commentField = form.comment
      while (commentField.value == "") {
        var response = prompt("${msg.get('core.comment.prompt')}");
        if (response === null) {
          return false;
        }
        commentField.value = response;
      }
    #elseif($xwiki.isEditCommentSuggested())
      var commentField = form.comment
      if (commentField.value == "") {
        var response = prompt("${msg.get('core.comment.prompt')}");
        if (response === null) {
          return false;
        }
        commentField.value = response;
      }
    #end
    return true;
  },
  onCancel : function(event) {
    event.stop();

    // Notify others we are going to cancel
    this.notify(event, "cancel");

    var location = event.element().form.action;
    if (typeof location != "string") {
       location = event.element().form.attributes.getNamedItem("action");
       if (location) {
         location = location.nodeValue;
       } else {
         location = window.self.location.href;
       }
    }
    if (location.indexOf('?') == -1) {
      location += '?';
    }
    window.location = location + '&action_cancel=true';
  },
  onPreview : function(event) {
    if (!this.validateForm(event.element().form)) {
      event.stop();
    } else {
      // Notify others
      this.notify(event, "preview");
    }
  },
  onSaveAndView : function(event) {
    if (!this.validateForm(event.element().form)) {
      event.stop();
    } else {
      this.notify(event, "save", {"continue" : false});
    }
  },
  onSaveAndContinue : function(event) {
    if (!this.validateForm(event.element().form)) {
      event.stop();
    } else {
      this.notify(event, "save", {"continue" : true});
    }
  },
  notify : function(event, action, params) {
    document.fire("xwiki:actions:" + action, Object.extend({originalEvent : event, form: event.element().form}, params || { }));
    // In IE, events can't be stopped from another event's handler, so we must call stop() again here
    if (event.stopped) {
      event.stop();
    }
  }
});

// ======================================
// Save and continue button: Ajax improvements
XWiki.actionButtons.AjaxSaveAndContinue = Class.create({
  initialize : function() {
    this.createMessages();
    this.addListeners();
  },
  createMessages : function() {
    this.savingBox = new XWiki.widgets.Notification("Saving...", "inprogress", {inactive: true});
    this.savedBox = new XWiki.widgets.Notification("Saved", "done", {inactive: true});
    this.failedBox = new XWiki.widgets.Notification("Failed to save the document. Reason: ", "error", {inactive: true});
  },
  addListeners : function() {
    document.observe("xwiki:actions:save", this.onSave.bindAsEventListener(this));
  },
  onSave : function(event) {
    if (event.memo["continue"]) {
      if (typeof (event.memo.originalEvent) != 'undefined') {
        event.memo.originalEvent.stop();
      }
      this.form = $(event.memo.form);
      this.savedBox.hide();
      this.failedBox.hide();
      this.savingBox.show();
      var formData = new Hash(this.form.serialize({hash: true, submit: 'action_saveandcontinue'}));
      if (!Prototype.Browser.Opera) {
        // Opera can't handle properly 204 responses.
        formData.set('ajax', 'true');
      }
      new Ajax.Request(this.form.action, {
        method : 'post',
        parameters : formData.toQueryString(),
        onSuccess : this.onSuccess.bindAsEventListener(this),
        on1223 : this.on1223.bindAsEventListener(this),
        on0 : this.on0.bindAsEventListener(this),
        onFailure : this.onFailure.bind(this)
      });
    }
  },
  // IE converts 204 status code into 1223...
  on1223 : function(response) {
    response.request.options.onSuccess(response);
  },
  // 0 is returned for network failures, except on IE where a strange large number (12031) is returned.
  on0 : function(response) {
    response.request.options.onFailure(response);
  },
  onSuccess : function(response) {
    // If there was a 'template' field in the form, disable it to avoid 'This document already exists' errors.
    if (this.form && this.form.template) {
      this.form.template.disabled = true;
      this.form.template.value = "";
    }
    this.savingBox.replace(this.savedBox);
    // Announce that the document has been saved
    // TODO: We should send the new version as a memo field
    document.fire("xwiki:document:saved");
  },
  onFailure : function(response) {
    this.savingBox.replace(this.failedBox);
    if (response.statusText == '' /* No response */ || response.status == 12031 /* In IE */) {
      $('ajaxRequestFailureReason').update('Server not responding');
    } else {
      $('ajaxRequestFailureReason').update(response.statusText);
    }
    // Announce that a document save attempt has failed
    document.fire("xwiki:document:saveFailed", {'response' : response});
  }
});
document.observe('dom:loaded', function() {
  new XWiki.actionButtons.EditActions();
  new XWiki.actionButtons.AjaxSaveAndContinue();
});
<|endoftext|>


<commit_before>var mockery = require('mockery')
require('chai').should()

describe('its-config', function() {
  before(function() {
    mockery.enable({
      warnOnUnregistered: false,
      warnOnReplace: false
    })

    mockery.registerMock('../.config/car', {
      color: 'blue'
    })
    mockery.registerMock('../.config/bob/car', {
      make: 'Honda',
      model: 'Civic',
      options: {
        'power-steering': true,
        roof: 'moonroof'
      }
    })
    mockery.registerMock('../.config/jane/car', {
      make: 'Ford',
      model: 'Bronco',
      options: {
        '4x4': true,
        roof: 'sunroof'
      }
    })
    mockery.registerMock('../.config/low-on-gas/car', {
      gasRemaning: 0.1
    })
    mockery.registerMock('../.config/power-package/car', {
      options: {
        'power-steering': true,
        'power-windows': true
      }
    })
  })

  after(function() {
    mockery.disable()
  })

  describe('specifying precedence', function() {
    var bobsBlueCar = {
      color: 'blue',
      make: 'Honda',
      model: 'Civic',
      options: {
        'power-steering': true,
        roof: 'moonroof'
      }
    }

    afterEach(function() {
      delete process.env.precedence;
      delete process.env['Its.Configuration.Precedence'];
    })

    it('should load default configuration given no precedence', function() {
      var config = require('../its.config')()
      config('car').should.deep.equal({ color: 'blue' })
    })

    it('should load configuration given default precedence, merged with the default', function() {
      var config = require('../its.config')('jane')
      config('car').should.deep.equal({
        color: 'blue',
        make: 'Ford',
        model: 'Bronco',
        options: {
          '4x4': true,
          roof: 'sunroof'
        }
      })
    })

    it('should load configuration from the precedence environment variable', function() {
      process.env.precedence = 'bob'

      var config = require('../its.config')()
      config('car').should.deep.equal(bobsBlueCar)
    })

    it('should load configuration from the Its.Configuration.Precedence environment variable', function() {
      process.env['Its.Configuration.Precedence'] = 'bob'

      require('../its.config')()('car').should.deep.equal(bobsBlueCar)
    })

    it('should load an environment precedence over the default precedence', function() {
      process.env['Its.Configuration.Precedence'] = 'bob'

      require('../its.config')('jane')('car').should.deep.equal(bobsBlueCar)
    })
  })

  describe('merging configuration', function() {
    it('should merge configurations given pipe-delimited aspects', function() {
      require('../its.config')('low-on-gas|jane')('car').should.deep.equal({
        color: 'blue',
        make: 'Ford',
        model: 'Bronco',
        options: {
          '4x4': true,
          roof: 'sunroof'
        },
        gasRemaning: 0.1
      })
    })

    it('should merge configurations preserving desired order of precedence', function() {
      require('../its.config')('bob|jane')('car').should.deep.equal({
        color: 'blue',
        make: 'Ford',
        model: 'Bronco',
        options: {
          '4x4': true,
          roof: 'sunroof',
          'power-steering': true
        }
      })
    })

    it('should merge a bunch of stuff correctly', function() {
      require('../its.config')('low-on-gas|power-package|jane')('car').should.deep.equal({
        color: 'blue',
        make: 'Ford',
        model: 'Bronco',
        options: {
          '4x4': true,
          roof: 'sunroof',
          'power-steering': true,
          'power-windows': true
        },
        gasRemaning: 0.1
      })
    })
  })
})<commit_msg>Fix its.config.js tests<commit_after>var mockery = require('mockery')
require('chai').should()

describe('its-config', function() {
  before(function() {
    mockery.enable({
      warnOnUnregistered: false,
      warnOnReplace: false
    })

    mockery.registerMock('../../.config/car', {
      color: 'blue'
    })
    mockery.registerMock('../../.config/bob/car', {
      make: 'Honda',
      model: 'Civic',
      options: {
        'power-steering': true,
        roof: 'moonroof'
      }
    })
    mockery.registerMock('../../.config/jane/car', {
      make: 'Ford',
      model: 'Bronco',
      options: {
        '4x4': true,
        roof: 'sunroof'
      }
    })
    mockery.registerMock('../../.config/low-on-gas/car', {
      gasRemaning: 0.1
    })
    mockery.registerMock('../../.config/power-package/car', {
      options: {
        'power-steering': true,
        'power-windows': true
      }
    })
  })

  after(function() {
    mockery.disable()
  })

  describe('specifying precedence', function() {
    var bobsBlueCar = {
      color: 'blue',
      make: 'Honda',
      model: 'Civic',
      options: {
        'power-steering': true,
        roof: 'moonroof'
      }
    }

    afterEach(function() {
      delete process.env.precedence;
      delete process.env['Its.Configuration.Precedence'];
    })

    it('should load default configuration given no precedence', function() {
      var config = require('../its.config')()
      config('car').should.deep.equal({ color: 'blue' })
    })

    it('should load configuration given default precedence, merged with the default', function() {
      var config = require('../its.config')('jane')
      config('car').should.deep.equal({
        color: 'blue',
        make: 'Ford',
        model: 'Bronco',
        options: {
          '4x4': true,
          roof: 'sunroof'
        }
      })
    })

    it('should load configuration from the precedence environment variable', function() {
      process.env.precedence = 'bob'

      var config = require('../its.config')()
      config('car').should.deep.equal(bobsBlueCar)
    })

    it('should load configuration from the Its.Configuration.Precedence environment variable', function() {
      process.env['Its.Configuration.Precedence'] = 'bob'

      require('../its.config')()('car').should.deep.equal(bobsBlueCar)
    })

    it('should load an environment precedence over the default precedence', function() {
      process.env['Its.Configuration.Precedence'] = 'bob'

      require('../its.config')('jane')('car').should.deep.equal(bobsBlueCar)
    })
  })

  describe('merging configuration', function() {
    it('should merge configurations given pipe-delimited aspects', function() {
      require('../its.config')('low-on-gas|jane')('car').should.deep.equal({
        color: 'blue',
        make: 'Ford',
        model: 'Bronco',
        options: {
          '4x4': true,
          roof: 'sunroof'
        },
        gasRemaning: 0.1
      })
    })

    it('should merge configurations preserving desired order of precedence', function() {
      require('../its.config')('bob|jane')('car').should.deep.equal({
        color: 'blue',
        make: 'Ford',
        model: 'Bronco',
        options: {
          '4x4': true,
          roof: 'sunroof',
          'power-steering': true
        }
      })
    })

    it('should merge a bunch of stuff correctly', function() {
      require('../its.config')('low-on-gas|power-package|jane')('car').should.deep.equal({
        color: 'blue',
        make: 'Ford',
        model: 'Bronco',
        options: {
          '4x4': true,
          roof: 'sunroof',
          'power-steering': true,
          'power-windows': true
        },
        gasRemaning: 0.1
      })
    })
  })
})<|endoftext|>


<commit_before>/**
 * "jQuery UI Resizable Snap" - Extension to the jQuery UI Resizable plugin for snapping while resizing.
 *
 * @copyright       Copyright 2011, Alexander Polomoshnov
 * @license         MIT license (https://raw.github.com/polomoshnov/jQuery-UI-Resizable-Snap-extension/master/LICENSE.txt)
 * @link            https://github.com/polomoshnov/jQuery-UI-Resizable-Snap-extension
 * @version         1.6
 */
(function(a){function f(b,c,d){var e=a.ui.resizable.prototype[b];a.ui.resizable.prototype[b]=function(){if(d)d.apply(this,arguments);e.apply(this,arguments);if(c)c.apply(this,arguments)}}function e(a){return parseInt(a.css("margin-top"),10)||0}function d(a){return parseInt(a.css("margin-left"),10)||0}function c(a){return a.sort(function(a,b){return!a?1:!b?-1:Math.abs(a)-Math.abs(b)})[0]}function b(a,b,c){return Math.abs(a)<c?-a:Math.abs(b)<c?-b:0}a.extend(a.ui.resizable.prototype.options,{snapTolerance:20,snapMode:"both"});a.ui.plugin.add("resizable","snap",{start:function(){var b=a(this),c=b.data("resizable"),f=c.options.snap;c.ow=c.helper.outerWidth()-c.size.width;c.oh=c.helper.outerHeight()-c.size.height;c.lm=d(b);c.tm=e(b);c.coords=[];a(typeof f=="string"?f:":data(resizable)").each(function(){if(this==c.element[0]||this==c.helper[0])return;var b=a(this),f=b.position(),g=f.left+d(b),h=f.top+e(b);c.coords.push({l:g,t:h,r:g+b.outerWidth(),b:h+b.outerHeight()})})},resize:function(){var d=[],e=[],f=[],g=[],h=a(this).data("resizable"),i=h.axis.split(""),j=h.options.snapTolerance,k=h.options.snapMode,l=h.position.left+h.lm,m=l-j,n=h.position.top+h.tm,o=n-j,p=l+h.size.width+h.ow,q=p+j,r=n+h.size.height+h.oh,s=r+j;a.each(h.coords,function(){var a=Math.min(q,this.r)-Math.max(m,this.l),c=Math.min(s,this.b)-Math.max(o,this.t);if(a<0||c<0)return;for(var h=0;h<i.length;h++){if(k=="outer"){switch(i[h]){case"w":case"e":if(a>j*2)return;break;case"n":case"s":if(c>j*2)return}}else if(k=="inner"){switch(i[h]){case"w":case"e":if(a<j*2)return;break;case"n":case"s":if(c<j*2)return}}switch(i[h]){case"w":d.push(b(l-this.l,l-this.r,j));break;case"n":e.push(b(n-this.t,n-this.b,j));break;case"e":f.push(b(p-this.l,p-this.r,j));break;case"s":g.push(b(r-this.t,r-this.b,j))}}});if(g.length)h.size.height+=c(g);if(f.length)h.size.width+=c(f);if(d.length){var t=c(d);h.position.left+=t;h.size.width-=t}if(e.length){var t=c(e);h.position.top+=t;h.size.height-=t}}});f("_mouseStop",null,function(){if(this._helper){this.position={left:parseInt(this.helper.css("left")),top:parseInt(this.helper.css("top"))};this.size={width:this.helper.outerWidth(),height:this.helper.outerHeight()}}});f("_mouseStart",function(){if(this._helper){this.size={width:this.size.width-(this.helper.outerWidth()-this.helper.width()),height:this.size.height-(this.helper.outerHeight()-this.helper.height())};this.originalSize={width:this.size.width,height:this.size.height}}});f("_renderProxy",function(){if(this._helper){var b=a.browser.msie&&a.browser.version<7,c=b?1:0,d=b?2:-1;this.helper.css({left:"+="+c,top:"+="+c,width:"-="+d,height:"-="+d})}});var g=a.ui.resizable.prototype.plugins.resize;a.each(g,function(a,b){if(b[0]=="ghost"){g.splice(a,1);return false}});a.each(a.ui.resizable.prototype.plugins.start,function(b,c){if(c[0]=="ghost"){var d=c[1];c[1]=function(){d.apply(this,arguments);a(this).data("resizable").ghost.css({width:"100%",height:"100%"})};return false}})})(jQuery)<commit_msg>Edited to add radix.<commit_after>/**
 * "jQuery UI Resizable Snap" - Extension to the jQuery UI Resizable plugin for snapping while resizing.
 *
 * @copyright       Copyright 2011, Alexander Polomoshnov
 * @license         MIT license (https://raw.github.com/polomoshnov/jQuery-UI-Resizable-Snap-extension/master/LICENSE.txt)
 * @link            https://github.com/polomoshnov/jQuery-UI-Resizable-Snap-extension
 * @version         1.6
 */
(function(a){function f(b,c,d){var e=a.ui.resizable.prototype[b];a.ui.resizable.prototype[b]=function(){if(d)d.apply(this,arguments);e.apply(this,arguments);if(c)c.apply(this,arguments)}}function e(a){return parseInt(a.css("margin-top"),10)||0}function d(a){return parseInt(a.css("margin-left"),10)||0}function c(a){return a.sort(function(a,b){return!a?1:!b?-1:Math.abs(a)-Math.abs(b)})[0]}function b(a,b,c){return Math.abs(a)<c?-a:Math.abs(b)<c?-b:0}a.extend(a.ui.resizable.prototype.options,{snapTolerance:20,snapMode:"both"});a.ui.plugin.add("resizable","snap",{start:function(){var b=a(this),c=b.data("resizable"),f=c.options.snap;c.ow=c.helper.outerWidth()-c.size.width;c.oh=c.helper.outerHeight()-c.size.height;c.lm=d(b);c.tm=e(b);c.coords=[];a(typeof f=="string"?f:":data(resizable)").each(function(){if(this==c.element[0]||this==c.helper[0])return;var b=a(this),f=b.position(),g=f.left+d(b),h=f.top+e(b);c.coords.push({l:g,t:h,r:g+b.outerWidth(),b:h+b.outerHeight()})})},resize:function(){var d=[],e=[],f=[],g=[],h=a(this).data("resizable"),i=h.axis.split(""),j=h.options.snapTolerance,k=h.options.snapMode,l=h.position.left+h.lm,m=l-j,n=h.position.top+h.tm,o=n-j,p=l+h.size.width+h.ow,q=p+j,r=n+h.size.height+h.oh,s=r+j;a.each(h.coords,function(){var a=Math.min(q,this.r)-Math.max(m,this.l),c=Math.min(s,this.b)-Math.max(o,this.t);if(a<0||c<0)return;for(var h=0;h<i.length;h++){if(k=="outer"){switch(i[h]){case"w":case"e":if(a>j*2)return;break;case"n":case"s":if(c>j*2)return}}else if(k=="inner"){switch(i[h]){case"w":case"e":if(a<j*2)return;break;case"n":case"s":if(c<j*2)return}}switch(i[h]){case"w":d.push(b(l-this.l,l-this.r,j));break;case"n":e.push(b(n-this.t,n-this.b,j));break;case"e":f.push(b(p-this.l,p-this.r,j));break;case"s":g.push(b(r-this.t,r-this.b,j))}}});if(g.length)h.size.height+=c(g);if(f.length)h.size.width+=c(f);if(d.length){var t=c(d);h.position.left+=t;h.size.width-=t}if(e.length){var t=c(e);h.position.top+=t;h.size.height-=t}}});f("_mouseStop",null,function(){if(this._helper){this.position={left:parseInt(this.helper.css("left"),10),top:parseInt(this.helper.css("top"),10)};this.size={width:this.helper.outerWidth(),height:this.helper.outerHeight()}}});f("_mouseStart",function(){if(this._helper){this.size={width:this.size.width-(this.helper.outerWidth()-this.helper.width()),height:this.size.height-(this.helper.outerHeight()-this.helper.height())};this.originalSize={width:this.size.width,height:this.size.height}}});f("_renderProxy",function(){if(this._helper){var b=a.browser.msie&&a.browser.version<7,c=b?1:0,d=b?2:-1;this.helper.css({left:"+="+c,top:"+="+c,width:"-="+d,height:"-="+d})}});var g=a.ui.resizable.prototype.plugins.resize;a.each(g,function(a,b){if(b[0]=="ghost"){g.splice(a,1);return false}});a.each(a.ui.resizable.prototype.plugins.start,function(b,c){if(c[0]=="ghost"){var d=c[1];c[1]=function(){d.apply(this,arguments);a(this).data("resizable").ghost.css({width:"100%",height:"100%"})};return false}})})(jQuery)<|endoftext|>


<commit_before>//best part of this is that if i want some OTHER scene to be able to have romantic dialgoue (say i write a general purpose dialogue scene)
//it's render function can just call new QuadrantDialogue(this.session).renderContent(div); and be done.
//resuability, yo
//http://www.neoseeker.com/forums/26839/t1277308-random-npc-conversations/   (or i guess i could just play oblivion, but I want a LIST dammit, of memes to add.)
function QuadrantDialogue(session){
	this.session=session;
	this.canRepeat = true;
	this.player1 = null;
	this.player2 = null;
	this.player1Start = null;
	this.player2Start = null;

	//this should have a higher priority than land quests, 'cause the point is relationships distract you from playing the damn game.
	this.trigger = function(){
		this.player1 = null;
		this.player2 = null;

		if(Math.seededRandom() > 0.0001){ //fiddle with rate later, for now, i want to see this happen.
			findSemiRandomQuadrantedAvailablePlayer();
			findQuardrantMate();
		}
		return false;
	}

	this.findSemiRandomQuadrantedAvailablePlayer =function(){
		//set this.player1 to be a random quadranted player.
		//BUT, if there is a player in a moiralligence who is on the verge of flipping their shit, return them.  so not completely random.
	}

	this.findQuardrantMate =function(){
		//set this.player2 to be one of player1's quadrant mates. first diamond, then heart, then spade, then clubs.
	}

	this.getDiscussSymbol =function(){
		//TODO, turn which quadrant player1 and player2 are in into a png to pass.  Create pngs for diamonds and clubs.
	}

	this.getQuadrant = function(){
		var r = this.player1.getRelationshipWith(this.player2);
		return r;
	}

	this.chatAboutInterests = function(trait,relationship){
		return  "\n<insert random 'interest in common' ( " + trait + ") chat here>\n"
		//calls different methods depending on trait, THOSE methods determine what they randomly talk about (based on relationship value)
		//trolls talking about pop culture should just list out a huge movie title because i am trash.
		//maybe randomly generate the movie title because holy fuck does that sound amazing.
		//if i do that, i should have an easter egg page that is nothing BUT listing out bullshit movie titles
		//which means the code to do that should live in NOT this scene. Maybe??????????

		//having interests in common keeps the relationship from getting too boring.
		relationship.moreOfSame();
		relationship.moreOfSame();
		relationship.moreOfSame();
	}

	/*
		The itnerest functions should pick p1 or p2 to start. If starting player isn't interested in subject, they say "umm" or "uh" or whatever.

		IMPORTANT: two ways these can be called, can be called by sharing a trait. OR by "lackOfInterest";
	*/
	this.chatAboutAcademic = function(relationship){

	}

	this.chatAboutMusic = function(relationship){
			//if both characters like rap/hiphop, etc, they rap here????
	}

	//did you get to the cloud district recently, what am i saying of course you didn't.
	this.chatAboutCulture = function(relationship){

	}

	//oh lord, tell bad jokes here.  especially puns
	this.chatAboutComedy = function(relationship){

	}

	this.chatAboutDomestic = function(relationship){

	}

	this.chatAboutAthletic = function(relationship){

	}

	this.chatAboutTerrible = function(relationship){

	}

	this.chatAboutFantasy = function(relationship){

	}

	//stop right there, criminal scum
	this.chatAboutJustice = function(relationship){

	}

	this.chatAboutLackOfInterests = function(relationship){
		//either p1 or p2 will try to say something about their interests.
		//other player will be bored to tears.
		//other player MUST be able to respond with "hrmm", "yes" and "interesting". and "horrible creatures, I hate the things."
		//call an interest directly (chatAboutJustice)
		//it'll handle responses no matter who is interested in what.
		return  "\n<insert random 'lack of interest' chat here>\n"
	}

	this.chatAboutQuadrant = function(relationship){
		//calls different methods based on quadrant.  THOSE methods have different shit in them based on value (foreshadows break up.)
		if(relationship.saved_type == relationship.diamond)return this.diamondsChat(relationship);
		if(relationship.saved_type == relationship.heart)return this.heartChat(relationship);
		if(relationship.saved_type == relationship.clubs)return this.clubsChat(relationship);
		if(relationship.saved_type == relationship.spades) return this.spadesChat(relationship);
	}

	this.clubsChat = function(relationship){
		console.log("Clubs Chat in: " + this.session.session_id)
		return  "\n<insert random 'clubs' chat here>\n"
	}

	this.spadesChat = function(relationship){
		console.log("Spades Chat  in: " + this.session.session_id)
		return  "\n<insert random 'spades' chat here>\n"
	}

	this.heartChat = function(relationship){
		console.log("Heart Chat  in: " + this.session.session_id)
		return  "\n<insert random 'heart' chat here>\n"
	}

	this.diamondsChat = function(relationship){
		console.log("Diamonds Chat  in: " + this.session.session_id)
		return  "\n<insert random 'diamond' chat here>\n"
	}

	this.feelingsJam = function(relationship){
		console.log("Feelings Jam in: " + this.session.session_id)
		//figure out which player is flipping out, make them "flippingOut", make other player "shoosher"
		//have them talk about flipOUtREason.  flippingOut has triggerLevel reduced by a good amount.
		//maybe even parse out flipOUtReason a bit. if they mention "dead" that's gonna be a different convo than ultimate riddle bullshit, right? same with time clones.
		//if i can't parse out what it's about, or don't care, then have a generic thing where they generically talk about flipOutReason
		return  "\n<insert random 'diamond flipping the fuck out' chat here>\n"
	}

	this.interestAndQuadrantChat = function(trait, relationship){
		var ret = "";
		for(var i = 0; i<3; i++){
			if(Math.seededRandom() > 0.3){ //maybe make them MORE likely to chat about interests?
				ret += this.chatAboutInterests(trait,relationship); //more likely to talk about interests.
			}else{
				ret += this.chatAboutQuadrant(relationship);
			}
		}
		return ret;
	}

	this.lackOfInterestAndQuadrantChat = function(relationship){
		var ret = "";
		for(var i = 0; i<3; i++){
		if(Math.seededRandom() > 0.5){
				ret += this.chatAboutLackOfInterests(relationship); //one character tries to talk about something that interests them, other character is bored as fuck.
			}else{
				ret += this.chatAboutQuadrant(relationship);
			}
		}
		return ret;
	}

	this.getChat =function(relationship){

		relationship.moreOfSame(); //strengthens bonds in whatever direction.
		//feelings jams have highest priority.
		if(relationship.saved_type == relationship.diamond && (this.player1.flipOutReason || this.player2.flipOutReason)){
			return this.feelingsJam(relationship);  //whole convo
		}
		var trait = whatDoPlayersHaveInCommon(this.player1, this.player2);
		if(trait != "nice"){
			return this.interestAndQuadrantChat(trait, relationship);
		}else{  //no option to chat about interests.
			return this.lackOfInterestAndQuadrantChat(relationship);
		}
	}

	this.getGreeting = function(relationship){
		var ret = "";
		var r1 = relationship;
		var r2 = this.player2.getRelationshipWith(this.player1);
		ret += chatLine(this.player1Start, this.player1,getRelationshipFlavorGreeting(r1, r2, this.player1, this.player2))
		ret += chatLine(this.player2Start, this.player2,getRelationshipFlavorGreeting(r2, r1, this.player2, this.player1))
		return ret;
	}

	this.fareWell = function(relationship){
		//fuck yes oblivion, you taught me what a good AI "goodbye" is.
		var goodByes = ["Good day.","Farewell.","Bye bye.","Bye.", "Talk to you later!", "ttyl", "seeya"];
		var badByes = ["I have nothing more to say to you.","I've heard others say the same.","Yeah, I'm done here.","I'm out.","I'm going to ollie outtie.","I'm through speaking with you."];
		var ret = "";

		var r2 = this.player2.getRelationshipWith(this.player1);
		if(relationship.value > 0){
			ret += chatLine(this.player1Start, this.player1, getRandomElementFromArray(goodByes));
		}else{
			ret += chatLine(this.player1Start, this.player1, getRandomElementFromArray(badByes));
		}

		if(r2.value > 0){
			ret += chatLine(this.player2Start, this.player2, getRandomElementFromArray(badByes));
		}else{
			ret += chatLine(this.player2Start, this.player2, getRandomElementFromArray(badByes));
		}

		return ret;
	}

	this.chat = function(div){
		var canvasHTML = "
<canvas id='canvas" + (div.attr("id")) +"' width='" +canvasWidth + "' height="+canvasHeight + "'>  </canvas>";
		div.append(canvasHTML);
		var relationship = this.getQuadrant();
		var chatText = this.getGreeting(relationship);
		chatText += this.getChat(relationship);
		chatText += this.fareWell(relationship); //<-- REQUIRED for ultimate oblivion shittieness. "I have nothing more to say to you." "good day."
		drawChat(document.getElementById("canvas"+ (div.attr("id"))), this.player1, this.player2, chatText, 0,this.getDiscussSymbol());
	}

	//have test page (link to easter eggs) where it generates some players and shoves them into relationships and
	//makes thiem this.player1 and 2 and then calls renderContent.
	this.renderContent = function(div){
		if(this.player1.aspect != "Time") removeFromArray(this.player1, this.session.availablePlayers);
		if(this.player2.aspect != "Time") removeFromArray(this.player2, this.session.availablePlayers);
		this.player1Start = this.player1.chatHandleShort()+ ": "
		this.player2Start = this.player2.chatHandleShortCheckDup(this.player1.chatHandleShort())+ ": "; //don't be lazy and usePlayer1Start as input, there's a colon.

		/*
				Since this dialogue has no "purpose", no information that HAS to be conveyed, can treat it as more dynamic.
				Go for bullshit elder scrolls pairs.

				Greeting (based on quadrant, not generic greetings)
				Greeting

				chatPair1, chatPair2, chatPair3

				where chatPair is a call and response about one of several topics, each of which have multiple random call/response things it can deploy

				Have you heard about Kvatch?
				No.

				I have been to the Imperial City recently.
				I've heard others say the same.

				I have nothing more to say to you.
				Good day.

				<3<3<3 elder scrolls. They are such ASSHOLES to each other.

				Chat pairs can be generated from: interests in common, quadrants
				ALSO, flipOutReason is special case. highest priority.

		*/
		this.chat(div);

	}

	this.content = function(){
		return "NEVER RUN IN 1.0 YOU DUNKASS. Seriously, I don't support it anymore."
	}

}
<commit_msg>symbols for dialogue chat<commit_after>//best part of this is that if i want some OTHER scene to be able to have romantic dialgoue (say i write a general purpose dialogue scene)
//it's render function can just call new QuadrantDialogue(this.session).renderContent(div); and be done.
//resuability, yo
//http://www.neoseeker.com/forums/26839/t1277308-random-npc-conversations/   (or i guess i could just play oblivion, but I want a LIST dammit, of memes to add.)
function QuadrantDialogue(session){
	this.session=session;
	this.canRepeat = true;
	this.player1 = null;
	this.player2 = null;
	this.player1Start = null;
	this.player2Start = null;

	//this should have a higher priority than land quests, 'cause the point is relationships distract you from playing the damn game.
	this.trigger = function(){
		this.player1 = null;
		this.player2 = null;

		if(Math.seededRandom() > 0.0001){ //fiddle with rate later, for now, i want to see this happen.
			findSemiRandomQuadrantedAvailablePlayer();
			findQuardrantMate();
		}
		return false;
	}

	this.findSemiRandomQuadrantedAvailablePlayer =function(){
		//set this.player1 to be a random quadranted player.
		//BUT, if there is a player in a moiralligence who is on the verge of flipping their shit, return them.  so not completely random.
	}

	this.findQuardrantMate =function(){
		//set this.player2 to be one of player1's quadrant mates. first diamond, then heart, then spade, then clubs.
	}

	this.getDiscussSymbol =function(){
		//TODO, turn which quadrant player1 and player2 are in into a png to pass.  Create pngs for diamonds and clubs.
	}

	this.getQuadrant = function(){
		var r = this.player1.getRelationshipWith(this.player2);
		return r;
	}

	this.chatAboutInterests = function(trait,relationship){
		return  "\n<insert random 'interest in common' ( " + trait + ") chat here>\n"
		//calls different methods depending on trait, THOSE methods determine what they randomly talk about (based on relationship value)
		//trolls talking about pop culture should just list out a huge movie title because i am trash.
		//maybe randomly generate the movie title because holy fuck does that sound amazing.
		//if i do that, i should have an easter egg page that is nothing BUT listing out bullshit movie titles
		//which means the code to do that should live in NOT this scene. Maybe??????????

		//having interests in common keeps the relationship from getting too boring.
		relationship.moreOfSame();
		relationship.moreOfSame();
		relationship.moreOfSame();
	}

	/*
		The itnerest functions should pick p1 or p2 to start. If starting player isn't interested in subject, they say "umm" or "uh" or whatever.

		IMPORTANT: two ways these can be called, can be called by sharing a trait. OR by "lackOfInterest";
	*/
	this.chatAboutAcademic = function(relationship){

	}

	this.chatAboutMusic = function(relationship){
			//if both characters like rap/hiphop, etc, they rap here????
	}

	//did you get to the cloud district recently, what am i saying of course you didn't.
	this.chatAboutCulture = function(relationship){

	}

	//oh lord, tell bad jokes here.  especially puns
	this.chatAboutComedy = function(relationship){

	}

	this.chatAboutDomestic = function(relationship){

	}

	this.chatAboutAthletic = function(relationship){

	}

	this.chatAboutTerrible = function(relationship){

	}

	this.chatAboutFantasy = function(relationship){

	}

	//stop right there, criminal scum
	this.chatAboutJustice = function(relationship){

	}

	this.chatAboutLackOfInterests = function(relationship){
		//either p1 or p2 will try to say something about their interests.
		//other player will be bored to tears.
		//other player MUST be able to respond with "hrmm", "yes" and "interesting". and "horrible creatures, I hate the things."
		//call an interest directly (chatAboutJustice)
		//it'll handle responses no matter who is interested in what.
		return  "\n<insert random 'lack of interest' chat here>\n"
	}

	this.chatAboutQuadrant = function(relationship){
		//calls different methods based on quadrant.  THOSE methods have different shit in them based on value (foreshadows break up.)
		if(relationship.saved_type == relationship.diamond)return this.diamondsChat(relationship);
		if(relationship.saved_type == relationship.heart)return this.heartChat(relationship);
		if(relationship.saved_type == relationship.clubs)return this.clubsChat(relationship);
		if(relationship.saved_type == relationship.spades) return this.spadesChat(relationship);
	}

	this.getQuadrantASCII = function(relationship){
		//calls different methods based on quadrant.  THOSE methods have different shit in them based on value (foreshadows break up.)
		if(relationship.saved_type == relationship.diamond)return "<>"
		if(relationship.saved_type == relationship.heart)return "<3"
		if(relationship.saved_type == relationship.clubs)return "c3<"
		if(relationship.saved_type == relationship.spades) return "<3<"
	}

	this.clubsChat = function(relationship){
		console.log("Clubs Chat in: " + this.session.session_id)
		return  "\n<insert random 'clubs' chat here>\n"
	}

	this.spadesChat = function(relationship){
		console.log("Spades Chat  in: " + this.session.session_id)
		return  "\n<insert random 'spades' chat here>\n"
	}

	this.heartChat = function(relationship){
		console.log("Heart Chat  in: " + this.session.session_id)
		return  "\n<insert random 'heart' chat here>\n"
	}

	this.diamondsChat = function(relationship){
		console.log("Diamonds Chat  in: " + this.session.session_id)
		return  "\n<insert random 'diamond' chat here>\n"
	}

	this.feelingsJam = function(relationship){
		console.log("Feelings Jam in: " + this.session.session_id)
		//figure out which player is flipping out, make them "flippingOut", make other player "shoosher"
		//have them talk about flipOUtREason.  flippingOut has triggerLevel reduced by a good amount.
		//maybe even parse out flipOUtReason a bit. if they mention "dead" that's gonna be a different convo than ultimate riddle bullshit, right? same with time clones.
		//if i can't parse out what it's about, or don't care, then have a generic thing where they generically talk about flipOutReason
		return  "\n<insert random 'diamond flipping the fuck out' chat here>\n"
	}

	this.interestAndQuadrantChat = function(trait, relationship){
		var ret = "";
		for(var i = 0; i<3; i++){
			if(Math.seededRandom() > 0.3){ //maybe make them MORE likely to chat about interests?
				ret += this.chatAboutInterests(trait,relationship); //more likely to talk about interests.
			}else{
				ret += this.chatAboutQuadrant(relationship);
			}
		}
		return ret;
	}

	this.lackOfInterestAndQuadrantChat = function(relationship){
		var ret = "";
		for(var i = 0; i<3; i++){
		if(Math.seededRandom() > 0.5){
				ret += this.chatAboutLackOfInterests(relationship); //one character tries to talk about something that interests them, other character is bored as fuck.
			}else{
				ret += this.chatAboutQuadrant(relationship);
			}
		}
		return ret;
	}

	this.getChat =function(relationship){

		relationship.moreOfSame(); //strengthens bonds in whatever direction.
		//feelings jams have highest priority.
		if(relationship.saved_type == relationship.diamond && (this.player1.flipOutReason || this.player2.flipOutReason)){
			return this.feelingsJam(relationship);  //whole convo
		}
		var trait = whatDoPlayersHaveInCommon(this.player1, this.player2);
		if(trait != "nice"){
			return this.interestAndQuadrantChat(trait, relationship);
		}else{  //no option to chat about interests.
			return this.lackOfInterestAndQuadrantChat(relationship);
		}
	}

	this.getGreeting = function(relationship){
		var ret = "";
		var r1 = relationship;
		var r2 = this.player2.getRelationshipWith(this.player1);
		ret += chatLine(this.player1Start, this.player1,getRelationshipFlavorGreeting(r1, r2, this.player1, this.player2) + this.getQuadrantASCII(relationship))
		ret += chatLine(this.player2Start, this.player2,getRelationshipFlavorGreeting(r2, r1, this.player2, this.player1)+ this.getQuadrantASCII(relationship))
		return ret;
	}

	this.fareWell = function(relationship){
		//fuck yes oblivion, you taught me what a good AI "goodbye" is.
		var goodByes = ["Good day.","Farewell.","Bye bye.","Bye.", "Talk to you later!", "ttyl", "seeya"];
		var badByes = ["I have nothing more to say to you.","I've heard others say the same.","Yeah, I'm done here.","I'm out.","I'm going to ollie outtie.","I'm through speaking with you."];
		var ret = "";

		var r2 = this.player2.getRelationshipWith(this.player1);
		if(relationship.value > 0){
			ret += chatLine(this.player1Start, this.player1, getRandomElementFromArray(goodByes));
		}else{
			ret += chatLine(this.player1Start, this.player1, getRandomElementFromArray(badByes));
		}

		if(r2.value > 0){
			ret += chatLine(this.player2Start, this.player2, getRandomElementFromArray(badByes));
		}else{
			ret += chatLine(this.player2Start, this.player2, getRandomElementFromArray(badByes));
		}

		return ret;
	}

	this.chat = function(div){
		var canvasHTML = "
<canvas id='canvas" + (div.attr("id")) +"' width='" +canvasWidth + "' height="+canvasHeight + "'>  </canvas>";
		div.append(canvasHTML);
		var relationship = this.getQuadrant();
		var chatText = this.getGreeting(relationship);
		chatText += this.getChat(relationship);
		chatText += this.fareWell(relationship); //<-- REQUIRED for ultimate oblivion shittieness. "I have nothing more to say to you." "good day."
		drawChat(document.getElementById("canvas"+ (div.attr("id"))), this.player1, this.player2, chatText, 0,this.getDiscussSymbol());
	}

	//have test page (link to easter eggs) where it generates some players and shoves them into relationships and
	//makes thiem this.player1 and 2 and then calls renderContent.
	this.renderContent = function(div){
		if(this.player1.aspect != "Time") removeFromArray(this.player1, this.session.availablePlayers);
		if(this.player2.aspect != "Time") removeFromArray(this.player2, this.session.availablePlayers);
		this.player1Start = this.player1.chatHandleShort()+ ": "
		this.player2Start = this.player2.chatHandleShortCheckDup(this.player1.chatHandleShort())+ ": "; //don't be lazy and usePlayer1Start as input, there's a colon.

		/*
				Since this dialogue has no "purpose", no information that HAS to be conveyed, can treat it as more dynamic.
				Go for bullshit elder scrolls pairs.

				Greeting (based on quadrant, not generic greetings)
				Greeting

				chatPair1, chatPair2, chatPair3

				where chatPair is a call and response about one of several topics, each of which have multiple random call/response things it can deploy

				Have you heard about Kvatch?
				No.

				I have been to the Imperial City recently.
				I've heard others say the same.

				I have nothing more to say to you.
				Good day.

				<3<3<3 elder scrolls. They are such ASSHOLES to each other.

				Chat pairs can be generated from: interests in common, quadrants
				ALSO, flipOutReason is special case. highest priority.

		*/
		this.chat(div);

	}

	this.content = function(){
		return "NEVER RUN IN 1.0 YOU DUNKASS. Seriously, I don't support it anymore."
	}

}
<|endoftext|>


<commit_before>$(document).ready(function(){

   /*
    * jQuery simple and accessible modal window, using ARIA
    * Website: http://a11y.nicolas-hoffmann.net/modal/
    * License MIT: https://github.com/nico3333fr/jquery-accessible-modal-window-aria/blob/master/LICENSE
    */
   // loading modal ------------------------------------------------------------------------------------------------------------

   // init
   var $modals = $( '.js-modal' ),
       $body = $( 'body' );

   $modals.each( function(index_to_expand) {
       var $this = $(this) ,
           index_lisible = index_to_expand+1;

       $this.attr({
             'id' : 'label_modal_' + index_lisible
              });

   });

   // jQuery formatted selector to search for focusable items
   var focusableElementsString = "a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]";

   if ( $('#js-modal-page').length === 0 ) { // just to avoid missing #js-modal-page
       $body.wrapInner('

');
       }

   // events ------------------
   $body.on( 'click', '.js-modal', function( event ) {
         var $this = $(this),
             options = $this.data(),
             $modal_starter_id = $this.attr('id'),
             $modal_prefix_classes = typeof options.modalPrefixClass !== 'undefined' ? options.modalPrefixClass + '-' : '',
             $modal_text = options.modalText || '',
             modal_content_id = typeof options.modalContentId !== 'undefined' ? options.modalContentId : '',
             $modal_content = $('#' + modal_content_id),
             $modal_title = options.modalTitle || '',
             $modal_close_text = options.modalCloseText || 'Close',
             $modal_close_title = options.modalCloseTitle || options.modalCloseText,
             $modal_background_click = options.modalBackgroundClick || '',
             $modal_code,
             $modal_overlay,
             $page = $('#js-modal-page');

         // insert code at the end
         $modal_code = '<dialog id="js-modal" class="' + $modal_prefix_classes + 'modal" role="dialog" aria-labelledby="modal-title">
';
         $modal_code += '<button id="js-modal-close" class="' + $modal_prefix_classes + 'modal-close" data-content-back-id="' + modal_content_id + '" data-focus-back="' + $modal_starter_id + '" title="' + $modal_close_title + '">' + $modal_close_text + '</button>';
         if ($modal_title !== ''){
            $modal_code += '
' + $modal_title + '
';
            }

         if ($modal_text !== ''){
            $modal_code += '
' + $modal_text + '
';
            }
            else {
                  if (modal_content_id !== '' && $modal_content.length ){
                     //var $modal_content_id = $('#' + $modal_content_id);
                     $modal_code += '
';
                     $modal_code += $modal_content.html();
                     $modal_code += '
';
                     $modal_content.empty();
                     }
                  }
         $modal_code += '
</dialog>';

         $( $modal_code ).insertAfter($page);
         $body.addClass('no-scroll');

         $page.attr('aria-hidden', 'true');

         // add overlay
         if ( $modal_background_click != 'disabled' ){
            $modal_overlay = 'Close modal';
            }
            else { $modal_overlay = ''; }

         $( $modal_overlay ).insertAfter($('#js-modal'));

         $('#js-modal-close').focus();

         event.preventDefault();

   })
   // close button and esc key
   $body.on( 'click', '#js-modal-close', function( event ) {
         var $this = $(this),
             $focus_back = '#' + $this.attr('data-focus-back'),
             $content_back_id = $this.attr('data-content-back-id'),
             $js_modal = $('#js-modal'),
             $js_modal_content = $('#js-modal-content'),
             $class_element = $js_modal.attr('class'),
             $class_element_reverse = $class_element + '--reverse',
             $js_modal_overlay = $('#js-modal-overlay'),
             $page = $('#js-modal-page');

         $page.removeAttr('aria-hidden');

         var delay = $js_modal.css( "animation-duration" );
         //alert(delay);
         if ( delay != '0s' ){
             var timeout = parseFloat(delay.replace('s','')) * 1000;
             timeout++;

             $js_modal.removeClass( $class_element );
             setTimeout(function() { $js_modal.addClass( $class_element_reverse ); }, 1);
             setTimeout(function() {
                  $body.removeClass('no-scroll');
                  $js_modal.remove();
                  $js_modal_overlay.remove();
                  if ($content_back_id !== ''){
                     $('#' + $content_back_id).html( $js_modal_content.html() );
                     }
                  $( $focus_back ).focus();
                  $js_modal.removeClass( $class_element_reverse );
                  $js_modal.addClass( $class_element );
                }, timeout);
            }
            else {
                  $body.removeClass('no-scroll');
                  $js_modal.remove();
                  $js_modal_overlay.remove();
                  if ($content_back_id !== ''){
                     $('#' + $content_back_id).html( $js_modal_content.html() );
                     }
                  $( $focus_back ).focus();
                 }

   })
   .on( 'click', '#js-modal-overlay', function( event ) {
         var $close = $('#js-modal-close');

         event.preventDefault();
         $close.trigger('click');

   })
   .on( 'keydown', '#js-modal-overlay', function( event ) {
          var $close = $('#js-modal-close');

          if ( event.keyCode == 13 || event.keyCode == 32 ) { // space or enter
              event.preventDefault();
              $close.trigger('click');
              }
   })
   .on( "keydown", "#js-modal", function( event ) {
         var $this = $(this),
             $close = $('#js-modal-close');

         if ( event.keyCode == 27 ) { // esc
             $close.trigger('click');
            }
         if ( event.keyCode == 9 ) { // tab or maj+tab

            // get list of all children elements in given object
            var children = $this.find('*');

            // get list of focusable items
            var focusableItems = children.filter(focusableElementsString).filter(':visible');

            // get currently focused item
            var focusedItem = $( document.activeElement );

            // get the number of focusable items
            var numberOfFocusableItems = focusableItems.length;

            var focusedItemIndex = focusableItems.index(focusedItem);

            if ( !event.shiftKey && (focusedItemIndex == numberOfFocusableItems - 1) ){
                focusableItems.get(0).focus();
                event.preventDefault();
               }
            if ( event.shiftKey && focusedItemIndex == 0 ){
                focusableItems.get(numberOfFocusableItems - 1).focus();
                event.preventDefault();
               }

            }

   })
   .on( "keyup", ":not(#js-modal)", function( event ) {
          var $this = $(this),
              $js_modal = $('#js-modal'),
              focusedItem = $( document.activeElement ),
              in_jsmodal = focusedItem.parents('#js-modal').length ? true : false;
              $close = $('#js-modal-close');

          if ( $js_modal.length && event.keyCode == 9 && in_jsmodal === false ) { // tab or maj+tab
             $close.focus();
          }

   })
   .on( 'focus', '#js-modal-tabindex', function( event ) {
         $close.focus();
   });

});
<commit_msg>Added class for close text<commit_after>$(document).ready(function(){

   /*
    * jQuery simple and accessible modal window, using ARIA
    * Website: http://a11y.nicolas-hoffmann.net/modal/
    * License MIT: https://github.com/nico3333fr/jquery-accessible-modal-window-aria/blob/master/LICENSE
    */
   // loading modal ------------------------------------------------------------------------------------------------------------

   // init
   var $modals = $( '.js-modal' ),
       $body = $( 'body' );

   $modals.each( function(index_to_expand) {
       var $this = $(this) ,
           index_lisible = index_to_expand+1;

       $this.attr({
             'id' : 'label_modal_' + index_lisible
              });

   });

   // jQuery formatted selector to search for focusable items
   var focusableElementsString = "a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]";

   if ( $('#js-modal-page').length === 0 ) { // just to avoid missing #js-modal-page
       $body.wrapInner('

');
       }

   // events ------------------
   $body.on( 'click', '.js-modal', function( event ) {
         var $this = $(this),
             options = $this.data(),
             $modal_starter_id = $this.attr('id'),
             $modal_prefix_classes = typeof options.modalPrefixClass !== 'undefined' ? options.modalPrefixClass + '-' : '',
             $modal_text = options.modalText || '',
             modal_content_id = typeof options.modalContentId !== 'undefined' ? options.modalContentId : '',
             $modal_content = $('#' + modal_content_id),
             $modal_title = options.modalTitle || '',
             $modal_close_text = options.modalCloseText || 'Close',
             $modal_close_title = options.modalCloseTitle || options.modalCloseText,
             $modal_background_click = options.modalBackgroundClick || '',
             $modal_code,
             $modal_overlay,
             $page = $('#js-modal-page');

         // insert code at the end
         $modal_code = '<dialog id="js-modal" class="' + $modal_prefix_classes + 'modal" role="dialog" aria-labelledby="modal-title">
';
         $modal_code += '<button id="js-modal-close" class="' + $modal_prefix_classes + 'modal-close" data-content-back-id="' + modal_content_id + '" data-focus-back="' + $modal_starter_id + '" title="' + $modal_close_title + '">' + $modal_close_text + '</button>';
         if ($modal_title !== ''){
            $modal_code += '
' + $modal_title + '
';
            }

         if ($modal_text !== ''){
            $modal_code += '
' + $modal_text + '
';
            }
            else {
                  if (modal_content_id !== '' && $modal_content.length ){
                     //var $modal_content_id = $('#' + $modal_content_id);
                     $modal_code += '
';
                     $modal_code += $modal_content.html();
                     $modal_code += '
';
                     $modal_content.empty();
                     }
                  }
         $modal_code += '
</dialog>';

         $( $modal_code ).insertAfter($page);
         $body.addClass('no-scroll');

         $page.attr('aria-hidden', 'true');

         // add overlay
         if ( $modal_background_click != 'disabled' ){
            $modal_overlay = 'Close modal';
            }
            else { $modal_overlay = ''; }

         $( $modal_overlay ).insertAfter($('#js-modal'));

         $('#js-modal-close').focus();

         event.preventDefault();

   })
   // close button and esc key
   $body.on( 'click', '#js-modal-close', function( event ) {
         var $this = $(this),
             $focus_back = '#' + $this.attr('data-focus-back'),
             $content_back_id = $this.attr('data-content-back-id'),
             $js_modal = $('#js-modal'),
             $js_modal_content = $('#js-modal-content'),
             $class_element = $js_modal.attr('class'),
             $class_element_reverse = $class_element + '--reverse',
             $js_modal_overlay = $('#js-modal-overlay'),
             $page = $('#js-modal-page');

         $page.removeAttr('aria-hidden');

         var delay = $js_modal.css( "animation-duration" );
         //alert(delay);
         if ( delay != '0s' ){
             var timeout = parseFloat(delay.replace('s','')) * 1000;
             timeout++;

             $js_modal.removeClass( $class_element );
             setTimeout(function() { $js_modal.addClass( $class_element_reverse ); }, 1);
             setTimeout(function() {
                  $body.removeClass('no-scroll');
                  $js_modal.remove();
                  $js_modal_overlay.remove();
                  if ($content_back_id !== ''){
                     $('#' + $content_back_id).html( $js_modal_content.html() );
                     }
                  $( $focus_back ).focus();
                  $js_modal.removeClass( $class_element_reverse );
                  $js_modal.addClass( $class_element );
                }, timeout);
            }
            else {
                  $body.removeClass('no-scroll');
                  $js_modal.remove();
                  $js_modal_overlay.remove();
                  if ($content_back_id !== ''){
                     $('#' + $content_back_id).html( $js_modal_content.html() );
                     }
                  $( $focus_back ).focus();
                 }

   })
   .on( 'click', '#js-modal-overlay', function( event ) {
         var $close = $('#js-modal-close');

         event.preventDefault();
         $close.trigger('click');

   })
   .on( 'keydown', '#js-modal-overlay', function( event ) {
          var $close = $('#js-modal-close');

          if ( event.keyCode == 13 || event.keyCode == 32 ) { // space or enter
              event.preventDefault();
              $close.trigger('click');
              }
   })
   .on( "keydown", "#js-modal", function( event ) {
         var $this = $(this),
             $close = $('#js-modal-close');

         if ( event.keyCode == 27 ) { // esc
             $close.trigger('click');
            }
         if ( event.keyCode == 9 ) { // tab or maj+tab

            // get list of all children elements in given object
            var children = $this.find('*');

            // get list of focusable items
            var focusableItems = children.filter(focusableElementsString).filter(':visible');

            // get currently focused item
            var focusedItem = $( document.activeElement );

            // get the number of focusable items
            var numberOfFocusableItems = focusableItems.length;

            var focusedItemIndex = focusableItems.index(focusedItem);

            if ( !event.shiftKey && (focusedItemIndex == numberOfFocusableItems - 1) ){
                focusableItems.get(0).focus();
                event.preventDefault();
               }
            if ( event.shiftKey && focusedItemIndex == 0 ){
                focusableItems.get(numberOfFocusableItems - 1).focus();
                event.preventDefault();
               }

            }

   })
   .on( "keyup", ":not(#js-modal)", function( event ) {
          var $this = $(this),
              $js_modal = $('#js-modal'),
              focusedItem = $( document.activeElement ),
              in_jsmodal = focusedItem.parents('#js-modal').length ? true : false;
              $close = $('#js-modal-close');

          if ( $js_modal.length && event.keyCode == 9 && in_jsmodal === false ) { // tab or maj+tab
             $close.focus();
          }

   })
   .on( 'focus', '#js-modal-tabindex', function( event ) {
         $close.focus();
   });

});
<|endoftext|>


<commit_before>// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-

define(['review'], function($) {
    "use strict";

    $(document).ready(function() {
        $("#files").reviewify(false);
        $("#diff").reviewify(true);
    });
});
<commit_msg>js: Fix review JS<commit_after>// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-

define(['jquery', 'review'], function($) {
    "use strict";

    $(document).ready(function() {
        $("#files").reviewify(false);
        $("#diff").reviewify(true);
    });
});
<|endoftext|>


<commit_before>import Component from 'flarum/component';
import humanTime from 'flarum/utils/human-time';
import username from 'flarum/helpers/username';

/**
  Displays information about a the first or last post in a discussion.

  @prop discussion {Discussion} The discussion to display the post for
  @prop lastPost {Boolean} Whether or not to display the last/start post
  @class TerminalPost
  @constructor
  @extends Component
 */
export default class TerminalPost extends Component {
  view() {
    var discussion = this.props.discussion;
    var lastPost = this.props.lastPost && discussion.repliesCount();

    return m('span', [
      username(discussion[lastPost ? 'lastUser' : 'startUser']()),
      lastPost ? ' replied ' : ' started ',
      m('time', humanTime(discussion[lastPost ? 'lastTime' : 'startTime']()))
    ])
  }
}
<commit_msg>Clean up, use time helper rather than util<commit_after>import Component from 'flarum/component';
import humanTime from 'flarum/helpers/human-time';
import username from 'flarum/helpers/username';

/**
  Displays information about a the first or last post in a discussion.

  @prop discussion {Discussion} The discussion to display the post for
  @prop lastPost {Boolean} Whether or not to display the last/start post
  @class TerminalPost
  @constructor
  @extends Component
 */
export default class TerminalPost extends Component {
  view() {
    var discussion = this.props.discussion;
    var lastPost = this.props.lastPost && discussion.repliesCount();

    var user = discussion[lastPost ? 'lastUser' : 'startUser']();
    var time = discussion[lastPost ? 'lastTime' : 'startTime']();

    return m('span', [
      username(user),
      lastPost ? ' replied ' : ' started ',
      humanTime(time)
    ])
  }
}
<|endoftext|>