Introduction
Scal is a simple, javascript calendar/date picker based on the Prototype js library.
script.aculo.us and scal
scriptaculous is a nifty effect library for javascript (and a whole lot more). Previous versions of scal required you to include scriptaculous when calling up the calendar. This dependency does not exist in v0.2. However, scal still supports scriptaculous Effects (see scal options for more information).
Supported Browsers
- Internet Explorer 6 & 7
- Firefox
- Safari
- Opera
Features
- Lightweight
- Fast and easy to setup
- Multiple Calendars can be initiated without conflict
- Valid HTML/XHTML generated code
- Skinnable
- Language translation supported
- Event Planner
How to Use
It's easy to use, just include the javascript and the css file.
<script type="text/javascript" src="/javascripts/prototype.js"> </script>
<script type="text/javascript" src="/javascripts/scal.js"> </script>
<link href="/styles/scal.css" rel="stylesheet" type="text/css"/>To create a calendar, just create an instance of scal with your base element and the update callback, along with optional parameters.
<div id="samplecal" class="scal"></div>
<div id="scalupdate"> </div>
var samplecal = new scal('samplecal', 'scalupdate');Test It
Project Team
Ian Tyndall - Lead Developer v0.2
Jamie Grove - Project Founder (and general layabout)
Special Thanks To
Andrew Reutter
Thomas Walpole
Kangax
DMenT
Links to Scal
New! jPint Scal is part of the stack for Journyx's web-based iPhone development kit. Thanks to Andrew Reutter!
Ajaxian Thanks, Dion!
script.aculo.us samplr Thanks, Leonardo!
Scripteka: Prototype Extensions Library Thanks, Scripteka Dudes!
del.icio.us popular links Thanks, well, everyone! :)
License
This open-source library is licensed under a MIT-style license, so you can use it for anything you like, as long as you include the copyright notice.
As members of an all-volunteer project, we encourage you to contribute any changes to the further development of the control and think about other code contributions you can make to the general open-source community.
Scal is available free of charge. Any donations received are dispersed to other projects in the open source community (see PayPal link below).
Bug found when changing months:Please see inside for description
showcal.setPlannerValue(2008,02,11,"Test",'rank_1');
showcal.setPlannerValue(2008,02,11,"Test 2",'rank_2');
With the code above, when changing a month and going back, it will apply both rank_1 and rank_2 classes to each event messing up the coloring scheme you may have applied on the classes.
Any idea about this?
planner class when changing months
Hmmm, that's kinda weird. It doesn't happen with the test planner. (see link below)
http://scal.fieldguidetoprogrammers.com/scal-v02-documentation/scal-plan...
Can you email me your code? I'll see if I can work out what's wrong.
- J
Re your reply
Jamie,
Thanks for getting back to me. On your test planner, there isn't a day that has multiple events with multiple classes, and this is when the bug happens. I didn't change anything in your js files.
I'll email you my js file.
multiple dates style bug confirmed
I used firebug to change the style manually and that worked. Of course, when I tested your code, I found the bug. Woo hoo!
It's kinda deep so I need to noodle through it. I should have a fix in a day or two.
Thanks for reporting it!
still testing code changes
just an update here... we have a fix and are testing the code changes.
multiple evets at one day
hi there!
my problem: i have more events at one day, that they shold be in different classes. example:
2008-02-04 : "my event"
2008-02-01 > 2008-02-14 : "conference"
will output only "conference" from 1st to 14th. i think this is problem with this one:
scalplanner.js : line 9 :
splanner[planDate] = { cls: planclass, val: plan.label };
this sets only one event at day, only thing that i could separate it, is via "multi-labels", but then all events at that day have same class.
you know what i mean? splanner array shold be multidimensional?
greetings, m.
fix in the works
We have a fix for this. Sorry for the delay. We're almost done testing.
multiple dates
You should be able make this work with the planner code as is. I've just tried it with the sampler and it is working.
Hi, can you post the actual code you are using to set the dates? I might be able to troubleshoot that for you.
- J
multiple events
hm, i submit comment, but nowhere exists, did u get it? (comment-37), just asking :)
m.
comment 37
m, akismet canned it. I approved it and now it lives again! :)
Integrating with iUI
In order to get this calendar working inside of the iUI platform for the iPhone I had to slightly modify prototype.js. On what is line 23 in my version where it sets the BrowserFeatures I had to set SpecificElementExtensions to false because the boolean statement where it checks the several document.createElement statements was throwing errors in MobileSafari. So now that section for me looks like this:
BrowserFeatures: {
XPath: !!document.evaluate,
ElementExtensions: !!window.HTMLElement,
SpecificElementExtensions: false
// document.createElement('div').__proto__ &&
// document.createElement('div').__proto__ !==
// document.createElement('form').__proto__
},
You can see in prototype that it already sets SpecificElementExtensions to false for MobileSafari several lines later so a better change might have been to code logic to not be specific to MobileSafari but for my app that's all I need.
Hope that helps anyone else trying this.
-David Ethell
iUI
Thanks, David. I'll pass this along to the prototype folks too.
Two calendars interacting
Hey is it possible to make two scal calendars on the same page interact? Lets say you would use it to make bookings. Then you would not want it to be possible to select and earlier date on the second calendar then whats selected on the first calendar.
calendar interaction
Sure. Just create two instances of scal and set each one use a different update function that works your magic. Logic below (though not a code sample). :)
function changecal1(d){
// d is the date scal sends on update
// write a bit of code here that:
// 1) makes sure that d is not greater
// the selecteddate in scal2
// 2) changes all of the styles on scal2
// days prior to d to some "inactive" color
};
function changecal2(d){
// same as above but with scal1
};
var scal1 = new scal('calendardiv', changecal2);
var scal2 = new scal('calendardiv', changecal1);
// the second parameter is updateelement
// and we pass a pointer to the functions above
Change month bug
Hi and thanks for an excellent calendar!
When selecting a date that does not exist in next month, for example 31 mars and then going forward to april it jumps to may. Since 31 april does not exist (only 30 days in april).
Is this simple to fix?
change month bug fixed
You're quite welcome!
Thanks for the great bug find!
This is now corrected. :)
Hit control refresh on this page to see the results in the test control above. To download the fix, just grab the ZIP archive again.
----
To those of you working off SVN, this correction is in the scaljsbranches/versions/v0.2 directory. I have also added the code change to the next release (which is sitting in the trunk now).
oncalchange..?
oncalchange is only firing when I change months, not when I click on a date, like you said below.
What's up?
My bad... oncalchange should be updateelement
I misread the question below and thus provided the wrong answer. Doh!
oncalchange does indeed fire only when the user hits the calendar controls for month/year advance. If you want to automatically close the calendar or push the date value into an element on the page, you need to supply a pointer to a function in the updateelement parameter when you create your scal instance:
function dostuffthenclosecalendar(d){
// d is the date scal sends on update
// you might want to do something with it
// below, we will hide the calendar...
scalinstance.toggleCalendar();
};
var scalinstance = new scal('calendardiv', dostuffthenclosecalendar);
// the second parameter is updateelement
// and we pass a pointer to the function above
// if you want to close the calendar you'd just
Ian posted a working example that changes a SELECT:
http://scal.fieldguidetoprogrammers.com/scal-v02-documentation/scal-onca...
Speed
I'm interested in using this control. I'd love to see a prototype/open source calendar control like this become the most used.
One thing is holding me back, though - when comparing this control to something like Yahoo's YUI Calendar Control (http://developer.yahoo.com/yui/calendar/), pressing the button that loads the next month is quite a lot quicker in Yahoo's calendar control.
I'd hate to support yahoo's control - are you guys planning on spending any time on efficiency/speed? Am I the only one who thinks the month transitions are slow?
Great job though, looking forward to implementing scal on my site soon!
handling date selection
is there an option to handle the selection of a date. to be more precise: i want to close the calendar if the user has selected a date.
lg
michal
webdevbros.net
oncalchange
Absolutely, Michal. The oncalchange option allows you to pass in a callback function when you create your calendar. That function will be called when the user clicks a date. The example in the docs updates a field elsewhere on the page but you could really do anything you want.
- Jamie
[update] I read your question too quickly, Michal. See above comment about updateelement which will allow you to accomplish the desired effect. Sorry.
Wrapper to have floating calendar.
I've extended the scal.prototype to add a wrapper functionality so I can easily build floating calendars.
Object.extend(scal.prototype,
{
toggleCalendar: function()
{
var element = $(this.options.wrapper) || this.element;
this.options[element.visible() ? 'closeeffect' : 'openeffect'](element);
},
isOpen: function()
{
return ( $(this.options.wrapper) || this.element).visible();
}
});
The HTML will look like this:
<input type="text" id="mydate"/>
<img src="calendar.jpg" onclick="showCalendar(this, 'mydate');"/>
<br/>
<div id="calendar-container" style="width:221px; position:absolute; display:none;">
<b class="rtop">
<b class="r1"></b> <b class="r2"></b> <b class="r3"></b> <b class="r4"></b>
</b>
<div class="googleblue" id="calendar"></div>
</div>
This way I can have a floating calendar using script.aculo.us:
new Draggable("calendar-container", {handle: "rtop"});
var calendar = null;
function showCalendar(element, input)
{
if (!calendar)
{
calendar = new scal('calendar', $(input), {updateformat: 'mm/dd/yyyy', closebutton: ' ', wrapper: 'calendar-container'});
}
else
{
calendar.updateelement = $(input);
}
var date = new Date($F(input));
calendar.setCurrentDate(isNaN(date) ? new Date() : date);
if (element = $(element))
{
var container = $("calendar-container");
Position.clone($(element), container, {setWidth: false, setHeight: false, offsetLeft: element.getWidth() + 2});
}
calendar.openCalendar();
}
I hope this help somebody who is using this great Calendar.
Thanks to SCAL team =)
(sorry for my english, I'm spanish speaker)
Regards from Mexico,
DMenT.
need draggable Scal Calendar
Hey DMenT.
A draggable Calendar which does not break my design is what i need!
But i can't reconstruct your script snippets. Can you give a more precise documentation?
I would be very thankful for that.
greetings from Germany
Hi
Huum, I will work in a demo for you, but I don't certainly know where to post it, can you leave your email here?
DMenT =)
DMenT - Floating Calendar
If you send it to me, I'll make a little page for it. :)
- Jamie
jamiegrove _at_ gmail
Already sent.
Jaime, I have sent you the code =)
DMenT.
Floating Calendar Demo Live
Thanks so much! What a great looking skin for scal too!
http://scal.fieldguidetoprogrammers.com/scal-v02-documentation/scal-floa...
Nice to see it online =)
I forgot to tell you that you can drag the calendar from the little top blue line, the one with round corners.
Regards,
DMenT
nice one!
Love it! Thanks for the contribution!
weekdaystart display problems
Firstly, awesome script.
On to my problem: I'm building an app that is going to be used on oil rigs in the Middle East. Their weekend is on either Thursday/Friday or Friday/Saturday so I wanted the week to start from Friday. Setting weekdaystart to 5 take a look at January 2008. The month starts from the 4th!
Cheers,
Vishal Parpia.
weekdaystart fun
Vishal, sorry for the delay but I've fixed the bug. Code is available now!
The problem was in _buildWrapper. If weekdaystart-firstdaycal.getDay() < firstdaycal.getDate() then the original formula to set the first day of the month will skip to the future (which is what happens in 01/2008 when using weekdaystart of 5). So, I added the below. Continuing the example of 01/2008:
1) 01/01/2008 is a Tuesday (getDay = 2)
2) Original formula would set calendar to start on (1 - 2 + 5) = 1/4/2008 : not good
3) New formula sets calendar to start on (1 - (1 + 7 - 5)) = 12/28 : good!
Basically, take it all the way back to Sunday. Go back a week. Then, add the days for weekdaystart. It's wacky, but solved the problem.
[original]
firstdaycal.setDate(firstdaycal.getDate() - firstdaycal.getDay() + this.options.weekdaystart);
[extra crispy]
if(this.options.weekdaystart-firstdaycal.getDay() < firstdaycal.getDate()){
firstdaycal.setDate(firstdaycal.getDate() - firstdaycal.getDay() + this.options.weekdaystart);
} else {
firstdaycal.setDate(firstdaycal.getDate() - (firstdaycal.getDay() + 7 - this.options.weekdaystart));
}
P.S. My head hurts now.
daynames ordering bug ?
I'm italian, so i need weekdays starting from monday, but if i use weekdaystart=1, the names come out scrambled - i have to use weekdaystart=6, that has no accord with the original ordering.
With this change in _buildHead method:
Date.prototype.daynames.sortBy(function(s,i){i-=this.options.weekdaystart;
if(i<0){i+=7;}
return i;
}.bind(this))......
everithing works as expected (in the end, we need to work with a change of sign).
bye !
Ubik
weekdaystart corrected
Bene grazie, Ubik!
The weekdaystart property was added just for folks like you (I worked in Switzerland for a year and so I know how important that is). Seems like something changed between 0.1 and 0.2 but your fix is now in place and available on the site. Thanks, again!
- Jamie