jquery .after deleting entire li or table element - javascript

I'm seeing a problem using jquery .after to insert a div into an li. Essentially, the action is deleting the entire li...and I'm not sure why. I also saw this kind of problem using .after on different table elements which makes more sense to me because I can see that would break a table.
Take a look at this jsfiddle: http://jsfiddle.net/XrUtq/
The reason I have to do it this way is because I have to come up with a generic way to be able to put a div as CLOSE in the dom as possible to another element which I don't have control over (could be any kind of element). The div will then be relatively/absolutely positioned on the page to go over top the element which it is going after. I'm doing this because we need a solution instead of appending the div to the body, because if the view is changed then that appended element will stay on the page instead of dissapearing with the content which it is supposed to.
I hope I have made the problem clear enough. I've tried approaches like this:
if (nodeName === 'td' || nodeName === 'tr' || nodeName === 'th' || nodeName === 'tbody'){
popover.appendTo(editable.closest(':visible:not(tr):not(td):not(table):not(tbody)'));
}
else if(editable.is(':visible')){
popover.after(editable);
}
else{
$('body').append(popover);
}
but this is not accounting for the current problem with li.
Thanks for help/suggestions!

You're using slightly incorrect syntax (sort of backwards), use this instead:
Change this:
$('<div>Blabablabla</div>').after($('.editable'));
To this:
$('.editable').after('<div>Blabablabla</div>');
Working fixed example
jQuery .after(CONTENT) inserts the supplied content after the element you have selected. The after method should be appended to your jQuery selector. In your code you were placing the selector inside the after method.
I think you were intending to use .insertAfter() which would have worked with your original syntax.

http://jsfiddle.net/XrUtq/1/
$('li').click(function(){
$('.editable').after('<div>Blabablabla</div>');
});
jQuery .after() inserts a target element (the div) after each element in the matched set (the .editable items). The syntax you were using is for jQuery .insertAfter(), an alternative method for doing a similar thing.
$('li').click(function(){
$('<div>Blabablabla</div>').insertAfter('.editable');
});

Related

How to target a specific element without knowing it's class or id, but do have all DOM details of the element

To place an external widget without having to let non-technical people paste embed code on every desired spot on a webpage, I'm working on a visual div and p tag selector where people can just pinpoint the desired element(s).
When people hover over an element, it will show a red border to show them what's selected.
For us to place the widget, normally we would target by class or id. However, the class / id should be unique for it to work and unique classes for a random div / p tag is pretty rare.
Via a piece of jquery code:
$(document).on('mouseenter mouseleave', '.sj-highlight',
function (e) {
}
I can get the DOM details about the selected element.
Is there a way I can target the highlighted element by using some data from the DOM details and if yes how?
Tried the code above but just don't know much about DOM selecting possibilities.
To make the whole highlight per element possible, I wrote this:
$( document ).ready(function() {
$('div, p').each(function(i){
$(this).addClass('sj-highlight sjhighlight'+i+'');
$(this).attr('data-sj', 'sjhighlight'+i+'');
});
$(document).on('mouseenter mouseleave', '.sj-highlight', function (e) {
var sjhighlighter = $(this).attr("data-sj");
// hide other highlights
$('.sj-highlight').css("border","2px solid transparent");
if(e.type == 'mouseenter')
{
$('.'+sjhighlighter+'').css("border","2px solid #ff0000");
}
});
The end result would be to somehow target the selected elements with the DOM instead of a class or id.
From the pieces that i put together i think if you can get to the element using
$(document).on('mouseenter mouseleave', '.sj-highlight',
function (e) {});
that means you already have it, because $(document).on() form works for dynamically added elements (that means even if you add element dynamically it still works properly), you can use :
var elementClass = $(this).attr('class');
and you have complete control over the element from there.
And you have also all possibility over its children or it parent which returned as dom elements objects.
I think that your question need a little bit of clarification too.
Here is an option that I used when trying to target elements without the ID or Class. You first need to figure out what each of these highlighted elements have in common. Either it be a specific color, element hierarchy, etc. Then you could use the filter() jquery to find all elements with that spec. This is what I used.
/*select an element that contains this piece of code your trying to target*/
$('#Parent_container').filter(function() {
/*here you will specify what you're trying to identify or target*/
return $(this).find('div[class="sj-highlight"]').length >0;
/*optional but you can create a condition to add code or do whatever you want*/
}).find('div[class="sj-highlight"]').after('<p>some stuff</p>');
Hope that helps. It might give you some idea of what options you have.

How do I remove non-visible elements from an entire document?

I want to use Javascript and JQuery to make a copy of the web page's entire html and remove all elements that are not visible to the user. This is what I've tried so far:
$('html').not(':visible').remove()
However, it does not seem to work. Does anyone know how I can accomplish this?
Right now you are only targeting the <html> element with your selector. You need to iterate through all the elements and check their visibility like this:
$('*').each(function(){
if($(this).not(':visible')){
$(this).remove();
}
});
Even more concise would be to just target hidden elements and remove them as such:
$('*:hidden').remove();
The jQuery API reference states that elements are considered visible if they take up space in the document. So elements that have a height and width greater than 0 are considered visible. This means we should instead look at the computed CSS if you are having issues with the above code removing things that are visible.
$('*').each(function(){
if($(this).css('visibility') == 'hidden' || $(this).css('display') == 'none'){
$(this).remove()
}
});
you are removing html elements which are not visible. you should remove its children.
try this
$('html').children().not(':visible').remove()
EDIT:
as Barmar said this only removes immediate children of html. use other answers to remove all elements.
This should do it:
$("body :hidden").remove();

JQuery not working on inserted/inject DOM element

I am still a bit new to JS & JQuery, so please excuse what may be a simple and stupid question.
Background:
I have a div on my page that holds several divs (#idle-variable). On click of the top level div, it basically shows the other divs (#addvariable). Nothing more than display: none; and .show(). Easy. On another action within that div (change of drop down), I essentially want to inject/insert that top level div (#idle-variable) underneath the first instance.
Issue:
Essentially, the .click function is not working on my newly inserted div. This may be because the two div's share the same ID, BUT I have a sneaky suspicion that it's not recognized in the DOM. A friend of mine said something about I have to "re-run" my jquery in order for it to be readable in the DOM.
Question:
How can i make this work properly? I want to be able to add a dynamic number of these idle-variables to the page and I need to make sure my .click function works for all added DIVS.
$(function(){
$('#idle-variable').click(function(event) {
$("#addvariable").show(400);
});
});
//create variable in db & show value entry
$("#variabletype").change(function() {
$("#varholder").css("display", "inline-block");
$.ajax({
type: "POST",
url: "/myphpfile.php",
data: {"variabletype": $("#variabletype").val()},
success: function(){
$( "#idle-variable" ).after("<div id="#idle-variable>content</div>");
}
});
});
Well to make the code work it would need to use on and ids are only supposed to be on one element. If it can be on the page multiple times you need to use classes.
$(document).on("click,'#idle-variable', function(event) {
$("#addvariable").show(400);
});
you should be using classes
$(document).on("click,'.idle-variable', function(event) {
//$("#addvariable").show(400); //not sure how this relates to the clicked element.
$(this).find(".addvariable").show(400); //if it is a child
});
You also have a typo in your code with quotes.
The ID based selector will be applied to the first element only.
See the example here http://jsfiddle.net/9GN2P/2/
If you are looking to bind same event handler to multiple elements, definitely go with the class based approach, instead of ID based approach.
And, you are expecting event handler to work with dynamically created elements as well. If you are using older versions of jquery, use the live method like
$('yourselector').live('click',function(){
});
Since live is deprecated and if you are in a new version, use the 'on' method
$('containerselector').on('click','yourselector',function(){
});
Editing to answer your comment:
To create dynamic element and append to DOM, you can follow the bellow pattern. Here, I will create a DIV with id "newID", class "newClass", content "NEW DIV!!" and a click event handler for it. And it will be pushed into another div with id 'containerID'
$('<div />',{
id:'newID',
'class':'newClass',
text:'NEW DIV!!',
click:function(){alert('hi');}
})
.appendTo('div#containerID');
This is just a demo.

Why .closest(selector) returns more than one value?

Here is a part of my html. (it is written using ejs)
<div class="objAddDiv">
<tr><td><button class="addObj">Do this action</button></td></tr>
<table><div class="objects"></div></table>
</div>
I have several objAddDiv divs on this page. Each has the same structure inside of it. I use .append() to add more ejs to .objects. I am having a hard time adding to only the .objects div that is inside of the same div as the button. I tried doing the following
".addObj click": function(el, element){
$(".addObj").closest(".objAddDiv").find(".objects").append(//my ejs utility here)
}
The problem is that $(".addObj").closest(".objAddDiv") returns all .objAddDiv on the page. I have looked at the jquery documentation for .closest and it says closest should only return one element. Is there a better way to do this? What am I doing wrong. (these are not my real class names btw)
It's because you are calling that method on every element with a class of 'addObj':
For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
So you get the closest objAddDiv to each addObj element.
Assuming you are doing this inside the click event of the button use this to get the correct element:
$(this).closest(".objAddDiv").find(".objects").append(//my ejs utility here)
Here is the answer that I figured out (for anyone who comes next) I needed to use the element I passed into the function:
el.closest(".objAddDiv").find(".objects").append(//ejs append stuff)

Hiding the <p> and showing the <textarea> on a <a> click

I know the title sounds quite easy but the real problem is the markup. I have a link in a div which also in another div but the textarea and the paragraph are in another div so that's why I am having problem on how to show and hide elements in a completely different markuped div from a completely different markuped div.
I saw .parent() and .children() and .siblings(). But they couldn't help me or I think that I was not able to take help of those.
Here's the fiddle.
Here is the JS I tried:
$(".no_link").click(function(e) {
e.preventDefault();
});
$(".edit_offer").on('click', function() {
$(this).parent().parent().siblings().children("textarea").toggle();
});
You can use these selectors, but it will rely on the class username being in the heirarchy as you have in your code:
$(".edit_offer").on('click', function () {
$(this).closest('.username').find("textarea").toggle();
});
jsFiddle example
.closest() will traverse up the DOM until it hits the element with class username, then .find() will go down through the children looking for the textarea.
I did it using find(). http://jsfiddle.net/SZUT8/2/ To make the script more accurate and future-proof you could consider adding a class to the paragraph and matching it, as in here: http://jsfiddle.net/SZUT8/4/
You could always assign an ID (or a class, for multiple) to each of the desired elements ("p" and "textarea" in your case). Then use your ID/class to reference them for the show() or hide() methods, rather than navigating the DOM via parent(), sibling() and children().
Then your click handler will only need the line:
$('#idOfElement).toggle();

Categories