Passing "this" to a function in jQuery problems

sorry but couldn't find a solution for my problem so far.

I am writing a kind of an email template editor as a little task for my boss.

$('a, span').click(function(event){
    var editableElement = $(this);

    if($(this).is('a')){
        event.preventDefault();
    }

    if(editableElement.is('span')){
        processType(editableElement, 'simpleText', modalContent)

When I send the 'editableElement' variable first time, everything's fine, sends object to my function, where I open up a modal window, where there is a textarea, which if i enter text and submit it using only jQuery it will put the text from the textarea (using .val()) to my desired element, in this case a "span" element which is the 'editableElement' using .text() on it. No problem, it works for the first time. After I try to edit a second span, it constantly modifies the previous span too, with whatever I enter in to the textarea (which is cleared out completely, the problem is NOT here) I've ran a fast debug with a simple foreach on the editable element, and the problem is that for some reason it keeps adding objects to the editableElement variable everytime I send it to the function. The number of spans I try to edit, the number of objects will be in my variable all with the index of 0.

Any idea what could be the cause of this?

Thanks in advance!

EDIT: As requested the whole code in one piece which I have problem with, though it was the whole code before too, I'm in an early stage of writing it, I understand that it was hard to read though, perhaps now it is properly formatted as requested.

$(window).load(function()
{
  var modalContent = $('#modalContent');
  modalOverlay = $('#modalOverlay');

  $('a, span').click(function(event)
  {
    var editableElement = $(this);

    if($(this).is('a'))
    {
        event.preventDefault();
    }

    if(editableElement.is('span'))
    {
        processType(editableElement, 'simpleText', modalContent)
    }
  });

  $('#codeGenButton').click(function()
  {
    var container = $('#codeContainer');

    container.empty();
    container.text(getPageHTML());
  });

  $('#modalClose').click(function()
  {
    $(this).parent().parent().animate({'opacity': '0'}, 200, 
      function(){
        $(this).css({'display': 'none'});
      });
    });
  });

function fillData(targetDomElement, modalObject)
{
  $('#modalSubmit').click(function(){
    targetDomElement.text($('#simpleTextEdit').val());
    closeModalWindow();
  });
}

function processType(targetDomElement, type, modalObject)
{
  modalObject.empty();

  if(type == 'simpleText')
  {
    modalObject.append("<p id='simpleTextEditTitle'>Text editor</p><textarea id='simpleTextEdit'></textarea>");
    getModalWindow();
    fillData(targetDomElement, modalObject);
  }
}

Step by step of what it should do:

First of all, the html should not be needed for this, it does not matter, and this is the whole code honestly.

    • When you click on either an element of (span) or an element of (a) it triggers the function.
    • It will check if it was actually a (span), or an (a) element.
    • Currently if it is an element (a), it does nothing, not implemented yet, but if it is a (span), it will call in the processType function, which it sends the "handler?" of the element to namely "editableElement" which has been declared right after the click event, the 'simpleText' which gets send too, is just to differentiate between element types I will send to the processType function later on, and for the last, "modalConotent" is only a div container, nothing more.
    • Once the function gets the data first, it will make sure, that the modal window gets cleared of ALL data that is inside of it, then it will append a bit of html code as you can see, in to the modal window, which pops up right after I have appended data in to it, it is literally just a 'display: block' and 'animate: opacity: 1' nothing special there.
    • Lastly it will trigger the 'fillData' function, which will put my desired data from '#simpleTextField' which is only a (textarea) where you can write in, to my desired element 'editableElement' which is the element you have clicked at the first place, a (span) element after the submit, which is again, just a css of 'display: none' and 'opacity: 0' closes the modal window.

THE END.

Upvotes: 0

Views: 116

Answers (2)

Jon P
Jon P

Reputation: 19772

Your problem is here

function fillData(targetDomElement, modalObject)
{
  $('#modalSubmit').click(function(){
    targetDomElement.text($('#simpleTextEdit').val());
    closeModalWindow();
  });
}

Each time this function is called it adds a new click handler with the perameters at the time the handler was created. This handler is added in addition to the already created handlers. See a demo here. After successive clicks on the spans notices how fillData is called multiple times for a single click.

To give you the best possible answer I need to know where your modalSubmit button is in relation to modalContent. Also is is modalSubmit dynamic or static on the page?

Here is a fairly hacky fix in the mean time using on and off to bind and remove the handler respectively:

function fillData(targetDomElement, modalObject)
{
  $('#modalSubmit').off("click"); /*Clear Hanlders*/
    $('#modalSubmit').on("click", function(){
      console.log("fill data");
      console.log(targetDomElement);

    targetDomElement.text($('#simpleTextEdit').val());
    /*closeModalWindow(); Don't have anything for this so ignoring it*/
  });
}

Demo

Upvotes: 1

I've solved it myself by using .submit() (of course this means adding form, and an input with the type of submit) instead of .click() when I send the request to modify the element I've clicked on originally.

I don't understand though, why it did what it did when I've used the .click() trigger.

Upvotes: 0

Related Questions