HEAVILY EDITED:
I have a form which has this input field:
<input id="RR_No" type="text" size="15" name="RR_No" readonly></div></TD>
In that field, I need to put the date in the format:
DDMMYYYY
And a Serial Number that is 6 numbers long to make a number like this:
DDMMYYYYABCDEF
Here is the Javascript to make the date:
function autoDate () {
var tDay = new Date();
var tMonth = tDay.getMonth()+1;
var tDate = tDay.getDate();
if ( tMonth < 10) tMonth = "0"+tMonth;
if ( tDate < 10) tDate = "0"+tDate;
document.getElementById("RR_Date").value = tDate+"/"+tMonth+"/"+tDay.getFullYear();
document.getElementById("RR_No").value = tDate+""+tMonth+""+tDay.getFullYear();
}
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
addLoadEvent(function() {
autoDate();
});
Which works.
I then have this JavaScript that copies the Serial Number into the same Input box:
$(function(){
$("#copyCheck").change(function() {
if ($("#copyCheck:checked").length > 0) {
bindGroups();
} else {
unbindGroups();
}
});
});
var bindGroups = function() {
// First copy values
$("input[name='RR_No']").val($("input[name='S_Serial_No']").val());
// Then bind fields
$("input[name='S_Serial_No']").keyup(function() {
$("input[name='RR_S_No']").val($(this).val());
});
};
var unbindGroups = function() {
$("input[name='SN_No0']").unbind("keyup");
};
But this second code overwrites the date already in the Input box.
I need it to show beside the Date within the same Input box.
Hope this makes more sense.
Chris
When you concatenate these two fields into a new 3rd field, you need to add the values together...
$("input[name='ID_field']").val($("input[name='Date_field']").val() + $("input[name='Other-value_field']").val());
If the date is being generated dynamically...
var d = new Date();
$("input[name='ID_field']").val(d.getTime() + $("input[name='Other-value_field']").val());
Related
I took this code from internet to modify, to practice JS, though I fail to call the function when the input length is equal 0. So basically I click on the "Add a column" and it opens the console to give the name of the column you want to make, though when the input length as I said is equal to 0, it raises and alert, but it doesn't ask again for the input (I don't know how to call the function so the input console will show up again).
Down below you have the JS code, for the whole code (html, css, js) click here.
function Column(name) {
if (name.length > 0) {
var self = this; // useful for nested functions
this.id = randomString();
this.name = name;
this.$element = createColumn();
function createColumn() {
var $column = $("<div>").addClass("column");
var $columnTitle = $("<h2>")
.addClass("column-title")
.text(self.name);
var $columnCardList = $("<ul>").addClass("column-card-list");
var $columnDelete = $("<button>")
.addClass("btn-delete")
.text("x");
var $columnAddCard = $("<button>")
.addClass("add-card")
.text("Add a card");
$columnDelete.click(function() {
self.removeColumn();
});
$columnAddCard.click(function(event) {
self.addCard(new Card(prompt("Enter the name of the card")));
});
$column
.append($columnTitle)
.append($columnDelete)
.append($columnAddCard)
.append($columnCardList);
return $column;
}
} else if (name.length == 0) {
alert("please type something");
} else {
return;
}
}
Column.prototype = {
addCard: function(card) {
this.$element.children("ul").append(card.$element);
},
removeColumn: function() {
this.$element.remove();
}
};
function Card(description) {
var self = this;
this.id = randomString();
this.description = description;
this.$element = createCard();
function createCard() {
var $card = $("<li>").addClass("card");
var $cardDescription = $("<p>")
.addClass("card-description")
.text(self.description);
var $cardDelete = $("<button>")
.addClass("btn-delete")
.text("x");
$cardDelete.click(function() {
self.removeCard();
});
$card.append($cardDelete).append($cardDescription);
return $card;
}
}
Card.prototype = {
removeCard: function() {
this.$element.remove();
}
};
var board = {
name: "Kanban Board",
addColumn: function(column) {
this.$element.append(column.$element);
initSortable();
},
$element: $("#board .column-container")
};
function initSortable() {
$(".column-card-list")
.sortable({
connectWith: ".column-card-list",
placeholder: "card-placeholder"
})
.disableSelection();
}
$(".create-column").click(function() {
var name = prompt("Enter a column name");
var column = new Column(name);
board.addColumn(column);
});
// ADDING CARDS TO COLUMNS
todoColumn.addCard(card1);
doingColumn.addCard(card2);
});
After the line:
alert("please type something");
Add the following:
$(".create-column").click();
That programmatically "clicks" the Create Column button.
If you want to prompt the user to enter column name if length is 0, just add this lines of code to your if-stament:
var name = prompt("Enter a column name");
var column = new Column(name);
board.addColumn(column);.
As shown below:
else if (name.length == 0) {
alert("please type something");
var name = prompt("Enter a column name");
var column = new Column(name);
board.addColumn(column);
} else {
return;
}
If that was your question, this should be able to fix it.
I would like to add the condition, that the function is only triggered if both
addEventListener('change', SwitchG) Events are True (=both have changed).
The code which I use currently activates the function already when one of the two has changed.
var hallo = document.getElementById("S131_01");
var hallo1 = document.getElementById("S130_01");
hallo.addEventListener('change', SwitchG);
hallo1.addEventListener('change', SwitchG);
function SwitchG () {
var test1 = document.getElementById("submit");
test1.classList.add("css");
}
You need another variable, which checks if both have been changed and only executes the handler function if both changes already happened:
var hallo = document.getElementById("S131_01");
var hallo1 = document.getElementById("S130_01");
var countChanges = 0; // <-- this tracks changes
hallo.addEventListener('change', SwitchG);
hallo1.addEventListener('change', SwitchG);
function SwitchG () {
countChanges += 1; // <-- count up
if (countChanges >= 2) {
countChanges = 0; // <-- reset (if needed)
var test1 = document.getElementById("submit");
test1.classList.add("css");
}
}
A more robust implementation however, also tracks the elements which changed and ensures a repeating change event from a single element won't succeed to run the handler.
For example with this utility:
function ChangedCounter (minChanges) {
var elements = new Set();
return {
changed(element) {
elements.add(element);
},
clear() {
elements.clear();
},
isReady() {
return elements.size >= minChanges;
}
};
}
You'd write it like this:
var hallo = document.getElementById("S131_01");
var hallo1 = document.getElementById("S130_01");
var countChanges = ChangedCounter(2);
hallo.addEventListener('change', SwitchG);
hallo1.addEventListener('change', SwitchG);
function SwitchG (e) {
countChanges.changed(e.target);
if (countChanges.isReady()) {
countChanges.clear();
var test1 = document.getElementById("submit");
test1.classList.add("css");
}
}
You could create a "state" to store when the both has changed. I've created two variables, halloState and hallo1State. The snippet below shows how it could be done:
var hallo = document.getElementById("S131_01");
var hallo1 = document.getElementById("S130_01");
var halloState = false;
var hallo1State = false;
hallo.addEventListener('change', SwitchG);
hallo1.addEventListener('change', SwitchG);
function SwitchG (e) {
if(e.target.id === "S131_01") halloState = true;
else if(e.target.id === "S130_01") hallo1State = true;
if(halloState && hallo1State){
var test1 = document.getElementById("submit");
test1.classList.add("css");
}
}
.css {
background-color:red;
}
<input id="S131_01" type="text"/>
<input id="S130_01" type="text"/>
<button id="submit">Submit</button>
When using The Final Countdown jQuery timer, it's easy to make a timezone aware timer based on one of the examples they provide. But now I want to use multiple instances on one page and don't know how. The code they provide for using multiple instances is this:
HTML:
<div data-countdown="2016/01/01"></div>
<div data-countdown="2017/01/01"></div>
<div data-countdown="2018/01/01"></div>
<div data-countdown="2019/01/01"></div>
JS:
$('[data-countdown]').each(function() {
var $this = $(this), finalDate = $(this).data('countdown');
$this.countdown(finalDate, function(event) {
$this.html(event.strftime('%D days %H:%M:%S'));
});
});
Doesn't look to difficult but when trying to implement it into my code it just doesn't work. As you can see in my code it also uses a different format of showing the time. Can anyone show me the correct way to do it with an explanation? This is my code:
$(window).on('load', function () { "use strict";
var labels = ['weeks', 'days', 'hours', 'minutes', 'seconds'],
nextYear = moment.tz("2017-05-03 17:00", "America/Los_Angeles"),
template = _.template($('#main-countdown-template').html()),
currDate = '00:00:00:00:00',
nextDate = '00:00:00:00:00',
parser = /([0-9]{2})/gi,
$countdown = $('#main-countdown');
function strfobj(str) {
var parsed = str.match(parser),
obj = {};
labels.forEach(function (label, i) {
obj[label] = parsed[i];
});
return obj;
}
function diff(obj1, obj2) {
var diff = [];
labels.forEach(function (key) {
if (obj1[key] !== obj2[key]) {
diff.push(key);
}
});
return diff;
}
var initData = strfobj(currDate);
labels.forEach(function (label, i) {
$countdown.append(template({
curr: initData[label],
next: initData[label],
label: label
}));
});
$countdown.countdown(nextYear.toDate(), function (event) {
var newDate = event.strftime('%w:%d:%H:%M:%S'),
data;
if (newDate !== nextDate) {
currDate = nextDate;
nextDate = newDate;
data = {
'curr': strfobj(currDate),
'next': strfobj(nextDate)
};
diff(data.curr, data.next).forEach(function (label) {
var selector = '.%s'.replace(/%s/, label),
$node = $countdown.find(selector);
$node.removeClass('flip');
$node.find('.curr').text(data.curr[label]);
$node.find('.next').text(data.next[label]);
_.delay(function ($node) {
$node.addClass('flip');
}, 50, $node);
});
}
});
});
I have running script which moves the tr elements from one container to another on double click. But i have below mentioned issues:
1) If we do are very quick double-click on elements than it moves but its values doesn't come, it shows empty tags.
2) I want to change the background color on double click and it color should remove when we click outside or another elements.
<script>
$(function () {
function initTabelMgmt() {
selectInvitees();
moveSelectedInvitees();
deleteInvitees();
//scrollOpen();
}
var tmContainer = $("div.cv-tm-body");
var toggleAssignBtn = tmContainer.find('.cv-move-items button');
/*
function scrollOpen() {
var position = $('div.cv-item li.open').first().position();
var offsetTop = $('div.cv-tm-col-r .cv-helper-grid-overflow').scrollTop();
var unitHeight = $('div.cv-item li.open').first().height();
var containerHeight = $('div.cv-tm-col-r .cv-helper-grid-overflow').height();
var scrollAmount = offsetTop + position.top;
if ((offsetTop - position.top) <= 0 && (offsetTop - position.top) >= (-containerHeight + unitHeight)) {
//do nothing
} else {
$('div.cv-tm-col-r .cv-helper-grid-overflow').animate({
scrollTop: scrollAmount
});
}
};
*/
// scrollOpen end
function selectInvitees() {
//select items from invitee list
var startIndex, endIndex;
var dbclick = false;
tmContainer.find("table.cv-invitees").on('click', 'tr', function (e) {
var row = $(this);
setTimeout(function () {
//singleclick functionality start.
if (dbclick == false) {
if (!row.is('.assigned')) {
toggleAssignBtn.removeClass('is-disabled');
if (e.shiftKey) {
row.parents('.cv-invitees').find('tr').removeClass('selected');
endIndex = row.parents('.cv-invitees').find('tr').index(this);
var range = row.closest('table').find('tr').slice(Math.min(startIndex, endIndex), Math.max(startIndex, endIndex) + 1).not('.assigned');
range.addClass('selected');
} else if (e.ctrlKey) {
startIndex = row.parents('.cv-invitees').find('tr').index(this);
row.toggleClass('selected');
} else {
startIndex = row.parents('.cv-invitees').find('tr').index(this);
row.parents('.cv-invitees').find('tr').not(this).removeClass('selected');
row.toggleClass('selected');
}
}
}
}, 200)
})
.dblclick(function () {
dbclick = true
//doubleclick functionality start.
toggleAssignBtn.addClass('is-disabled');
function moveSelectedInviteesDBClick() {
var row = tmContainer.find("table.cv-invitees tr.selected");
if (!row.is('.assigned')) {
var allOpenSeat = $('.cv-item .open');
var numberOpen = allOpenSeat.length;
var name = row.find("td").eq(0).text();;
var company = row.find("td").eq(1).text();
var addedInvitees = [];
allOpenSeat.each(function (index) {
if (index < 1) {
var openSeat = $(this);
openSeat.find('.name').text(name);
if (company != '') {
openSeat.find('.company').addClass('show').text(company);
}
var seatAssignment = new Object();
seatAssignment.company = "";
addedInvitees.push(seatAssignment);
openSeat.removeClass('open');
}
row.remove();
});
}
} // moveSelectedInviteesDBClick
moveSelectedInviteesDBClick();
setTimeout(function () {
dbclick = false
}, 300)
});
} // selectInvitees end
function moveSelectedInvitees() {
//move invitees from left to right
tmContainer.find('button.cvf-moveright').click(function () {
var selectedItem = $('.cv-invitees .selected');
var allOpenSeat = $('.cv-item .open');
var numberSelected = selectedItem.length;
var numberOpen = allOpenSeat.length;
var errorMsg = tmContainer.prev('.cv-alert-error');
if (numberSelected > numberOpen) {
errorMsg.removeClass('is-hidden');
} else {
var name;
var company;
var invitee = [];
var selectedInvitees = [];
var count = 0;
selectedItem.each(function () {
var $this = $(this);
name = $this.find("td").eq(0).text();
company = $this.find("td").eq(1).text();
invitee = [name, company];
selectedInvitees.push(invitee);
count = count + 1;
i = 0;
$this.remove();
});
var addedInvitees = [];
var items = $('div.cv-item li');
var seatItems = $('div.cv-order li');
allOpenSeat.each(function (index) {
if (index < count) {
var openSeat = $(this);
openSeat.find('.name').text(selectedInvitees[index][0]);
if (selectedInvitees[index][1] != '') {
openSeat.find('.company').addClass('show').text(selectedInvitees[index][1]);
}
var seatAssignment = new Object();
seatAssignment.company = "";
addedInvitees.push(seatAssignment);
//selectedInvitees.shift();
openSeat.removeClass('open');
}
});
selectedInvitees = [];
}
toggleAssignBtn.addClass('is-disabled');
});
} // moveSelectedInvitees end
function deleteInvitees() {
//move invitees from left to right
tmContainer.find('div.cv-tm-col-r .cv-icon-remove').click(function () {
//delete seat assignment
var icon = $(this);
var idx = $('.ui-sortable li').index(icon.parent());
icon.parent().fadeTo(0, 0).addClass('open').find('.name').text('Open').end().fadeTo(750, 1);
icon.parent().find('.company').removeClass('show').text('');
// icon.parent().find('.entitystub').text('00000000-0000-0000-0000-000000000000');
// icon.parent().find('.entitytype').text('0');
// icon.parent().find('.pipe').remove();
// icon.hide();
// var testSeat = $('.seat-numbers li').get(idx);
//var seatStub = j$.trim(j$(testSeat).find('.seatstub').text());
//var input = { 'seatStub': seatStub };
//AssignSeats(input, "/Subscribers/WS/SeatAssignmentService.asmx/DeleteRegistrant");
});
}
initTabelMgmt();
}); // document.ready end
</script>
Your code looks pretty nice. You should also use in order to register from jQuery a single click event the native method .click(...). So please change the following line
tmContainer.find("table.cv-invitees").on('click', 'tr', function (e) {
To:
tmContainer.find("table.cv-invitees").click(function (e) {
and everything should work fine. For some strange reasons the function
$("#someelement").on("click", ...);
does not work always, only sometimes. JQuery officially recommends you to use the native functions for predefined events (such as onclick, onkeyup, onchange etc.) because of this strange behavior.
Edit:
If dblick does not work now, then make 2 lines please, like this:
tmContainer.find("table.cv-invitees").click(function (e) {
// [...]
;
tmContainer.find("table.cv-invitees").dbclick(function (e) {
// [...]
Edit2:
If it does not work, too, then please remove the single click event listener when you are in the .click() closure. Because if this happens, jQuery´s behavior is to treat it always as a single click. So, in other words dblick() will never be triggered, because .click() will always happens before. And then jQuery won´t count up to 2 fast clicks. Expect the unexpected^^
Edit3: This is the full code, which should hopefully work now as it is:
$(function ()
{
function initTabelMgmt()
{
selectInvitees();
moveSelectedInvitees();
deleteInvitees();
//scrollOpen();
}
var tmContainer = $("div.cv-tm-body");
var toggleAssignBtn = tmContainer.find('.cv-move-items button');
var iClickCounter = 0;
var dtFirstClick, dtSecondClick;
/*
function scrollOpen() {
var position = $('div.cv-item li.open').first().position();
var offsetTop = $('div.cv-tm-col-r .cv-helper-grid-overflow').scrollTop();
var unitHeight = $('div.cv-item li.open').first().height();
var containerHeight = $('div.cv-tm-col-r .cv-helper-grid-overflow').height();
var scrollAmount = offsetTop + position.top;
if ((offsetTop - position.top) <= 0 && (offsetTop - position.top) >= (-containerHeight + unitHeight)) {
//do nothing
} else {
$('div.cv-tm-col-r .cv-helper-grid-overflow').animate({
scrollTop: scrollAmount
});
}
};
*/
// scrollOpen end
function selectInvitees()
{
//select items from invitee list
var startIndex, endIndex;
var dbclick = false;
tmContainer.find("table.cv-invitees").click(function(e)
{
iClickCounter++;
if (iClickCounter === 1)
{
dtFirstClick = new Date();
var row = $(this);
window.setTimeout(function ()
{
//singleclick functionality start.
if (dbclick == false)
{
if (!row.is('.assigned'))
{
toggleAssignBtn.removeClass('is-disabled');
if (e.shiftKey)
{
row.parents('.cv-invitees').find('tr').removeClass('selected');
endIndex = row.parents('.cv-invitees').find('tr').index(this);
var range = row.closest('table').find('tr').slice(Math.min(startIndex, endIndex), Math.max(startIndex, endIndex) + 1).not('.assigned');
range.addClass('selected');
}
else if (e.ctrlKey)
{
startIndex = row.parents('.cv-invitees').find('tr').index(this);
row.toggleClass('selected');
}
else
{
startIndex = row.parents('.cv-invitees').find('tr').index(this);
row.parents('.cv-invitees').find('tr').not(this).removeClass('selected');
row.toggleClass('selected');
}
}
}
},
200);
}
else if (iClickCounter === 2)
{
dtSecondClick = new Date();
}
else if (iClickCounter === 3)
{
if (dtSecondClick.getTime() - dtFirstClick.getTime() < 1000)
{
return;
}
iClickCounter = 0;
dbclick = true
//doubleclick functionality start.
toggleAssignBtn.addClass('is-disabled');
function moveSelectedInviteesDBClick()
{
var row = tmContainer.find("table.cv-invitees tr.selected");
if (!row.is('.assigned'))
{
var allOpenSeat = $('.cv-item .open');
var numberOpen = allOpenSeat.length;
var name = row.find("td").eq(0).text();;
var company = row.find("td").eq(1).text();
var addedInvitees = [];
allOpenSeat.each(function (index)
{
if (index < 1)
{
var openSeat = $(this);
openSeat.find('.name').text(name);
if (company != '') {
openSeat.find('.company').addClass('show').text(company);
}
var seatAssignment = new Object();
seatAssignment.company = "";
addedInvitees.push(seatAssignment);
openSeat.removeClass('open');
}
row.remove();
}
);
}
}
// moveSelectedInviteesDBClick
moveSelectedInviteesDBClick();
window.setTimeout(function ()
{
dbclick = false
}, 300);
}
}
);
} // selectInvitees end
function moveSelectedInvitees()
{
//move invitees from left to right
tmContainer.find('button.cvf-moveright').click(function ()
{
var selectedItem = $('.cv-invitees .selected');
var allOpenSeat = $('.cv-item .open');
var numberSelected = selectedItem.length;
var numberOpen = allOpenSeat.length;
var errorMsg = tmContainer.prev('.cv-alert-error');
if (numberSelected > numberOpen) {
errorMsg.removeClass('is-hidden');
}
else
{
var name;
var company;
var invitee = [];
var selectedInvitees = [];
var count = 0;
selectedItem.each(function () {
var $this = $(this);
name = $this.find("td").eq(0).text();
company = $this.find("td").eq(1).text();
invitee = [name, company];
selectedInvitees.push(invitee);
count = count + 1;
i = 0;
$this.remove();
});
var addedInvitees = [];
var items = $('div.cv-item li');
var seatItems = $('div.cv-order li');
allOpenSeat.each(function (index)
{
if (index < count)
{
var openSeat = $(this);
openSeat.find('.name').text(selectedInvitees[index][0]);
if (selectedInvitees[index][1] != '')
{
openSeat.find('.company').addClass('show').text(selectedInvitees[index][1]);
}
var seatAssignment = new Object();
seatAssignment.company = "";
addedInvitees.push(seatAssignment);
//selectedInvitees.shift();
openSeat.removeClass('open');
}
}
);
selectedInvitees = [];
}
toggleAssignBtn.addClass('is-disabled');
}
);
} // moveSelectedInvitees end
function deleteInvitees()
{
//move invitees from left to right
tmContainer.find('div.cv-tm-col-r .cv-icon-remove').click(function ()
{
//delete seat assignment
var icon = $(this);
var idx = $('.ui-sortable li').index(icon.parent());
icon.parent().fadeTo(0, 0).addClass('open').find('.name').text('Open').end().fadeTo(750, 1);
icon.parent().find('.company').removeClass('show').text('');
// icon.parent().find('.entitystub').text('00000000-0000-0000-0000-000000000000');
// icon.parent().find('.entitytype').text('0');
// icon.parent().find('.pipe').remove();
// icon.hide();
// var testSeat = $('.seat-numbers li').get(idx);
//var seatStub = j$.trim(j$(testSeat).find('.seatstub').text());
//var input = { 'seatStub': seatStub };
//AssignSeats(input, "/Subscribers/WS/SeatAssignmentService.asmx/DeleteRegistrant");
}
);
}
initTabelMgmt();
}
); // document.ready end
I guess that you interpret in your special case a double click as 3 times clicked at the same table entry. And if a user do so and if the time difference between first and second click is longer than one second, a double click will be fired. I think should be the solution to deal with this special case.
Edit 4: Please test, if it is possible to click on 3 different table column and get also double click fired. I think this is an disadvantage on how my code handles the double click. So, you need to know from which table column you have already 1 to 3 clicks set. How can we do this? Basically, there are 3 possibilities to do this:
(HTML5 only:) Make data attribute on each tr and the value for this data attribute
should be the clicks already clicke on this tr.
Define a global object key/value pair object, which holds the
event-ID (but I don´t know how to get this back by jQuery driven
events) as the key and the amount of clicks already done as the
value. And then if you are on the next click, you can decide what is
to do now for this tr. This is my favorite alternative!
Last but not least: Only register the click event on every tr and
make for each click-registering an own global area, so that we just
avoid the actual problem. You can do this e. g. by making an JS
Object which hold a member variable as the iclickCounter and you
make a new object of this class, each time a new click event is
registered. But this alternative need a lot more code and is main-memory-hungry.
All of thes possible options need a wrap around your click event, e. g. a loop, that iterates over all tr elements in the given table. You did this already partially by calling the jQuery-function .find(..). This executes the closure on every found html element. So, in your case on all tr elements in the searched table. But what you need to do is to make the workaround of one of my options given above.
Hi I am having a problem where scoping seems to be lost. What I am doing wrong?
Suppose the logic is that 1 second is decreased from every counter and not from the last counter only.
What I am doing wrong?
<html>
<head>
<link rel="stylesheet" href="http://static.jquery.com/files/rocker/css/reset.css" type="text/css" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
(function($){
$.fn.extend({
countdown: function(options) {
var defaults = {
daysSelector : 'span.days',
hoursSelector : 'span.hours',
minutesSelector : 'span.minutes',
secondsSelector : 'span.seconds'
}
var options = $.extend(defaults, options);
var _this = $(this);
tick = function()
{
var days = _this.find(options.daysSelector);
var hours = _this.find(options.hoursSelector);
var minutes = _this.find(options.minutesSelector);
var seconds = _this.find(options.secondsSelector);
console.log(_this);
var currentSeconds=seconds.text();
currentSeconds--;
if(currentSeconds<0)
{
seconds.text("59");
var currentMinutes=minutes.text();
currentMinutes--;
if(currentMinutes<0)
{
(minutes).text("59");
var currentHours=(hours).text();
currentHours--;
if(currentHours<0)
{
(hours).text("23");
var currentDays=(hours).text();
currentDays--;
}
else
{
if(currentHours.toString().length==1)
{
(hours).text('0'+currentHours);
}
else
{
(hours).text(currentHours);
}
}
}
else
{
if(currentMinutes.toString().length==1)
{
(minutes).text('0'+currentMinutes);
}
else
{
(minutes).text(currentMinutes);
}
}
}
else
{
if(currentSeconds.toString().length==1)
{
seconds.text('0'+currentSeconds);
}
else
{
seconds.text(currentSeconds);
}
}
}
return this.each(function()
{
console.log(_this);
setInterval("this.tick()",1000);
});
}
});
})(jQuery);
$(document).ready(function()
{
$("#timer1").countdown();
$("#timer2").countdown();
$("#timer3").countdown();
});
</script>
</head>
<body>
<div id="timer1">
<span class="days">1</span>
<span class="hours">18</span>
<span class="minutes">6</span>
<span class="seconds">45</span>
</div>
<div id="timer2">
<span class="days">2</span>
<span class="hours">28</span>
<span class="minutes">1</span>
<span class="seconds">59</span>
</div>
<div id="timer3">
<span class="days">10</span>
<span class="hours">0</span>
<span class="minutes">59</span>
<span class="seconds">59</span>
</div>
</body>
I edited your code
(function($){
$.fn.extend({
countdown: function(options) {
var defaults = {
daysSelector : 'span.days',
hoursSelector : 'span.hours',
minutesSelector : 'span.minutes',
secondsSelector : 'span.seconds'
}
var options = $.extend(defaults, options);
var _this = $(this);
var tick = function()
{
var days = _this.find(options.daysSelector);
var hours = _this.find(options.hoursSelector);
var minutes = _this.find(options.minutesSelector);
var seconds = _this.find(options.secondsSelector);
console.log(_this);
var currentSeconds=seconds.text();
currentSeconds--;
if(currentSeconds<0)
{
seconds.text("59");
var currentMinutes=minutes.text();
currentMinutes--;
if(currentMinutes<0)
{
(minutes).text("59");
var currentHours=(hours).text();
currentHours--;
if(currentHours<0)
{
(hours).text("23");
var currentDays=(hours).text();
currentDays--;
}
else
{
if(currentHours.toString().length==1)
{
(hours).text('0'+currentHours);
}
else
{
(hours).text(currentHours);
}
}
}
else
{
if(currentMinutes.toString().length==1)
{
(minutes).text('0'+currentMinutes);
}
else
{
(minutes).text(currentMinutes);
}
}
}
else
{
if(currentSeconds.toString().length==1)
{
seconds.text('0'+currentSeconds);
}
else
{
seconds.text(currentSeconds);
}
}
}
return _this.each(function()
{
console.log(_this);
setInterval(tick,1000);
});
}
});
})(jQuery);
$(document).ready(function()
{
$("#timer1").countdown();
$("#timer2").countdown();
$("#timer3").countdown();
});
tick was global and that was the problem (also never pass code to be evalued to setInterval!
Fiddle here: http://jsfiddle.net/kvqWR/1/
If I have to guess what the issue is... only 1 timer actually counts down and the other two doesn't?
That's because the extended countdown timer function you have never passes the name (id) of the countdown timer through to the function. So it always only executes the last one since the last one is what was called...last.
You'd need to send through the name (id) of the div for it to count down all 3 simultaneously.
You declared tick in global scope. Make it local:
var tick = function()...
and don't pass a string to setInterval:
setInterval(tick,1000);
A better structure of your plugin would be to declare the tick function only once and pass the current element (or the time fields) as argument:
(function($){
var tick = function(days, hours, minutes, seconds) {
//...
};
$.fn.countdown = function(options) {
var defaults = {
daysSelector : 'span.days',
hoursSelector : 'span.hours',
minutesSelector : 'span.minutes',
secondsSelector : 'span.seconds'
}
var options = $.extend(defaults, options);
return this.each(function(){
var days = $(this).find(options.daysSelector);
var hours = $(this).find(options.hoursSelector);
var minutes = $(this).find(options.minutesSelector);
var seconds = $(this).find(options.secondsSelector);
setInterval(function() {
tick(days, hours, minutes, seconds);
},1000);
});
};
}(jQuery));
Then your plugin also works if you select multiple elements at once:
$("#timer1, #timer2, #timer3").countdown();
which would not work otherwise (see here http://jsfiddle.net/fkling/kvqWR/5/).
Working DEMO
It might also be better to have only setInterval going on which iterates over selected elements and performs the operation. The fewer timers you have, the better. Have a look at this example: http://jsfiddle.net/fkling/kvqWR/4/