I have small problem.
What I want to achieve is adding sum of values from above elements to each one.
For example every position have got it own time value hidden in attribute. I can get it by using jQuery
var time = $(ui.draggable).attr("time");
now we got 4 positions with time as follows:
432 sec
123 sec
5634 sec
654 sec
Now I want to sum it like this:
1. 432
2. 432+123
3. 432+123+5634
4. 432+123+5634+654
Any ideas how can I do this?
This is my code:
$(document).ready(function(){
$(".trash").sortable({
tolerance: 'touch',
receive: function (event, ui) {
ui.item.remove();
}
});
$(".DragContainer_dest").sortable({helper:'clone',
opacity: 0.5,
connectWith: '.trash',
scroll: true,
update : function () {
var order = $('.DragContainer_dest').sortable('serialize',{key:'string'});
$.post('includes/ajaxify.php',order+'&action=update');
var time = $(this).attr("time");
},
out : function () {
ui.item.remove();
}
});
$("div[class=DragContainer] .DragBox").draggable({helper:'clone'});
$(".DragContainer_dest").droppable({
accept: ".DragBox",
tolerance: "touch",
drop: function(ev, ui) {
$(this).append($(ui.draggable).clone().addClass("added"));
}
});
});
I want every element dropped or sorted in DragContainer_dest to sum values from other elements above him. Can this be done?
As I can understand, you need to collect all siblings of a node that come before the element in question and collect their attributes. Let's try this:
var nodeSiblings = $(this).parent().children();
// We need to find the index of our element in the array
var stopIndex = nodeSiblings.index(this);
var time = 0;
nodeSiblings.each( function(index, element){
if (index > stopIndex) return;
var attribute = parseInt($(element).attr("time"), 10);
if (!isNaN(attribute)) time += attribute;
});
// Here you have the sum of all time attributes
alert(time);
Maybe add a global variable called timeSum and then increase it for each element dropped?
var timeSum = 0;
$(".DragContainer_dest").droppable({
drop: function(ev, ui) {
timeSum += parseInt($(ul.draggable).attr('time'));
}
});
If you're using parseInt as instructed elsewhere, don't forget to include the radix:
parseInt($(ul.draggable).attr('time'), 10);
If you have a zero at the start it will treat it as octal unless you specify the radix.
Related
I have this code but is not working properly.
The idea is that every input has a value and sum or subtract its value from the total price depending if you click up or down.
Right now is just adding and adding and adding like crazy.
Thank you very much.
the JS:
$( document ).ready(function() {
$(".quantity").each(function(){
$(this).change(function(){
var quantity = ($(this).val());
var ammount = ($(this).attr("data-price"));
var price = $(this).closest(".bookSection").find(".item_price").html();
var subtotal = ammount * quantity;
var total = parseInt(subtotal) + parseInt(price);
$(this).closest(".bookSection").find(".item_price").html(total);
});
});
});
here the example:
http://jsbin.com/tolequyobi/1/edit?html,js,output
Instead of trying to use the .item_price just calculate it from the start. If not you will need to store the old value to know if you need to add or subtract.
You can do something like this
$('.quantity').change(function(){ // check change on the inputs
var total = 0; // set the total to 0
$(this).parent().find('.quantity').each(function() { // loop on all the items thats in this block
total += parseInt($(this).attr('data-price')) * parseInt($(this).val()); // add to the total their value
});
$(this).parent().find(".item_price").html(total); // and then add it to your html
});
How about recomputing the total from scratch whenever the quantity changes, instead of trying to keep a running total that you have to maintain?
$( document ).ready(function() {
var price = 0;
$(".quantity").each(function(){
$(this).change(function(){
var total = computeTotal($(this).closest(".bookSection"));
$(this).closest(".bookSection").find(".item_price").html(total);
});
});
});
function computeTotal(bookSection){
var total=0;
bookSection.children('.quantity').each(function(item){
total += $(this).val() * $(this).attr("data-price");
});
return total;
http://jsbin.com/rimubocijo/edit?html,js,output
I have noticed this question asked a few times but with no actual correct answer or good feedback to direct in the right path.
I am using fullcalendar javascript plugin and trying to add the total hours of multiple events for each day which then I will display the sum in the header or footer of each day.
I have tried many different ways to accomplish this but the closest I got to my result is with this code:
eventAfterRender: function(event, element, view) {
if (event.totalhrs > 0) {
var sd = event.startdate;
if (dateTotal.hasOwnProperty(sd)) {
dateTotal[event.startdate] = (dateTotal[event.startdate] + +event.totalhrs);
} else {
dateTotal[event.startdate] = +(event.totalhrs);
}
$(".fc-day-top[data-date='"+event.startdate+"']").find('.fc-dailytotal').text(dateTotal[event.startdate]);
}
}
This works when the calendar is rendered for the first time, but if there is an event change, it will keep adding the totals incorrectly showing very high values. I understand why its adding the totals incorrectly (dateTotal[event.startdate] + +event.totalhrs) but I am hoping someone can help direct me in the right direction to accomplish the correct result.
Appreciate any feedback/help.
I figured out an alternative way to make this work without an Array of dates holding the sum for each day. I hope this helps anyone that has been searching as long as I have.
Keep in mind, this example is only for the month view... there's a few tweaks to make it work for week/day view.
Also, the event must have a total hours object which is used to sum the total. You will see this below as event.totalhrs
viewRender: function(view, element) {
$.each($(".fc-day-top"), function(key, val) {
var dateYMD = $(this).attr("data-date");
$(this).append("<div class='fc-dailytotal' id='dailytotal-"+dateYMD+"'></div>");
});
},
eventRender: function(event, element, view) {
$(".fc-dailytotal").text(0); //Clear total sum
},
eventAfterRender: function(event, element, view) {
var currentday = moment(event.start).format("YYYY-MM-DD");
if (event.totalhrs > 0) {
var prev = $("#dailytotal-"+currentday).text() || 0;
$("#dailytotal-"+currentday).text(+prev + +event.totalhrs);
}
}
You can use this method to calculate a weekly total as well.
Here's the same solution for fullcalendar v5:
datesSet: function(dateInfo) {
$.each($(".fc-col-header-cell.fc-day"), function(key, val) {
var dateYMD = $(this).attr("data-date");
$(this).append("<div class='fc-dailytotal' id='dailytotal-" + dateYMD + "'></div>");
});
$(".fc-dailytotal").html(0);
},
eventDidMount: function(info) {
var currentday = moment(info.event.start).format("YYYY-MM-DD");
if (info.event._def.extendedProps.totalhrs > 0) {
var prev = parseInt($("#dailytotal-" + currentday).html()) || 0;
$("#dailytotal-" + currentday).html(prev + info.event._def.extendedProps.totalhrs);
console.log(info.event._def.extendedProps.totalhrs);
}
},
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/
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
Here's what should happen.
1. Get the rel attribute of the clicked link
2. For every div with class 'entry':
(i)Get its 'left' position
(ii) Calculate its outer height
(iii)Loop through all instances of 'a.tag_filter'. If it finds the same string in the 'rel' as the one oringinally clicked on then add 1 to 'V' and break out of the loop.
(iv)If 'V' is equal to 0 after the loop we know the same tag isn't present within that '.entry' so fade it out.
(v)Once the fadeout has finished loop through all the '.entry' after the faded out one and get their 'left' values.
(vi)If the left value of the faded entry = the left value of the current '.entry' then reposition it to the new 'top' value.
What is currently happening.
It runs through and fades out all the correct '.entry' elements and only after all of them have faded out does it reposition them remaining '.entry' elements.
After each element is faded out I would like the repositioning loop to run so it essentially positions the remaining elements one at a time rather than all at once.
Heres my code EDIT:
$('a.tag_filter').click(function(e){
e.preventDefault();
var selectTag = $(this).attr('rel');
$('div.spotlight_entry_container_grid').each(function(i){
var $entry = $(this);
var tagArray = [];
$('a.tag_filter', this).each(function(){
tagArray.push ($(this).attr('rel'));
});
if($.inArray(selectTag,tagArray) == -1){
var leftPos = $entry.css("left");
var topPos = $entry.css("top");
$entry.fadeOut(1000, function(){
var nextLeftPos;
var nextTopPos;
$('div.spotlight_entry_container_grid:gt('+i+')').each(function(j) {
var $laterEntry = $(this);
nextLeftPos = $laterEntry.css("left");
nextTopPos = $laterEntry.css("top");
//we need to keep the entries in their columns.
//matching left values will do it. No need to animate left values.
if(leftPos == nextLeftPos){
$laterEntry.animate({ top: topPos});
}
});
});
}
});
});
Hopefully that makes sense
Any help would be appreciated!
I'm probably doing something crazy but I just can't spot it.
Thanks
in here
$('a.tag_filter', this).each(function(){
var curTag = $(this).attr('rel');
if(curTag == selectTag){
v++;
return false;
}
});
returning false inside of $().each() breaks the looping through each element in the wrapped set.
From the documentation
Returning 'false' from within the each
function completely stops the loop
through all of the elements (this is
like using a 'break' with a normal
loop). Returning 'true' from within
the loop skips to the next iteration
(this is like using a 'continue' with
a normal loop).
Also, I would recommend caching $(this) inside of each each() in a local variable for performance instead of referencing it several times.
EDIT:
After looking at the code further, I think the following should do it
$('a.tag_filter').click(function(e){
// prevent the default anchor behaviour
e.preventDefault();
var selectTag = $(this).attr('rel');
$('div.entry').each(function(i){
var $entry = $(this);
// get an array of the anchor tag rel attributes
var tagArray = [];
$('a.tag_filter', this).each(function() {
tagArray.push ($(this).attr('rel'));
});
// if we can't find the selected tag in the entries tags
if ($.inArray(selectTag,tagArray) == -1) {
var leftPos = $entry.css("left");
var topPos = $entry.css("top");
$entry.fadeOut(1000, function(){
var nextLeftPos;
var nextTopPos;
$('div.entry:gt('+i+')').each(function(j) {
var $laterEntry = $(this);
nextLeftPos = $laterEntry.css("left");
nextTopPos = $laterEntry.css("top");
// for the first element, set top and left to the faded out element values
if (j == 0) {
$laterEntry.animate({ top: topPos, left: leftPos });
}
// for later elements in the loop, ste the values to the previous element values
else {
$laterEntry.animate({ top: nextTopPos, left: nextLeftPos });
}
});
});
}
});
});
You don't need to cache $(this), jQuery auto caches the this selector for function callbacks.