$('body').append($('#add-done-modal, #add-failed-modal', data));
This code should append the div
with id
add-done-modal
and add-failed-modal
to body
. Those div
are served in data
among other stuff. I'm sure the html
in data
is perfectly fine and intended.
The code never find the id
. I'm using jQuery 3.3.1.
I know classes are a solution, but would be rather unwieldy due to various modal that could be or not chosen depending on the client calling.
EDIT: A simple $('#add-done-modal', data)
returns an empty jQuery object. I am, once again, sure #add-done-modal
is in data
.
EDIT: This function is called by a click
event:
function popup(url, name) {
$.get(url, (data) => {
$('#loading-modal .modal-body').html($('#product', data));
// Can't find '#add-done-modal' nor '#add-failed-modal'
let x = $('#add-done-modal', data);
x = $('#add-failed-modal', data);
$('body').append($('#add-done-modal, #add-failed-modal', data));
// Initialize jQuery-UI or Bootstrap stuff loaded above here. Working.
});
$('#loading-modal .modal-header .modal-title').html(name);
$('#loading-modal').modal('show');
}
Here is the content returned by the AJAX call:
<!DOCTYPE html>
<html lang="fr">
<head>
<!-- Head stuff -->
</head>
<body>
<div id="all">
<div class="top-bar">
<div class="container">
<div class="row d-flex align-items-center">
<div class="col-8 col-lg-9">
<form action="/updatelocale/" method="POST">
<select class="bs-select" onchange="this.form.submit();">
<!-- Locale options, can be disregarded -->
</select>
</form>
</div>
<div class="col justify-content-md-end">
<div class="row">
<!-- Login and some buttons, not used -->
</div>
</div>
</div>
</div>
</div>
<header class="nav-holder make-sticky">
<div id="navbar" role="navigation" class="navbar navbar-expand-lg">
<!-- A pretty navbar -->
</div>
</header>
<div id="heading-breadcrumbs">
<!-- Cute breadcrumbs -->
</div>
<div id="content">
<!-- Product, loading this from data works -->
<div id="product" class="container">
<div id="productMain" class="row">
<!-- Stuff inside #product -->
</div>
</div>
</div>
<footer class="main-footer">
<!-- Pretty footer -->
</footer>
</div>
<!-- Modal #add-done-modal -->
<div id="add-done-modal" tabindex="-1" role="dialog" aria-labelledby="add-done-modalLabel" aria-hidden="true" class="modal fade">
<div role="document" class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 id="add-done-modalLabel" class="modal-title">cart.add.done</h4>
<button type="button" data-dismiss="modal" aria-label="Close" class="close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">cart.add.done.long</div>
<div class="modal-footer"><button data-dismiss="modal" class="btn">modal.close</button></div>
</div>
</div>
</div>
<!-- Modal #add-failed-modal -->
<div id="add-failed-modal" tabindex="-1" role="dialog" aria-labelledby="add-failed-modalLabel" aria-hidden="true" class="modal fade">
<div role="document" class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 id="add-failed-modalLabel" class="modal-title">cart.add.failed</h4>
<button type="button" data-dismiss="modal" aria-label="Close" class="close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">cart.add.failed.long</div>
<div class="modal-footer"><button data-dismiss="modal" class="btn">modal.close</button></div>
</div>
</div>
</div>
<div id="login-modal" tabindex="-1" role="dialog" aria-labelledby="login-modalLabel" aria-hidden="true" class="modal fade">
<div role="document" class="modal-dialog">
<!-- I don't care about this modal -->
</div>
</div>
</body>
</html>
EDIT: Here is a fiddle with some tests. After rendering the document to the DOM, $('#add-done-modal, #add-failed-modal')
and $('#add-done-modal')
find the modals, before it doesn't.
In this second fiddle with static HTML, I checked if the modals were found, they were.
Is there any limit to jQuery context length for HTML strings?
If you want to work with the HTML string properly, I'd suggest parsing it into a document, eg
const domParser = new DOMParser()
const doc = domParser.parseFromString(data, 'text/html')
then use doc
in your jQuery selectors, eg
$('#add-done-modal', doc)
When jQuery encounters a context, it simply converts the expression to...
jQuery(context).find(selector)
See https://github.com/jquery/jquery/blob/3.3.1/src/core/init.js#L99
The issue here is that jQuery parses entire documents into a jQuery object containing the top-level elements under <body>
. See http://api.jquery.com/jQuery/#jQuery2
But if the string appears to be an HTML snippet, jQuery attempts to create new DOM elements as described by the HTML
For example, taking your HTML as a string...
$(html)
gives me a jQuery object with 15 elements, mostly empty text and some comment nodes but including
#3 <div id="all">...</div>
#7 <div id="add-done-modal"...>...</div>
#11 <div id="add-failed-modal"...>...</div>
#13 <div id="login-modal"...>...</div>
Using this object as a selector context, you can find elements that are children of those 5 but not those elements themselves. This is why you can find #product
for example.