Javascript Print <li> with data-name - javascript

I'm trying to use JavaScript to generate JQuery ListView, once I click on the listview item it will show an alert message.
In the demo I found in Stack Overflow it works perfectly.
Once I try to integrate my code with it, it does not work anymore. Is the way I'm generating data-name in my listview is correct?
Sample of my Fiddle: http://jsfiddle.net/TLGY7/416/
$('#mylistview ul').children('li').bind('click', function(e) {
var item = $(this).attr('data-name')
alert('Selected Name=' + item );
});
function view() {
if (db==null) {
alert('Error: Database is null.');
return;
}
$('#listData').empty();
db.executeSql(
'SELECT `id`, `activityname`, `location`, `sdate`, `stime`, `reporter` FROM `record` ORDER BY `id` ASC',
[],
function(resultset) {
var length = resultset.rows.length;
for(var i=0; i<length; i++) {
$('#listData').append('<li class="activitylist" data-name='+resultset.rows.item(i).id+'>'+resultset.rows.item(i).id+'.'+stringconverter(resultset.rows.item(i).activityname)+'</li>');
}
$("#listData").listview( "refresh" );
},
function(error) {
alert('Error: '+error.message);
}
);
}

var linkElement = $('<a href="#pageDetail" class="anchor">').text(resultset.rows.item(i).id + '.' + stringconverter(resultset.rows.item(i).activityname));
var listElement = $('<li class="activitylist">').attr('data-name', resultset.rows.item(i).id)).append(linkElement);
$('#listData').append(listElement)
append method requires JQuery node element, not text
you also can make a $() around your '' statement. the node building itself looks ok for the first view.

If you are adding the listitems dynamically, you should use event delegation to handle the click event:
$('#mylistview ul').on("click", "li", function(){
var item = $(this).data('name')
alert('Selected Name = ' + item );
});
In his way the listitems don't have to exist yet when you setup the click handler.
Updated FIDDLE

Related

domConstruct place button not firing

I am creating table rows dynamically using dojo domConstruct. One of the column contains a button for delete function.But i dont know how to connect onclick event for the delete button. Below is my js code for creating the row.
domConstruct.place("<tr class='test'><td>" +
" Account name"+ XXXX+" "+" Account number is is $" + data1 +
"</td><td><input type ='button' onclick='deleteFunction(this);' value='remove' id=" +
buttonId + "/></td></tr>","tradeInValue","");
So now how i connect it to
on(dom.byId("buttonId"),"click",function(){
// my code goes in here
});
I have no clue here. Basically i need to remove the row from a table on click of a button.
I am using dojo in javascript file.
Updated.
o
n(dom.byId("submitButton"), "click", function(evt){
var name=registry.byId("name").get('value');
var detail = registry.byId("manufacturer").get('value');
var id=registry.byId("model").get('value');
var make=registry.byId("shaft").get('value');
var xhrArgs={
url:"./name/getValue",
content:{name:name,detail:detail,id:id,make:make},
handleAs:"json",
load:function(data){
var data1=data/100;
var row=domConstruct.create("tr",null,"tradeInValue");
domConstruct.create("td",{innerHTML:" Name
"+ detail+" "+id+" Value is $"+data1},row);
var actions=domConstruct.create("td",null,row);
var btn=domConstruct.create("input",{
id:idRow,
type:"button",
value:"Remove"
},actions);
btn.addEventListener("click", function(evt) {
console.log("Deleting");
console.log(evt.target.parentNode.parentNode.idRow);
domConstruct.destroy(evt.target.parentNode.parentNode);
});
var test={
"name" : name,
"detail" : detail,
"id" :id,
"tradePrice" :data,
"make":make
};
tradeDetails.clubDetails.push(test);
}
}
var deferred=dojo.xhrPost(xhrArgs);
}
});
The easiest way is to create your DOM nodes individually, for example:
var row = domConstruct.create("tr", null, "myData");
domConstruct.create("td", { innerHTML: person.id }, row);
domConstruct.create("td", { innerHTML: person.name }, row);
var actions = domConstruct.create("td", null, row);
var btn = domConstruct.create("input", {
type: "button",
value: "Remove"
}, actions);
This allows you to easily attach event handlers to btn, while still preserving context and still having access to the data you're working with, for example:
btn.addEventListener("click", function() {
console.log("Deleting", person);
});
To delete the row itself you could use the Event.target property, which gives you access to the button node itself. If you use the Node.parentNode property, you can eventually access the row itself, and then you can remove it using dojo/dom-construct::destroy()
For example:
btn.addEventListener("click", function(evt) {
domConstruct.destroy(evt.target.parentNode.parentNode);
});
A full example can be found on JSFiddle.

How to get ID of listview item Clicked. [javascript / jquery / jquery mobile]

I need advice on how to detect which <li> is tap/click by the user, then write the 'ID' of the tap/clicked <li> into Localstorage, then use the saved Localstorage to retrieve data for Detail Page.
I'm new to javascript/jquery, if you can provide some simple example code will be very much appreciated.
I know how to write Localstorage, read Localstorage, get JSON data from server API, generate Loop for Listview with unique ID for each <li>.
What I need is, how to use JS to make <li> clickable (link to Detail Page) and write to Localstorage at the same time.
I have tried:
$('.liClass').click(function() { //block of code to write Localstorage };
But the <li> is not clickable and no key/value written to Localstorage. Not to mention to detect which <li> is clicked (this I have no idea).
Please advice, thank you.
Code update:
//Show restaurant listing - NOTE: This is not first page. Link from other Page.
$('#restaurantList').on("pagebeforecreate", function() {
$.getJSON("http://mydomain.com/api/restaurant", function( data ) {
function rstListing(data) {
if ($.isEmptyObject(data) === true) {
alert ('JSON return empty');
} else {
for (i=0; i<data.length; i++){
$('#restaurantListing').append('<li id="' + data[i].restaurant_id + '" class="rstList"><img src="http://mydomain.com/file/img/' + data[i].restaurant_logo + '"><h2>' + data[i].name + '</h2><p>' + data[i].city + '</p></li>');
$('#restaurantListing').listview('refresh');
}
}
}
rstListing(data);
}
);
});
//Listview link to Detail Page
$(document).ready(function(){
$('.rstList').click(function() {
var id = $(this).attr("id"); // Get the ID
alert(id);
console.log(id);
});
});
Also tried:
//Listview link to Detail Page
$('#restaurantList').on("pageload", function() {
$('.rstList').click(function() {
var id = $(this).attr("id"); // Get the ID
alert(id);
console.log(id);
});
});
You don't need to make any <li> element to be clickable by your self, when you add the click event to any element, that will be triggered when the item is clicked.
Your problem will basically be that the element is not loaded when the event is bind to it. So you have to add your code inside document ready event like this.
$(document).ready(function(){
$('.liClass').click(function() {
var id= $(this).attr("id"); // Get the ID
};
});
$('.liclick').click(function() {
alert($(this).attr("id"));//Get id of clicked li
localStorage.setItem($(this).attr("id"),$(this).attr("id")); //stored into localStorage
alert("Data from localStorage "+localStorage.getItem($(this).attr("id"))); // get stored id
});
Working Fiddle
You will need to use the event delegation to assign the click event since you are building the HTML DOM dynamically via JSON request, thus not being able to locate the 'li' elements at the time of the page load. So, it would look like:
$(document).on("click", ".rstList", function (event) {
// click event
}
See this link for more details:
jQuery event delegation
I have solved my problem with the example code provided by stackoverflow member here. My previous problem is because I separate the creation of the listview and bind the click listener in two different page event.
After testing the page event sequence, I'm now putting the click listener into the same page event instead of separate to two. Now my code look like this, hope this will help someone bump into the same problem as me:
//Show restaurant listing
$('#restaurantList').on("pagebeforecreate", function() {
alert('pagebeforecreate event triggered');
$.getJSON("http://mydomain.com/api/restaurant", function( data ) {
function rstListing(data) {
if ($.isEmptyObject(data) === true) {
alert ('JSON return empty');
} else {
for (i=0; i<data.length; i++){
$('#restaurantListing').append('<li id="' + data[i].restaurant_id + '" class="rstList"><img src="http://mydomain.com/file/img/' + data[i].restaurant_logo + '"><h2>' + data[i].name + '</h2><p>' + data[i].city + '</p></li>');
$('#restaurantListing').listview('refresh');
}
}
}
rstListing(data);
alert('rstListing() executed');
$('.rstList').click(function() {
alert($(this).attr("id"));//Get id of clicked li
localStorage.setItem($(this).attr("id"),$(this).attr("id")); //stored into localStorage
alert("Data from localStorage "+localStorage.getItem($(this).attr("id"))); // get stored id
});
}
);
});

Binding events to list elements

I'm dynamically creating a list using JQuery and would like to bind each element to a "tap" event. How would I do this? Here is a sample of what I'm trying to do, but it isn't working.
for(var i=1; i <= 5; i++) {
var id = "item" + i;
var li = $("<li data-theme=\"d\" id=\"" + id + "\">Item " + i + "</li>");
li.appendTo(ul);
$(document).delegate("#"+id, "tap", function() {
$("#"+id).attr({ "data-theme" : "e", "class" : "ui-li ui-li-static ui-btn-up-e" });
});
}
This code triggers when tapping any element, however it always modifies the last element in the list for some reason.
YOUR OPTIONS
Either move the event handling to outside the loop
for(var i=1; i <= 5; i++) {
....
}
$(document).delegate("[id^=item]", "tap", function() {
});
Use the bind method and apply the tap event to the element, and not to the document.
for(var i=1; i <= 5; i++) {
//append li to ul
$("#"+id).bind("tap", function() {
$(this).attr({
"data-theme" : "e",
"class" : "ui-li ui-li-static ui-btn-up-e"
});
});
}
BUT, the best way to be to put the event outside the loop, and bind the event to ul which will later delegate it to li.
for(var i=1; i <= 5; i++) {
....
}
$("ul").delegate("[id^=item]", "tap", function() {
});
NOTE
If you want to change your theme, you also need to update your layout once.
$("ul").delegate("[id^=item]", "tap", function() {
$(this).attr({
"data-theme" : "e",
"class" : "ui-li ui-li-static ui-btn-up-e"
}).parent("ul").listview().listview("refresh");
});
USE OF STARTS WITH SELECTOR
You've put this in your code :
var id = "item" + i;
That means for the whole loop of 5 elements, your ids are gonna look like this :
<li id="item1">..
<li id="item2">..
<li id="item3">..
<li id="item4">..
Looking at the common thing here, I'd say it is :
item
So, since your ids start with item you could generalise it by using the starts with selector. So,
id^=item
means that you're searching for elements with id that starts with item. And since its an attribute,
[id^=item]
A MORE MODULAR APPROACH
This method involves lesser HTML :
//your ul tag
var ul = $("ul")
//set up an array for adding li to it.
var li = [];
//a temporary element to store "li"
var $li;
for(var i=1; i <= 5; i++) {
//add required attributes to the element
var $li = $("<li/>", {
"data-theme" : "d",
"id" : "item" + i,
"html" : "Item " + i
});
//push that into array
li.push($li);
}
//wait for append to finish
ul.append(li).promise().done(function () {
//wait for list to be added - thats why you wait for done() event in promise()
//add the click events to this - event delegation - this way your click event is added only once
$(this).on("tap", "[id^=item]", function () {
$(this).attr({
"data-theme" : "e",
"class" : "ui-li ui-li-static ui-btn-up-e"
}).parent("ul").listview().listview("refresh");
});
//then refresh
$(this).listview().listview("refresh");
});
Here's a demo for this : http://jsfiddle.net/hungerpain/TdHXL/
Hope this helps!
Just move the event handler to outside the for loop.
And replace
$(document).delegate("#"+id, "tap", function() {
with
$(document).delegate("[id*=item], "tap", function() {
JS
for (var i = 1; i <= 5; i++) {
var id = "item" + i;
var li = $("<li data-theme=\"d\" id=\"" + id + "\">Item " + i + "</li>");
li.appendTo(ul);
}
$(document).delegate("[id*=item]", "tap", function () {
$("#" + id).attr({
"data-theme": "e",
"class": "ui-li ui-li-static ui-btn-up-e"
});
});
Here is what I'd do:
var items = []; // an actual JavaScript array - a list of items.
for(var i=1;i<=5;i++){
items.push({theme:'d'}); //add an item to our list,
//Anything that actually relates to the item should be
//here, text, other data and such. This is our 'view model'.
}
items.forEach(function(item,i){ // for each item, bind to the dom
var el = document.createElement("li"); //create an element
el.textContent = i+1; // set its text
el.onclick = function(e){ // or ontap or whatever
el.className = "ui-li ui-li-static ui-btn-up-e";
item.theme = "d";
}//you mind want to use addEventListener instead at a later point
item.el = el;
ul.appendChild(el); // you need access to ul, currently being a jQuery object ul[0].
});
Note we have access to the items directly from our code, we can update them directly and such and have a direct reference to them. We don't need to query our own data - we own it and know directly how to get to it.
Also - we don't have a 80kb dependency. No complex selectors, no 'magic' bindings. Everything is straight forward and it's just plain ol' javascript.
Note: forEach should be shimmed (easily) for older browsers.

Jquery creating checkboxs dynamically, and finding checked boxes

I have information that comes out of a database and gets put into a list with a checkbox by each element. This is how it is currently done:
function subjects(){
$.ajax({
url: "lib/search/search.subject.php",
async: "false",
success: function(response){
alert(response);
var responseArray = response.split(',');
for(var x=0;x<responseArray.length;x++){
$("#subjects").append("<br />");
$("#subjects").append(responseArray[x]);
$("#subjects").append("<input type='checkbox' />");
}
}
});
}
it works fine, but I need a way to pick up on if a checkbox is clicked, and if it is clicked then display which one was clicked, or if multiple ones are clicked.
I can't seem to find a way to pick up on the checkboxs at all.
the response variable is "math,science,technology,engineering"
Because you are populating the Checkboxes Dynamically you need to Delegate the event
$("#subjects").on("click", "input[type='checkbox']", function() {
if( $(this).is(":checked") ) {
alert('Checkbox checked')
}
});
To better capture the data it is better if you encase the corresponding data into a span , so that it can be easier to search..
$("#subjects").append('<span>'+responseArray[x] + '</span>');
$("#subjects").on("click", "input[type='checkbox']", function() {
var $this = $(this);
if( $this.is(":checked") ) {
var data = $this.prev('span').html();
alert('Current checkbox is : '+ data )
}
});
It would be best to give your dynamically injected checkboxes a class to target them better, but based on your code try:
$("#subjects").on("click", "input", function() {
if( $(this).is(":checked") ) {
// do something
}
});
Since your input elements are added dynamically, you need to use jQuery's .on() function to bind the click event to them. In your case you need to use .on() to bind to an element that exist in the DOM when the script is loaded. In your case, the element with the ID #subjects.
This note from the docs is mainly for machineghost who downvoted my answer for no apparent reason:
Event handlers are bound only to the currently selected elements; they
must exist on the page at the time your code makes the call to .on().
To ensure the elements are present and can be selected, perform event
binding inside a document ready handler for elements that are in the
HTML markup on the page. If new HTML is being injected into the page,
select the elements and attach event handlers after the new HTML is
placed into the page.
$('#subjects input[type=checkbox]').on('click',function(){
alert($(this).prop('checked'));
});
or the change event: in case someone uses a keyboard
$('#subjects input[type=checkbox]').on('change',function(){
alert($(this).prop('checked'));
});
simple fiddle example:http://jsfiddle.net/Dr8k8/
to get the array example use the index of the inputs
alert($(this).prop('checked') +'is'+ $(this).parent().find('input[type=checkbox]').index(this)+ responseArray[$(this).parent().find('input[type=checkbox]').index(this) ]);
simplified example: http://jsfiddle.net/Dr8k8/1/
EDIT: Just for an example, you could put the results in an array of all checked boxes and do somthing with that:
$('#subjects>input[type=checkbox]').on('change', function() {
var checklist = [];
$(this).parent().find('input[type=checkbox]').each(function() {
$(this).css('background-color', "lime");
var myindex = $(this).parent().find('input[type=checkbox]').index(this);
if ($(this).prop('checked') == true) {
checklist[myindex] = responseArray[myindex];
}
});
$('#currentlyChecked').text(checklist);
});
EDIT2:
I thought about this a bit and you can improve it by using .data() and query that or store it based on an event (my button called out by its id of "whatschecked")
var responseArray = ['math', 'science', 'technology', 'engineering'];// just for an example
var myList = '#subjects>input[type=checkbox]';//to reuse
for (var x = 0; x < responseArray.length; x++) {
// here we insert it all so we do not hit the DOM so many times
var iam = "<br />" + responseArray[x] + "<input type='checkbox' />";
$("#subjects").append(iam);
$(myList).last().data('subject', responseArray[x]);// add the data
}
var checklist = [];// holds most recent list set by change event
$(myList).on('change', function() {
checklist = [];
$(myList).each(function() {
var myindex = $(this).parent().find('input[type=checkbox]').index(this);
if ($(this).prop('checked') == true) {
checklist.push($(this).data('subject'));
alert('This one is checked:' + $(this).data('subject'));
}
});
});
// query the list we stored, but could query the checked list data() as well, see the .each() in the event handler for that example
$("#whatschecked").click(function() {
var numberChecked = checklist.length;
var x = 0;
for (x = 0; x < numberChecked; x++) {
alert("Number " + x + " is " + checklist[x] + " of " + numberChecked);
}
});
live example of last one: http://jsfiddle.net/Dr8k8/5/
The general pattern to do something when a checkbox input is clicked is:
$('input[type=checkbox]').click(function() {
// Do something
})
The general pattern to check whether a checkbox input is checked or not is:
var isItChecked = $('input[type=checkbox]').is(':checked');
In your particular case you'd probably want to do something like:
$('#subjects input[type=checkbox]').click(function() {
to limit the checkboxes involved to the ones inside your #subjects element.

Create hidden field element for each drop

I know this is a similar question to my previous one however its slightly different.
I have this script adding each 'dropped' element to a list. Now i need it adding into a variable / hidden field so i can pass it to the next page via a form.
When i run it at the moment. It alerts for each one however, it does it not just for every item dropped but if there are 10 items dropped it will run 10 times per item droped rather than once per item dropped.
Any help would be great.
//Record and add dropped items to list
var txt = $("#listbox");
var dtstart = copiedEventObject.start + '\n'
var caltitle = copiedEventObject.title
var txt = $('#listbox');
txt.append("<li class ='listItem'> "+dtstart +"</li>")
var listItems = $('.listItem');
$('#calendarform').submit(function() {
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
return false;
});
// remove the element from the "Draggable Events" list
$(this).remove();
the problem lies in this code
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
you are alerting the text of all the list items for each list item.
use jQuery(this) to access the current item within an each block
listItems.each(function(){ //For each event do this:
alert( $(this).text() );
});
Assuming your code is within a drop event handler, you are also adding a submit handler each time you drop. This means that each time you drop, you queue up another submit event. This is probably not desired. Move this submit(function(){}) block outside your drop handler to prevent it from firing that function more than once.
$('#calendarform').submit(function(e) {
var listItems = $('.listItem');
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
e.preventDefault();//stop normal behavior
return false;
});
and to create elements on the fly you just pass jQuery the html, and append it to your form.
$('<input type="hidden" name="listItem[]"/>').appendTo("#calendarForm").val(listItem.text())
you may have to fiddle with the name element to get it to submit as an array in your server side language, but you're also within an each loop, which provides you with an index, so you can do the following.
$('#calendarform').submit(function(e) {
var form = $(this);
var listItems = $('.listItem');
listItems.each(function(index){ //For each event do this:
var listItem = $(this);
$("<input type='hidden'/>").val(listItem.text()).appendTo(form).attr('name', 'listItem[' + index + ']');
});
e.preventDefault();//stop normal behavior
return false;
});

Categories

Resources