0

So i'm having this issue where everytime i create a new element that my Jscolor function doest work on the new elements, because it needs a unique Id. And i dont know how to pull that off.

I have tried with for loops and so on and cant figure out how. Because in the JS function i need to select a ID, but how do i select a ID that just have been created?

hope anyone can help me with this issue:)

HTML Code:

<p class="half-circle">
    <button class="addNoteBtn">
        <i class="ion-android-add-circle"></i>
    </button>
</p>

JS Code:

    createNote = function(){

    var stickerEl = document.createElement('div'),
        barEl = document.createElement('div'),
        color = document.createElement('button'),
        colorIcon = document.createElement('i'),
        deleteBtn = document.createElement('button'),
        deleteBtnIcon = document.createElement('i'),
        moveIcon = document.createElement('i'),
        colorEl = document.createElement('input'),
        textareaEl = document.createElement('textarea');

    var transformCSSPosition = "translateX(" + Math.random() * 800 + "px) translateY(" + Math.random() * 400 + "px)";

    stickerEl.style.transform = transformCSSPosition; 


    barEl.classList.add('bar');
    stickerEl.classList.add('sticker');
    color.classList.add('color');
    deleteBtn.classList.add('deleteBtn');
    deleteBtnIcon.classList.add('ion-android-delete');
    colorIcon.classList.add('ion-android-color-palette');
    stickerEl.id = "1";

    colorEl.classList.add('jscolor');
    colorEl.onchange = function(){update(this.jscolor)};
    colorEl.value = "cc66ff";

    color.onclick = function() {showColorPicker};


    // tilføj til:
    stickerEl.append(barEl);
    stickerEl.append(color);
    stickerEl.append(deleteBtn);
    stickerEl.append(colorEl);
    stickerEl.appendChild(textareaEl); 
    color.append(colorIcon);
    deleteBtn.append(deleteBtnIcon);
    barEl.append(moveIcon);

    stickerEl.addEventListener('mousedown', onDragStart, false);

    document.body.appendChild(stickerEl);

};

    createNote();

    addNoteBtnEl = document.querySelector('.addNoteBtn');
    addNoteBtnEl.addEventListener('click', createNote, false);

    document.addEventListener('mousemove', onDrag, false);
    document.addEventListener('mouseup', onDragEnd, false);

    function update(jscolor) {
           document.getElementById('1').style.backgroundColor = '#' + jscolor;
    }
  • why not `document.createElement('div').id = 'your_random_id';` ? – Nir Ben-Yair May 07 '17 at 11:15
  • @NirBen-Yair It still won't create a uniwue id. I'm setting the id a bit below, but i want to make the id unique everytime otherwise the jscolor wont work! –  May 07 '17 at 11:21
  • what do you need an ID for? you have a reference to the node itself: `colorEl.onchange = function(){ stickerEl.style.backgroundColor = '#' + colorEl.value };` – Thomas May 07 '17 at 11:32
  • May be, it will be useful http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript – Bor Laze May 07 '17 at 11:42
  • I need it because i have to reference to a different 'div'. And when i create a new 'div' i need it to have a ned unique id, because i can't use the same twice. Check my code here: https://codepen.io/Qbinx/pen/OmObRg –  May 07 '17 at 12:10

1 Answers1

0

You could use a base name that is likely to be unique and then append a counter to that, increment the counter after each new element is created:

let getNewElement = (function () {
  const idBase = 'my-unique-id-';
  let count = 0;
  return function (type = 'div') {
    let el = document.createElement(type);
    el.id = idBase + count;
    count += 1;
    return el;
  }
}());

// create 3 new elements in an array
let newElements = [getNewElement('div'), getNewElement('div'), getNewElement()];

// make the text of the elements the same as the id and
// add them to the document
newElements.forEach(function (el) {
  el.textContent = el.id;
  document.body.appendChild(el);
});
div {
  border: 1px solid #ccc;
  margin: 1em;
  padding: 1em;
}

In the above code I'm using a Immediately Invoked Function Expression (IIFE) to encapsulate the counter and base name so outside code can't interfere with them. That IIFE returns another function, which is what is actually called when you invoke getNewElement. The inner function has access to counter via closure, it creates the new element, gives it its id and then increments counter so the next time getNewElement is called it will get a new name.

This kind of function that returns another function is possible because JavaScript supports higher-order programming, which simply put means you can pass around functions like you would any other variable either as parameters in function calls or returning them from function calls. Since the IIFE is called right away when the code runs, it returns the inner function which is what is assigned to getNewElement.

Useless Code
  • 12,123
  • 5
  • 35
  • 40
  • okay, but how do i use it in the code i already have? Because i already have a div created and want to name them rect1, rect2 and so on. I dont want to use arrays because i need to create a new element when pressing the add button. Check my code here: https://codepen.io/Qbinx/pen/OmObRg –  May 07 '17 at 12:07
  • I just used the array so I could easily iterate over the new objects in the example to add them to the DOM, it has nothing to do with using this technique. In your code, wrap your `createNote` function in an IIFE and return the existing function from the IFFE. You would just use a base name of `'rect'` and start the counter at `1` to generate a sequence of names like `'rect1`, `'rect2'`, `'rect3'`, etc. – Useless Code May 07 '17 at 12:16
  • Okay, so what when thats done how do i grab the by using the getElement ById function? function update(jscolor) { document.getElementById('rect1').style.backgroundColor = '#' + jscolor; } Here im only grabbing the first. But how do i grab the next? –  May 07 '17 at 12:25
  • You could just return a reference to `stickerEl` from the `createNote` function, then the calling code would have a reference to the element without the need to call `getElementById`. i.e. `var newNote = createNote(); /* newNote is the stickerElement that createNote made */` – Useless Code May 07 '17 at 12:31
  • Hmm how do i wrap the createNote function in an IIFE and return the existing function from the IFFE? Iøm really confused. I know i need to create a function but where do i throw it in? Do is throw it in the createNote function? –  May 07 '17 at 12:58
  • `createNote = (function () {return function () {/* this is the existing createNote funciton from your code */};}());` If you read each of the sources I cited in my answer (particularly the IIFE one) it should become more clear. – Useless Code May 07 '17 at 13:13
  • isn't this right? let newId = (function(){ const idBase = 'rect'; let count = 1; return function() { let el = stickerEl; el.id = idBase + count; count += 1; return el; }; }()); And this? function update(jscolor) { var newNote = createNote.newId.id = el; } –  May 08 '17 at 11:17