Class-based Javascript analog clock

Discussion in 'Programming' started by movvadinesh, Feb 1, 2008.

  1. #1
    his is an analog clock script designed to jump in place of a div element of class 'analogclock'.

    The div tag is not replaced in this custom element, but instead is used as a pseudo-document to hold the clock itself. The 'hands' are implemented using arrays of generated divs.

    The basics: You control the look of the numbers and the 'box' model of the clock using basic CSS. You control the clock's size (it will always be square) using the 'size' attribute.

    The 'seconds', 'minutes', and 'hours' attributes are for the color of the 'hand's. 'numstyle' can be 1, i, I, or '.', each refering to a different type of face-numbering for the clock

    The 'localzone' attribute tells the script to use the user's local time zone. If it's '0', 'false' or 'no', the clock will use the 'clockzone' attribute to determine what time it is (the clock zone is relative to GMT, so, for example, US Eastern is -5. The clock automagically figures out if we're in DST, so you don't have to.)

    The 'city' and 'country' are for if you want to put in the city/country of origin for your clock. To be honest, you can put anything there.

    Lastly, I designed my version of the clock to be able to not 'tick', i.e., work like the old-school analog clocks. If you want ticking, add 'tick=1' to the attribute list

    As with all of my widgets, the idea here is that you can just include the .js file and start dropping in tags without needing to know any ECMAScript at all.

    Additionally, for you ECMAScripters, I was very careful to keep my pollution of the global namespace to one class: analogClock.

    Example of use:

















    Code:

    var analogClock = function (divElem, index) { this.mainElem = divElem; this.index = index; var numStyles = Array(); numStyles["1"] = Array("1","2","3","4","5","6","7","8","9","10","11","12"); numStyles["i"] = Array("i","ii","iii","iv","v","vi","vii","viii","ix","x","xi","xii"); numStyles["I"] = Array("I","II","III","IV","V","VI","VII","VIII","IX","X","XI","XII"); numStyles["."] = Array("·","·","—","·","·","|","·","·","—","·","·","||"); this.position = analogClock.prototypes.position; numstyle = String(this.mainElem.getAttribute('numstyle')); if ("1I.".indexOf(numstyle.toUpperCase())==-1) numstyle="1"; var numstyle=numStyles[numstyle]; var radius = Math.floor(parseInt(this.mainElem.getAttribute('size'))/2); if (isNaN(radius)) radius=50; this.mainElem.style.width=radius*2; this.mainElem.style.height=radius*2; this.mainElem.style.position='relative'; this.mainElem.style.overflow='hidden'; this.mainElem.style.margin='0px'; this.mainElem.style.padding='0px'; //Create Hour labels this.hourLabels = Array(); for (var i=0; i<12; i++) { this.hourLabels=document.createElement("div"); this.hourLabels.appendChild(document.createTextNode(numstyle)); this.hourLabels.style.position='absolute'; this.mainElem.appendChild(this.hourLabels); } var numhours = Math.floor(radius*0.5); this.hourHand = Array(); for (i=0; i<numhours; i++) { this.hourHand=document.createElement("div"); this.hourHand.style.backgroundColor=this.mainElem.getAttribute("hours"); this.hourHand.style.width=Math.ceil(radius*3/75)+1; this.hourHand.style.height=Math.ceil(radius*3/75)+1; this.hourHand.style.position='absolute'; this.hourHand.style.overflow='hidden'; this.mainElem.appendChild(this.hourHand);
    }
    var numminutes = Math.floor(radius*0.75);
    this.minuteHand = Array();
    for (i=0; i<numminutes; i++) {
    this.minuteHand=document.createElement("div");
    this.minuteHand.style.backgroundColor=this.mainElem.getAttribute("minutes");
    this.minuteHand.style.width=Math.round(radius*2/75)+1;
    this.minuteHand.style.height=Math.round(radius*2/75)+1;
    this.minuteHand.style.position='absolute';
    this.minuteHand.style.overflow='hidden';
    this.mainElem.appendChild(this.minuteHand);
    }
    var numseconds = Math.floor(radius*0.90);
    this.secondHand = Array();
    for (i=0; i<numseconds; i++) {
    this.secondHand=document.createElement("div");
    this.secondHand[i].style.backgroundColor=this.mainElem.getAttribute("seconds");
    this.secondHand[i].style.width=Math.floor(radius*1/75)+1;
    this.secondHand[i].style.height=Math.floor(radius*1/75)+1;
    this.secondHand[i].style.position='absolute';
    this.secondHand[i].style.overflow='hidden';
    this.mainElem.appendChild(this.secondHand[i]);
    }
    this.AmPm=document.createElement("div");
    this.AmPm.style.position="absolute";
    this.mainElem.appendChild(this.AmPm);

    this.DoW=document.createElement("div");
    this.DoW.style.position="absolute";
    this.mainElem.appendChild(this.DoW);

    this.City=document.createElement("div");
    this.City.style.position="absolute";
    this.City.font="8pt Times";
    this.mainElem.appendChild(this.City);

    this.Country=document.createElement("div");
    this.Country.style.position="absolute";
    this.Country.font="8pt Times";
    this.mainElem.appendChild(this.Country);

    this.position();
    }
    analogClock.prototypes = Array();
    analogClock.prototypes.position = function () {
    var Week = Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
    var radius = Math.floor(parseInt(this.mainElem.getAttribute('size'))/2);
    if (isNaN(radius)) radius=50;
    var Today = new Date();
    var Mills = Today.getMilliseconds();
    var Second = Today.getSeconds()+Mills/1000;
    var Minute = Today.getMinutes()+Second/60;
    var Hour = Today.getHours()+Minute/60;
    if (this.mainElem.getAttribute('tick')) {
    Hour=Math.floor(Hour);
    Minute=Math.floor(Minute);
    Second=Math.floor(Second);
    }
    if ("1\\yes\\true".indexOf(this.mainElem.getAttribute('localzone').toLowerCase())==-1) {
    Hour-=analogClock.getGMT();
    cz=parseInt(this.mainElem.getAttribute('clockzone'));
    Hour+=cz+analogClock.needDST(cz);
    }

    while (Hour>=24) Hour-=12;
    while (Hour<0) Hour+=12;
    for (var i=0; i<this.hourLabels.length; i++) {
    radpos = (i+1)*2*Math.PI/12-Math.PI/2;
    this.hourLabels[i].style.top=radius+Math.sin(radpos)*radius*0.90-parseInt(this.hourLabels[i].offsetHeight)/2;
    this.hourLabels[i].style.left=radius+Math.cos(radpos)*radius*0.90-parseInt(this.hourLabels[i].offsetWidth)/2;
    }
    radpos=(Hour%12)*Math.PI*2/12-Math.PI/2;
    for (i=0; i<this.hourHand.length; i++) {
    this.hourHand[i].style.top=radius+Math.sin(radpos)*i;
    this.hourHand[i].style.left=radius+Math.cos(radpos)*i;
    }
    radpos=Minute*Math.PI*2/60-Math.PI/2;
    for (i=0; i<this.minuteHand.length; i++) {
    this.minuteHand[i].style.top=radius+Math.sin(radpos)*i;
    this.minuteHand[i].style.left=radius+Math.cos(radpos)*i;
    }
    radpos=Second*Math.PI*2/60-Math.PI/2;
    for (i=0; i<this.secondHand.length; i++) {
    this.secondHand[i].style.top=radius+Math.sin(radpos)*i;
    this.secondHand[i].style.left=radius+Math.cos(radpos)*i;
    }
    this.AmPm.innerHTML=(Hour>=12)?"PM":"AM";
    this.AmPm.style.bottom=1.333*radius;
    this.AmPm.style.left=radius-parseInt(this.AmPm.offsetWidth)/2;
    this.AmPm.style.zIndex=-1;

    this.DoW.innerHTML=Week[Today.getDay()];
    this.DoW.style.top=0.666*radius;
    this.DoW.style.left=radius-parseInt(this.DoW.offsetWidth)/2;
    this.DoW.style.zIndex=-1;


    this.City.innerHTML=this.mainElem.getAttribute('city');
    this.City.style.bottom=0.666*radius;
    this.City.style.left=radius-parseInt(this.City.offsetWidth)/2;
    this.City.style.zIndex=-1;

    this.Country.innerHTML=this.mainElem.getAttribute('country');
    this.Country.style.top=1.333*radius;
    this.Country.style.left=radius-parseInt(this.Country.offsetWidth)/2;
    this.Country.style.zIndex=-1;
    }

    analogClock.arClocks = new Array();

    analogClock.replace = function () {
    var Divs = document.getElementsByTagName('div');
    for (var i=0; i<Divs.length; i++)
    if (Divs[i].className.toLowerCase().indexOf("analogclock")!=-1)
    analogClock.arClocks[analogClock.arClocks.length]=new analogClock(Divs[i],analogClock.arClocks.length);
    setTimeout('analogClock.update();', 100);
    }

    analogClock.update = function () {
    for (var i=0; i<analogClock.arClocks.length; i++)
    analogClock.arClocks[i].position();
    var interval = Math.floor(50*Math.pow(analogClock.arClocks.length,1.5));
    setTimeout('analogClock.update();', (analogClock.active)?(interval):(1000))
    }

    analogClock.getGMT = function () {
    var day;
    var Today = new Date();
    var gmtAdjust=-Today.getTimezoneOffset()/60;
    var lsm = new Date;
    var lso = new Date;
    lsm.setMonth(2); lsm.setDate(31); day = lsm.getDay(); lsm.setDate(31-day);
    lso.setMonth(9); lso.setDate(31); day = lso.getDay(); lso.setDate(31-day);
    if (Today < lsm || Today >= lso) gmtAdjust -= 1;
    return gmtAdjust;
    }

    analogClock.needDST = function (a) {
    if ((a<-8)||(a>-5)) return 0;
    var day;
    var Today = new Date();
    var dst=0;
    var lsm = new Date;
    var lso = new Date;
    lsm.setMonth(2); lsm.setDate(31); day = lsm.getDay(); lsm.setDate(31-day);
    lso.setMonth(9); lso.setDate(31); day = lso.getDay(); lso.setDate(31-day);
    if (Today >= lsm || Today < lso) dst = 1;
    return dst;
    }

    analogClock.suspend = function () {
    analogClock.active=false;
    }

    analogClock.resume = function () {
    analogClock.active=true;
    }

    analogClock.attach = function () {
    if (window.attachEvent) {
    window.attachEvent('onload',analogClock.replace);
    window.attachEvent('onblur',analogClock.suspend);
    window.attachEvent('onfocus',analogClock.resume);
    }
    if (window.addEventListener) {
    window.addEventListener('load',analogClock.replace,false);
    window.addEventListener('blur',analogClock.suspend,false);
    window.addEventListener('focus',analogClock.resume,false);
    }
    }

    analogClock.active=true;
    analogClock.attach();[/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]

     
    movvadinesh, Feb 1, 2008 IP