the YUI Calendar control, including
- setting the date in the control
- getting the date from the control (after selection)
- dynamically displaying and hiding the control
- manipulating ISO dates into the format that YUI requires
- setting min and max dates on the fly – specifically, this shows you how to manipulate YUI “config” parameters which the documentation implies are readonly (look for functions in source code named like
configMinDate)
- simple YUI animations (to show that a field value has been changed)
- detecting keystrokes (DEL and ESC) using YUI
- adding functionality using Javascript, after the DOM loads
This assumes:
- you have an Input field for the start date with DOM
id="id_event_start"
- you have an Input field for the end date with DOM
id="id_event_end"
- that the Form (or a parent element of the Form, up to Body) has DOM
class="yui-skin-sam"
Add the following Script inclusions to your HTML (note: not all of these are probably needed, and there’s more efficient ways to include YUI JS, especially for production deployments):
<script type="text/javascript"
src="http://yui.yahooapis.com/2.8.0r4/build/json/json-min.js"></script>
<script type="text/javascript"
src="http://yui.yahooapis.com/2.8.0r4/build/event/event-min.js"></script>
<script type="text/javascript"
src="http://yui.yahooapis.com/2.8.0r4/build/connection/connection-min.js"></script>
<script type="text/javascript"
src="http://yui.yahooapis.com/2.8.0r4/build/dom/dom-min.js"></script>
<script type="text/javascript"
src="http://yui.yahooapis.com/2.8.0r4/build/element/element-min.js"></script>
<script type="text/javascript"
src="http://yui.yahooapis.com/2.8.0r4/build/button/button-min.js"></script>
<script type="text/javascript"
src="http://yui.yahooapis.com/2.8.0r4/build/dragdrop/dragdrop-min.js"></script>
<script type="text/javascript"
src="http://yui.yahooapis.com/2.8.0r4/build/container/container-min.js"></script>
<script type="text/javascript"
src="http://yui.yahooapis.com/2.8.0r4/build/yuiloader/yuiloader-min.js"></script>
<script type="text/javascript"
src="http://yui.yahooapis.com/2.8.0r4/build/container/container_core-min.js"></script>
<script type="text/javascript"
src="http://yui.yahooapis.com/2.8.0r4/build/calendar/calendar-min.js"></script>
<script type="text/javascript"
src="http://yui.yahooapis.com/2.8.0r4/build/animation/animation-min.js"></script>
Add the following CSS inclusions to your HTML:
<link rel="stylesheet" type="text/css"
href="http://yui.yahooapis.com/2.8.0r4/build/button/assets/skins/sam/button.css" />
<link rel="stylesheet" type="text/css"
href="http://yui.yahooapis.com/2.8.0r4/build/container/assets/skins/sam/container.css" />
<link rel="stylesheet" type="text/css"
href="http://yui.yahooapis.com/2.8.0r4/build/calendar/assets/skins/sam/calendar.css" />
Add the following CSS to your HTML:
<style type="text/css">
#id_calendar {
position: absolute;
z-index: 15;
}
.yui-skin-sam .yui-panel .bd, .yui-skin-sam .yui-panel .ft {
background-color:#FFFFFF;
}
</style>
Add the following HTML fragment:
<div id="id_calendar_wrapper">
<div id="id_calendar"></div>
</div>
And finally, here’s the JS that makes it all work
<script type="text/javascript">
calendar_js = {
c : null,
start_e : null,
end_e : null,
current_e : 0,
supress : 0,
create : function() {
calendar_js.start_e = YAHOO.util.Dom.get("id_event_start");
calendar_js.end_e = YAHOO.util.Dom.get("id_event_end");
YAHOO.util.Event.addListener(calendar_js.start_e, "click", calendar_js.onclick, this);
YAHOO.util.Event.addListener(calendar_js.end_e, "click", calendar_js.onclick, this);
YAHOO.util.Dom.get(calendar_js.start_e).readOnly = true;
YAHOO.util.Dom.get(calendar_js.end_e).readOnly = true;
(new YAHOO.util.KeyListener(document, { keys:27 }, { fn:calendar_js.onesc })).enable();
(new YAHOO.util.KeyListener(document, { keys:8 }, { fn:calendar_js.ondel })).enable();
},
onesc : function() {
calendar_js.current_e = null;
if (calendar_js.c) {
calendar_js.c.hide();
}
},
ondel : function() {
if (calendar_js.current_e) {
calendar_js.current_e.value = "";
calendar_js.current_e = null;
}
if (calendar_js.c) {
calendar_js.c.hide();
}
},
toydate : function(d) {
if (!d) {
return null;
}
if (d.value) {
d = d.value;
}
if (d && d.length) {
d = d.replace(/(\d\d\d\d)-(\d\d)-(\d\d)/, "$2/$3/$1");
if (d.indexOf('/') == 2) {
return d;
}
}
return null;
},
onclick : function(evt, obj) {
var e_e = YAHOO.util.Event.getTarget(evt);
if (calendar_js.c == null) {
calendar_js.c = new YAHOO.widget.Calendar(null, "id_calendar");
calendar_js.c.render();
calendar_js.c.selectEvent.subscribe(calendar_js.ondate, calendar_js.c, true);
}
var c_e = YAHOO.util.Dom.get("id_calendar");
if (calendar_js.current_e == e_e) {
calendar_js.current_e = null;
calendar_js.c.hide();
} else {
YAHOO.util.Dom.setAttribute(c_e, "display", "block");
calendar_js.current_e = e_e;
var region = YAHOO.util.Region.getRegion(e_e);
calendar_js.c.show();
if (e_e.value.length) {
var d = calendar_js.toydate(e_e);
if (d) {
calendar_js.supress = 1;
calendar_js.c.select(d);
}
}
if (e_e == calendar_js.start_e) {
var d = calendar_js.toydate(calendar_js.end_e);
if (d) {
calendar_js.c.configMaxDate(null, [ d ], null);
calendar_js.c.configMinDate(null, [ "01/01/1970" ], null);
}
} else {
var d = calendar_js.toydate(calendar_js.start_e);
if (d) {
calendar_js.c.configMinDate(null, [ d ], null);
calendar_js.c.configMaxDate(null, [ "01/01/2200" ], null);
}
}
calendar_js.c.render();
YAHOO.util.Dom.setXY(c_e, [ region.right + 2, region.top ]);
}
},
ondate : function(type, args, obj) {
if (calendar_js.supress) {
calendar_js.supress = 0;
return;
}
var date = this.toDate(args[0][0]);
var year = "" + date.getFullYear();
var month = "" + ( 1 + date.getMonth() );
while (month.length < 2) {
month = "0" + month;
}
var day = "" + date.getDate();
while (day.length < 2) {
day = "0" + day;
}
var animate = new YAHOO.util.ColorAnim(calendar_js.current_e,
{backgroundColor: { from: '#ffff99', to: '#FFFFFF' } }
);
animate.duration = 0.75;
animate.method = YAHOO.util.Easing.easeOut;
animate.animate();
calendar_js.current_e.value = year + "-" + month + "-" + day;
calendar_js.c.hide();
calendar_js.current_e = null;
},
end : 0
};
YAHOO.util.Event.onDOMReady(calendar_js.oninit);
</script>
Notes:
- no apologies for verboseness – I write code so I can understand it in 24 months time
- my original code is a lot more “tabby” – I flattened to a single space so they’d fit in the space constraints here
- the code should be fairly self explanatory if you step through it – the hard stuff is probably YUI weirdness and you can probably just accept that “that’s just the way it is”