2

I have an element that gets generated dynamically:

// gathers the name of the file the user is uploading
let fileName = escape(e.target.files[0].name).slice(0,9);

let icon = $(` // this extra space is for readability on SO
        <div class="fileImage" id="${fileName}">
           <div class="glyph-stack">
              <i class="glyphicon glyphicon-file file-icon"></i>
              <i class="glyphicon glyphicon-file file-icon overlay"></i>
              <i class="glyphicon glyphicon-remove file-icon" onclick="removeFile(${fileName})"></i>
        </div>
        <span class="file-title">${fileName}</span>
        </div>`);

When I append the element to the DOM and inspect it, all instances of ${fileName} appear correctly. If a file named freeicons.zip is uploaded, "freeicons" appears everywhere I placed ${fileName}. However, once the removeFile function is called in the onclick handler:

 function removeFile(fileName){ 
    $('#'+fileName).remove();
 }

The variable fileName inside the function no longer equals "freeicons". When I inspect it, the variable is set to div#freeicons.fileImage, which is the selector for the entire element.

If, in the onclick handler call to removeFile() I wrap ${fileName} in single quotes:

`onclick="removeFile('${fileName}')"`

I get the string "freeicons" inside removeFile().

Why in the first case does it replace the string with the element selector? Is this something JQuery is doing when it creates this little element tree?

Cruiser
  • 1,618
  • 2
  • 16
  • 20
  • @bassxzero The function body is included at Question – guest271314 Oct 19 '17 at 14:47
  • what is `${fileName}` is this a new jquery thing?? – Huangism Oct 19 '17 at 14:49
  • 2
    You shouldn't be binding JS handlers inline. Instead, simply bind the click event to the remove icon instead (you might have to rely on event bubbling since the click icon isn't present at runtime). When the click event callback is fired, simply calling `$(event.target).closest('.fileImage').remove()` will suffice. – Terry Oct 19 '17 at 14:50
  • 1
    @Huangism That's string interpolation in template literals in ES6: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals – Terry Oct 19 '17 at 14:50

1 Answers1

5

fileName is a string, without quotes the parameter passed to the function at onclick is interpreted as a global identifier

function removeFile(fn) {
  console.log(fn)
}

let fileName = "abc";

let el = `<div onclick="removeFile('${fileName}')">click</div>`;

$("body").append(el);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>

function removeFile(fn) {
  console.log(fn)
}

let fileName = "abc";
// `abc` is not defined at `catch`, where `id` is not set to `fileName`
let el = `<div onclick="try {removeFile(${fileName})} catch(err) {console.error(err)}">click</div>`;

$("body").append(el);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>

Why does this string get changed to full element selector?

id of element in document is global, attribute event handler is global. Without quotation marks surrounding the argument, the global id freeicons is referenced, resulting in the DOM element #freeicon being logged within the global event handler attribute event function

function removeFile(fn) {
  console.log(fn)
}

let fileName = "abc";
// `abc` references the global `id` `"abc"`
let el = `<div id="${fileName}" onclick="try {removeFile(${fileName})} catch(err) {console.error(err)}">click</div>`;

$("body").append(el);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
guest271314
  • 1
  • 15
  • 104
  • 177
  • just as a point of clarity, i didn't downvote, and I agree it was meaningless. do you have reference to docs for this behavior? I'd like to read up on it – Cruiser Oct 19 '17 at 15:12
  • 2
    @Cruiser [When did using global event handler attributes within html become “considered bad practice”?](https://stackoverflow.com/questions/36388227/when-did-using-global-event-handler-attributes-within-html-become-considered-ba?), [id](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id). Try `console.log(freeicons)` – guest271314 Oct 19 '17 at 15:17