I have two functions that generate DOM el开发者_StackOverflow社区ements. They both attempt to create the same container element. (I'd prefer not to enforce a specific run order for these functions, or tightly couple them to the side-effect of creating this element). I've been trying to discover a method that would get an element if it exists, or create a single instance of it if it doesn't, and return a jQuery object containing that element or all the matched elements if they already exist.
I haven't found this to exist in searching through jQuery documentation, but I thought I'd ask here to see if anyone else has encountered a similar problem and has suggestions.
You can use this poorly written code:
var $element = $('#element').length ? $('#element') : $('<div id="element"></div>').appendTo('#containerToPutIt');
Or make it a bit cleaner:
var $element = $('#element');
if(!$element.length)
$element = $('<div id="element"></div>').appendTo('#containerToPutIt');
There isn't really a place in jQuery where you are guaranteed to have enough information to create an element if it doesn't exist. For example, if you do $('#something')
, and you want jQuery to ensure it exists, what element do you expect jQuery to create? Where do you want it located in the DOM?
It's something you should be doing yourself with a helper method:
function getContainer() {
var container = $('.yourContainer');
if (!container.length) {
container = $('<div class="container" />').appendTo('#something');
}
return container;
}
And then use it like this:
getContainer().html('Foo Bar Baz');
getContainer().children().each(..);
You can just select the DOM element in jQuery and then test its length:
if ($('div.someclass').length > 0) {...}
Do NOT test for the existence of the jQuery object, since it will always return true
even if there are no DOM elements inside of it. You must always test its length.
If the length
test fails, you can then create the DOM element wherever you want using some appropriate DOM insertion method.
Hmm... interesting question... You might try something like.
function checkExists(selector) {
var exists = $(selector).length;
if(exists > 0) {
return $(selector);
} else {
return createElement();
}
}
Where createElement()
would be your function that makes the DOM element you are looking for. (It would return the newly created element) Then you can call it with a jquery selector like checkExists('.myClass');
for example
Since I always try to find shortest way, so:
$( $("selector", parent)[0] || $("elementHTMLTag").appendTo(parent) )
The line tries to get the DOM of the element, or create the element if it doesn't exist, and make jQuery object of it.
Let's put the convenience in convenience method (in addition to keeping a separation of concerns!! Here's an jQuery function titled upsert
that will either locate an existing element or create a new element if none exist.
So just include this jQuery anywhere:
$.fn.upsert = function(selector, htmlString) {
// upsert - find or create new element
// find based on css selector https://api.jquery.com/category/selectors/
// create based on jQuery() http://api.jquery.com/jquery/#jQuery2
var $el = $(this).find(".message");
if ($el.length == 0) {
// didn't exist, create and add to caller
$el = $("<span class='message'></span>");
$(this).append($el);
}
return $el;
};
Then you could use like this:
$("input[name='choice']").click(function(){
var $el = $(this).closest("form").upsert(".message", "<span class='message'></span>");
// guaranteed to have element - update if we want
$el.html("You've chosen "+this.value)
})
Ideally, it would be nice to simply pass in a selector and have jQuery create an element that matches that selector automatically, but it doesn't seem like there's a light weight vehicle for creating an element based off the CSS Selector syntax (based on Question 1 & Question 2).
Some further enhancements might provide more fine tuned control for DOM insertion instead of just always using .append()
.
Demo in jsFiddle | Demo in Stack Snippets:
$.fn.upsert = function(selector, htmlString) {
// upsert - find or create new element
// find based on css selector https://api.jquery.com/category/selectors/
// create based on jQuery() http://api.jquery.com/jquery/#jQuery2
var $el = $(this).find(".message");
if ($el.length == 0) {
// didn't exist, create and add to caller
$el = $("<span class='message'></span>");
$(this).append($el);
}
return $el;
};
$("input[name='choice']").click(function(){
var $el = $(this).closest("form").upsert(".message", "<span class='message'></span>");
// guaranteed to have element - update if we want
$el.html("You've chosen "+this.value)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="">
<div>
<input type="radio" id="ca" name="choice" value="A" /><label for='ca'>A</label>
<input type="radio" id="cb" name="choice" value="B" /><label for='cb'>B</label>
<input type="radio" id="cc" name="choice" value="C" /><label for='cc'>C</label>
</div>
</form>
精彩评论