Save selected data of a variable to use in another page - javascript

I have a list of items that are filled dynamically:
function ViewData(data) {
var SI = (typeof data) == 'string' ? eval('(' + data + ')') : data;
$('#ListContainer').empty();
for (var i = 0; i < SI.length; i++) {
var text = '<a href="Page.htm" rel="external" onclick= "SaveData();"
class="lesson" LessonID="' + SI[i].lessonID
'"><span class="lesson_subject">' + SI[i].sbj_Name +
'</span></b></a>
$('#ListContainer').append(text).trigger("create");
}
}
When one item of them is clicked, the page should navigate to another page carrying the data of this link.
I made this function to save the values of found in the link:
function SaveData() {
localStorage["LessonID"] = $('#ListContainer').find('.lesson').attr('LessonID');
localStorage["SubjectName"] = $('#ListContainer').find('.lesson_subject').text();
}
but it saves "All of the data". I want to save the data of the selected item only.
Do you have any ideas ?
Thanks.

It saves all of the data because your find('.lesson') will find every link inside #ListContainer. I would suggest removing your inline event handlers and taking advantage of event delegation with the on method:
$("#ListContainer").on("click", ".lesson", function() {
localStorage["LessonID"] = $(this).data("lessonid");
localStorage["SubjectName"] = $(this).data("subject");
});
Notice that I've used the data method instead of attr. That will require another change to your markup:
<a href="Page.htm" rel="external" class="lesson" data-lessonid="someID" data-subject="someSubject">
This uses HTML5 data-* attributes, which are the recommended approach when it comes to storing arbitrary data on an element.
Why use event delegation? It is more efficient, as it results in less event handlers bound to elements. Instead of one on every a.lesson element, there is just one on the #ListContainer element.
Because most DOM events bubble up the tree, a click on a descendant of #ListContainer will bubble up through the DOM tree, eventually reaching #ListContainer. The jQuery on method will pick up the event at this element, and check to see if it originated at an element matching .lesson. If so, it will execute the event handler.

Change this
onclick= "SaveData();"
to
onclick= "SaveData(this);"
Then change the saveData function to
function SaveData(elem) {
localStorage["LessonID"] = $(elem).attr('LessonID');
localStorage["SubjectName"] = $(elem).find('.lesson_subject').text();
}
Or even better, you can use $.on like #James Allardice showed in his answer.

You're mixing old world JavaScript and jQuery.
Use $("<a ...") to create your element, append it and then attach a .click handler which can use $(this) when it is fired. Use .data to add data to the elements when you add them which the .click handler can utilise.

Related

javascript click event not firing action

On page load, I have a search box that, once used, populates a div with multiple images. The javascript from the search uses this function to append all images into the div
function appendSomeItems(url, id, name, style) {
return '<div><div class="md-card md-card-hover"> <div id="getImage" class="gallery_grid_item md-card-content"> <img class ="uk-align-center imageClick"></a> <div class="gallery_grid_image_caption"> <span class="gallery_image_title uk-text-truncate">' + name + '</span> <span>' + style + '</span> </div></div></div></div>';
}
This works perfectly. Now I'm trying to make it so that when I click any one of the images it triggers an action (in this case a console log)
$('.imageClick').click(function handleImage() {
console.log(good);
});
However, it does nothing. No error but no console log.
What am I doing wrong here?
You need to use event-delegation in order to bind an event to dynamically created elements:
This approach uses document as the parent element, however, a good practice is to use the closest parent element.
$(document).on('click', '.imageClick', function handleImage() {
console.log(good);
});
Try with .on() to attach event on dynamically created element. This will allow attaching the event to the elements that are added to the body at a later time:
$('body').on('click', '.imageClick' function handleImage() {
console.log(good);
});
The problem is that you are calling $(".imageClick").click() before you dynamically create the items.
This means that jQuery doesn't actually bind the click listener to the items, since when $(".imageClick").click() is run, the elements don't actually exist yet.
Try this:
$("body").on("click", ".imageClick", function handleImage() {
console.log("good");
});
Also see this post for more information: In jQuery, how to attach events to dynamic html elements?

Two Html select drop down apply class for span element using Javascript

I am working on HTML select Dropdown. I have two dropdowns one is for font size adjust and other is for text alignment.
When I select the fontsize from the dropdown it has to apply along with text-capitalize (bootstrap css) and If I select the font alignment all three should apply for the span element. For Example.
<div>
<span id="Title"class="text-capitalize">check</span>
</div>
Right now the code was like this
function changeFont_size () {
var select = document.getElementById('font_size');
// Bind onchange event
select.onchange = function() {
document.querySelector("#Title").className = this.value += " text-
capitalize";
};
}
function changeAlignment () {
var select = document.getElementById('text_align');
// Bind onchange event
select.onchange = function() {
document.querySelector("#Title").className = this.value;
};
}
Actually I am newbe on Javascript. Some how I am not getting.
The output result would be the combination of :
<span class="h1 left text-capitalize">Text</span>
Everything should be in pure javascript.
Thanks in advance. Kindly help me.
Here is the Link
This jsfiddle makes your code work. You need to run the code when the document is loaded, so that your onchange functions are being hooked in time.
It does not work exactly like you intended though. Your alignment classes need to be on the parent element and when you select your alignment, you disregard the previously set h1 or h2 class.
window.onload = function() {
var font_size = document.querySelector('#font_size');
// Bind onchange event
font_size.onchange = function() {
document.querySelector("#Title").className = this.options[this.selectedIndex].value += " text-capitalize";
};
var text_align = document.querySelector('#text_align');
// Bind onchange event
text_align.onchange = function() {
document.querySelector("#Title").className = this.options[this.selectedIndex].value;
};
};
You are mixing things up. There are two ways to bind events (well, two ways which are still common even with recent browsers).
The first one is to put a function call in the onsomething property of an element in the html code. Whatever is put there will be executed when the event happens.
<button onclick="alert('hi');">Click me</button>
You should pass the event object to an event handler instead of writing inline code.
<button id="helloworld" onclick="helloworld_onclick(event)">Run</button>
...
function helloworld_onclick(e) {
alert("Hello world!");
}
If you want to be able to bind events dynamically, if you want to bind multiple events to an object and if you want to keep the JavaScript outside of your HTML, the modern way to to so is with addEventListener.
document.querySelector("#helloworld").addEventListener("click", function(e) {
alert("Hello world!");
});
The event object passed (called e in my functions) contains information about what triggered the event and can be used to prevent default behavior and to control event propagation. You can't use "this" in event handlers, but the element which called the handler will be stored in e.target.
In your code, you created functions which, when called, bind events to the elements. Then you bound those functions to the elements with the html attributes.
Finally, you seem to be stuck between querySelector and getElementById. Note that querySelector(All) returns a static node/nodelist while getElement(s)By(...) returns a live node/nodelist. A static node is a copy of all the information about the element. A live node is a reference to the real element. If you modify the element, it modifies the live node, but the static node will keep the old information. You should use getElementById over querySelector for that, and because it runs faster. For code simplicity however, you might prefer always using querySelector. Just don't mix using querySelector("#something") on a line and getElementById("something") on another one, it's the best way to get confused and end up wasting time on a bug because you wrote querySelector("something") or getElementById("#something") instead.
function changeFont_size (element) {
if(element.options[element.selectedIndex].value != 'select'){
document.getElementById('Title').className = element.options[element.selectedIndex].value;
} else{
document.getElementById('Title').className = '' }
}
function changeAlignment (element) {
if(element.options[element.selectedIndex].value != 'select'){
document.getElementById('container').className = element.options[element.selectedIndex].value;
} else{
document.getElementById('container').className = '' }
}
Try this, Hope it will work

jquery created select, and triggering on change

I cannot seem to get this to work. I am using jquery to create an html select, and I want some code to execute when its value changes.
code follows:
<script type ="text/javascript">
var firstweddingturn = '400';
$('#weddingturn').change(function() {
alert ("Wedding select change triggered!");
//var wedturn = $('#weddingturnselectid').val();
//$('#div3').append('<br>Wedding turn selected, ' + wedturn + '</br>')
});
$(document).ready(function() {
var html = [];
html[html.length] = '<select name="weddingturn" id="weddingturn">';
var a = firstweddingturn;
var b = Number(firstweddingturn) + 16;
while (a < b) {
// do some code
html[html.length] = '<option name="asdf" value = "1">' + a + '</option>';
a++;
} // end while
html[html.length] = '</select>';
$('#div1').append(html.join(''));
});
</script>
What am I doing wrong?
You need to use .delegate() (or .live()) since you are adding the select dynamically. When you attach an onChange handler with .change() it is only attached to existing matching elements, not elements which are added later on. To attach an event to all matching elements including those added to the page later, you use the .delegate() function, like this:
$('body').delegate('#weddingturn','change', function(){
alert('Wedding select changed to ' + $(this).find('option:selected').val() );
});
However, as some people point out, you can merely attach the event handler immediately after adding the <select> to the DOM. That way, you can still use .change() and your code should run faster.
Include this:
$('#weddingturn').live('change', function() {
alert ("Wedding select change triggered!");
//var wedturn = $('#weddingturnselectid').val();
//$('#div3').append('<br>Wedding turn selected, ' + wedturn + '</br>')
});
in your $(document).ready
And change it to use live
When the .change() event is bound, the element does not exist yet. You have 2 choices:
Bind the event after you create the element (the simplest and recommended option)
Use .delegate() (or .live()) to tell jQuery to bind the event to any element matching the selector whenever it is added to the DOM. If you choose this option, delegate() is the preferred method if you are using a recent version of jQuery > 1.4.2 since it is more performant than live().
You'll need to bind using live, since it is loaded post-DOM load:
$("#weddingturn").live("change", function() {
});
Also, I would place this within scope of $(document).ready, preferably after the code which loads it (just for the sake of logical linearity.)
You're hooking up the event handler BEFORE you've created the element.
(you can use .live() or you can just swap the order of operations)
your are dynamically adding the select to the DOM, at the time of declaration of your event handler the select doest not exists so the event handler doesn't get binded to the element use .live to attach the event handler to dynamically added element
$('#weddingturn').live('change',function() {
alert ("Wedding select change triggered!");
//var wedturn = $('#weddingturnselectid').val();
//$('#div3').append('<br>Wedding turn selected, ' + wedturn + '</br>')
});
DEMO
jquery live
You are setting the change function on a select that does not yet exist. Move that .change call to after the .append

Passing argument to JS function from link onclick

I have a link that looks like this:
<a id="mylink" onclick="deleteHike( 3 );" href="javascript:void(0);">Yes</a>
It is able to call this JavaScript:
window.onload = function()
{
//Get a reference to the link on the page
// with an id of "mylink"
var a = document.getElementById("mylink");
//Set code to run when the link is clicked
// by assigning a function to "onclick"
a.onclick = function( hike_id )
{
// Somecode her
// But when I try to use the hike_id it displays as [object MouseEvent]
}
}
But the value that comes in is [object MouseEvent], not the number that I was expecting. Any idea why this happens and how to fix this? :)
Thanks!
You are trying to assign the function to your link in two different and conflicting ways.
Using the eval-ed function string, onclick = "function(value)", works but is deprecated.
The other way of binding the click handler in the onload event works too, but if you want a particular value to be passed, you'll have to change your script a bit because the value as given in the initial onclick is completely lost when you set the onclick to a new function.
To make your current method work, you don't need an onload handler at all. You just need this:
function deleteHike(hike_id) {
// Some code here
}
To do it the second way, which I recommend, it would look like this:
<a id="mylink" href="javascript:void(0);">Yes</a>
with this script:
function deleteHike(e, hike_id) {
// Some code here
// e refers to the event object which you can do nifty things with like
// - learn the actual clicked element if it was a parent or child of the `this` element
// - stop the event from bubbling up to parent items
// - stop the event from being captured by child items
// (I may have these last two switched)
}
function getCall(fn, param) {
return function(e) {
e = e || window.event;
e.preventDefault(); // this might let you use real URLs instead of void(0)
fn(e, param);
};
}
window.onload = function() {
var a = document.getElementById("mylink");
a.onclick = getCall(deleteHike, 3);
};
The parameter of a DOM event function is the event object (in Firefox and other standards-compliant browsers). It is nothing in IE (thus the need to also grab window.event). I added a little helper function for you that creates a closure around your parameter value. You could do that each time yourself but it would be a pain. The important part is that getCall is a function that returns a function, and it is this returned function that gets called when you click on the element.
Finally, I recommend strongly that instead of all this, you use a library such as jQuery because it solves all sorts of problems for you and you don't have to know crazy JavaScript that takes much expertise to get just right, problems such as:
Having multiple handlers for a single event
Running JavaScript as soon as possible before the onload event fires with the simulated event ready. For example, maybe an image is still downloading but you want to put the focus on a control before the user tries to use the page, you can't do that with onload and it is a really hard problem to solve cross-browser.
Dealing with how the event object is being passed
Figuring out all the different ways that browsers handle things like event propagation and getting the clicked item and so on.
Note: in your click handler you can just use the this event which will have the clicked element in it. This could be really powerful for you, because instead of having to encode which item it was in the JavaScript for each element's onclick event, you can simply bind the same handler to all your items and get its value from the element. This is better because it lets you encode the information about the element only in the element, rather than in the element and the JavaScript.
You should just be able to declare the function like this (no need to assign on window.onload):
function deleteHike(hike_id)
{
// Somecode her
// But when I try to use the hike_id it displays as [object MouseEvent]
}
The first parameter in javascript event is the event itself. If you need a reference back to the "a" tag you could use the this variable because the scope is now the "a" tag.
Here's my new favorite way to solve this problem. I like this approach for its clarity and brevity.
Use this HTML:
<a onclick="deleteHike(event);" hike_id=1>Yes 1</a><br/>
<a onclick="deleteHike(event);" hike_id=2>Yes 2</a><br/>
<a onclick="deleteHike(event);" hike_id=3>Yes 3</a><br/>
With this JavaScript:
function deleteHike(event) {
var element = event.target;
var hike_id = element.getAttribute("hike_id");
// do what you will with hike_id
if (confirm("Delete hike " + hike_id + "?")) {
// do the delete
console.log("item " + hike_id + " deleted");
} else {
// don't do the delete
console.log("user canceled");
}
return;
}
This code works because event is defined in the JavaScript environment when the onclick handler is called.
For a more complete discussion (including why you might want to use "data-hike_id" instead of "hike_id" as the element attribute), see: How to store arbitrary data for some HTML tags.
These are alternate forms of the HTML which have the same effect:
<a onclick="deleteHike(event);" hike_id=4 href="javascript:void(0);">Yes 4</a><br/>
<button onclick="deleteHike(event);" hike_id=5>Yes 5</button><br/>
<span onclick="deleteHike(event);" hike_id=6>Yes 6</span><br/>
When you assign a function to an event on a DOM element like this, the browser will automatically pass the event object (in this case MouseEvent as it's an onclick event) as the first argument.
Try it like this,
a.onclick = function(e, hike_id) { }

Issue with selectors & .html() in jquery?

The function associated with the selector stops working when I replace it's contents using .html(). Since I cannot post my original code I've created an example to show what I mean...
Jquery
$(document).ready(function () {
$("#pg_display span").click(function () {
var pageno = $(this).attr("id");
alert(pageno);
var data = "<span id='page1'>1</span><span id='page2'> 2</span><span id='page3'> 3</span>";
$("#pg_display").html(data);
});
});
HTML
<div id="pg_display">
<span id="page1">1</span>
<span id="page2">2</span>
<span id="page3">3</span>
</div>
Is there any way to fix this??...Thanks
Not sure I understand you completely, but if you're asking why .click() functions aren't working on spans that are added later, you'll need to use .live(),
$("#someSelector span").live("click", function(){
# do stuff to spans currently existing
# and those that will exist in the future
});
This will add functionality to any element currently on the page, and any element that is later created. It keeps you have having to re-attach handlers when new elements are created.
You have to re-bind the event after you replace the HTML, because the original DOM element will have disappeared. To allow this, you have to create a named function instead of an anonymous function:
function pgClick() {
var pageno = $(this).attr("id");
alert(pageno);
var data="<span id='page1'>1</span><span id='page2'> 2</span><span id='page3'> 3</span>";
$("#pg_display").html(data);
$("#pg_display span").click(pgClick);
}
$(document).ready(function(){
$("#pg_display span").click(pgClick);
});
That's to be expected, since the DOM elements that had your click handler attached have been replaced with new ones.
The easiest remedy is to use 1.3's new "live" events.
In your situation, you can use 'Event delegation' concept and get it to work.
Event delegation uses the fact that an event generated on a element will keep bubbling up to its parent unless there are no more parents. So instead of binding click event to span, you will find the click event on your #pg_display div.
$(document).ready(
function()
{
$("#pg_display").click(
function(ev)
{
//As we are binding click event to the DIV, we need to find out the
//'target' which was clicked.
var target = $(ev.target);
//If it's not span, don't do anything.
if(!target.is('span'))
return;
alert('page #' + ev.target.id);
var data="<span id='page1'>1</span><span id='page2'>2</span><span id='page3'>3</span>";
$("#pg_display").html(data);
}
);
}
);
Working demo: http://jsbin.com/imuye
Code: http://jsbin.com/imuye/edit
The above code has additional advantage that instead of binding 3 event handlers, it only binds one.
Use the $("#pg_display span").live('click', function....) method instead of .click. Live (available in JQuery 1.3.2) will bind to existing and FUTURE matches whereas the click (as well as .bind) function is only being bound to existing objects and not any new ones. You'll also need (maybe?) to separate the data from the function or you will always add new span tags on each click.
http://docs.jquery.com/Events/live#typefn

Categories

Resources