FANDOM


/*
 * Parser for CDYNE Weather web service
 * Copyright (C) 2008 Nicolas Alvarez
 *
 * Usage information available at:
 * http://konfabulator.wikia.com/wiki/CDYNE_weather_forecast
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
CDYNE = {};
CDYNE.getForecast = (function() {
    function parseForecastReturn(elem) {
        if (elem.tagName != "ForecastReturn") {
            throw "Parse error (root tagname doesn't match)";
        }
        var ret = {};
        for (var e = elem.firstChild; e != null; e = e.nextSibling) {
            if (e.nodeType != DOMNode.ELEMENT_NODE) continue;
            switch (e.tagName) {
            case "Success":
                ret[e.tagName] = (e.firstChild.nodeValue=="true"?true:false);
            break;
            case "ResponseText":
            case "State":
            case "City":
            case "WeatherStationCity":
                ret[e.tagName] = e.firstChild.nodeValue;
            break;
            case "ForecastResult":
                ret[e.tagName] = parseForecastResult(e);
            }
        }
        return ret;
    }
    function parseForecastResult(elem) {
        if (elem.tagName != "ForecastResult") {
            throw "parseForecastResult called with invalid element";
        }
        var ret = [];
        for (var e = elem.firstChild; e != null; e = e.nextSibling) {
            if (e.nodeType != DOMNode.ELEMENT_NODE) continue;
            if (e.tagName == "Forecast") {
                ret.push(parseForecast(e));
            }
        }
        return ret;
    }
    function parseForecast(elem) {
        if (elem.tagName != "Forecast") {
            throw "parseForecast called with invalid element";
        }
        var ret = {};
        for (var e = elem.firstChild; e != null; e = e.nextSibling) {
            if (e.nodeType != DOMNode.ELEMENT_NODE) continue;
            switch (e.tagName) {
                case "Date":
                    ret[e.tagName] = parseDatetime(e);
                break;
                case "WeatherID":
                    ret[e.tagName] = parseNumber(e);
                break;
                //this typo is not an error, the webservice actually returns this
                case "Desciption": //sic
                    ret[e.tagName] = e.firstChild.nodeValue;
                break;
                case "Temperatures":
                    ret[e.tagName] = parseTemperatures(e);
                break;
                case "ProbabilityOfPrecipiation": //sic
                    ret[e.tagName] = parsePOP(e);
            }
        }
        return ret;
    }
    function parseDatetime(elem) {
        var str = elem.firstChild.nodeValue;
        //FIXME this should cope with date-only and other formats
        var m = str.match(/^(\d{4})-?(\d\d)-?(\d\d)T(\d\d):?(\d\d):?(\d\d)(?:(Z|)|([+-]\d\d)(?::?(\d\d))?)$/);
 
        for(var i=1; i<=6; i++) {
            m[i] = parseInt(m[i], 10);
        }
 
        var tz_offset = 0; //in minutes
        if (m[7] != 'Z' && m[7] != '') {
            tz_offset = parseInt(m[8])*60 + parseInt(m[9]);
        }
 
        var d = new Date();
        //I have to use the methods, because the constructor takes local time
        //values, not UTC
        d.setUTCFullYear(m[1]);
        d.setUTCMonth(m[2]);
        d.setUTCDate(m[3]);
        d.setUTCHours(m[4]);
        d.setUTCMinutes(m[5] + tz_offset);
        d.setUTCSeconds(m[6]);
        d.setUTCMilliseconds(0);
 
        return d;
    }
    function parseNumber(elem) {
        return parseInt(elem.firstChild.nodeValue);
    }
    function parseTemperatures(elem) {
        if (elem.tagName != "Temperatures") {
            throw "parseTemperatures called with invalid element";
        }
        var ret = {};
        for (var e = elem.firstChild; e != null; e = e.nextSibling) {
            if (e.nodeType != DOMNode.ELEMENT_NODE) continue;
            switch (e.tagName) {
                case "MorningLow":
                case "DaytimeHigh":
                    ret[e.tagName] = e.firstChild.nodeValue;
                break;
            }
        }
        return ret;
    }
    function parsePOP(elem) {
        if (elem.tagName != "ProbabilityOfPrecipiation") { //sic
            throw "parsePOP called with invalid element";
        }
        var ret = {};
        for (var e = elem.firstChild; e != null; e = e.nextSibling) {
            if (e.nodeType != DOMNode.ELEMENT_NODE) continue;
            switch (e.tagName) {
                case "Nighttime":
                case "Daytime":
                    ret[e.tagName] = e.firstChild.nodeValue;
                break;
            }
        }
        return ret;
    }
    return function getForecast(zip, callback) {
        var async = !!(callback);
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "http://ws.cdyne.com/WeatherWS/Weather.asmx/GetCityForecastByZIP?ZIP=" + zip, async);
        if (async) {
            xhr.onreadystatechange = function() {
                callback(parseForecastReturn(xhr.responseXML.documentElement));
            };
        }
        xhr.send();
        if (!async) {
            return parseForecastReturn(xhr.responseXML.documentElement);
        }
    }
})();

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.