I using the FullCalendar and i would like display the count of events per day in all views for each days.
Example :
<div class="fc-day-number">1</div>
Change to :
<div class="fc-day-count">X</div>
<div class="fc-day-number">1</div>
Please find a screenshoot as example:
link
Thanks in advance
I hope this helps someone but don't know if it's the exact answer you're looking for.
To get the number of events that occur on a day you can use the following code:
$('#calendar').fullCalendar( 'clientEvents', function(eventObj){
if (eventObj.start.isSame('2014-11-21')) {
return true;
} else {
return false;
}
}).length;
As per fullcalendar documentation you can search for events with a filter function clientEvents.
The if statement in the function compares dates using moment.js which is included in fullcalendar 2.0
Sample in Month View EventsPerDay variable gives count
eventRender: function (event, element, view) {
$(element).each(function () { $(this).addClass('dateClass-' + event.start.getDate().toString()); $(this).attr('date-num', event.start.getDate().toString()); });
if (view.name == "month") {
// $('.shifts,.tasks,.shiftOut,.shiftIn').hide();
var CellDates = [];
var EventDates = [];
var EventCount = 0, i = 0;
$('.fc-view-month').find('.fc-day-number').each(function () {
CellDates[i] = $(this).text();
// alert( $(this).text());
i++;
});
for (j = 0; j < CellDates.length; j++) {
EventsPerDay = $(".fc-view-month>div>.dateClass-" + CellDates[j]).length;}}
I added a line to fullcalendar.js in the method named
function fetchEventSource(source, fetchID):
function fetchEventSource(source, fetchID) {
_fetchEventSource(source, function(events) {
if (fetchID == currentFetchID) {
if (events) {
if (options.eventDataTransform) {
events = $.map(events, options.eventDataTransform);
}
if (source.eventDataTransform) {
events = $.map(events, source.eventDataTransform);
}
// TODO: this technique is not ideal for static array event sources.
// For arrays, we'll want to process all events right in the beginning, then never again.
for (var i=0; i<events.length; i++) {
events[i].source = source;
normalizeEvent(events[i]);
}
cache = cache.concat(events);
}
pendingSourceCnt--;
if (!pendingSourceCnt) {
reportEvents(cache);
}
}
// add this next line here to dump the running count
$("#someElement").html("There are " + cache.length + " events scheduled for this view");
});
}
This has the net effect of leveraging what fullcalendar is already doing. You can then save yourself the extra network call on the database.
Related
Am getting key Combination from the server. Based on that am assigning key Combination to function dynamically. The below code is working for last iteration in loop. how below code is work for all iterations.
In my page i have two buttons save and cancel the below code is working for last iteration in for loop, It means btnCanel button triggers if i press key for save function.Any suggestions. hope understand my question.
$(document).ready(function fn() {
var keyCombination = new Object();
keyCombination['btnAdd'] = "Alt+S";
keyCombination['btnCancel'] = "Alt+C";
for (var k in keyCombination) {
if (keyCombination.hasOwnProperty(k)) {
shortcut.add(String(keyCombination[k]), function () {
var btnAdd = document.getElementById(String(k));
btnAdd.focus();
btnAdd.click();
});
}
}
});
if i give like this means it is working
shortcut.add("Alt+S", function () {
var btnAdd = document.getElementById('btnAdd ');
btnAdd .focus();
btnAdd .click();
});
shortcut.add("Alt+C", function () {
var btnCancel = document.getElementById('btnCancel');
btnCancel.focus();
btnCancel.click();
});
but if i try to add dynamically its overriding help me this issue.
Thanks in Advance.
I created a separate function outside the document.ready function like this now its working fine.
$(document).ready(function fn() {
var keyCombination = new Object();
keyCombination['btnAdd'] = "Alt+S";
keyCombination['btnCancel'] = "Alt+C";
for (var k in keyCombination) {
if (keyCombination.hasOwnProperty(k)) {
Set_KeyCombinations(k, keyCombination);
}
}
});
function Set_KeyCombinations(k, keyCombination) {
shortcut.add(String(keyCombination[k]), function () {
var eleId = document.getElementById(String(k));
if (eleId) {
if ($('#' + String(k).trim()).css('display') !== 'none' && eleId.getAttribute("disabled") !== "disabled") {
eleId.click();
eleId.focus();
}
}
});
}
Try this:
var keyCombinations = [ "Ctrl+Shift+X" , "Ctrl+Shift+Y" ];
for(var i=0; i<keyCombinations.length; i++){
(function(shorcutCombination){
shortcut.add(shorcutCombination,function() {
alert("i am " + shorcutCombination);
});
})(keyCombinations[i]);
}
The idea is that you need to preserve the value of keyCombinations[i]
as i increases in the loop. Tested this here: Openjs
I'm using the jquery plugin called shapeshift. It's like jqueryui sortable but with better animations. The divs can be dragged and dropped. But I can't seem to figure out how to save their order so that on browser refesh the order remains the same where I left them.
Here is the jsfiddle http://jsfiddle.net/Shikhar_Srivastava/aC367/
$(".container").shapeshift({minColumns: 3});
I'm initiating the plugin as above.
Please help me on my fiddle.
Thanks.
I would create a cookie. So I would first include the jQuery Cookie script (found here: https://github.com/carhartl/jquery-cookie/blob/master/src/jquery.cookie.js), then create the cookies (one for each each .container) each time an element is moved:
/* save cookie */
$('.container').on("ss-drop-complete", function() {
var containerCookieCounter = 0;
$('.container').each(function() {
/* cookie = 12h */
var date = new Date();
date.setTime(date.getTime() + (720 * 60 * 1000));
$.cookie('savepositions' + containerCookieCounter, $(this).html(), { expires: date, path: '/' });
containerCookieCounter += 1;
});
});
Then, before initiating the shapeshift-function, check if there are existing cookies:
/* cookies... */
if ($.cookie('savepositions0')) {
var containerCounter = 0;
$('.container').each(function() {
$(this).html($.cookie('savepositions' + containerCounter));
containerCounter += 1;
});
}
Here is a working fiddle: http://jsfiddle.net/Niffler/FvUcQ/
Only one container
Fiddle
var $con=$(".container").shapeshift({
minColumns: 3
});
function getPos(id){
var p=localStorage[id];
var ro={left:100000,top:-1,unknown:true};
if(p!==undefined) ro=JSON.parse(p);
//alert('get Pos:'+id+' '+JSON.stringify(ro));
return ro;
}
function setPos(id,p){
//alert('set Pos:'+id+' '+JSON.stringify(p));
localStorage[id]=JSON.stringify(p);
}
function arrange(){
var o={};
var con=$(".container:nth-child(1)");
var els=$(".container:nth-child(1) div");
els.each(function(x){
var me=$(this);
var id=me.attr('id');
var o_=o[id]={};
o_.id=me.attr('id');
o_.p=getPos(id);
});
for(var i in o){
var oo=o[i];
var el=$('#'+oo.id);
if(!oo.unknown){
el.css('left',''+oo.p.left+'px');
}
}
}
function savePs(){
var els=$(".container:nth-child(1) div");
els.each(function(){
var me=$(this);
setPos(me.attr('id'),me.position());
});
}
var $con=$(".container:nth-child(1)");
$con.on('ss-rearranged',function(e,selected){
var id=$(selected);
setTimeout(function(){
//var me=$(selected);
savePs();
//setPos(me.attr('id'),me.position());
},500);
});
arrange();
//savePs();
Fiddle
As commenters have suggested, you need to use localStorage to store and retrieve the state, and save that state after the ss-drop-complete event.
Here is the entire JS I used in this updated jsFiddle:
$(function () {
// retrieve from localStorage if there is a saved state
var saved = localStorage.getItem('arrangement');
if (saved) {
populateArrangement($('.container').parent(), JSON.parse(saved));
}
$(".container").shapeshift({
minColumns: 3
}).on('ss-drop-complete', function () {
// get the new arrangement and serialise it to localStorage as a string
var rows = getArrangement();
localStorage.setItem('arrangement', JSON.stringify(rows));
});
// return the data needed to reconstruct the collections as an array of arrays
function getArrangement() {
var rows = [];
$('.container').each(function () {
var elementsInRow = [];
$(this).find('.ss-active-child').each(function () {
elementsInRow.push({
value: parseInt($(this).text(), 10),
colspan: $(this).data('ss-colspan') || 1
});
});
rows.push(elementsInRow);
});
return rows;
}
// use the arrangement to populate the DOM correctly
function populateArrangement(container, newArrangement) {
$(container).find('.container').remove();
$.each(newArrangement, function (index, row) {
var $container = $('<div class="container"></div>');
$container.appendTo(container);
$.each(row, function (index, element) {
var $div = $('<div></div>');
$div.text(element.value);
if (element.colspan > 1)
$div.attr('data-ss-colspan', element.colspan);
$container.append($div);
});
});
}
});
If you have some sort of server side code you can add the order to a hidden field on the ss-drop-complete function and then post this back to the server on post back. You can then just re-output the values back when the page re-renders and you can use this information in any server side code you need.
I've done something similar when working with jquery mobile and ASP.NET to save back to a database the order.
If not, the local storage option could be a good way to go.
I have three URLs that return different JSON responses (say user mobiles, addresses and emails) being populated from different beans.
url='/mobile.do?username=x&password=y'
url='/email.do?username=x&password=y'
url='/address.do?username=x&password=y'
For the following autocomplete plugin (fcbkcomplete):
<script type="text/javascript">
$(document).ready(function(){
$("#mySelect").fcbkcomplete({
json_url: "?!!",
});
});
</script>
Now I want to use these URLs to populate and add data to a single field rather than three different fields. Hence, somehow I need to mix these URL or something like this.
I was wondering what is the best way for this? Can we set more than one URLs or something?
You could modify the plugin, by changing the function load_feed. This isn't tested, so might need some tweeking.
function load_feed(etext) {
counter = 0;
if (options.json_url_list && maxItems()) {
if (options.cache && json_cache_object.get(etext)) {
addMembers(etext);
bindEvents();
} else {
getBoxTimeout++;
var getBoxTimeoutValue = getBoxTimeout;
setTimeout(function () {
if (getBoxTimeoutValue != getBoxTimeout) return;
var count = 0;
var all_data = [];
var finished = function () {
if (!isactive) return; // prevents opening the selection again after the focus is already off
json_cache_object.set(etext, 1);
bindEvents();
};
for (var i = 0; i < options.json_url_list.length; i++) {
$.getJSON(options.json_url_list[i], {
"tag": xssDisplay(etext)
}, function (data) {
addMembers(etext, data);
count += 1;
if (count === options.json_url_list.length) finished();
});
}
}, options.delay);
}
} else {
addMembers(etext);
bindEvents();
}
}
Can anyone tell me why this might not work
Drupal.behaviors.toggleGroups = {
attach:function(context, settings) {
for (var i = 1; i < 8; i++) {
$('#edit-group-' + i.toString() + '-toggle').unbind('click').click(function(i) {
$('#category-' + i.toString()).slideToggle();
});
}
}
};
But this ugly thing works just fine
Drupal.behaviors.toggleGroups = {
attach:function(context, settings) {
$('#edit-group-1-toggle').unbind('click').click(function() {
$('#category-1').slideToggle();
});
$('#edit-group-2-toggle').unbind('click').click(function() {
$('#category-2').slideToggle();
});
$('#edit-group-3-toggle').unbind('click').click(function() {
$('#category-3').slideToggle();
});
$('#edit-group-4-toggle').unbind('click').click(function() {
$('#category-4').slideToggle();
});
$('#edit-group-5-toggle').unbind('click').click(function() {
$('#category-5').slideToggle();
});
$('#edit-group-6-toggle').unbind('click').click(function() {
$('#category-6').slideToggle();
});
$('#edit-group-7-toggle').unbind('click').click(function() {
$('#category-7').slideToggle();
});
}
};
Ideally I'd like to do something like "while selector returns result do something" - the problem is that I need the incremented number, and each click will toggle a separate div. It possible I'm just thinking about it all wrong, but regardless, I can't figure out why what I have isn't valid...
And while your at it, any advise on the jQuery once() method so I don't have to unbind/bind the click handler would also be appreciated...
THANK YOU!
Classic closure issue..
Try this
Drupal.behaviors.toggleGroups = {
attach:function(context, settings) {
for (var i = 1; i < 8; i++) {
(function(num){
$('#edit-group-' + num + '-toggle')
.unbind('click').click(function(num) {
$('#category-' + num).slideToggle();
});
})(i)
}
}
};
By the time the functions are assigned the variable i shares the same memory location.
SO it will always point to the last instance of i
This is a common case of "iditis". If you use two common classes everything will be much easier to manipulate. Remove ids and add classes, edit-group-toggle and category, then you can grab their corresponding targets by index:
attach: function( context, settings ) {
$('.edit-group-toggle').click(function() {
$('.category').eq( $(this).index() ).slideToggle();
});
}
I have some jQuery plugin that changes some elements, i need some event or jQuery plugin that trigger an event when some text input value changed.
I've downloaded jquery.textchange plugin, it is a good plugin but doesn't detect changes via external source.
#MSS -- Alright, this is a kludge but it works:
When I call boxWatcher() I set the value to 3,000 but you'd need to do it much more often, like maybe 100 or 300.
http://jsfiddle.net/N9zBA/8/
var theOldContent = $('#theID').val().trim();
var theNewContent = "";
function boxWatcher(milSecondsBetweenChecks) {
var theLoop = setInterval(function() {
theNewContent = $('#theID').val().trim();
if (theOldContent == theNewContent) {
return; //no change
}
clearInterval(theLoop);//stop looping
handleContentChange();
}, milSecondsBetweenChecks);
};
function handleContentChange() {
alert('content has changed');
//restart boxWatcher
theOldContent = theNewContent;//reset theOldContent
boxWatcher(3000);//3000 is about 3 seconds
}
function buttonClick() {
$('#theID').value = 'asd;lfikjasd;fkj';
}
$(document).ready(function() {
boxWatcher(3000);
})
try to set the old value into a global variable then fire onkeypress event on your text input and compare between old and new values of it. some thing like that
var oldvlaue = $('#myInput').val();
$('#myInput').keyup(function(){
if(oldvlaue!=$('#myInput').val().trim())
{
alert('text has been changed');
}
});
you test this example here
Edit
try to add an EventListner to your text input, I don't know more about it but you can check this Post it may help
Thanks to #Darin because of his/her solution I've marked as the answer, but i have made some small jQuery plugin to achieve the same work named 'txtChgMon'.
(function ($) {
$.fn.txtChgMon = function (func) {
var res = this.each(function () {
txts[0] = { t: this, f: func, oldT: $(this).val(), newT: '' };
});
if (!watchStarted) {
boxWatcher(200);
}
return res;
};
})(jQuery);
var txts = [];
var watchStarted = false;
function boxWatcher(milSecondsBetweenChecks) {
watchStarted = true;
var theLoop = setInterval(function () {
for (var i = 0; i < txts.length; i++) {
txts[i].newT = $(txts[i].t).val();
if (txts[i].newT == txts[i].oldT) {
return; //no change
}
clearInterval(theLoop); //stop looping
txts[i].f(txts[i], txts[i].oldT, txts[i].newT);
txts[i].oldT = $(txts[i].t).val();
boxWatcher(milSecondsBetweenChecks);
return;
}
}, milSecondsBetweenChecks);
}