Jquery mobile - Click button to add to UL - javascript

i am trying to build an application that when the user enters text into a textbox on a jquery based mobile app and clicks save it adds it to the list on the screen
so by default i won't have a list, but as the user adds an item the list should be created or if the list already exists, the new item added as a new list item.
in terms of saving it i will work on that after, for the time being i just want to dynamically append to a ul in jqm on the screen
Can someone assist with code that may help with this. it is giving me an item added saying "item undefined" however numslist is my list and txtbox is the textbox so im not sure where i am going wrong
thanks
<script>
var $txtbox = $("#txtbox").val();
var count = 0;
$("#main").live("pagecreate", function(event) {
$("#numlist").listview({create: function(event, ui) {
$("#addBtn").bind("click", function(event, ui) {
var str = "<li><a href='#'>Item " + ($txtbox) + "</a></li>";
$("#numlist").append(str);
$("#numlist").listview("refresh");
});
$("#removeBtn").bind("click", function(event, ui) {
// if (--count < 0) {
// count = 0;
// return;
// }
$("#numlist").find("li").remove();
$("#numlist").listview("refresh");
});
}});
});
</script>

Well, you can use localstorage, that way you won't need to code extra functions that save/store data.

try this:
var $lst = $('#productList');
$("#btnID").on("click",function() {
var $txtBox = $("#txtBox");
var $li = $('<li/>').html($txtBox.val());
$lst.append($li).listview('refresh');
$txtBox.val("");
});
working fiddle here: http://jsfiddle.net/REthD/21/

If I understood your question correctly, something similar to the following should work for you:
$('input[type=button]').on('click', function() {
var ul = $('#ul_id').length > 0 ? $('#ul_id') : $('<ul />', { id: 'ul_id'}).appendTo('#parent');
$('<li />').text($('#textbox').val()).appendTo(ul);
});
The first line in the event will check if the element exists, if it does, it returns that, otherwise, creates a new and appends to the specified parent element. Then, it appends a to the with the text from the textbox.
jsFiddle example

Related

Using jQuery to insert tags into box?

What I’m looking to create is something like the Stack overflow tag insert. I want to be able to type the tag into the insert box and when I click the ‘Add’ button, it adds it to the box above. I also want it to push the new tag into the ‘SelectedTags’ array. If the user removes it from the box, it'll need to be removed from the array. I guess I would need to push into the array first then populate the box based on the arrays content? I’ve tried creating it in JSFiddle but can’t get it working. Can someone help using the JSFiddle example? http://jsfiddle.net/uVxXg/117/
I assume this is what make it look like a tag?
$("#tags").tagit({
availableTags: SelectedTags
});
This is how you do it:
$(document).ready(function() {
var sampleTags = [];
$('#tags').tagit({
availableTags: sampleTags,
afterTagRemoved: function(evt, ui) {
console.log(ui.tagLabel)
for(var i = 0; i < sampleTags.length; i++) {
if (sampleTags[i] == ui.tagLabel) {
sampleTags.splice(i, 1); //Here is the update
}
}
}
});
$('form').submit(function(e) {
var inp = $('#tagInput').val();
$('#tagInput').val('');
$('#tags').tagit('createTag', inp);
sampleTags.push(inp);
e.preventDefault();
console.log(sampleTags)
});
$("#array").click(function(e){
console.log("MyArray",sampleTags)
})
});
Try out the fiddle, and when you add something to the SelectedTags array you will then have the tags as "find wile type" in the tags input.

Sortable using 2 parameters javascript

I am using sortable for sorting some entries. It works fine with simple position numbers and when drag and drop any entry i can update those position number and display accordingly. But my problem is when user drags any entry I also want to update another parameter which is time.
I have created jsfiddle demo here so that you can have more idea of my problem.
Initially it looks like this which is fine
But when I drag any entries it only updates the position number and not the time. I want the time to be updated as well.
As suggested by Alex, you should just call calculateTime again. The only change is rather than grabbing the data from input again, you can store the input in an variable and grab the data from that variable.
//Here you set the stored variable
var stored_starttime, stored_minuteperround;
$(document).ready(function() {
$("#timing").click(
function() {
//Here you set the value of the stored variable
stored_starttime = document.getElementById("stime").value;
stored_minuteperround = document.getElementById("rounds").value;
calculatetime(stored_starttime, stored_minuteperround);
}
);
});
$("#sortable_nav").sortable({
placeholder: "ui-state-highlight",
helper: 'clone',
sort: function(e, ui) {
$(ui.placeholder).html(Number($("#sortable_nav > li:visible").index(ui.placeholder)) + 1);
},
update: function(event, ui) {
var $lis = $(this).children('li');
$lis.each(function() {
var $li = $(this);
var newVal = $(this).index() + 1;
$(this).children('.sortable-number').html(newVal);
//Here you check if the stored variables are defined
if (stored_starttime !== undefined && stored_minuteperround !== undefined){
calculatetime(stored_starttime, stored_minuteperround);
}
});
}
});
$("#sortable_nav").disableSelection();
Here is the jsfiddle http://jsfiddle.net/zjhez393/5/

jQuery prepend only to next list item after each click, not all list items at once

Simply put, my goal is to make the "next" button add a class active to the previous list item, then if the active class exists, also prepend a YES to that list item, not all list items as it is currently doing in my code.
Currently, my attempt is adding YES to all list items, I want to add YES only to the previous items after each click.
My attempt is here:
var $tabs = $('li');
$('.next').on('click', function () {
$tabs.next('li').addClass("active").css("background-color","yellow");
if ($($tabs).next().hasClass("active")){
$($tabs).prepend('YES').prev();
} else {
$($tabs).append('NO');
}
});
Code can be seen here:
http://codepen.io/anon/pen/yrjvb
I'm not sure if I understood you correctly, but this might be what you're looking for :
var $tabs = $('li');
var count = 0;
$('.next').click(function () {
var tab = $tabs.eq(count);
var link = tab.find('a[data-toggle="tab"]');
link.addClass("active").css("background-color","yellow");
if (link.hasClass("active")) {
tab.prepend('YES');
count++;
} else {
tab.append('NO');
}
});
Forked Codepen : http://codepen.io/anon/pen/pnKAc?editors=101
Basically, you were selecting all the <li> items. In my code, I select an item one-by-one.
Surely there is a better way to do it (selecting directly the next element etc., but I guess with this code you can see what's different.
Also, you say you want to add, did you mean "append", then ?
How about this approach (codepen): Store the current one, clear its active state, pick the next one ?
$('.next').on('click', function () {
var $current = $('li.active');
if(!$current.length){
$current = $('li:first');
$current.addClass('active');
}else{
$current.removeClass('active');
$current.next('li').addClass('active');
}
});

Recursive IDs and duplicating form elements

I have the following fiddle:
http://jsfiddle.net/XpAk5/63/
The IDs increment appropriately. For the first instance. The issue is when I try to add a sport, while it duplicates, it doesn't duplicate correctly. The buttons to add are not creating themselves correctly. For instance, if I choose a sport, then fill in a position, and add another position, that's all fine (for the first instance). But when I click to add another sport, it shows 2 positions right away, and the buttons aren't duplicating correctly. I think the error is in my HTML, but not sure. Here is the JS I am using to duplicate the sport:
$('#addSport').click(function(){
//increment the value of our counter
$('#kpSport').val(Number($('#kpSport').val()) + 1);
//clone the first .item element
var newItem = $('div.kpSports').first().clone();
//recursively set our id, name, and for attributes properly
childRecursive(newItem,
// Remember, the recursive function expects to be able to pass in
// one parameter, the element.
function(e){
setCloneAttr(e, $('#kpSport').val());
});
// Clear the values recursively
childRecursive(newItem,
function(e){
clearCloneValues(e);
});
Hoping someone has an idea, perhaps I've just got my HTML elements in the wrong order? Thank you for your help! I'm hoping the fiddle is more helpful than just pasting a bunch of code here in the message.
The problem is in your clearCloneValues function. It doesn't differentiate between buttons and other for elements that you do want to clear.
Change it to:
// Sets an element's value to ''
function clearCloneValues(element){
if (element.attr('value') !== undefined && element.attr('type') !== 'button'){
element.val('');
}
}
As #PHPglue pointed out in the comments above, when new positions are added, they are incorrectly replicated (I'm assuming here) to the newly cloned for
There is a similar problem with the add years functionality.
A quick fix would be to initialize a variable with a clone of the original form fields:
var $template = $('div.kpSports').first().clone();
Then change your addSport handler to:
$('#addSport').click(function () {
//increment the value of our counter
$('#kpSport').val(Number($('#kpSport').val()) + 1);
//clone the first .item element
var newItem = $template.clone();
…
});
However, there are no event bindings for the new buttons, so that functionality is still missing for any new set of form elements.
Demo fiddle
Using even a simple, naive string based templates the code can be simplified greatly. Linked is an untested fiddle that shows how it might be done using this approach.
Demo fiddle
The code was simplified to the following:
function getClone(idx) {
var $retVal = $(templates.sport.replace(/\{\{1\}\}/g, idx));
$retVal.find('.jsPositions').append(getItemClone(idx, 0));
$retVal.find('.advtrain').append(getTrainingClone(idx, 0));
return $retVal;
}
function getItemClone(setIdx, itemIdx) {
var retVal = itemTemplate.replace(/\{\{1\}\}/g, setIdx).replace(/\{\{2\}\}/g, itemIdx);
return $(retVal);
}
function getTrainingClone(setIdx, trainingIdx) {
var retVal = trainingTemplate.replace(/\{\{1\}\}/g, setIdx).replace(/\{\{2\}\}/g, trainingIdx);
return $(retVal);
}
$('#kpSportPlayed').on('click', '.jsAddPosition', function() {
var $container = $(this).closest('.kpSports');
var containerIdx = $container.attr('data_idx');
var itemIdx = $container.find('.item').length;
$container.find('.jsPositions').append(getItemClone(containerIdx, itemIdx));
});
$('#kpSportPlayed').on('click', '.jsAddTraining', function() {
var $container = $(this).closest('.kpSports');
var containerIdx = $container.attr('data_idx');
var trainIdx = $container.find('.advtrain > div').length;
$container.find('.advtrain').append(getTrainingClone(containerIdx, trainIdx));
});
$('#addSport').click(function () {
var idx = $('.kpSports').length;
var newItem = getClone(idx);
newItem.appendTo($('#kpSportPlayed'));
});

Filtering the list of friends extracted by Facebook graph api ( more of a JavaScript/Jquery question than Facebook API question)

Hello there JavaScript and Jquery gurus, I am getting and then displaying list of a facebook user's friend list by using the following code:
<script>
function getFriends(){
var theword = '/me/friends';
FB.api(theword, function(response) {
var divInfo = document.getElementById("divInfo");
var friends = response.data;
divInfo.innerHTML += '<h1 id="header">Friends/h1><ul id="list">';
for (var i = 0; i < friends.length; i++) {
divInfo.innerHTML += '<li>'+friends[i].name +'</li>';
}
divInfo.innerHTML += '</ul></div>';
});
}
</script>
graph friends
<div id = divInfo></div>
Now, in my Facebook integrated website, I would eventually like my users to choose their friends and send them gifts/facebook-punch them..or whatever. Therefore, I am trying to implement a simple Jquery filter using this piece of code that manipulates with the DOM
<script>
(function ($) {
// custom css expression for a case-insensitive contains()
jQuery.expr[':'].Contains = function(a,i,m){
return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
};
function listFilter(header, list) { // header is any element, list is an unordered list
// create and add the filter form to the header
var form = $("<form>").attr({"class":"filterform","action":"#"}),
input = $("<input>").attr({"class":"filterinput","type":"text"});
$(form).append(input).appendTo(header);
$(input)
.change( function () {
var filter = $(this).val();
if(filter) {
// this finds all links in a list that contain the input,
// and hide the ones not containing the input while showing the ones that do
$(list).find("a:not(:Contains(" + filter + "))").parent().slideUp();
$(list).find("a:Contains(" + filter + ")").parent().slideDown();
} else {
$(list).find("li").slideDown();
}
return false;
})
.keyup( function () {
// fire the above change event after every letter
$(this).change();
});
}
//ondomready
$(function () {
listFilter($("#header"), $("#list"));
});
}(jQuery));
</script>
Now, This piece of code works on normal unordered list, but when the list is rendered by JavaScript, it does not. I have a hunch that it has to do something with the innerHTML method. Also, I have tried putting the JQuery filter code within and also right before tag. Neither seemed to work.
If anyone knows how to resolve this issue, please help me out. Also, is there a better way to display the friends list from which users can choose from?
The problem is here:
$(list).find("a:not(:Contains(" + filter + "))").parent().slideUp();
$(list).find("a:Contains(" + filter + ")").parent().slideDown();
Since you're rendering this:
divInfo.innerHTML += '<li>'+friends[i].name +'</li>';
There is no anchor wrapper, the text is directly in the <li> so change the first two lines to look in those elements accordingly, like this:
$(list).find("li:not(:Contains(" + filter + "))").slideUp();
$(list).find("li:Contains(" + filter + ")").slideDown();
You could also make that whole section a bit faster by running your Contains() code only once, making a big pact for long lists, like this:
$(input).bind("change keyup", function () {
var filter = $(this).val();
if(filter) {
var matches = $(list).find("li:Contains(" + filter + ")").slideDown();
$(list).find("li").not(matches).slideUp();
} else {
$(list).find("li").slideDown();
}
});
And to resolve those potential (likely really) innerHTML issues, build your structure by using the DOM, like this:
function getFriends(){
var theword = '/me/friends';
FB.api(theword, function(response) {
var divInfo = $("#divInfo"), friends = response.data;
divInfo.append('<h1 id="header">Friends/h1>');
var list = $('<ul id="list" />');
for (var i = 0; i < friends.length; i++) {
$('<li />', { text: friends[i].name }).appendTo(list);
}
divInfo.append(list);
});
}
By doing it this way you're building your content all at once, the <ul> being a document fragment, then one insertion....this is also better for performance for 2 reasons. 1) You're currently adding invalid HTML with the .innerHTML calls...you should never have an unclosed element at any point, and 2) you're doing 2 DOM manipulations (1 for the header, 1 for the list) after the much faster document fragment creation, not repeated .innerHTML changes.

Categories

Resources