jQuery Add object to dynamic parent - javascript

New to jQuery, having an issue with dynamically changing the selector.
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script>
function addFirst(){
var fc = document.getElementById("fc").value;
$("#parent").append("<div id='firstChild" + fc + "'>My boring text.</div><a href='#' onClick='addSecond(\"firstChild" + fc +"\")'>Add Second Child</a>");
fc = (fc - 1) + 2;
document.getElementById("fc").value = fc;
}
function addSecond(){
$(***THE PARENT SELECTOR***).append("<div>Some more boring text.</div>");
}
</script>
<body>
<input type="hidden" id="fc" value="1"
<div id="parent"></div>
Add First Child
</body>
</html>
I need a selector that gets me the direct parent of an object when that parent object has been created dynamically, as indicated by my text "THE PARENT SELECTOR".
EDIT
My solution to this, in case anyone else comes across this question, was to use .call inside the onClick event.
Located in the string of the addFirst() function:
<a href='#' onClick='addSecond.call(this,\"firstChild" + fc +"\"); return false;'>
Then, changed the addSecond() function:
$(this.parentNode).prepend("<div>BlahBlah");

It shouldn't matter how the object was created, the selector will work the same.
$(this).parent().append("<div>Some more boring text.</div>");
As noted, this will not work unless you pass a reference to your object. You could leverage jQuery more and all of this will be much easier:
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script>
$(function() {
$("body").on('click', '.addsecond', function() {
$(this).parent().append("<div>Some more boring text.</div>");
});
$("body").on('click', '.addfirst', function() {
var fc = $('.fc').length + 1;
$("#parent").append("<div id='firstChild" + fc + "' class='fc'>My boring text.</div><a href='#' class='addsecond'>Add Second Child</a>");
});
});
</script>
</head>
<body>
<div id="parent">
Add First Child
</div>
</body>
</html>
Note, that I added a class addfirst and addsecond. These are used to add handlers to the links automatically (or more accurately, attach handlers to the body, which trigger when divs with these classes are clicked). When they are clicked, this is passed to the function, allowing you to find that object's parent, etc.
You could clean this code up even further, but I can't guess how you are using it. I am guessing you want the children added somewhere different than where they are actually ending up.
Example: http://jsfiddle.net/2LjYH/
If I were to guess, I would make #parent wrap the "Add First Child" link, like this:
<input type="hidden" id="fc" value="1"
<div id="parent">
Add First Child
</div>
Example: http://jsfiddle.net/XjUzA/
This seems to work more intuitively. And if you want the second child added directly after the link, you don't want .parent().append() at all, you simply want to use .after():
Example: http://jsfiddle.net/XjUzA/1/

Assuming that the this keyword refers to the target element you can select the parent using
$(this).parent();

Related

Adding a div on clicking a button but the divs which are added are not responding same

I am performing that On Button Clicked a div is created but issue is that it is not performing as same as main div is performing like resizing & draggable.Please Help?
<html>
<head>
<link rel="stylesheet" href="test.css">
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script>
$(function () {
$("#box").resizable({
alsoResize:"#main",
alsoResize:"#title_bar",
alsoResize:"#container"
});
$('#main').draggable();
$("#button").click(function () {
if ($(this).html() == "-") {
$(this).html("+");
} else {
$(this).html("-");
}
$("#box").slideToggle();
});
$("#NewWidget").click(function() {
$("#container").append('<div class="main" id="main"><div id="title_bar" ><div id="button">-</div></div><div id="box"><div><h4>Hi user</h4><p>Hello Users. How are YOU?</p> </div></div>');
});
});</script>
</head>
<body>
<input type="button" id="NewWidget" value="Add New Widget"/>
<div id="container">
<div class="main" id="main" >
<div id="title_bar" >
<div id="button">-</div>
</div>
<div id="box">
<div>
The ID's needs to be unique, so if you create a lot of elements, either make ID's unique or use classes or data-id attribute to recognize which box is which - in the example in codepen i showed you how to create ID's with simple counter variable, that is available in this scope (remember about closures).
What you did in your code is only appending a new structure to DOM, there is no event handlers/hooks attached to this element, that's why you either need to create new event handler/hooks when adding the element to the DOM, or after, in my example, i will to it before adding the element to the DOM.
Here's link to codepen:
https://codepen.io/anon/pen/GEyPXr
Additional hint: whenever possible, avoid creating anonymous function, always either name them, or reffer to them, meaning:
$(".main").find('.button').on('click',function(){
// this looks weak, plus anonymous function doesn't tell you what it does
});
use this instead:
$(".main").find('.button').on('click',makeButtonWork);
function makeButtonWork(){
//this looks much better, plus you named the function and you know the purspose of it, without looking through code
}
To respond to comments:
changing starting position of given element can be done by adding:
$('#main-' + counter).css({'top': 100, 'left' : 20}) //your positions here
in the makeButtonWork
see updated codepen for more info
Javascript events don't work this way. Take it as that in the moment when you call $('#main').draggable();, then browser finds matching element (here the one with ID 'main') and does some action with it (here enables the draggable functionality).
If you later add another element, which would also have been matching, it doesn't mean anything - it is just a plain div, until you call some script again.
Also, keep in mind that ID's must be unique on your page, you can't have two id="main" divs on same page. Use classes instead.
$("#NewWidget").click(function() {
var $newElement = $('<div class="main"><div class="title_bar" ><div class="button">-</div></div><div class="box"><div><h4>Hi user</h4><p>Hello Users. How are YOU?</p> </div></div>');
$newElement.find('.main').draggable();
$newElement.find('.button').click( /* add the click handler function here */ );
$newElement.find('.box').resizable( /* resizable params goes here */ );
$("#container").append($newElement);
});

Travel to outer component until reaching the one that has a specific attribute

Example html code (Looks weird but my intention is to show that the outer components can be anything)
<div>
<div/a/p/.. myAttribute="123">
<p>
<a>
<script type="text/javascript">
jQuery.ajax({url: "local.host?attribute= "});
</script>
</a>
</p>
</div/a/p/..>
</div>
What I want is that, from the inner script, before the ajax call is fired, I want to travel to outer parent components, till I can reach the component that has myAttribute. Then I will take the value of myAttribute and fill it into my url as "local.host?attribute= 123"
I found the closest of JQuery, but it requires to know the component type in advanced.
Any help is appreciated.
Thank you very much.
I think '*[myAttribute]' will do it fine.
$(el).parents('*[myAttribute]');
To target the current script. you can use
document.currentScript;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div>
<div/a/p/.. myAttribute="123">
<p>
<a>
<script type="text/javascript">
var self = document.currentScript,
e = $(self).closest('*[myAttribute]'),
attrVal = (e.attr('myAttribute') );
console.log( attrVal );
// commented
// jQuery.ajax({url: "local.host?attribute="+attrVal });
</script>
</a>
</p>
</div/a/p/..>
</div>

Javascript / JQuery DOM Update [duplicate]

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 6 years ago.
I'm trying to create a form that allows user to edit the input through new window. PHP will process the input then append the new input with the new values. Apparently, when I try to edit the appended input, the JavaScript just won't fire. Please enlighten me on what I did wrong.
This is my html code:
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$('.races').click(function(e){
console.log("Inside Testing");
e.preventDefault();
var currID = this.id;
var content = '<form id="theForm" action="ct.php" method="post"> Race: <input type="text" id="race" name="race"><button type="submit" onClick="OKClicked()">Click this!</button></form>';
childWin = window.open('', "_blank", "height=400, width=550, status=yes, toolbar=no, menubar=no, location=no,addressbar=no");
toBeAdded = $(this).closest('div');
childWin.document.close();
childWin.document.write(content);
popupRace = childWin.document.getElementById("race");
parentRace = document.getElementById(currID);
transferValues();
})
});
function transferValues()
{
popupRace.value = parentRace.value;
}
function setValue(text)
{
childWin.close();
toBeAdded.parent().append(text);
toBeAdded.remove();
}
</script>
</head>
<body>
<div>
Name: <input type="text" name="name">
</div>
<div>
<div>
<input type="hidden" name="race-0" value="Human" id="race-0">
<span>race: Human</span>
Edit
</div>
</div>
<div>
Name: <input type="text" name="name">
</div>
<div>
<div>
<input type="hidden" name="race-1" value="God" id="race-1">
<span>race: God</span>
Edit
</div>
</div>
</body>
</html>
And this is my php code:
<?php
$postDataKey = array_keys($_POST);
$text = "";
foreach ( $postDataKey as $currPostKey )
{
$currValue = $_POST[$currPostKey];
$text .= '<div><input type="hidden" name="'.$currPostKey.'-1" value="'.$currValue.'" id="'.$currPostKey.'-1"><span>'.$currPostKey.': '.$currValue.'</span> Edit</div>';
}
echo
'
<html>
<head>
<script>
window.opener.setValue(\''.$text.'\');
</script>
</head>
</html>
'
;
?>
jQuery is only aware of the elements in the page at the time that it runs, so new elements added to the DOM are unrecognized by jQuery. To combat that use event delegation, bubbling events from newly added items up to a point in the DOM that was there when jQuery ran on page load. Many people use document as the place to catch the bubbled event, but it isn't necessary to go that high up the DOM tree. Ideally you should delegate to the nearest parent that exists at the time of page load.
You will likely want to change event handlers so they use the on() method.
This was solved in older versions of jQuery with the live function, opposed to the bindfunction.
The bind function attached an event to all the matching elements, as long as they existed in the moment of execution. Any element appended afterwards would be excluded.
The livefunciton would attach the event on any matching element, even if the element was created after the execution of the instruction.
On the present version of jQuery, bind and live has been replaced by on. The default behavior of on()is like bind. Fortunately there is a way to use on so that it works like live.
I wrote an article about it, which it may help you understand how.
To sum it up...
// This behaves like `bind`
$(".clickable").on("click", function(){...});
// This behaves like `live`
$(".parent-element").on("click", ".clickable", function(){...});
So just search the common parent element that all possible elements could possibly have (you could use $(document) if you do not want to think too hard) and you are golden.
jQuery on Method is what you're looking for; click the link and look for delegated events.
"Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. "

How to know which type of Html object is using jQuery click event?

How can I know on which type of HTML object I have clicked using jQuery?
For Example, If I click on Button then it should inform me that This is button object or Text input or Textarea... like that.
Why I asked this question?
Because I am facing one issue of this type.
I have one Textarea and just below underneath I have file input HTML object. I have bound Caret function (which returns current cursor position in Textarea) to that Textarea. But when I click on Browse button to upload file it gives me an error. So I want to prevent this by know which type of HTML object is?
you may do it like
$(".myBtn").click(function(){
alert($(this).prop("tagName"));
});
update
here is a demo fiddle
in the click event
function(e){
var type=$(this).prop('tagName'); // I think it will need jQuery >1.6
// or
var type=$(this)[0].tagName;
}
Actually, there are quite a few posts in the past about this question.
Well you may use attr("tagName") which will return name of the tag.
Example code snippet: Suppose you click on some element having id as #myId then bind click event and get the attr("tagName") (The jQuery way)
$('#myId').on('click', function(){
console.log($(this).attr('tagName'));
});
This should help.
demo
$(this).attr("tagName")
or can use
$(this).prop('tagName');
reference attr and prop
<!doctype html>
<html lang="en">
<head>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>
<div id="log"></div>
<input type="button" id="myButton" value="Button">
<input type="submit" id="myButton" value="submit">
<input type="text" id="myButton" value="text">
<input type="date" id="myButton" value="date">
<textarea>Test</textarea>
<script>
$("input, textarea").on('click', function (e) {
$( "#log" ).html( "clicked: " + event.target.nodeName + " Type: " + this.type);
});
</script>
</body>
</html>
$(e.target) - Contains DOM element user clicked on. We can use this object to get anything and everything regarding object user has clicked on.
e.target is always going to be the top element clicked.So while every click on the screen is technically click on the body, e.target will always return the furthest child element in the tree that occupies clicked area. However, we might have multiple absolutely positioned elements occupying the same area. In this case, the element with higher z-index will be returned.
You can also use some DOM properties to getting the object type:
e.target.nodeName
OR
e.target.tagName
For example:
HTML -
<input class="Track" type="button" value="Submit" />
<button class="Track">Submit</button>
Jquery -
$('.Track').click(function (e) {
alert("Object: " + e.target.nodeName + " Type: " + e.target.type);
});
Try This

Using jquery to write information from other parts of the document

<script type="text/javascript" src="jquery.js"></script>
<script>
var printLinks = function () {
var links = $(.info).code;
document.write(links);
};
</script>
<form>
<input type="button" value="printlinks" onclick="printLinks()"></input>
</input>
</form>
I am trying to write to a document all of the text in a certain element type that is a child of an element I query by class $(.info). I know document.write is not the best method for writing to a document. info is the class of the parent element of the <code> tags that contain the links I want to print. I am very new to jQuery so I am probably misusing it. Any help would be appreciated.
Okay, if I understand correctly, you want to grab the content in the element with the class info. If that is correct you want to take the following approach:
<script type="text/javascript">
function printLinks() {
var content = $('.info').html(); // Grab innerHTML of element
$('#idOfTargetElement').html( content ); // write the content here
}
</script>
EDIT:
See this fiddle for clarification:
http://jsfiddle.net/XD5qj/
You can use the html() function of jQuery.
For example:
<script>
$(function(){
var links = $('.info code').html();
$('.output').html(links);
});
</script>
<div class="info"><code>Example code</code></div>
<div class="output"></div>
If you have multiple "< code>" tags, you want to use the handy "each()" function of jQuery:
$('.info code').each(function(){
$('.output').append($(this).html());
});

Categories