I have a very simple HTML page. After everything is loaded, the user can interact with it perfectly. Now, at some point, the user clicks on an element. An ajax call is made and new data is being requested. I now want to remove the previous element the user clicked on with the element(s) the user has requested (on the same page) - practically remove the old element from the DOM and add the new one. Well, I did this as well, but I am unable to add a function to the newly created element. This is my function:
setCountry = function(value){
document.getElementById('country').innerHTML = value;
}
and I'm trying to add it like this to my element
a_tag.setAttribute("href", "javascript:setCountry(countries[i]);");
The function is being called and writes "undefined" to the innerHTML element. I set the attribute using a for loop and just above the for loop I alert an element from the array to be sure it's correct, and it prints out the correct value.
I assume the problem happens because the function is being created on the first load of the DOM, but I'm not sure. Can anyone shed some light on what is really happening here and what I should do to correct it? I want to be able to add more functions so not looking for a work around writing an innerHTML tag, I just want to understand what I'm doing wrong.
Thank you.
Edited with more code
//declare an array to hold all countries form the db
var countries = new Array();
function getCountries(region) {
document.getElementById('scroller').innerHTML = '';
//send the data to the server and retreive a list of all the countries based on the current region
$.ajax({
type: "POST",
url: "scripts/get_countries.php",
data: {
region: region
},
success: saveDataToArray,
async: false,
dataType: 'json'
});
//save the data to an array
function saveDataToArray(data){
var i = 0;
while (data[i]){
countries[i] = data[i];
i++;
}
}
scroller = document.getElementById('scroller');
//create a ul element
var holder = document.createElement("ul");
//here create a back button which will recreate the whole list of regions
var total = countries.length;
for(i=0;i<total;i++){
//create the first field in the list
var bullet_item = document.createElement("li");
//create an a tag for the element
var a_tag = document.createElement("a");
//set the redirect of the tag
a_tag.setAttribute("href", "javascript:setCountry(this);");
//create some text for the a_tag
var bullet_text = document.createTextNode(countries[i]);
//apend the text to the correct element
a_tag.appendChild(bullet_text);
//apend the a_tag to the li element
bullet_item.appendChild(a_tag);
//apend the item to the list
holder.appendChild(bullet_item);
}
//apend the holder to the scroller
scroller.appendChild(holder);
}
function setRegion(region){
document.getElementById('region').innerHTML = region;
}
setCountry = function(value){
document.getElementById('country').innerHTML = value;
}
There is no need for quoting the code in a string. Instead of this:
a_tag.setAttribute("href", "javascript:...")
Try to form a closure:
a_tag.onclick = function () { ... }
Note that by default <A> elements without HREF do not look normal, but you can fix that with CSS.
Problem solved
Everything was good apart from the way I was declaring the href parameter
a_tag.setAttribute("href", "javascript:setCountry("+'"'+countries[i]+'"'+")");
it's all the usual, a game of single quotes and double quotes.
Thanks everyone for pitching in ideas. Much appreciated as usual
Adrian
Related
I'm quiet new above all on Javascript technology. I want to create various div according to the number of string into an array of checked checkboxes but after my code it only displays one div every time... I must go through a jquery dialog to display it !
My JSP
<div style="overflow: scroll;" id="listCurrentContact"></div>
My listContact.js
varPopup = $('#dialogMultiplesDeleteConfirmation').dialog({
resizable : false,
modal : true,
autoOpen : false,
width : 500,
open: function(){
var SuppressCheckboxItems = [];
// I put into an array the different value of checked checkboxes
$("input:checkbox[id=suppressCheckbox]:checked").each(function() {
SuppressCheckboxItems.push($(this).val());
});
var z = document.createElement('div');
// I suppress the ',' between each element
var test = SuppressCheckboxItems.toString();
var tab = test.split(",");
for(var i = 0; i < tab.length; i++){
z.innerHTML = tab[i];
$('#listCurrentContact').html(z);
}
Have you tried using .append instead of .html while concatenating your checkboxes to #listCurrentContact.
You can refer this document: https://www.w3schools.com/jquery/html_html.asp to see that .html() replaces the previous content with the new content whereas what you are trying to achieve here is appending the entire array of values to the div. Look at how .append() works in this link : https://www.javascripttutorial.net/javascript-dom/javascript-append/. Just to give you a brief overview, when you write a .append() on any element, it doesnot replace the previous content with the new content but instead attaches/concatenates the new content after the previous content.
You should use $('#listCurrentContact').append(z);
Thanks to SaloniMishra Ive found the good answer. It just needed to change the .html() to .append() but with that if the customer just quit the jquery dialog and retry the previous elements stayed in the div so you need to clean every elements before to relaunch the function with the function removeChild()! Thanks all !
open : function() {
var SuppressCheckboxItems = [];
const currentDiv = document.getElementById('listCurrentContact');
while (currentDiv.firstChild) {
currentDiv.removeChild(currentDiv.lastChild);
}
$("input:checkbox[id=suppressCheckbox]:checked").each(function() {
var z = document.createElement('div');
z.innerHTML = $(this).attr("name");
$("#listCurrentContact").append(z);
});
When you click the addFruit button, the input text value gets appended to the fruitList as it should. localStorage is activated at the same time, and it works, the data is still there after page refresh.
When you double click on the item that you just appended, you can edit it (contentEditiable), but when you refresh the page, the localStorage retrieves the original name instead of the modified one.
I think it's an an updating issue. When you double click on a list item, it should call the storestate function as soon as you're done editing, so it overwrites what was previously added to localStorage.
I've tried adding storestate() numerous places, and tried to move around my functions, suspecting that my code is written in the wrong order.
Sometimes it actually works after page refresh, but it's usually if I add several items, and then edit one of them. But not always. It's confusing!
I can't find a single similar example on SO, can someone point me in the right direction? :)
(function() {
var fruitList = document.querySelector('#fruitList');
var fruitInput = document.querySelector('.fruitInput');
var addFruitButton = document.querySelector('.addFruitButton');
var removeFruits = document.querySelector('.removeFruits');
// Add fruits
// Store fruits
function storestate() {
localStorage.fruitList = fruitList.innerHTML;
};
// Retrieve stored fruits from localStorage
function retrievestate() {
if (localStorage.fruitList) {
fruitList.innerHTML = localStorage.fruitList;
}
}
retrievestate();
// Remove fruit storage
function removeStorage() {
localStorage.clear(fruitList);
fruitList.innerHTML = ''; // removes HTML
}
function addFruit() {
if (fruitInput.value) {
var li = document.createElement('li');
li.className = 'fruit-item';
li.innerHTML = fruitInput.value;
li.contentEditable = 'true';
fruitList.append(li);
fruitInput.value = ''; // Reset input field
}
storestate();
}
// Clear all fruits
removeFruits.onclick = removeStorage;
//Add fruit
addFruitButton.onclick = addFruit;
})();
I tried to embed the entire code-snippet on SO, but I get an error because of localStorage. Works fine on jsFiddle and other editors:
https://jsfiddle.net/bx39gd0n/10/
https://jsfiddle.net/xbrra7yt/1/
(function() {
...
//change state of item
function changestate() {
console.log('changed');
}
...
fruitList.addEventListener('keyup', changestate);
})();
You would simply chain an eventlistener to be called on keyup. In the fiddle it simply logs 'changed' to the console. Just replace that with your own code to replace the list in localStorage and you should be fine!
I am currently receiving Push notifications. Here is my part of my JS.
Instead of Alerts (pop ups), I want to display the messages one after the other.
var channel = pusher.subscribe('test_channel');
channel.bind('my_event', function(data) {
alert(data.message);
});
I tried creating a div and going with this instead. It doesn't work.
var channel = pusher.subscribe('test_channel');
channel.bind('my_event', function(data) {
document.getElementById("MyEdit").innerHTML = (data.message);
});
And this is my DIV.
<div id="MyEdit"> </div>
I also tried this:
var channel = pusher.subscribe('test_channel');
channel.bind('my_event', function(data) {
document.write(data.message);
}
});
Still nothing is showing up. Alerts work. Writes don't.
Try this:
document.getElementById("MyEdit").innerHTML += data.message;
If you use jQuery you can do something like this:
$('#MyEdit').append(data.message);
Below code will make for jQuery append method. Simply instead of adding next text to innnerHtml, add new div elements, it will help to wrap them with some css, add some padding etc.
var messageRow = document.createElement("div");
var textNode = document.createTextNode(data.message);
messageRow.appendChild(textNode);
document.appendChild(messageRow);
I'm trying to swap select option values with jQuery when a links clicked, at the moment its just resetting the select when the links clicked, not sure what's going wrong?:
jQuery:
$(function () {
$("#swapCurrency").click(function (e) {
var selectOne = $("#currency-from").html();
var selectTwo = $("#currency-to").html();
$("#currency-from").html(selectTwo);
$("#currency-to").html(selectOne);
return false;
});
});
JS Fiddle here: http://jsfiddle.net/tchh2/
I wrote it in a step-by-step way so it is easier to understand:
$("#swapCurrency").click(function (e) {
//get the DOM elements for the selects, store them into variables
var selectOne = $("#currency-from");
var selectTwo = $("#currency-to");
//get all the direct children of the selects (option or optgroup elements)
//and remove them from the DOM but keep events and data (detach)
//and store them into variables
//after this, both selects will be empty
var childrenOne = selectOne.children().detach();
var childrenTwo = selectTwo.children().detach();
//put the children into their new home
childrenOne.appendTo(selectTwo);
childrenTwo.appendTo(selectOne);
return false;
});
jsFiddle Demo
Your approach works with transforming DOM elements to HTML and back. The problem is you lose important information this way, like which element was selected (it is stored in a DOM property, not an HTML attribute, it just gives the starting point).
children()
detach()
appendTo()
That happens because you remove all elements from both <select> fields and put them as new again. To make it working as expected you'd better move the actual elements as follows:
$("#swapCurrency").click(function(e) {
var options = $("#currency-from > option").detach();
$("#currency-to > option").appendTo("#currency-from");
$("#currency-to").append(options);
return false;
});
DEMO: http://jsfiddle.net/tchh2/2/
You are replacing the whole HTML (every option) within the <select>. As long as each select has the same amount of options and they correspond to each other, you can use the selected index property to swap them:
$("#swapCurrency").click(function (e) {
var selOne = document.getElementById('currency-from'),
selTwo = document.getElementById('currency-to');
var selectOne = selOne.selectedIndex;
var selectTwo = selTwo.selectedIndex;
selOne.selectedIndex = selectTwo;
selTwo.selectedIndex = selectOne;
return false;
});
JSFiddle
I have an xml document (from a feed), which I'm extracting values from:
$(feed_data).find("item").each(function() {
if(count < 3) {
//Pull attributes out of the current item. $(this) is the current item.
var title = $(this).find("title").text();
var link = $(this).find("link").text();
var description = $(this).find("description").text();
Now inside "description" i need to get the img element, but this is causing me some problems. "descripttion" is a regular string element and it seems i can't call the ".find()" method on this, so what do i do?
I have tried calling .find():
var img = $(this).find("description").find("img");
But it's a no go. The img is wrapped in a span, but I can't get to this either. Any suggestions? I'd prefer to avoid substrings and regex solutions, but I'm at a loss.
I've also tried turning the "description" string into an xml object like so:
var parser = new DOMParser();
var desc = parser.parseFromString(test,'text/xml');
$(desc).find("img").each(function() {
alert("something here");
});
But that doesn't work either. It seems like it would, but I get a "document not well formed" error.
Try enclosing the contents of the description tag in a dummy div, that seemed to work better for me, and allowed jQuery's .find() to work as expected.
e.g.
$(feed_data).find("item").each(function() {
if(count < 3) {
//Pull attributes out of the current item. $(this) is the current item.
var title = $(this).find("title").text();
var link = $(this).find("link").text();
var description = '<div>' + $(this).find("description").text() + '</div>';
var image = $(description).find('img');
Hi and thanks for the prompt replies. I gave GregL the tick, as I'm sure his solution would have worked, as the principle is the same as what I ended up with. My solution looks like this:
$(feed_data).find("item").each(function() {
if(count < 3) {
//Pull attributes out of the current item. $(this) is the current item.
var title = $(this).find("title").text();
var link = $(this).find("link").text();
var description = $(this).find("description").text();
var thumbnail = "";
var temp_container = $("<div></div>");
temp_container.html(description);
thumbnail = temp_container.find("img:first").attr("src");
So wrap the string in a div, and then use "find()" to get the first img element. I now have the image source, which can be used as needed.
maybe you should try to convert the description text to html tag and then try to traverse it via jquery
$('<div/>').html($(this).find("description").text()).find('img')
note: not tested