Frank
Frank

Reputation: 323

edit and replace DOM node without the element ID

I have a div with a list created with jQuery on the load event. When I click on a list item the item text is copied to an editable div. After the text is edited, I click on a button and the new list item text is replaced. This is the code:

<div id="div"></div> 
<div id="editor" contenteditable='true'></div>
<input type="button" value="replace text" id="replace"/>

Javascript

var listID, itemINDEX;

var item1 = $( "<li/>", {
    "id": "li1", 
    text: "list 1 - item 1", 
    click: function() { 
    //alert( jQuery(this).index() );    
    }
});
var item2 = $( "<li/>", {"class": "test3", text: "list 1 - item 2"});
var list1 = $( "<ol/>", {"id": "list-1"}).append( item1 ).append( item2 );
list1.appendTo('#div');

$(document).on( "click", "li", function(){
    $("#editor").text( $(this).text() );
    itemINDEX = $(this).index();
    listID = $(this).closest("ol").attr("id");
} );

$('#replace').click(function(){
    if(listID){                
        $("#"+listID).find("li").eq(itemINDEX).text( $("#editor").text() );
    } else { 
        alert('this list have no id! I dont know where the text goes');
    }
});

Demo: http://jsfiddle.net/frankroger/FKUkb/32/

As you can see a list id is created on the fly with jquery. This id allow me to find the list and replace the text at the right place.

My question: do you know a way to do this without using ids?

I want to do the same thing with all elements like headings, paragraphs, links...I don't want to create a unique id for each html element.

An other way to create a similar system could be to let the user insert html element directly in a editable div with the help of some document.execCommand (a kind of WYSIWYG). By this way the user could edit the elements text straight foward in the editable div and after all I should do is getting the html and store it in the DB...but I don't want to deal with the different browser comportment...for instance when you press the ENTER key, FF insert BR, webkit DIV and IE/Opera P...

Upvotes: 1

Views: 1032

Answers (3)

Hassaan
Hassaan

Reputation: 932

I think you are trying to approach this problem the wrong way. There is no need to store the location of an element in the DOM if you are just going to be updating it only. Just keep the jQuery object pointing to the element as a variable. Empty or null the variable when you have updated your element.

I have updated your JS to show you what I mean.

// Creating a global variable to store a reference to the list item 
// currently being edited.
var listItem = null;

// No need to give any element you create an ID
var item1 = $( "<li/>", { text: "list 1 - item 1" });
var item2 = $( "<li/>", {"class": "test3", text: "list 1 - item 2"});
var list1 = $( "<ol/>", {"id": "list-1"}).append( item1 ).append( item2 );
list1.appendTo('#div');

$(document).on( "click", "li", function() {
    $("#editor").text( $(this).text() );

    // Storing the jQuery object for the list element into our variable.
    listItem = $(this);
});

$('#replace').click(function() {
    if(listItem != null) {
        // Replacing the text in our selected list item and then
        // clearing the reference to the list item from our memory.
        listItem.text( $("#editor").text() );
        $("#editor").text("");
        listItem = null;
    } else { 
        alert('Pick an item to replace the text in first!');
    }
});

// Nothing changed here...
$('#addlist').click(function() {    
    var i1 = $( "<li/>", {text: "list - item"});    
    var i2 = $( "<li/>", {text: "list - item"});
    var list =  $( "<ol/>").append( i1 ).append( i2 );  
    list.appendTo('#div');
});

Hope this helps!

Upvotes: 0

cookie monster
cookie monster

Reputation: 10972

"do you know a way to do this without using ids?"

Yes, or at least without unique IDs for each item.

Just give the clicked list item an ID when it is clicked. This ID will only be assigned to one item at a time.

http://jsfiddle.net/EH82q/

$(document).on( "click", "li", function() {
    // Just in case there's an previous item clicked, remove the ID.
    $("#active").prop("id", "");

    // give the `LI` the ID "active"
    this.id = "active";
    $("#editor").text($(this).text());
});

Then use and remove that ID when doing the replace.

$('#replace').click(function() {
    // select the "active" element, update its text, and remove the "active" ID
    $("#active").text($("#editor").text()).prop("id", "");
});

No need for shared variables, individual IDs and index numbers this way.

Upvotes: 1

JackArbiter
JackArbiter

Reputation: 5785

You can try assigning each list element (and other elements you want to work with) its own id programmatically (I edited this on the fly so I'm not sure it'll run right out of the box for your purposes):

$('li').each(function () {
    $(this).attr("id", "listItem" + ($(this).index() + 1));
});

Would take the grunt work out of having to do it all manually.

Upvotes: 1

Related Questions