SPICEWORKS.plugin.add(     { name:"Help Desk Responses", version:"0.10", description:"A way to define common ticket responses.  Fully commented for those wanting to learn more about how plugins are built.", guid:"p-597aa800-9708-012b-81c0-0016353cc494-1229461086", settings:{"responses":"[{\"name\": \"Reboot\", \"text\": \"Please reboot your machine and try again.\"}, {\"name\": \"Log out\", \"text\": \"Please try logging out entirely, and then logging in again.\"}, {\"name\": \"HPI Retail Site Setup\", \"text\": \"our subscription for HPI retail site has been received with thanks and your site is now active.\\n\\nYOUR RETAIL SITE URL \u0026 FORWARDING DETAILS: \\n\\nYour RETAIL SITE URL is as follows : \\nhttp://www.storesonlinepro.com/store/1988048/?id=xxxxxxxx\\n(where xxxxxxxx is your Herbalife ID number)\\n\\n1. ENSURE YOUR DETAILS ARE COMPLETE\\n\\nPlease log into your www.my-healthyprofits.com account, and goto your User Panel, by clicking the \\\\'Modify User\\\\' link at the bottom of the home page. Please ensure your email address and contact number are completed correctly. \\n\\nYour Active Website link(s) can also be viewed on the User Panel for future reference and testing.\\n\\n2. IF YOU CURRENTLY HAVE A WEBSITE NAME\\n\\nIf you currently own a domain name, then you can forward your website name (domain name) to the above URL. \\nPLEASE NOTE : non-framed / non-cloaked web forwarding must be used. \\n\\nIf you need assistance with setting up your website forwarding, please update this ticket with the following details:\\n- Your Website Name\\n- The name of the registration company, eg 123-reg.co.uk, godaddy, etc\\n- Your username for the above\\n- Your Password for the above\\nWe will then complete the setup on your behalf.\\n\\n3. IF YOU NEED A NEW WEBSITE NAME\\n\\nIf you need a new Website Name, (Domain Name) then please refer to the \\\\\\\"Setting Up Your Website\\\\\\\" link within the Resources section of your HPI account. \\n\\n\\nKind regards\\nHPI Support Team\"}, {\"name\": \"PayPal Cancellation\", \"text\": \"We have recently received a notice from Paypal cancelling your Website Subscription.\\n\\nAs Paypal cancellation notices are automatically sent if details on your PayPal account are changed, this ticket has been raised asking you to :\\n\\n1. Confirm your cancellation request \\nOR\\n2. Request a new Payment Mandate \\n\\nPlease respond to this Support Ticket within the next 48hrs to avoid disruption of  service.\\n\\nSubscription Details :\"}, {\"name\": \"HPI Retail Config\", \"text\": \"Your subscription for HPI retail site has been received with thanks and your site is now being activated.  To complete the setup, we now require the following Business details from you : \\n\\n1. CONTACT DETAILS \\n\\nYour Herbalife ID Number : \\nYour business contact number as displayed on your site :\\nYour business address details as displayed on your site :\\nYour business email address :\\n\\n2. DO YOU CURRENTLY HAVE A WEBSITE NAME ? : \\n\\nPlease provide us with the website name( Domain name) if you have one already registered.\\n\\nPlease provide the details by updating this support ticket.\\n\\nKind regards\\nHPI Support Team\"}]","link_text":"Quick Fill..."}, contentAreas: [{"content_type":"text/plain","updated_at":"2009/12/30 10:36:18 +0000","id":15,"description":null,"content_name":"README","user_id":null},{"content_type":"text/javascript","updated_at":"2009/12/30 10:36:18 +0000","id":16,"description":null,"content_name":"initialize.js","user_id":null},{"content_type":"text/css","updated_at":"2009/12/30 10:36:18 +0000","id":17,"description":null,"content_name":"plugin.css","user_id":null}], initialize:function(plugin){ plugin.includeStyles();

defineResponsesEditor();
configurePlugin();
addResponsesToHelpDesk();

// Define the responses editor that we'll be using to edit the responses.  This is used in configure plugin.
function defineResponsesEditor() {

  // CUSTOM FIELD TYPE
  // Let's create a custom editor called "responses_editor".  This will give us a better experience for defining settings.
  // NOTE: A field is just a function that adds content to an element, then returns a getter and a setter for that content.
  SPICEWORKS.field.registerFieldType({
    typeName: 'responses_editor',
    operators: [], // no operators allowed on hidden fields, doesn't make sense.
    buildEditor: function (element, fieldDef) {
      var addDiv, textarea, listElem, editorArea, newResponseItem, message, parent, id = element.id + "_value", itemEditorMap = {};   

      element.style.display = 'block';

      // temporary hack: replace P with DIV (makes ie7 work. won't need this after patch)
      if (element.nodeName === 'P') {
        parent = element.up();
        element.remove();
        parent.insert( element = new Element('div', {'class':''}));      
      }

      listElem = new Element('ul', {'id':'response_list_ul', 'class':'response_list'});
      element.insert(listElem);

      newResponseItem = addNewResponse();

      editorArea = new Element('div', {'class':'response_editor_area'});  
      element.insert(editorArea);

      editorArea.insert(message = new Element('h2').update('&larr; Select a response to edit, or create a new one.'));

      listElem.observe('click',function (e) {
        Event.stop(e);
        $$('div.response_editor_area div.response_editor_wrap').invoke('hide');
        $$('ul.response_list li').invoke('removeClassName', 'selected');
        message.show();
      });

      // Adds the response list item and associated editor to the appropriate parts of the page.
      function addResponse(res) {
        var listItem, itemName, editorWrap, nameEditor, textEditor, showListItem, deleteElem;
        window.response = res;

        editorWrap = new Element('div', {'class':'response_editor_wrap'});
        editorArea.insert(editorWrap);

        nameEditor = new Element('input', {'class':'response_name_editor text', 'value':res.name});
        editorWrap.insert(nameEditor);

        textEditor = new Element('textarea', {'class':'response_text_editor text', 'autocomplete':'off'});
        textEditor.value = res.text;
        editorWrap.insert(textEditor);


        listItem = new Element('li', {'class':'response_list_item'});
        deleteElem = new Element('a', {'class':'delete_response'});
        itemName = new Element('span').update(res.name);

        listItem.insert(deleteElem);
        listItem.insert(itemName);
        newResponseItem.insert({before: listItem});

        editorWrap.hide();

        itemEditorMap[listItem.identify()] = editorWrap;


        // EVENTS
        listItem.observe('click', function (e) {
          Event.stop(e);
          showListItem();        
        });

        listItem.observe('mouseover', function (e) {
          Event.stop(e);
          listItem.addClassName('hover');
        });

        listItem.observe('mouseout', function (e){
          Event.stop(e);
          listItem.removeClassName('hover');
        });

        deleteElem.observe('click', function (e) {
          Event.stop(e);
          if (confirm('Are you sure you want to delete this response?')) {
            listItem.remove();
            editorWrap.remove();
            $$('div.response_editor_area div.response_editor_wrap').invoke('hide');
            message.show();
          }
        });
        nameEditor.observe('keyup', function (e) {
          itemName.innerHTML = nameEditor.value;
        });

        // helper function to select the list item and show the editor.
        function showListItem() {
          $$('div.response_editor_area div.response_editor_wrap').invoke('hide');
          $$('ul.response_list li').invoke('removeClassName', 'selected');
          listItem.addClassName('selected');
          editorWrap.show();
          message.hide();
        }

        return {
          show: showListItem
        };
      }

      // Add the link to create a new response.
      function addNewResponse() {
        newResponseItem = new Element('li', {'class':'new_response_link'}).update('New Response...');
        listElem.insert(newResponseItem);

        newResponseItem.observe('mouseover', function (e) {
          Event.stop(e);
          newResponseItem.addClassName('hover');
        });
        newResponseItem.observe('mouseout', function (e){
          Event.stop(e);
          newResponseItem.removeClassName('hover');
        });
        newResponseItem.observe('click', function (e) {
          Event.stop(e);
          Sortable.destroy('response_list_ul');
          addResponse({name:'New Response', text:'Modify this to be your text!'}).show();
          Sortable.create('response_list_ul', {only:'response_list_item'});
        });
        return newResponseItem;
      }

      // Return get/set methods.  These methods will act on the elements that we defined and inserted above and will be called by the framework (you'll never
      // call them yourself).
      return {
        // Grab text from the text area an split on ~~~~ then create JSON with the name/text of each response.
        get: function () {
          var responses = [];

          $$('li.response_list_item').each(function (li) {
            var editorWrap = itemEditorMap[li.id];
            responses.push({
              name: editorWrap.down('.response_name_editor').value,
              text: editorWrap.down('.response_text_editor').value
            });            
          });

          return responses.length==0 ? null : Object.toJSON(responses);
        },

        // Parse JSON into the appropriate textarea value.
        set: function (value) {
          if (value) {
            value.evalJSON().each(addResponse);
            setTimeout( function () {
              Sortable.create('response_list_ul', {only:'response_list_item'});
            }, 100);
          }
        }
      };
    }
  });

} // end defineResponsesEditor()


// PLUGIN CONFIGURATION
// The configuration is what's displayed when the user clicks "configure" in /settings/plugins.  If this section is excluded,
// then no configure link will appear.
// There's only one configuration and that's the responses.  By default, we dump in some helper text to guide the user.
function configurePlugin() {
  var settingDefs = [];
  settingDefs.push({name:'link_text', label:'Link Text', type:'string', defaultValue:'Append'});
  settingDefs.push({
    name:'responses', label:'Responses', type:'responses_editor', 
    defaultValue: Object.toJSON([
      {"name":"Reboot", "text":"Please reboot your machine and try again."},
      {"name":"Log out", "text":"Please try logging out entirely, and then logging in again."}
    ])
  });

  plugin.configure({
    settingDefinitions: settingDefs
  });  
}



// Add the responses to the helpdesk if that's where we are.
function addResponsesToHelpDesk() {
  var responses = plugin.settings.responses.evalJSON();

  // REGISTER FOR TICKET READY EVENT
  // Each time the ticket is "ready" (loaded) we need to make sure we add the arrow and the div.
  SPICEWORKS.app.helpdesk.ticket.comments.ready(function () {
    var tipText, theTip, hideTimer, response, commentDiv;

    setupResponses();

    if (!$('add_comment_details')) {
      return; // Ticket is most likely closed...
    }

    // If the arrow is already there, then we already did this and should just return without doing anything.
    if($('append_link') || $('append_arrow')) {
      return;
    } else {
      setupAppendLink();
    }

    // Set up the events for the mouseover/outs
    Event.observe(response, 'mouseover', mouseover);
    Event.observe(theTip, 'mouseover', mouseover);
    Event.observe(response, 'mouseout', mouseout);
    Event.observe(theTip, 'mouseout', mouseout);


    // Create the responses menu
    function setupResponses() {
      tipText = new Element('ul', {'style':'margin:0px'});
      responses.each(function (response) {
        var li, link;
        li = new Element('li');
        link = new Element('a', {href:'#', 'class':'icon helpdesk_response_link'});
        li.insert(link);
        link.innerHTML = response.name;
        link.observe('click', function (event) {
          Event.stop(event);
          theTip.hide();

          $('comment_body').focus();
          setTimeout( function () {            
            $('comment_body').value = $('comment_body').value + response.text;
          }, 10); // timeout will allow help message to be cleaned out first.
          return false; 
        });
        tipText.insert( li );
      });      
    }


    // Helper Functions for shoing/hiding the menu at the appropriate times.
    // Uses a timer to make everything play nice together.
    function mouseover(event){
      Event.stop(event);
      clearTimeout(hideTimer);
      if (!theTip.visible()) {
        theTip.clonePosition(response, {
          setWidth:false,
          setHeight:false,
          offsetTop:response.offsetHeight
        });

        theTip.show();
      }

    }
    function mouseout(event){
      Event.stop(event);
      clearTimeout(hideTimer);
      hideTimer = setTimeout(function () {
        theTip.hide();
      }, 200);
    }

    function setupAppendLink() {
      commentDiv = $('add_comment_details');

      // Create the Arrow link and add it to the page
      response = new Element('a', {id:'append_link', href: '#', border:'0'});
      response.innerHTML = plugin.settings['link_text'];
      commentDiv.insert({'top': response});

      // Add the response choices to a pivotable menu (this is a css class defined by spiceworks and used for all menus)
      theTip = new Element('div', {'id':'response_choices', 'class':'pivotable', 'style':'display:none'});
      theTip.update(tipText);
      commentDiv.insert(theTip);

    }

  }); // end ticket.ready

} // end addResponsesToHelpDesk


      }
    }
 );
