Using jQuery can't dynamically add more than one element [duplicate] - javascript

This question already has answers here:
Why do multiple `.appendTo` calls on a newly created jQuery element only append it once?
(2 answers)
Closed 3 months ago.
I'm making a multi file uploader using ASP.NET, and i know that IE doesn't support multiple attribute inside <input type="file"/>.
So i wrote a jQuery code which checks if the user uses IE or not. If yes then show a button that let's the user add more than one file upload control, so he can upload more than one file too.
The problem is, When user clicks on that link to generate the <input/> control, and then clicks again to add a third one. Nothing happen! .. Only one control is added so it'd be two controls to use. Not more, no matter how much he clicks no more <input/> controls is added.
Here's my code :
$(function () {
if (!('multiple' in document.createElement('input'))) {
var add_btn = $("<a href='#'>Add more photos</a>").insertAfter("#ContentPlaceHolder1_upload_lbl");
var upload_pnl = $('<input type="file" runat="server"/>');
var upload_holder = $("#fileinput_placeholder");
add_btn.on("click", function () {
upload_holder.append(upload_pnl);
alert("click event called(debugging)");
});
}
});
Here's a picture of the node tree of that portion :

On the click event you are appending upload_pnl, and each consecutive click you are appending the same element, hence you only get 2.
To add more you either need to create the element inside the click event callback, or maybe use something like the jquery clone function to create a new one.
var upload_pnl = $('<input type="file" runat="server"/>');
var upload_holder = $("#fileinput_placeholder");
add_btn.on("click", function () {
upload_pnl.clone().appendTo(upload_holder);
alert("click event called(debugging)");
});
Also as fscan pointed out the runat="server" wouldn't make this new element accessible in the code behind as the page is now client side.

First, you have to create a new element every time you insert it with append. Append will move the element from the old parent.
Secondly, runat="server" afaik is a asp.net attribute and does absolutely nothing in html. You would have to do the posting and stuff yourself if you create the elements with javascript.

Related

Javascript addEventListener not working for a specific element

I am running into a strange issue: I create 8 different HTML elements using Javasript (in almost exactly the same way for each one) and add event listeners to them all, but 1 specific element does not have the event listener added.
Here is the code for one of the elements that works well:
var primaryProductImageLink = document.createElement("a");
primaryProductImageLink.setAttribute("id", "primaryProductImageLink");
primaryProductImageLink.setAttribute("href", result.primaryProduct.pageLink);
primaryProductImageLink.setAttribute("data-resultRequestID", getResultResponse.resultRequestID);
primaryProductImageLink.setAttribute("data-linkName", "primaryProduct");
primaryProductImageLink.addEventListener("click", clickedLinkInResultSection);
And here is the code for the element which does not have any event listeners applied:
var primaryProductNameLink = document.createElement("a");
primaryProductNameLink.setAttribute("id", "primaryProductNameLink");
primaryProductNameLink.setAttribute("href", result.primaryProduct.pageLink);
primaryProductNameLink.setAttribute("data-resultRequestID", getResultResponse.resultRequestID);
primaryProductNameLink.setAttribute("data-linkName", "primaryProduct");
primaryProductNameLink.addEventListener("click", clickedLinkInResultSection);
When I clear my cache, upload changes, and view the page I run the following commands and it confirms event listeners are added to the first element but not the second:
getEventListeners(document.getElementById("primaryProductImageLink"));
{click: Array(1)}
getEventListeners(document.getElementById("primaryProductNameLink"));
{}
However, if I add the following code to the very end of my Javascript, the event listener is successfully added to the primaryProductNameLink element:
document.getElementById("primaryProductNameLink").addEventListener("click", clickedLinkInResultSection);
Verification:
getEventListeners(document.getElementById("primaryProductNameLink"));
{click: Array(1)}
I have tried adding different event listeners to this element, but none have worked. I added test attributes as well, and they show up just fine. Test code:
var primaryProductNameLink = document.createElement("a");
primaryProductNameLink.setAttribute("id", "primaryProductNameLink");
primaryProductNameLink.setAttribute("href", result.primaryProduct.pageLink);
primaryProductNameLink.setAttribute("data-resultRequestID", getResultResponse.resultRequestID);
primaryProductNameLink.setAttribute("data-linkName", "primaryProduct");
primaryProductNameLink.addEventListener("mouseover", function() { console.log("test"); });
primaryProductNameLink.addEventListener("mouseout", function() { console.log("test"); });
primaryProductNameLink.addEventListener("click", clickedLinkInResultSection);
primaryProductNameLink.setAttribute("data-test", "test");
Result:
.
I have gone through my whole Javascript file and there are no other references to "primaryProductNameLink" which could possibly remove any event listeners.
I know there are workarounds (like the one I showed by adding the event listener at the end of the script), but I am genuinely curious and would love to know what is causing this issue. Thanks!
EDIT: Full Javascript can be found here: https://jsfiddle.net/fbchm4ov/ (The elements described in my post are only generated once the 4 questions are answered.)
From the fiddle I read that you append primaryProductNameLink to primaryProductInfoDiv and later after that you modify primaryProductInfoDiv by using primaryProductInfoDiv.innerHTML +=.
When you set innerHTML property, you are overwriting existing HTML that was set there.
Doing
primaryProductInfoDiv.innerHTML += '<br>';
is basically creating a new HTML structure using the current innerHTML structure plus <br> and assign it to innerHTML. Your event handler is attached to the old innerHTML, not the new one.
So instead of doing concatenation, we can use createElement and appendChild to avoid such a problem.

I want to attach `onclick` on DOMs using javascript [duplicate]

This question already has answers here:
How to add click event to an element?
(4 answers)
Closed 5 years ago.
Whenever I open a page I am working on, the page makes a lots of amount of doms using javascript, and each one looks like this:
<span class="link img">text</span>
Let me say I assign one of them to a variable called a, for temporary.
I have another function that is to put every of them, including the a, an onclick event, which should be written in the HTML code page, so I can store the whole page and load it later.
The moment it attaches is before loading the doms into document body. Creating doms, and then this function attaches onclick on them, and then load them in the document body.
What it is supposed to do is making this a to:
<span class="link img"
onclick="function(){window.open('http://example.com')}">
text
</span>
So clicking a opens a new window. I made a CSS so every 'link' class looks like a link anyway.
I tried contain one of these into the function to achieve the above change:
a.onclick = function(){window.open('http://example.com')};
,
a["onclick"] = function(){window.open('http://example.com')};
,
const openFunc = function(){
window.open('http://example.com')
};
a["onclick"] = openFunc;
I don't know why, they don't attach onclick property on a.
I didn't understand what you are saying but if you want to add a event on variable 'a' which have the object reference of an element:
Use a event listener
a.addEventListener("click",funcNametocall,false);
read about it here
http://www.w3schools.com/js/js_htmldom_eventlistener.asp
Thomas' reply made me look back at the anchor tag once more time, and it awkwardly solved the problem.
Here's what I put in the function that is to make every one of the doms to a link one:
actually changed 'span' tag to 'a' tag.
I could use a['href'] = 'http://example.com'; to add the link to the tags, or doms, and leave it in HTML code.
Hello Put these code in your head section
<script type="text/javascript">
function openWindows(argument) {
window.open('http://example.com')
}
</script>
and replace your span tag with the following code...
<span class="link img" onClick="openWindows();">text</span>
May check this code and it work, I hope this will also help you.

Manipulating retrieved data that is being echoed by an external PHP script

I don't consider myself a professional by any means. I decided to spend this summer picking up a few web languages that would allow me to prototype my ideas (I am a designer).
To get with the question, I am having a tough time figuring out how to manipulate elements that I am echoing back from an external .php script. Essentially I am doing this.
process_feed.php:
- Gets data, does SQL search based on data, outputs rows
while ($row = mysql_fetch_assoc($feedResult))
{
$ctime = date("U",strtotime($row['timestamp']));
echo '<div id="secretmsg">'.$row['secretmsg'].'</br>';
echo '<div id="postedby">Posted By: '.$row['postedby'].'</div>';
echo '<div id="timestamp">'.ago($ctime).'</div><button type ="button" name="'.$row['m_id'].'">Reply</button></div>';
}
main page:
function RefreshFeed()
{
var SchoolName = document.getElementById('schoolname').innerHTML;
$.post('../../process_feed.php', {name: SchoolName}, processResponse);
function processResponse(data) {
$('.secretfeed').html(data);
}
}
Perhaps not the best solution, but I have RefreshFeed on an interval so I can constantly get updated information.
The issue is this: I am trying to work on a comment system where users can respond to each post. On my process page, I am adding a Reply button with the name set to the ID in the database. I am trying to setup basic functionality where the Reply button will open up a text input for commenting, send the message to the DB based on the ID, etc etc. However, on my main page I am not able to manipulate the element because it's being echoed? What can I change in order to echo information from the database onto my main page, and then from my main page manipulate the echoed div's.
I hope this makes sense - thanks for the help :)
If I understand you correctly then you would like to modify the DOM once the data has been added - so you can then just use a selector to get the desired element and do what ever you want - e.g.:
function processResponse(data) {
// Selector to get all elements by class name within the whole document
$('.secretfeed').html(data);
// Selector to get all buttons by tag name inside $('.secretfeed')
$('.secretfeed').find('button').text('foo');
// Selector to get all buttons by attribute inside $('.secretfeed')
$('.secretfeed').find('[type="button"]').text('bar');
// Selector to get the element with the given id within the whole document
$('#secretmsg').css('color', '#ff0000');
}
Notes:
Ids for HTML elements should always be unique within the whole document! In your example you possibly echo multiple elements with the same id (as it is inside a while loop) - use class="" instead.
It is recommended to save selectors so that jQuery does not need to parse the DOM over and over again - e.g.:
var $myselector = $('.myclass');
$myselector.text('foo');
But keep in mind that the selector is not updated when you modify the DOM by e.g. adding another element with class="myclass" - you would then need to assign the variable again so the selector contains the newly inserted element as well.
Additionally be sure that the DOM is ready when you want to work on it - regarding your callback processResponse this will always be the case as jQuery takes care of it and does not execute the callback until it is ready - but when you come from a page reload wrap your code like this:
var $myselector = $();
$(document).ready(function(){
$myselector = $('.myclass');
});
Additional info:
Finally (out of the scope of your question) take a look at event delegation so that you do not need to select all elements directly - e.g. if you want to add a click handler to all of your buttons you do not need to register an event handler for each but can create a global one:
$(document).on('click', '.secretfeed button', function(){
alert($(this).attr('name'));
});

Javascript Document Write Inquiry

I have been trying many times to write a code using JavaScript events,
so I thought that JavaScript's document.write will be somehow similar to
PHP's echo.
Is there any way to force document.write to perform an inline write similar to PHP's echo?
The sample: Situation
My website
<input type="text" id="inputText" onchange="writeText()">
Script
<script>
function writeText(){document.write(document.getElementById("inputText").value);}
</script>
I want it to act like every time you change the value of the text box, it will display the value of the textbox just below the text box where it came from or much nicer have it executed by using PHP's echo with some how like this:
<script>
var inputs = document.getElementById("inputText").value;
function writeText(){document.write("<"."?php "."echo '".inputs."';"."?".">");}
</script>
Note: please don't use elements to catch the values, I know it but what I want to aim here is to write inline with document.write without deleting the other contents of the page.
document.write() is not designed for use from event handlers because if the current document has already finished loading (which it has when an event fires), then document.write() first clears the current document and then adds new content to the empty document.
To add content to a document after it has already loaded, you need to either modify the innerHTML of an existing element or create new elements and programmatically add them to the page.
In your question, it is not clear where you want the writeText() function to put the content that it generates, but here's an example of append some new content into a document at a particular location in the document.
function writeText(parentElem, newHTML) {
var elem = document.createElement("span");
elem.innerHTML = newHTML;
parentElem.appendChild(elem);
}

How to dynamically delete a div and clear the memory so I could add a new div with the same ID but different content using jQuery?

I am using the Picasa Web Integrator (PWI) code, that allows me to present a picture gallery using a picasa account. Using a form the user writes a keyword and then a code creates a div and calls for the PWI.
It works perfectly, but I'm trying to add a "back" button in order to let the user select a different keyword without refreshing.
But the code doesn't seem to clear the memory and the result is the same as the first time.
Here is the code:
//The button that the user presses when he has written the keyword.
$("#boton2").click(function() {
//Creates a new div
$(".shop3").append("<div></div>");
$('.shop3 > div').attr('id', 'container3');
//gets the keyword and creates a variable called "competidor"
competidor = $('#competidor_txt').val();
//calls for the PWI code...
$("#container3").pwi({
username: 'davidagnino',
mode: 'keyword',
...
//This part works perfectly.
//The "back" button that should delete the div called #container3
$('#back3').click(function() {
event.preventDefault();
competidor=null;
delete competidor;
$("#container3").empty(); //should make my div empty
$("#container3").remove(); //deletes the div...
});
I think the best approach here would be to change the Div's ID on the fly, and thus set it up as a whole new div each time.
I'd set up a counter variable (ideally static, but global if that's over your head):
var divCounter=0;
$("#container"+divCounter).pwi({/*...*/});
when it's time to destroy that, increment divCounter and generate a whole new div. Should get the job done!
Obviously, in all your event handlers you'd refer to it generically:
$("#container"+divCounter);
A quick note, removing something completely removes it from the DOM, thus emptying it in the same operation. It's also good jQuery practice to chain your functions together, like this:
$("#container3").append(/*whatever*/).attr(/*whatever*/);

Categories