From f2fc040e7fd15846d6fe3857489a7772d51c1979 Mon Sep 17 00:00:00 2001 From: MetaView Date: Tue, 16 Jul 2013 12:48:01 +0200 Subject: [PATCH 1/2] use 1.1 Twitter-API --- spazcore/spazcore-webos.js | 7826 ++++++++++++++++++------------------ 1 file changed, 3914 insertions(+), 3912 deletions(-) diff --git a/spazcore/spazcore-webos.js b/spazcore/spazcore-webos.js index 6571942..d663a85 100644 --- a/spazcore/spazcore-webos.js +++ b/spazcore/spazcore-webos.js @@ -1,5 +1,5 @@ /*********** Built 2011-06-01 14:39:47 CDT ***********/ -/*jslint +/*jslint browser: true, nomen: false, debug: true, @@ -7,37 +7,37 @@ forin: true, regexp: false, undef: true, white: false, -onevar: false +onevar: false */ /** * SPAZCORE * version 0.1.1 * 2009-08-06 - * + * * License - * + * * Copyright (c) 2008-2009, Edward Finkler, Funkatron Productions - * + * * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * + * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * 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. - * + * * Neither the name of Edward Finkler, Funkatron Productions nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. - * - * + * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 @@ -48,2301 +48,2304 @@ onevar: false * 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. - * - * + * + * * SpazCore includes code from other software projects. Their licenses follow: - * + * * date.js * @copyright: Copyright (c) 2006-2008, Coolite Inc. (http://www.coolite.com/). All rights reserved. * @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. - * + * * webtoolkit.info (hash libs, trim funcs, utf8 encoder/decoder) * http://www.webtoolkit.info/ * As long as you leave the copyright notice of the original script, or link * back to this website, you can use any of the content published on this * website free of charge for any use: commercial or noncommercial. */ - + /** - * @namespace + * @namespace */ var sc = {}; -/** - * @namespace - */ -sc.app = {}; +/** + * @namespace + */ +sc.app = {}; + +/** + * @namespace + */ +sc.helpers = {}; + +/** + * dump level for limiting what gets dumped to console + */ +sc.dumplevel = 1; + +/** + * method to set dump level + */ +sc.setDumpLevel = function(level) { + sc.dumplevel = parseInt(level, 10); +}; + +/** + * @namespace helper shortcuts + * this lets us write "sch.method" instead of "sc.helpers.method" + * + */ +var sch = sc.helpers; + + +sc.events = {}; + + + +/** + * various constant definitions that aren't specific to a single library + */ + +/** + * @constant + */ +var SPAZCORE_SERVICE_TWITTER = 'twitter'; +/** + * @constant + */ +var SPAZCORE_SERVICE_IDENTICA = 'identi.ca'; +/** + * @constant + */ +var SPAZCORE_SERVICE_FREELISHUS = 'freelish.us'; +/** + * @constant + */ +var SPAZCORE_SERVICE_WORDPRESS_TWITTER = 'wordpress-twitter'; +/** + * @constant + */ +var SPAZCORE_SERVICE_TUMBLR_TWITTER = 'tumblr-twitter'; +/** + * @constant + */ +var SPAZCORE_SERVICE_CUSTOM = 'custom'; + +/** + * @constant + */ +var SPAZCORE_BASEURL_TWITTER = 'https://twitter.com/'; +/** + * @constant + */ +var SPAZCORE_BASEURL_IDENTICA = 'https://identi.ca/'; +/** + * @constant + */ +var SPAZCORE_BASEURL_FREELISHUS = 'http://freelish.us/'; +/** + * @constant + */ +var SPAZCORE_APIVERSION_TWITTER = '1.1'; + + +/** + * Build the helpers + * @depends ../helpers/datetime.js + * @depends ../helpers/event.js + * @depends ../helpers/javascript.js + * @depends ../helpers/json.js + * @depends ../helpers/location.js + * @depends ../helpers/string.js + * @depends ../helpers/sys.js + * @depends ../helpers/view.js + * @depends ../helpers/xml.js + * + * Build the libs + * @depends spazcron.js + * @depends spazlocker.js + * @depends spazphotomailer.js + * @depends spazpingfm.js + * @depends spazprefs.js + * @depends spazshorttext.js + * @depends spazshorturl.js + * @depends spaztemplate.js + * @depends spaztimeline.js + * @depends spaztwit.js + */ +Date.CultureInfo = { + /* Culture Name */ + name: "en-US", + englishName: "English (United States)", + nativeName: "English (United States)", + + /* Day Name Strings */ + dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], + abbreviatedDayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], + shortestDayNames: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], + firstLetterDayNames: ["S", "M", "T", "W", "T", "F", "S"], + + /* Month Name Strings */ + monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + abbreviatedMonthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], + + /* AM/PM Designators */ + amDesignator: "AM", + pmDesignator: "PM", + + firstDayOfWeek: 0, + twoDigitYearMax: 2029, + + /** + * The dateElementOrder is based on the order of the + * format specifiers in the formatPatterns.DatePattern. + * + * Example: +
+     shortDatePattern    dateElementOrder
+     ------------------  ----------------
+     "M/d/yyyy"          "mdy"
+     "dd/MM/yyyy"        "dmy"
+     "yyyy-MM-dd"        "ymd"
+     
+ * + * The correct dateElementOrder is required by the parser to + * determine the expected order of the date elements in the + * string being parsed. + */ + dateElementOrder: "mdy", + + /* Standard date and time format patterns */ + formatPatterns: { + shortDate: "M/d/yyyy", + longDate: "dddd, MMMM dd, yyyy", + shortTime: "h:mm tt", + longTime: "h:mm:ss tt", + fullDateTime: "dddd, MMMM dd, yyyy h:mm:ss tt", + sortableDateTime: "yyyy-MM-ddTHH:mm:ss", + universalSortableDateTime: "yyyy-MM-dd HH:mm:ssZ", + rfc1123: "ddd, dd MMM yyyy HH:mm:ss GMT", + monthDay: "MMMM dd", + yearMonth: "MMMM, yyyy" + }, + + /** + * NOTE: If a string format is not parsing correctly, but + * you would expect it parse, the problem likely lies below. + * + * The following regex patterns control most of the string matching + * within the parser. + * + * The Month name and Day name patterns were automatically generated + * and in general should be (mostly) correct. + * + * Beyond the month and day name patterns are natural language strings. + * Example: "next", "today", "months" + * + * These natural language string may NOT be correct for this culture. + * If they are not correct, please translate and edit this file + * providing the correct regular expression pattern. + * + * If you modify this file, please post your revised CultureInfo file + * to the Datejs Forum located at http://www.datejs.com/forums/. + * + * Please mark the subject of the post with [CultureInfo]. Example: + * Subject: [CultureInfo] Translated "da-DK" Danish(Denmark) + * + * We will add the modified patterns to the master source files. + * + * As well, please review the list of "Future Strings" section below. + */ + regexPatterns: { + jan: /^jan(uary)?/i, + feb: /^feb(ruary)?/i, + mar: /^mar(ch)?/i, + apr: /^apr(il)?/i, + may: /^may/i, + jun: /^jun(e)?/i, + jul: /^jul(y)?/i, + aug: /^aug(ust)?/i, + sep: /^sep(t(ember)?)?/i, + oct: /^oct(ober)?/i, + nov: /^nov(ember)?/i, + dec: /^dec(ember)?/i, + + sun: /^su(n(day)?)?/i, + mon: /^mo(n(day)?)?/i, + tue: /^tu(e(s(day)?)?)?/i, + wed: /^we(d(nesday)?)?/i, + thu: /^th(u(r(s(day)?)?)?)?/i, + fri: /^fr(i(day)?)?/i, + sat: /^sa(t(urday)?)?/i, + + future: /^next/i, + past: /^last|past|prev(ious)?/i, + add: /^(\+|aft(er)?|from|hence)/i, + subtract: /^(\-|bef(ore)?|ago)/i, + + yesterday: /^yes(terday)?/i, + today: /^t(od(ay)?)?/i, + tomorrow: /^tom(orrow)?/i, + now: /^n(ow)?/i, + + millisecond: /^ms|milli(second)?s?/i, + second: /^sec(ond)?s?/i, + minute: /^mn|min(ute)?s?/i, + hour: /^h(our)?s?/i, + week: /^w(eek)?s?/i, + month: /^m(onth)?s?/i, + day: /^d(ay)?s?/i, + year: /^y(ear)?s?/i, + + shortMeridian: /^(a|p)/i, + longMeridian: /^(a\.?m?\.?|p\.?m?\.?)/i, + timezone: /^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt|utc)/i, + ordinalSuffix: /^\s*(st|nd|rd|th)/i, + timeContext: /^\s*(\:|a(?!u|p)|p)/i + }, + + timezones: [{name:"UTC", offset:"-000"}, {name:"GMT", offset:"-000"}, {name:"EST", offset:"-0500"}, {name:"EDT", offset:"-0400"}, {name:"CST", offset:"-0600"}, {name:"CDT", offset:"-0500"}, {name:"MST", offset:"-0700"}, {name:"MDT", offset:"-0600"}, {name:"PST", offset:"-0800"}, {name:"PDT", offset:"-0700"}] +}; + +/******************** + ** Future Strings ** + ******************** + * + * The following list of strings may not be currently being used, but + * may be incorporated into the Datejs library later. + * + * We would appreciate any help translating the strings below. + * + * If you modify this file, please post your revised CultureInfo file + * to the Datejs Forum located at http://www.datejs.com/forums/. + * + * Please mark the subject of the post with [CultureInfo]. Example: + * Subject: [CultureInfo] Translated "da-DK" Danish(Denmark)b + * + * English Name Translated + * ------------------ ----------------- + * about about + * ago ago + * date date + * time time + * calendar calendar + * show show + * hourly hourly + * daily daily + * weekly weekly + * bi-weekly bi-weekly + * fortnight fortnight + * monthly monthly + * bi-monthly bi-monthly + * quarter quarter + * quarterly quarterly + * yearly yearly + * annual annual + * annually annually + * annum annum + * again again + * between between + * after after + * from now from now + * repeat repeat + * times times + * per per + * min (abbrev minute) min + * morning morning + * noon noon + * night night + * midnight midnight + * mid-night mid-night + * evening evening + * final final + * future future + * spring spring + * summer summer + * fall fall + * winter winter + * end of end of + * end end + * long long + * short short + *//** + * @version: 1.0 Alpha-1 + * @author: Coolite Inc. http://www.coolite.com/ + * @date: 2008-04-13 + * @copyright: Copyright (c) 2006-2008, Coolite Inc. (http://www.coolite.com/). All rights reserved. + * @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. + * @website: http://www.datejs.com/ + */ + +(function () { + var $D = Date, + $P = $D.prototype, + $C = $D.CultureInfo, + p = function (s, l) { + if (!l) { + l = 2; + } + return ("000" + s).slice(l * -1); + }; + + /** + * Resets the time of this Date object to 12:00 AM (00:00), which is the start of the day. + * @param {Boolean} .clone() this date instance before clearing Time + * @return {Date} this + */ + $P.clearTime = function () { + this.setHours(0); + this.setMinutes(0); + this.setSeconds(0); + this.setMilliseconds(0); + return this; + }; + + /** + * Resets the time of this Date object to the current time ('now'). + * @return {Date} this + */ + $P.setTimeToNow = function () { + var n = new Date(); + this.setHours(n.getHours()); + this.setMinutes(n.getMinutes()); + this.setSeconds(n.getSeconds()); + this.setMilliseconds(n.getMilliseconds()); + return this; + }; + + /** + * Gets a date that is set to the current date. The time is set to the start of the day (00:00 or 12:00 AM). + * @return {Date} The current date. + */ + $D.today = function () { + return new Date().clearTime(); + }; + + /** + * Compares the first date to the second date and returns an number indication of their relative values. + * @param {Date} First Date object to compare [Required]. + * @param {Date} Second Date object to compare to [Required]. + * @return {Number} -1 = date1 is lessthan date2. 0 = values are equal. 1 = date1 is greaterthan date2. + */ + $D.compare = function (date1, date2) { + if (isNaN(date1) || isNaN(date2)) { + throw new Error(date1 + " - " + date2); + } else if (date1 instanceof Date && date2 instanceof Date) { + return (date1 < date2) ? -1 : (date1 > date2) ? 1 : 0; + } else { + throw new TypeError(date1 + " - " + date2); + } + }; + + /** + * Compares the first Date object to the second Date object and returns true if they are equal. + * @param {Date} First Date object to compare [Required] + * @param {Date} Second Date object to compare to [Required] + * @return {Boolean} true if dates are equal. false if they are not equal. + */ + $D.equals = function (date1, date2) { + return (date1.compareTo(date2) === 0); + }; + + /** + * Gets the day number (0-6) if given a CultureInfo specific string which is a valid dayName, abbreviatedDayName or shortestDayName (two char). + * @param {String} The name of the day (eg. "Monday, "Mon", "tuesday", "tue", "We", "we"). + * @return {Number} The day number + */ + $D.getDayNumberFromName = function (name) { + var n = $C.dayNames, m = $C.abbreviatedDayNames, o = $C.shortestDayNames, s = name.toLowerCase(); + for (var i = 0; i < n.length; i++) { + if (n[i].toLowerCase() == s || m[i].toLowerCase() == s || o[i].toLowerCase() == s) { + return i; + } + } + return -1; + }; + + /** + * Gets the month number (0-11) if given a Culture Info specific string which is a valid monthName or abbreviatedMonthName. + * @param {String} The name of the month (eg. "February, "Feb", "october", "oct"). + * @return {Number} The day number + */ + $D.getMonthNumberFromName = function (name) { + var n = $C.monthNames, m = $C.abbreviatedMonthNames, s = name.toLowerCase(); + for (var i = 0; i < n.length; i++) { + if (n[i].toLowerCase() == s || m[i].toLowerCase() == s) { + return i; + } + } + return -1; + }; + + /** + * Determines if the current date instance is within a LeapYear. + * @param {Number} The year. + * @return {Boolean} true if date is within a LeapYear, otherwise false. + */ + $D.isLeapYear = function (year) { + return ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); + }; + + /** + * Gets the number of days in the month, given a year and month value. Automatically corrects for LeapYear. + * @param {Number} The year. + * @param {Number} The month (0-11). + * @return {Number} The number of days in the month. + */ + $D.getDaysInMonth = function (year, month) { + return [31, ($D.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; + }; + + $D.getTimezoneAbbreviation = function (offset) { + var z = $C.timezones, p; + for (var i = 0; i < z.length; i++) { + if (z[i].offset === offset) { + return z[i].name; + } + } + return null; + }; + + $D.getTimezoneOffset = function (name) { + var z = $C.timezones, p; + for (var i = 0; i < z.length; i++) { + if (z[i].name === name.toUpperCase()) { + return z[i].offset; + } + } + return null; + }; + + /** + * Returns a new Date object that is an exact date and time copy of the original instance. + * @return {Date} A new Date instance + */ + $P.clone = function () { + return new Date(this.getTime()); + }; + + /** + * Compares this instance to a Date object and returns an number indication of their relative values. + * @param {Date} Date object to compare [Required] + * @return {Number} -1 = this is lessthan date. 0 = values are equal. 1 = this is greaterthan date. + */ + $P.compareTo = function (date) { + return Date.compare(this, date); + }; + + /** + * Compares this instance to another Date object and returns true if they are equal. + * @param {Date} Date object to compare. If no date to compare, new Date() [now] is used. + * @return {Boolean} true if dates are equal. false if they are not equal. + */ + $P.equals = function (date) { + return Date.equals(this, date || new Date()); + }; + + /** + * Determines if this instance is between a range of two dates or equal to either the start or end dates. + * @param {Date} Start of range [Required] + * @param {Date} End of range [Required] + * @return {Boolean} true is this is between or equal to the start and end dates, else false + */ + $P.between = function (start, end) { + return this.getTime() >= start.getTime() && this.getTime() <= end.getTime(); + }; + + /** + * Determines if this date occurs after the date to compare to. + * @param {Date} Date object to compare. If no date to compare, new Date() ("now") is used. + * @return {Boolean} true if this date instance is greater than the date to compare to (or "now"), otherwise false. + */ + $P.isAfter = function (date) { + return this.compareTo(date || new Date()) === 1; + }; + + /** + * Determines if this date occurs before the date to compare to. + * @param {Date} Date object to compare. If no date to compare, new Date() ("now") is used. + * @return {Boolean} true if this date instance is less than the date to compare to (or "now"). + */ + $P.isBefore = function (date) { + return (this.compareTo(date || new Date()) === -1); + }; + + /** + * Determines if the current Date instance occurs today. + * @return {Boolean} true if this date instance is 'today', otherwise false. + */ + + /** + * Determines if the current Date instance occurs on the same Date as the supplied 'date'. + * If no 'date' to compare to is provided, the current Date instance is compared to 'today'. + * @param {date} Date object to compare. If no date to compare, the current Date ("now") is used. + * @return {Boolean} true if this Date instance occurs on the same Day as the supplied 'date'. + */ + $P.isToday = $P.isSameDay = function (date) { + return this.clone().clearTime().equals((date || new Date()).clone().clearTime()); + }; + + /** + * Adds the specified number of milliseconds to this instance. + * @param {Number} The number of milliseconds to add. The number can be positive or negative [Required] + * @return {Date} this + */ + $P.addMilliseconds = function (value) { + this.setMilliseconds(this.getMilliseconds() + value * 1); + return this; + }; + + /** + * Adds the specified number of seconds to this instance. + * @param {Number} The number of seconds to add. The number can be positive or negative [Required] + * @return {Date} this + */ + $P.addSeconds = function (value) { + return this.addMilliseconds(value * 1000); + }; + + /** + * Adds the specified number of seconds to this instance. + * @param {Number} The number of seconds to add. The number can be positive or negative [Required] + * @return {Date} this + */ + $P.addMinutes = function (value) { + return this.addMilliseconds(value * 60000); /* 60*1000 */ + }; + + /** + * Adds the specified number of hours to this instance. + * @param {Number} The number of hours to add. The number can be positive or negative [Required] + * @return {Date} this + */ + $P.addHours = function (value) { + return this.addMilliseconds(value * 3600000); /* 60*60*1000 */ + }; + + /** + * Adds the specified number of days to this instance. + * @param {Number} The number of days to add. The number can be positive or negative [Required] + * @return {Date} this + */ + $P.addDays = function (value) { + this.setDate(this.getDate() + value * 1); + return this; + }; + + /** + * Adds the specified number of weeks to this instance. + * @param {Number} The number of weeks to add. The number can be positive or negative [Required] + * @return {Date} this + */ + $P.addWeeks = function (value) { + return this.addDays(value * 7); + }; + + /** + * Adds the specified number of months to this instance. + * @param {Number} The number of months to add. The number can be positive or negative [Required] + * @return {Date} this + */ + $P.addMonths = function (value) { + var n = this.getDate(); + this.setDate(1); + this.setMonth(this.getMonth() + value * 1); + this.setDate(Math.min(n, $D.getDaysInMonth(this.getFullYear(), this.getMonth()))); + return this; + }; + + /** + * Adds the specified number of years to this instance. + * @param {Number} The number of years to add. The number can be positive or negative [Required] + * @return {Date} this + */ + $P.addYears = function (value) { + return this.addMonths(value * 12); + }; + + /** + * Adds (or subtracts) to the value of the years, months, weeks, days, hours, minutes, seconds, milliseconds of the date instance using given configuration object. Positive and Negative values allowed. + * Example +

+    Date.today().add( { days: 1, months: 1 } )
+
+    new Date().add( { years: -1 } )
+    
+ * @param {Object} Configuration object containing attributes (months, days, etc.) + * @return {Date} this + */ + $P.add = function (config) { + if (typeof config == "number") { + this._orient = config; + return this; + } + + var x = config; + + if (x.milliseconds) { + this.addMilliseconds(x.milliseconds); + } + if (x.seconds) { + this.addSeconds(x.seconds); + } + if (x.minutes) { + this.addMinutes(x.minutes); + } + if (x.hours) { + this.addHours(x.hours); + } + if (x.weeks) { + this.addWeeks(x.weeks); + } + if (x.months) { + this.addMonths(x.months); + } + if (x.years) { + this.addYears(x.years); + } + if (x.days) { + this.addDays(x.days); + } + return this; + }; + + var $y, $m, $d; + + /** + * Get the week number. Week one (1) is the week which contains the first Thursday of the year. Monday is considered the first day of the week. + * This algorithm is a JavaScript port of the work presented by Claus Tøndering at http://www.tondering.dk/claus/cal/node8.html#SECTION00880000000000000000 + * .getWeek() Algorithm Copyright (c) 2008 Claus Tondering. + * The .getWeek() function does NOT convert the date to UTC. The local datetime is used. Please use .getISOWeek() to get the week of the UTC converted date. + * @return {Number} 1 to 53 + */ + $P.getWeek = function () { + var a, b, c, d, e, f, g, n, s, w; + + $y = (!$y) ? this.getFullYear() : $y; + $m = (!$m) ? this.getMonth() + 1 : $m; + $d = (!$d) ? this.getDate() : $d; + + if ($m <= 2) { + a = $y - 1; + b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0); + c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0); + s = b - c; + e = 0; + f = $d - 1 + (31 * ($m - 1)); + } else { + a = $y; + b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0); + c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0); + s = b - c; + e = s + 1; + f = $d + ((153 * ($m - 3) + 2) / 5) + 58 + s; + } + + g = (a + b) % 7; + d = (f + g - e) % 7; + n = (f + 3 - d) | 0; + + if (n < 0) { + w = 53 - ((g - s) / 5 | 0); + } else if (n > 364 + s) { + w = 1; + } else { + w = (n / 7 | 0) + 1; + } + + $y = $m = $d = null; + + return w; + }; + + /** + * Get the ISO 8601 week number. Week one ("01") is the week which contains the first Thursday of the year. Monday is considered the first day of the week. + * The .getISOWeek() function does convert the date to it's UTC value. Please use .getWeek() to get the week of the local date. + * @return {String} "01" to "53" + */ + $P.getISOWeek = function () { + $y = this.getUTCFullYear(); + $m = this.getUTCMonth() + 1; + $d = this.getUTCDate(); + return p(this.getWeek()); + }; + + /** + * Moves the date to Monday of the week set. Week one (1) is the week which contains the first Thursday of the year. + * @param {Number} A Number (1 to 53) that represents the week of the year. + * @return {Date} this + */ + $P.setWeek = function (n) { + return this.moveToDayOfWeek(1).addWeeks(n - this.getWeek()); + }; + + // private + var validate = function (n, min, max, name) { + if (typeof n == "undefined") { + return false; + } else if (typeof n != "number") { + throw new TypeError(n + " is not a Number."); + } else if (n < min || n > max) { + throw new RangeError(n + " is not a valid value for " + name + "."); + } + return true; + }; + + /** + * Validates the number is within an acceptable range for milliseconds [0-999]. + * @param {Number} The number to check if within range. + * @return {Boolean} true if within range, otherwise false. + */ + $D.validateMillisecond = function (value) { + return validate(value, 0, 999, "millisecond"); + }; + + /** + * Validates the number is within an acceptable range for seconds [0-59]. + * @param {Number} The number to check if within range. + * @return {Boolean} true if within range, otherwise false. + */ + $D.validateSecond = function (value) { + return validate(value, 0, 59, "second"); + }; + + /** + * Validates the number is within an acceptable range for minutes [0-59]. + * @param {Number} The number to check if within range. + * @return {Boolean} true if within range, otherwise false. + */ + $D.validateMinute = function (value) { + return validate(value, 0, 59, "minute"); + }; + + /** + * Validates the number is within an acceptable range for hours [0-23]. + * @param {Number} The number to check if within range. + * @return {Boolean} true if within range, otherwise false. + */ + $D.validateHour = function (value) { + return validate(value, 0, 23, "hour"); + }; + + /** + * Validates the number is within an acceptable range for the days in a month [0-MaxDaysInMonth]. + * @param {Number} The number to check if within range. + * @return {Boolean} true if within range, otherwise false. + */ + $D.validateDay = function (value, year, month) { + return validate(value, 1, $D.getDaysInMonth(year, month), "day"); + }; + + /** + * Validates the number is within an acceptable range for months [0-11]. + * @param {Number} The number to check if within range. + * @return {Boolean} true if within range, otherwise false. + */ + $D.validateMonth = function (value) { + return validate(value, 0, 11, "month"); + }; + + /** + * Validates the number is within an acceptable range for years. + * @param {Number} The number to check if within range. + * @return {Boolean} true if within range, otherwise false. + */ + $D.validateYear = function (value) { + return validate(value, 0, 9999, "year"); + }; + + /** + * Set the value of year, month, day, hour, minute, second, millisecond of date instance using given configuration object. + * Example +

+    Date.today().set( { day: 20, month: 1 } )
+
+    new Date().set( { millisecond: 0 } )
+    
+ * + * @param {Object} Configuration object containing attributes (month, day, etc.) + * @return {Date} this + */ + $P.set = function (config) { + if ($D.validateMillisecond(config.millisecond)) { + this.addMilliseconds(config.millisecond - this.getMilliseconds()); + } + + if ($D.validateSecond(config.second)) { + this.addSeconds(config.second - this.getSeconds()); + } + + if ($D.validateMinute(config.minute)) { + this.addMinutes(config.minute - this.getMinutes()); + } + + if ($D.validateHour(config.hour)) { + this.addHours(config.hour - this.getHours()); + } + + if ($D.validateMonth(config.month)) { + this.addMonths(config.month - this.getMonth()); + } + + if ($D.validateYear(config.year)) { + this.addYears(config.year - this.getFullYear()); + } + + /* day has to go last because you can't validate the day without first knowing the month */ + if ($D.validateDay(config.day, this.getFullYear(), this.getMonth())) { + this.addDays(config.day - this.getDate()); + } + + if (config.timezone) { + this.setTimezone(config.timezone); + } + + if (config.timezoneOffset) { + this.setTimezoneOffset(config.timezoneOffset); + } + + if (config.week && validate(config.week, 0, 53, "week")) { + this.setWeek(config.week); + } + + return this; + }; + + /** + * Moves the date to the first day of the month. + * @return {Date} this + */ + $P.moveToFirstDayOfMonth = function () { + return this.set({ day: 1 }); + }; + + /** + * Moves the date to the last day of the month. + * @return {Date} this + */ + $P.moveToLastDayOfMonth = function () { + return this.set({ day: $D.getDaysInMonth(this.getFullYear(), this.getMonth())}); + }; + + /** + * Moves the date to the next n'th occurrence of the dayOfWeek starting from the beginning of the month. The number (-1) is a magic number and will return the last occurrence of the dayOfWeek in the month. + * @param {Number} The dayOfWeek to move to + * @param {Number} The n'th occurrence to move to. Use (-1) to return the last occurrence in the month + * @return {Date} this + */ + $P.moveToNthOccurrence = function (dayOfWeek, occurrence) { + var shift = 0; + if (occurrence > 0) { + shift = occurrence - 1; + } + else if (occurrence === -1) { + this.moveToLastDayOfMonth(); + if (this.getDay() !== dayOfWeek) { + this.moveToDayOfWeek(dayOfWeek, -1); + } + return this; + } + return this.moveToFirstDayOfMonth().addDays(-1).moveToDayOfWeek(dayOfWeek, +1).addWeeks(shift); + }; + + /** + * Move to the next or last dayOfWeek based on the orient value. + * @param {Number} The dayOfWeek to move to + * @param {Number} Forward (+1) or Back (-1). Defaults to +1. [Optional] + * @return {Date} this + */ + $P.moveToDayOfWeek = function (dayOfWeek, orient) { + var diff = (dayOfWeek - this.getDay() + 7 * (orient || +1)) % 7; + return this.addDays((diff === 0) ? diff += 7 * (orient || +1) : diff); + }; + + /** + * Move to the next or last month based on the orient value. + * @param {Number} The month to move to. 0 = January, 11 = December + * @param {Number} Forward (+1) or Back (-1). Defaults to +1. [Optional] + * @return {Date} this + */ + $P.moveToMonth = function (month, orient) { + var diff = (month - this.getMonth() + 12 * (orient || +1)) % 12; + return this.addMonths((diff === 0) ? diff += 12 * (orient || +1) : diff); + }; + + /** + * Get the Ordinal day (numeric day number) of the year, adjusted for leap year. + * @return {Number} 1 through 365 (366 in leap years) + */ + $P.getOrdinalNumber = function () { + return Math.ceil((this.clone().clearTime() - new Date(this.getFullYear(), 0, 1)) / 86400000) + 1; + }; + + /** + * Get the time zone abbreviation of the current date. + * @return {String} The abbreviated time zone name (e.g. "EST") + */ + $P.getTimezone = function () { + return $D.getTimezoneAbbreviation(this.getUTCOffset()); + }; + + $P.setTimezoneOffset = function (offset) { + var here = this.getTimezoneOffset(), there = Number(offset) * -6 / 10; + return this.addMinutes(there - here); + }; + + $P.setTimezone = function (offset) { + return this.setTimezoneOffset($D.getTimezoneOffset(offset)); + }; + + /** + * Indicates whether Daylight Saving Time is observed in the current time zone. + * @return {Boolean} true|false + */ + $P.hasDaylightSavingTime = function () { + return (Date.today().set({month: 0, day: 1}).getTimezoneOffset() !== Date.today().set({month: 6, day: 1}).getTimezoneOffset()); + }; + + /** + * Indicates whether this Date instance is within the Daylight Saving Time range for the current time zone. + * @return {Boolean} true|false + */ + $P.isDaylightSavingTime = function () { + return Date.today().set({month: 0, day: 1}).getTimezoneOffset() != this.getTimezoneOffset(); + }; + + /** + * Get the offset from UTC of the current date. + * @return {String} The 4-character offset string prefixed with + or - (e.g. "-0500") + */ + $P.getUTCOffset = function () { + var n = this.getTimezoneOffset() * -10 / 6, r; + if (n < 0) { + r = (n - 10000).toString(); + return r.charAt(0) + r.substr(2); + } else { + r = (n + 10000).toString(); + return "+" + r.substr(1); + } + }; + + /** + * Returns the number of milliseconds between this date and date. + * @param {Date} Defaults to now + * @return {Number} The diff in milliseconds + */ + $P.getElapsed = function (date) { + return (date || new Date()) - this; + }; + + if (!$P.toISOString) { + /** + * Converts the current date instance into a string with an ISO 8601 format. The date is converted to it's UTC value. + * @return {String} ISO 8601 string of date + */ + $P.toISOString = function () { + // From http://www.json.org/json.js. Public Domain. + function f(n) { + return n < 10 ? '0' + n : n; + } + + return '"' + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z"'; + }; + } + + // private + $P._toString = $P.toString; + + /** + * Converts the value of the current Date object to its equivalent string representation. + * Format Specifiers +
+    CUSTOM DATE AND TIME FORMAT STRINGS
+    Format  Description                                                                  Example
+    ------  ---------------------------------------------------------------------------  -----------------------
+     s      The seconds of the minute between 0-59.                                      "0" to "59"
+     ss     The seconds of the minute with leading zero if required.                     "00" to "59"
+
+     m      The minute of the hour between 0-59.                                         "0"  or "59"
+     mm     The minute of the hour with leading zero if required.                        "00" or "59"
+
+     h      The hour of the day between 1-12.                                            "1"  to "12"
+     hh     The hour of the day with leading zero if required.                           "01" to "12"
+
+     H      The hour of the day between 0-23.                                            "0"  to "23"
+     HH     The hour of the day with leading zero if required.                           "00" to "23"
+
+     d      The day of the month between 1 and 31.                                       "1"  to "31"
+     dd     The day of the month with leading zero if required.                          "01" to "31"
+     ddd    Abbreviated day name. $C.abbreviatedDayNames.                                "Mon" to "Sun"
+     dddd   The full day name. $C.dayNames.                                              "Monday" to "Sunday"
+
+     M      The month of the year between 1-12.                                          "1" to "12"
+     MM     The month of the year with leading zero if required.                         "01" to "12"
+     MMM    Abbreviated month name. $C.abbreviatedMonthNames.                            "Jan" to "Dec"
+     MMMM   The full month name. $C.monthNames.                                          "January" to "December"
+
+     yy     The year as a two-digit number.                                              "99" or "08"
+     yyyy   The full four digit year.                                                    "1999" or "2008"
+
+     t      Displays the first character of the A.M./P.M. designator.                    "A" or "P"
+            $C.amDesignator or $C.pmDesignator
+     tt     Displays the A.M./P.M. designator.                                           "AM" or "PM"
+            $C.amDesignator or $C.pmDesignator
+
+     S      The ordinal suffix ("st, "nd", "rd" or "th") of the current day.            "st, "nd", "rd" or "th"
+
+|| *Format* || *Description* || *Example* ||
+|| d      || The CultureInfo shortDate Format Pattern                                     || "M/d/yyyy" ||
+|| D      || The CultureInfo longDate Format Pattern                                      || "dddd, MMMM dd, yyyy" ||
+|| F      || The CultureInfo fullDateTime Format Pattern                                  || "dddd, MMMM dd, yyyy h:mm:ss tt" ||
+|| m      || The CultureInfo monthDay Format Pattern                                      || "MMMM dd" ||
+|| r      || The CultureInfo rfc1123 Format Pattern                                       || "ddd, dd MMM yyyy HH:mm:ss GMT" ||
+|| s      || The CultureInfo sortableDateTime Format Pattern                              || "yyyy-MM-ddTHH:mm:ss" ||
+|| t      || The CultureInfo shortTime Format Pattern                                     || "h:mm tt" ||
+|| T      || The CultureInfo longTime Format Pattern                                      || "h:mm:ss tt" ||
+|| u      || The CultureInfo universalSortableDateTime Format Pattern                     || "yyyy-MM-dd HH:mm:ssZ" ||
+|| y      || The CultureInfo yearMonth Format Pattern                                     || "MMMM, yyyy" ||
+
+
+    STANDARD DATE AND TIME FORMAT STRINGS
+    Format  Description                                                                  Example ("en-US")
+    ------  ---------------------------------------------------------------------------  -----------------------
+     d      The CultureInfo shortDate Format Pattern                                     "M/d/yyyy"
+     D      The CultureInfo longDate Format Pattern                                      "dddd, MMMM dd, yyyy"
+     F      The CultureInfo fullDateTime Format Pattern                                  "dddd, MMMM dd, yyyy h:mm:ss tt"
+     m      The CultureInfo monthDay Format Pattern                                      "MMMM dd"
+     r      The CultureInfo rfc1123 Format Pattern                                       "ddd, dd MMM yyyy HH:mm:ss GMT"
+     s      The CultureInfo sortableDateTime Format Pattern                              "yyyy-MM-ddTHH:mm:ss"
+     t      The CultureInfo shortTime Format Pattern                                     "h:mm tt"
+     T      The CultureInfo longTime Format Pattern                                      "h:mm:ss tt"
+     u      The CultureInfo universalSortableDateTime Format Pattern                     "yyyy-MM-dd HH:mm:ssZ"
+     y      The CultureInfo yearMonth Format Pattern                                     "MMMM, yyyy"
+    
+ * @param {String} A format string consisting of one or more format spcifiers [Optional]. + * @return {String} A string representation of the current Date object. + */ + $P.toString = function (format) { + var x = this; + + // Standard Date and Time Format Strings. Formats pulled from CultureInfo file and + // may vary by culture. + if (format && format.length == 1) { + var c = $C.formatPatterns; + x.t = x.toString; + switch (format) { + case "d": + return x.t(c.shortDate); + case "D": + return x.t(c.longDate); + case "F": + return x.t(c.fullDateTime); + case "m": + return x.t(c.monthDay); + case "r": + return x.t(c.rfc1123); + case "s": + return x.t(c.sortableDateTime); + case "t": + return x.t(c.shortTime); + case "T": + return x.t(c.longTime); + case "u": + return x.t(c.universalSortableDateTime); + case "y": + return x.t(c.yearMonth); + } + } + + var ord = function (n) { + switch (n * 1) { + case 1: + case 21: + case 31: + return "st"; + case 2: + case 22: + return "nd"; + case 3: + case 23: + return "rd"; + default: + return "th"; + } + }; + + return format ? format.replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S)/g, + function (m) { + if (m.charAt(0) === "\\") { + return m.replace("\\", ""); + } + x.h = x.getHours; + switch (m) { + case "hh": + return p(x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12)); + case "h": + return x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12); + case "HH": + return p(x.h()); + case "H": + return x.h(); + case "mm": + return p(x.getMinutes()); + case "m": + return x.getMinutes(); + case "ss": + return p(x.getSeconds()); + case "s": + return x.getSeconds(); + case "yyyy": + return p(x.getFullYear(), 4); + case "yy": + return p(x.getFullYear()); + case "dddd": + return $C.dayNames[x.getDay()]; + case "ddd": + return $C.abbreviatedDayNames[x.getDay()]; + case "dd": + return p(x.getDate()); + case "d": + return x.getDate(); + case "MMMM": + return $C.monthNames[x.getMonth()]; + case "MMM": + return $C.abbreviatedMonthNames[x.getMonth()]; + case "MM": + return p((x.getMonth() + 1)); + case "M": + return x.getMonth() + 1; + case "t": + return x.h() < 12 ? $C.amDesignator.substring(0, 1) : $C.pmDesignator.substring(0, 1); + case "tt": + return x.h() < 12 ? $C.amDesignator : $C.pmDesignator; + case "S": + return ord(x.getDate()); + default: + return m; + } + } + ) : this._toString(); + }; +}()); /** + * @version: 1.0 Alpha-1 + * @author: Coolite Inc. http://www.coolite.com/ + * @date: 2008-04-13 + * @copyright: Copyright (c) 2006-2008, Coolite Inc. (http://www.coolite.com/). All rights reserved. + * @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. + * @website: http://www.datejs.com/ + */ + +(function () { + Date.Parsing = { + Exception: function (s) { + this.message = "Parse error at '" + s.substring(0, 10) + " ...'"; + } + }; + + var $P = Date.Parsing; + var _ = $P.Operators = { + // + // Tokenizers + // + rtoken: function (r) { // regex token + return function (s) { + var mx = s.match(r); + if (mx) { + return ([ mx[0], s.substring(mx[0].length) ]); + } else { + throw new $P.Exception(s); + } + }; + }, + token: function (s) { // whitespace-eating token + return function (s) { + return _.rtoken(new RegExp("^\s*" + s + "\s*"))(s); + // Removed .strip() + // return _.rtoken(new RegExp("^\s*" + s + "\s*"))(s).strip(); + }; + }, + stoken: function (s) { // string token + return _.rtoken(new RegExp("^" + s)); + }, + + // + // Atomic Operators + // + + until: function (p) { + return function (s) { + var qx = [], rx = null; + while (s.length) { + try { + rx = p.call(this, s); + } catch (e) { + qx.push(rx[0]); + s = rx[1]; + continue; + } + break; + } + return [ qx, s ]; + }; + }, + many: function (p) { + return function (s) { + var rx = [], r = null; + while (s.length) { + try { + r = p.call(this, s); + } catch (e) { + return [ rx, s ]; + } + rx.push(r[0]); + s = r[1]; + } + return [ rx, s ]; + }; + }, + + // generator operators -- see below + optional: function (p) { + return function (s) { + var r = null; + try { + r = p.call(this, s); + } catch (e) { + return [ null, s ]; + } + return [ r[0], r[1] ]; + }; + }, + not: function (p) { + return function (s) { + try { + p.call(this, s); + } catch (e) { + return [null, s]; + } + throw new $P.Exception(s); + }; + }, + ignore: function (p) { + return p ? + function (s) { + var r = null; + r = p.call(this, s); + return [null, r[1]]; + } : null; + }, + product: function () { + var px = arguments[0], + qx = Array.prototype.slice.call(arguments, 1), rx = []; + for (var i = 0 ; i < px.length ; i++) { + rx.push(_.each(px[i], qx)); + } + return rx; + }, + cache: function (rule) { + var cache = {}, r = null; + return function (s) { + try { + r = cache[s] = (cache[s] || rule.call(this, s)); + } catch (e) { + r = cache[s] = e; + } + if (r instanceof $P.Exception) { + throw r; + } else { + return r; + } + }; + }, + + // vector operators -- see below + any: function () { + var px = arguments; + return function (s) { + var r = null; + for (var i = 0; i < px.length; i++) { + if (px[i] == null) { + continue; + } + try { + r = (px[i].call(this, s)); + } catch (e) { + r = null; + } + if (r) { + return r; + } + } + throw new $P.Exception(s); + }; + }, + each: function () { + var px = arguments; + return function (s) { + var rx = [], r = null; + for (var i = 0; i < px.length ; i++) { + if (px[i] == null) { + continue; + } + try { + r = (px[i].call(this, s)); + } catch (e) { + throw new $P.Exception(s); + } + rx.push(r[0]); + s = r[1]; + } + return [ rx, s]; + }; + }, + all: function () { + var px = arguments, _ = _; + return _.each(_.optional(px)); + }, + + // delimited operators + sequence: function (px, d, c) { + d = d || _.rtoken(/^\s*/); + c = c || null; + + if (px.length == 1) { + return px[0]; + } + return function (s) { + var r = null, q = null; + var rx = []; + for (var i = 0; i < px.length ; i++) { + try { + r = px[i].call(this, s); + } catch (e) { + break; + } + rx.push(r[0]); + try { + q = d.call(this, r[1]); + } catch (ex) { + q = null; + break; + } + s = q[1]; + } + if (!r) { + throw new $P.Exception(s); + } + if (q) { + throw new $P.Exception(q[1]); + } + if (c) { + try { + r = c.call(this, r[1]); + } catch (ey) { + throw new $P.Exception(r[1]); + } + } + return [ rx, (r?r[1]:s) ]; + }; + }, + + // + // Composite Operators + // + + between: function (d1, p, d2) { + d2 = d2 || d1; + var _fn = _.each(_.ignore(d1), p, _.ignore(d2)); + return function (s) { + var rx = _fn.call(this, s); + return [[rx[0][0], r[0][2]], rx[1]]; + }; + }, + list: function (p, d, c) { + d = d || _.rtoken(/^\s*/); + c = c || null; + return (p instanceof Array ? + _.each(_.product(p.slice(0, -1), _.ignore(d)), p.slice(-1), _.ignore(c)) : + _.each(_.many(_.each(p, _.ignore(d))), px, _.ignore(c))); + }, + set: function (px, d, c) { + d = d || _.rtoken(/^\s*/); + c = c || null; + return function (s) { + // r is the current match, best the current 'best' match + // which means it parsed the most amount of input + var r = null, p = null, q = null, rx = null, best = [[], s], last = false; + + // go through the rules in the given set + for (var i = 0; i < px.length ; i++) { + + // last is a flag indicating whether this must be the last element + // if there is only 1 element, then it MUST be the last one + q = null; + p = null; + r = null; + last = (px.length == 1); + + // first, we try simply to match the current pattern + // if not, try the next pattern + try { + r = px[i].call(this, s); + } catch (e) { + continue; + } + + // since we are matching against a set of elements, the first + // thing to do is to add r[0] to matched elements + rx = [[r[0]], r[1]]; + + // if we matched and there is still input to parse and + // we don't already know this is the last element, + // we're going to next check for the delimiter ... + // if there's none, or if there's no input left to parse + // than this must be the last element after all ... + if (r[1].length > 0 && ! last) { + try { + q = d.call(this, r[1]); + } catch (ex) { + last = true; + } + } else { + last = true; + } + + // if we parsed the delimiter and now there's no more input, + // that means we shouldn't have parsed the delimiter at all + // so don't update r and mark this as the last element ... + if (!last && q[1].length === 0) { + last = true; + } + + + // so, if this isn't the last element, we're going to see if + // we can get any more matches from the remaining (unmatched) + // elements ... + if (!last) { + + // build a list of the remaining rules we can match against, + // i.e., all but the one we just matched against + var qx = []; + for (var j = 0; j < px.length ; j++) { + if (i != j) { + qx.push(px[j]); + } + } + + // now invoke recursively set with the remaining input + // note that we don't include the closing delimiter ... + // we'll check for that ourselves at the end + p = _.set(qx, d).call(this, q[1]); + + // if we got a non-empty set as a result ... + // (otw rx already contains everything we want to match) + if (p[0].length > 0) { + // update current result, which is stored in rx ... + // basically, pick up the remaining text from p[1] + // and concat the result from p[0] so that we don't + // get endless nesting ... + rx[0] = rx[0].concat(p[0]); + rx[1] = p[1]; + } + } + + // at this point, rx either contains the last matched element + // or the entire matched set that starts with this element. + + // now we just check to see if this variation is better than + // our best so far, in terms of how much of the input is parsed + if (rx[1].length < best[1].length) { + best = rx; + } + + // if we've parsed all the input, then we're finished + if (best[1].length === 0) { + break; + } + } + + // so now we've either gone through all the patterns trying them + // as the initial match; or we found one that parsed the entire + // input string ... + + // if best has no matches, just return empty set ... + if (best[0].length === 0) { + return best; + } + + // if a closing delimiter is provided, then we have to check it also + if (c) { + // we try this even if there is no remaining input because the pattern + // may well be optional or match empty input ... + try { + q = c.call(this, best[1]); + } catch (ey) { + throw new $P.Exception(best[1]); + } + + // it parsed ... be sure to update the best match remaining input + best[1] = q[1]; + } + + // if we're here, either there was no closing delimiter or we parsed it + // so now we have the best match; just return it! + return best; + }; + }, + forward: function (gr, fname) { + return function (s) { + return gr[fname].call(this, s); + }; + }, + + // + // Translation Operators + // + replace: function (rule, repl) { + return function (s) { + var r = rule.call(this, s); + return [repl, r[1]]; + }; + }, + process: function (rule, fn) { + return function (s) { + var r = rule.call(this, s); + return [fn.call(this, r[0]), r[1]]; + }; + }, + min: function (min, rule) { + return function (s) { + var rx = rule.call(this, s); + if (rx[0].length < min) { + throw new $P.Exception(s); + } + return rx; + }; + } + }; + + + // Generator Operators And Vector Operators + + // Generators are operators that have a signature of F(R) => R, + // taking a given rule and returning another rule, such as + // ignore, which parses a given rule and throws away the result. + + // Vector operators are those that have a signature of F(R1,R2,...) => R, + // take a list of rules and returning a new rule, such as each. + + // Generator operators are converted (via the following _generator + // function) into functions that can also take a list or array of rules + // and return an array of new rules as though the function had been + // called on each rule in turn (which is what actually happens). + + // This allows generators to be used with vector operators more easily. + // Example: + // each(ignore(foo, bar)) instead of each(ignore(foo), ignore(bar)) + + // This also turns generators into vector operators, which allows + // constructs like: + // not(cache(foo, bar)) + + var _generator = function (op) { + return function () { + var args = null, rx = []; + if (arguments.length > 1) { + args = Array.prototype.slice.call(arguments); + } else if (arguments[0] instanceof Array) { + args = arguments[0]; + } + if (args) { + for (var i = 0, px = args.shift() ; i < px.length ; i++) { + args.unshift(px[i]); + rx.push(op.apply(null, args)); + args.shift(); + return rx; + } + } else { + return op.apply(null, arguments); + } + }; + }; + + var gx = "optional not ignore cache".split(/\s/); + + for (var i = 0 ; i < gx.length ; i++) { + _[gx[i]] = _generator(_[gx[i]]); + } + + var _vector = function (op) { + return function () { + if (arguments[0] instanceof Array) { + return op.apply(null, arguments[0]); + } else { + return op.apply(null, arguments); + } + }; + }; + + var vx = "each any all".split(/\s/); + + for (var j = 0 ; j < vx.length ; j++) { + _[vx[j]] = _vector(_[vx[j]]); + } + +}()); + +(function () { + var $D = Date, $P = $D.prototype, $C = $D.CultureInfo; + + var flattenAndCompact = function (ax) { + var rx = []; + for (var i = 0; i < ax.length; i++) { + if (ax[i] instanceof Array) { + rx = rx.concat(flattenAndCompact(ax[i])); + } else { + if (ax[i]) { + rx.push(ax[i]); + } + } + } + return rx; + }; + + $D.Grammar = {}; + + $D.Translator = { + hour: function (s) { + return function () { + this.hour = Number(s); + }; + }, + minute: function (s) { + return function () { + this.minute = Number(s); + }; + }, + second: function (s) { + return function () { + this.second = Number(s); + }; + }, + meridian: function (s) { + return function () { + this.meridian = s.slice(0, 1).toLowerCase(); + }; + }, + timezone: function (s) { + return function () { + var n = s.replace(/[^\d\+\-]/g, ""); + if (n.length) { + this.timezoneOffset = Number(n); + } else { + this.timezone = s.toLowerCase(); + } + }; + }, + day: function (x) { + var s = x[0]; + return function () { + this.day = Number(s.match(/\d+/)[0]); + }; + }, + month: function (s) { + return function () { + this.month = (s.length == 3) ? "jan feb mar apr may jun jul aug sep oct nov dec".indexOf(s)/4 : Number(s) - 1; + }; + }, + year: function (s) { + return function () { + var n = Number(s); + this.year = ((s.length > 2) ? n : + (n + (((n + 2000) < $C.twoDigitYearMax) ? 2000 : 1900))); + }; + }, + rday: function (s) { + return function () { + switch (s) { + case "yesterday": + this.days = -1; + break; + case "tomorrow": + this.days = 1; + break; + case "today": + this.days = 0; + break; + case "now": + this.days = 0; + this.now = true; + break; + } + }; + }, + finishExact: function (x) { + x = (x instanceof Array) ? x : [ x ]; + + for (var i = 0 ; i < x.length ; i++) { + if (x[i]) { + x[i].call(this); + } + } + + var now = new Date(); + + if ((this.hour || this.minute) && (!this.month && !this.year && !this.day)) { + this.day = now.getDate(); + } + + if (!this.year) { + this.year = now.getFullYear(); + } + + if (!this.month && this.month !== 0) { + this.month = now.getMonth(); + } + + if (!this.day) { + this.day = 1; + } + + if (!this.hour) { + this.hour = 0; + } + + if (!this.minute) { + this.minute = 0; + } + + if (!this.second) { + this.second = 0; + } + + if (this.meridian && this.hour) { + if (this.meridian == "p" && this.hour < 12) { + this.hour = this.hour + 12; + } else if (this.meridian == "a" && this.hour == 12) { + this.hour = 0; + } + } + + if (this.day > $D.getDaysInMonth(this.year, this.month)) { + throw new RangeError(this.day + " is not a valid value for days."); + } + + var r = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second); + + if (this.timezone) { + r.set({ timezone: this.timezone }); + } else if (this.timezoneOffset) { + r.set({ timezoneOffset: this.timezoneOffset }); + } + + return r; + }, + finish: function (x) { + x = (x instanceof Array) ? flattenAndCompact(x) : [ x ]; + + if (x.length === 0) { + return null; + } + + for (var i = 0 ; i < x.length ; i++) { + if (typeof x[i] == "function") { + x[i].call(this); + } + } + + var today = $D.today(); + + if (this.now && !this.unit && !this.operator) { + return new Date(); + } else if (this.now) { + today = new Date(); + } + + var expression = !!(this.days && this.days !== null || this.orient || this.operator); + + var gap, mod, orient; + orient = ((this.orient == "past" || this.operator == "subtract") ? -1 : 1); + + if(!this.now && "hour minute second".indexOf(this.unit) != -1) { + today.setTimeToNow(); + } + + if (this.month || this.month === 0) { + if ("year day hour minute second".indexOf(this.unit) != -1) { + this.value = this.month + 1; + this.month = null; + expression = true; + } + } + + if (!expression && this.weekday && !this.day && !this.days) { + var temp = Date[this.weekday](); + this.day = temp.getDate(); + if (!this.month) { + this.month = temp.getMonth(); + } + this.year = temp.getFullYear(); + } + + if (expression && this.weekday && this.unit != "month") { + this.unit = "day"; + gap = ($D.getDayNumberFromName(this.weekday) - today.getDay()); + mod = 7; + this.days = gap ? ((gap + (orient * mod)) % mod) : (orient * mod); + } -/** - * @namespace - */ -sc.helpers = {}; + if (this.month && this.unit == "day" && this.operator) { + this.value = (this.month + 1); + this.month = null; + } -/** - * dump level for limiting what gets dumped to console - */ -sc.dumplevel = 1; + if (this.value != null && this.month != null && this.year != null) { + this.day = this.value * 1; + } -/** - * method to set dump level - */ -sc.setDumpLevel = function(level) { - sc.dumplevel = parseInt(level, 10); -}; + if (this.month && !this.day && this.value) { + today.set({ day: this.value * 1 }); + if (!expression) { + this.day = this.value * 1; + } + } -/** - * @namespace helper shortcuts - * this lets us write "sch.method" instead of "sc.helpers.method" - * - */ -var sch = sc.helpers; + if (!this.month && this.value && this.unit == "month" && !this.now) { + this.month = this.value; + expression = true; + } + if (expression && (this.month || this.month === 0) && this.unit != "year") { + this.unit = "month"; + gap = (this.month - today.getMonth()); + mod = 12; + this.months = gap ? ((gap + (orient * mod)) % mod) : (orient * mod); + this.month = null; + } -sc.events = {}; + if (!this.unit) { + this.unit = "day"; + } + if (!this.value && this.operator && this.operator !== null && this[this.unit + "s"] && this[this.unit + "s"] !== null) { + this[this.unit + "s"] = this[this.unit + "s"] + ((this.operator == "add") ? 1 : -1) + (this.value||0) * orient; + } else if (this[this.unit + "s"] == null || this.operator != null) { + if (!this.value) { + this.value = 1; + } + this[this.unit + "s"] = this.value * orient; + } + if (this.meridian && this.hour) { + if (this.meridian == "p" && this.hour < 12) { + this.hour = this.hour + 12; + } else if (this.meridian == "a" && this.hour == 12) { + this.hour = 0; + } + } -/** - * various constant definitions that aren't specific to a single library - */ + if (this.weekday && !this.day && !this.days) { + var temp = Date[this.weekday](); + this.day = temp.getDate(); + if (temp.getMonth() !== today.getMonth()) { + this.month = temp.getMonth(); + } + } -/** - * @constant - */ -var SPAZCORE_SERVICE_TWITTER = 'twitter'; -/** - * @constant - */ -var SPAZCORE_SERVICE_IDENTICA = 'identi.ca'; -/** - * @constant - */ -var SPAZCORE_SERVICE_FREELISHUS = 'freelish.us'; -/** - * @constant - */ -var SPAZCORE_SERVICE_WORDPRESS_TWITTER = 'wordpress-twitter'; -/** - * @constant - */ -var SPAZCORE_SERVICE_TUMBLR_TWITTER = 'tumblr-twitter'; -/** - * @constant - */ -var SPAZCORE_SERVICE_CUSTOM = 'custom'; + if ((this.month || this.month === 0) && !this.day) { + this.day = 1; + } -/** - * @constant - */ -var SPAZCORE_BASEURL_TWITTER = 'https://twitter.com/'; -/** - * @constant - */ -var SPAZCORE_BASEURL_IDENTICA = 'https://identi.ca/'; -/** - * @constant - */ -var SPAZCORE_BASEURL_FREELISHUS = 'http://freelish.us/'; + if (!this.orient && !this.operator && this.unit == "week" && this.value && !this.day && !this.month) { + return Date.today().setWeek(this.value); + } + if (expression && this.timezone && this.day && this.days) { + this.day = this.days; + } + return (expression) ? today.add(this) : today.set(this); + } + }; -/** - * Build the helpers - * @depends ../helpers/datetime.js - * @depends ../helpers/event.js - * @depends ../helpers/javascript.js - * @depends ../helpers/json.js - * @depends ../helpers/location.js - * @depends ../helpers/string.js - * @depends ../helpers/sys.js - * @depends ../helpers/view.js - * @depends ../helpers/xml.js - * - * Build the libs - * @depends spazcron.js - * @depends spazlocker.js - * @depends spazphotomailer.js - * @depends spazpingfm.js - * @depends spazprefs.js - * @depends spazshorttext.js - * @depends spazshorturl.js - * @depends spaztemplate.js - * @depends spaztimeline.js - * @depends spaztwit.js - */ -Date.CultureInfo = { - /* Culture Name */ - name: "en-US", - englishName: "English (United States)", - nativeName: "English (United States)", - - /* Day Name Strings */ - dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], - abbreviatedDayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], - shortestDayNames: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], - firstLetterDayNames: ["S", "M", "T", "W", "T", "F", "S"], - - /* Month Name Strings */ - monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], - abbreviatedMonthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], - - /* AM/PM Designators */ - amDesignator: "AM", - pmDesignator: "PM", - - firstDayOfWeek: 0, - twoDigitYearMax: 2029, - - /** - * The dateElementOrder is based on the order of the - * format specifiers in the formatPatterns.DatePattern. - * - * Example: -
-     shortDatePattern    dateElementOrder
-     ------------------  ---------------- 
-     "M/d/yyyy"          "mdy"
-     "dd/MM/yyyy"        "dmy"
-     "yyyy-MM-dd"        "ymd"
-     
- * - * The correct dateElementOrder is required by the parser to - * determine the expected order of the date elements in the - * string being parsed. - */ - dateElementOrder: "mdy", - - /* Standard date and time format patterns */ - formatPatterns: { - shortDate: "M/d/yyyy", - longDate: "dddd, MMMM dd, yyyy", - shortTime: "h:mm tt", - longTime: "h:mm:ss tt", - fullDateTime: "dddd, MMMM dd, yyyy h:mm:ss tt", - sortableDateTime: "yyyy-MM-ddTHH:mm:ss", - universalSortableDateTime: "yyyy-MM-dd HH:mm:ssZ", - rfc1123: "ddd, dd MMM yyyy HH:mm:ss GMT", - monthDay: "MMMM dd", - yearMonth: "MMMM, yyyy" - }, - - /** - * NOTE: If a string format is not parsing correctly, but - * you would expect it parse, the problem likely lies below. - * - * The following regex patterns control most of the string matching - * within the parser. - * - * The Month name and Day name patterns were automatically generated - * and in general should be (mostly) correct. - * - * Beyond the month and day name patterns are natural language strings. - * Example: "next", "today", "months" - * - * These natural language string may NOT be correct for this culture. - * If they are not correct, please translate and edit this file - * providing the correct regular expression pattern. - * - * If you modify this file, please post your revised CultureInfo file - * to the Datejs Forum located at http://www.datejs.com/forums/. - * - * Please mark the subject of the post with [CultureInfo]. Example: - * Subject: [CultureInfo] Translated "da-DK" Danish(Denmark) - * - * We will add the modified patterns to the master source files. - * - * As well, please review the list of "Future Strings" section below. - */ - regexPatterns: { - jan: /^jan(uary)?/i, - feb: /^feb(ruary)?/i, - mar: /^mar(ch)?/i, - apr: /^apr(il)?/i, - may: /^may/i, - jun: /^jun(e)?/i, - jul: /^jul(y)?/i, - aug: /^aug(ust)?/i, - sep: /^sep(t(ember)?)?/i, - oct: /^oct(ober)?/i, - nov: /^nov(ember)?/i, - dec: /^dec(ember)?/i, - - sun: /^su(n(day)?)?/i, - mon: /^mo(n(day)?)?/i, - tue: /^tu(e(s(day)?)?)?/i, - wed: /^we(d(nesday)?)?/i, - thu: /^th(u(r(s(day)?)?)?)?/i, - fri: /^fr(i(day)?)?/i, - sat: /^sa(t(urday)?)?/i, - - future: /^next/i, - past: /^last|past|prev(ious)?/i, - add: /^(\+|aft(er)?|from|hence)/i, - subtract: /^(\-|bef(ore)?|ago)/i, - - yesterday: /^yes(terday)?/i, - today: /^t(od(ay)?)?/i, - tomorrow: /^tom(orrow)?/i, - now: /^n(ow)?/i, - - millisecond: /^ms|milli(second)?s?/i, - second: /^sec(ond)?s?/i, - minute: /^mn|min(ute)?s?/i, - hour: /^h(our)?s?/i, - week: /^w(eek)?s?/i, - month: /^m(onth)?s?/i, - day: /^d(ay)?s?/i, - year: /^y(ear)?s?/i, - - shortMeridian: /^(a|p)/i, - longMeridian: /^(a\.?m?\.?|p\.?m?\.?)/i, - timezone: /^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt|utc)/i, - ordinalSuffix: /^\s*(st|nd|rd|th)/i, - timeContext: /^\s*(\:|a(?!u|p)|p)/i - }, - - timezones: [{name:"UTC", offset:"-000"}, {name:"GMT", offset:"-000"}, {name:"EST", offset:"-0500"}, {name:"EDT", offset:"-0400"}, {name:"CST", offset:"-0600"}, {name:"CDT", offset:"-0500"}, {name:"MST", offset:"-0700"}, {name:"MDT", offset:"-0600"}, {name:"PST", offset:"-0800"}, {name:"PDT", offset:"-0700"}] -}; - -/******************** - ** Future Strings ** - ******************** - * - * The following list of strings may not be currently being used, but - * may be incorporated into the Datejs library later. - * - * We would appreciate any help translating the strings below. - * - * If you modify this file, please post your revised CultureInfo file - * to the Datejs Forum located at http://www.datejs.com/forums/. - * - * Please mark the subject of the post with [CultureInfo]. Example: - * Subject: [CultureInfo] Translated "da-DK" Danish(Denmark)b - * - * English Name Translated - * ------------------ ----------------- - * about about - * ago ago - * date date - * time time - * calendar calendar - * show show - * hourly hourly - * daily daily - * weekly weekly - * bi-weekly bi-weekly - * fortnight fortnight - * monthly monthly - * bi-monthly bi-monthly - * quarter quarter - * quarterly quarterly - * yearly yearly - * annual annual - * annually annually - * annum annum - * again again - * between between - * after after - * from now from now - * repeat repeat - * times times - * per per - * min (abbrev minute) min - * morning morning - * noon noon - * night night - * midnight midnight - * mid-night mid-night - * evening evening - * final final - * future future - * spring spring - * summer summer - * fall fall - * winter winter - * end of end of - * end end - * long long - * short short - *//** - * @version: 1.0 Alpha-1 - * @author: Coolite Inc. http://www.coolite.com/ - * @date: 2008-04-13 - * @copyright: Copyright (c) 2006-2008, Coolite Inc. (http://www.coolite.com/). All rights reserved. - * @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. - * @website: http://www.datejs.com/ - */ - -(function () { - var $D = Date, - $P = $D.prototype, - $C = $D.CultureInfo, - p = function (s, l) { - if (!l) { - l = 2; - } - return ("000" + s).slice(l * -1); - }; - - /** - * Resets the time of this Date object to 12:00 AM (00:00), which is the start of the day. - * @param {Boolean} .clone() this date instance before clearing Time - * @return {Date} this - */ - $P.clearTime = function () { - this.setHours(0); - this.setMinutes(0); - this.setSeconds(0); - this.setMilliseconds(0); - return this; - }; - - /** - * Resets the time of this Date object to the current time ('now'). - * @return {Date} this - */ - $P.setTimeToNow = function () { - var n = new Date(); - this.setHours(n.getHours()); - this.setMinutes(n.getMinutes()); - this.setSeconds(n.getSeconds()); - this.setMilliseconds(n.getMilliseconds()); - return this; - }; - - /** - * Gets a date that is set to the current date. The time is set to the start of the day (00:00 or 12:00 AM). - * @return {Date} The current date. - */ - $D.today = function () { - return new Date().clearTime(); - }; - - /** - * Compares the first date to the second date and returns an number indication of their relative values. - * @param {Date} First Date object to compare [Required]. - * @param {Date} Second Date object to compare to [Required]. - * @return {Number} -1 = date1 is lessthan date2. 0 = values are equal. 1 = date1 is greaterthan date2. - */ - $D.compare = function (date1, date2) { - if (isNaN(date1) || isNaN(date2)) { - throw new Error(date1 + " - " + date2); - } else if (date1 instanceof Date && date2 instanceof Date) { - return (date1 < date2) ? -1 : (date1 > date2) ? 1 : 0; - } else { - throw new TypeError(date1 + " - " + date2); - } - }; - - /** - * Compares the first Date object to the second Date object and returns true if they are equal. - * @param {Date} First Date object to compare [Required] - * @param {Date} Second Date object to compare to [Required] - * @return {Boolean} true if dates are equal. false if they are not equal. - */ - $D.equals = function (date1, date2) { - return (date1.compareTo(date2) === 0); - }; - - /** - * Gets the day number (0-6) if given a CultureInfo specific string which is a valid dayName, abbreviatedDayName or shortestDayName (two char). - * @param {String} The name of the day (eg. "Monday, "Mon", "tuesday", "tue", "We", "we"). - * @return {Number} The day number - */ - $D.getDayNumberFromName = function (name) { - var n = $C.dayNames, m = $C.abbreviatedDayNames, o = $C.shortestDayNames, s = name.toLowerCase(); - for (var i = 0; i < n.length; i++) { - if (n[i].toLowerCase() == s || m[i].toLowerCase() == s || o[i].toLowerCase() == s) { - return i; - } - } - return -1; - }; - - /** - * Gets the month number (0-11) if given a Culture Info specific string which is a valid monthName or abbreviatedMonthName. - * @param {String} The name of the month (eg. "February, "Feb", "october", "oct"). - * @return {Number} The day number - */ - $D.getMonthNumberFromName = function (name) { - var n = $C.monthNames, m = $C.abbreviatedMonthNames, s = name.toLowerCase(); - for (var i = 0; i < n.length; i++) { - if (n[i].toLowerCase() == s || m[i].toLowerCase() == s) { - return i; - } - } - return -1; - }; - - /** - * Determines if the current date instance is within a LeapYear. - * @param {Number} The year. - * @return {Boolean} true if date is within a LeapYear, otherwise false. - */ - $D.isLeapYear = function (year) { - return ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0); - }; - - /** - * Gets the number of days in the month, given a year and month value. Automatically corrects for LeapYear. - * @param {Number} The year. - * @param {Number} The month (0-11). - * @return {Number} The number of days in the month. - */ - $D.getDaysInMonth = function (year, month) { - return [31, ($D.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; - }; - - $D.getTimezoneAbbreviation = function (offset) { - var z = $C.timezones, p; - for (var i = 0; i < z.length; i++) { - if (z[i].offset === offset) { - return z[i].name; - } - } - return null; - }; - - $D.getTimezoneOffset = function (name) { - var z = $C.timezones, p; - for (var i = 0; i < z.length; i++) { - if (z[i].name === name.toUpperCase()) { - return z[i].offset; - } - } - return null; - }; - - /** - * Returns a new Date object that is an exact date and time copy of the original instance. - * @return {Date} A new Date instance - */ - $P.clone = function () { - return new Date(this.getTime()); - }; - - /** - * Compares this instance to a Date object and returns an number indication of their relative values. - * @param {Date} Date object to compare [Required] - * @return {Number} -1 = this is lessthan date. 0 = values are equal. 1 = this is greaterthan date. - */ - $P.compareTo = function (date) { - return Date.compare(this, date); - }; - - /** - * Compares this instance to another Date object and returns true if they are equal. - * @param {Date} Date object to compare. If no date to compare, new Date() [now] is used. - * @return {Boolean} true if dates are equal. false if they are not equal. - */ - $P.equals = function (date) { - return Date.equals(this, date || new Date()); - }; - - /** - * Determines if this instance is between a range of two dates or equal to either the start or end dates. - * @param {Date} Start of range [Required] - * @param {Date} End of range [Required] - * @return {Boolean} true is this is between or equal to the start and end dates, else false - */ - $P.between = function (start, end) { - return this.getTime() >= start.getTime() && this.getTime() <= end.getTime(); - }; - - /** - * Determines if this date occurs after the date to compare to. - * @param {Date} Date object to compare. If no date to compare, new Date() ("now") is used. - * @return {Boolean} true if this date instance is greater than the date to compare to (or "now"), otherwise false. - */ - $P.isAfter = function (date) { - return this.compareTo(date || new Date()) === 1; - }; - - /** - * Determines if this date occurs before the date to compare to. - * @param {Date} Date object to compare. If no date to compare, new Date() ("now") is used. - * @return {Boolean} true if this date instance is less than the date to compare to (or "now"). - */ - $P.isBefore = function (date) { - return (this.compareTo(date || new Date()) === -1); - }; - - /** - * Determines if the current Date instance occurs today. - * @return {Boolean} true if this date instance is 'today', otherwise false. - */ - - /** - * Determines if the current Date instance occurs on the same Date as the supplied 'date'. - * If no 'date' to compare to is provided, the current Date instance is compared to 'today'. - * @param {date} Date object to compare. If no date to compare, the current Date ("now") is used. - * @return {Boolean} true if this Date instance occurs on the same Day as the supplied 'date'. - */ - $P.isToday = $P.isSameDay = function (date) { - return this.clone().clearTime().equals((date || new Date()).clone().clearTime()); - }; - - /** - * Adds the specified number of milliseconds to this instance. - * @param {Number} The number of milliseconds to add. The number can be positive or negative [Required] - * @return {Date} this - */ - $P.addMilliseconds = function (value) { - this.setMilliseconds(this.getMilliseconds() + value * 1); - return this; - }; - - /** - * Adds the specified number of seconds to this instance. - * @param {Number} The number of seconds to add. The number can be positive or negative [Required] - * @return {Date} this - */ - $P.addSeconds = function (value) { - return this.addMilliseconds(value * 1000); - }; - - /** - * Adds the specified number of seconds to this instance. - * @param {Number} The number of seconds to add. The number can be positive or negative [Required] - * @return {Date} this - */ - $P.addMinutes = function (value) { - return this.addMilliseconds(value * 60000); /* 60*1000 */ - }; - - /** - * Adds the specified number of hours to this instance. - * @param {Number} The number of hours to add. The number can be positive or negative [Required] - * @return {Date} this - */ - $P.addHours = function (value) { - return this.addMilliseconds(value * 3600000); /* 60*60*1000 */ - }; - - /** - * Adds the specified number of days to this instance. - * @param {Number} The number of days to add. The number can be positive or negative [Required] - * @return {Date} this - */ - $P.addDays = function (value) { - this.setDate(this.getDate() + value * 1); - return this; - }; - - /** - * Adds the specified number of weeks to this instance. - * @param {Number} The number of weeks to add. The number can be positive or negative [Required] - * @return {Date} this - */ - $P.addWeeks = function (value) { - return this.addDays(value * 7); - }; - - /** - * Adds the specified number of months to this instance. - * @param {Number} The number of months to add. The number can be positive or negative [Required] - * @return {Date} this - */ - $P.addMonths = function (value) { - var n = this.getDate(); - this.setDate(1); - this.setMonth(this.getMonth() + value * 1); - this.setDate(Math.min(n, $D.getDaysInMonth(this.getFullYear(), this.getMonth()))); - return this; - }; - - /** - * Adds the specified number of years to this instance. - * @param {Number} The number of years to add. The number can be positive or negative [Required] - * @return {Date} this - */ - $P.addYears = function (value) { - return this.addMonths(value * 12); - }; - - /** - * Adds (or subtracts) to the value of the years, months, weeks, days, hours, minutes, seconds, milliseconds of the date instance using given configuration object. Positive and Negative values allowed. - * Example -

-    Date.today().add( { days: 1, months: 1 } )
-     
-    new Date().add( { years: -1 } )
-    
- * @param {Object} Configuration object containing attributes (months, days, etc.) - * @return {Date} this - */ - $P.add = function (config) { - if (typeof config == "number") { - this._orient = config; - return this; - } - - var x = config; - - if (x.milliseconds) { - this.addMilliseconds(x.milliseconds); - } - if (x.seconds) { - this.addSeconds(x.seconds); - } - if (x.minutes) { - this.addMinutes(x.minutes); - } - if (x.hours) { - this.addHours(x.hours); - } - if (x.weeks) { - this.addWeeks(x.weeks); - } - if (x.months) { - this.addMonths(x.months); - } - if (x.years) { - this.addYears(x.years); - } - if (x.days) { - this.addDays(x.days); - } - return this; - }; - - var $y, $m, $d; - - /** - * Get the week number. Week one (1) is the week which contains the first Thursday of the year. Monday is considered the first day of the week. - * This algorithm is a JavaScript port of the work presented by Claus Tøndering at http://www.tondering.dk/claus/cal/node8.html#SECTION00880000000000000000 - * .getWeek() Algorithm Copyright (c) 2008 Claus Tondering. - * The .getWeek() function does NOT convert the date to UTC. The local datetime is used. Please use .getISOWeek() to get the week of the UTC converted date. - * @return {Number} 1 to 53 - */ - $P.getWeek = function () { - var a, b, c, d, e, f, g, n, s, w; - - $y = (!$y) ? this.getFullYear() : $y; - $m = (!$m) ? this.getMonth() + 1 : $m; - $d = (!$d) ? this.getDate() : $d; - - if ($m <= 2) { - a = $y - 1; - b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0); - c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0); - s = b - c; - e = 0; - f = $d - 1 + (31 * ($m - 1)); - } else { - a = $y; - b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0); - c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0); - s = b - c; - e = s + 1; - f = $d + ((153 * ($m - 3) + 2) / 5) + 58 + s; - } - - g = (a + b) % 7; - d = (f + g - e) % 7; - n = (f + 3 - d) | 0; - - if (n < 0) { - w = 53 - ((g - s) / 5 | 0); - } else if (n > 364 + s) { - w = 1; - } else { - w = (n / 7 | 0) + 1; - } - - $y = $m = $d = null; - - return w; - }; - - /** - * Get the ISO 8601 week number. Week one ("01") is the week which contains the first Thursday of the year. Monday is considered the first day of the week. - * The .getISOWeek() function does convert the date to it's UTC value. Please use .getWeek() to get the week of the local date. - * @return {String} "01" to "53" - */ - $P.getISOWeek = function () { - $y = this.getUTCFullYear(); - $m = this.getUTCMonth() + 1; - $d = this.getUTCDate(); - return p(this.getWeek()); - }; - - /** - * Moves the date to Monday of the week set. Week one (1) is the week which contains the first Thursday of the year. - * @param {Number} A Number (1 to 53) that represents the week of the year. - * @return {Date} this - */ - $P.setWeek = function (n) { - return this.moveToDayOfWeek(1).addWeeks(n - this.getWeek()); - }; - - // private - var validate = function (n, min, max, name) { - if (typeof n == "undefined") { - return false; - } else if (typeof n != "number") { - throw new TypeError(n + " is not a Number."); - } else if (n < min || n > max) { - throw new RangeError(n + " is not a valid value for " + name + "."); - } - return true; - }; - - /** - * Validates the number is within an acceptable range for milliseconds [0-999]. - * @param {Number} The number to check if within range. - * @return {Boolean} true if within range, otherwise false. - */ - $D.validateMillisecond = function (value) { - return validate(value, 0, 999, "millisecond"); - }; - - /** - * Validates the number is within an acceptable range for seconds [0-59]. - * @param {Number} The number to check if within range. - * @return {Boolean} true if within range, otherwise false. - */ - $D.validateSecond = function (value) { - return validate(value, 0, 59, "second"); - }; - - /** - * Validates the number is within an acceptable range for minutes [0-59]. - * @param {Number} The number to check if within range. - * @return {Boolean} true if within range, otherwise false. - */ - $D.validateMinute = function (value) { - return validate(value, 0, 59, "minute"); - }; - - /** - * Validates the number is within an acceptable range for hours [0-23]. - * @param {Number} The number to check if within range. - * @return {Boolean} true if within range, otherwise false. - */ - $D.validateHour = function (value) { - return validate(value, 0, 23, "hour"); - }; - - /** - * Validates the number is within an acceptable range for the days in a month [0-MaxDaysInMonth]. - * @param {Number} The number to check if within range. - * @return {Boolean} true if within range, otherwise false. - */ - $D.validateDay = function (value, year, month) { - return validate(value, 1, $D.getDaysInMonth(year, month), "day"); - }; - - /** - * Validates the number is within an acceptable range for months [0-11]. - * @param {Number} The number to check if within range. - * @return {Boolean} true if within range, otherwise false. - */ - $D.validateMonth = function (value) { - return validate(value, 0, 11, "month"); - }; - - /** - * Validates the number is within an acceptable range for years. - * @param {Number} The number to check if within range. - * @return {Boolean} true if within range, otherwise false. - */ - $D.validateYear = function (value) { - return validate(value, 0, 9999, "year"); - }; - - /** - * Set the value of year, month, day, hour, minute, second, millisecond of date instance using given configuration object. - * Example -

-    Date.today().set( { day: 20, month: 1 } )
-
-    new Date().set( { millisecond: 0 } )
-    
- * - * @param {Object} Configuration object containing attributes (month, day, etc.) - * @return {Date} this - */ - $P.set = function (config) { - if ($D.validateMillisecond(config.millisecond)) { - this.addMilliseconds(config.millisecond - this.getMilliseconds()); - } - - if ($D.validateSecond(config.second)) { - this.addSeconds(config.second - this.getSeconds()); - } - - if ($D.validateMinute(config.minute)) { - this.addMinutes(config.minute - this.getMinutes()); - } - - if ($D.validateHour(config.hour)) { - this.addHours(config.hour - this.getHours()); - } - - if ($D.validateMonth(config.month)) { - this.addMonths(config.month - this.getMonth()); - } - - if ($D.validateYear(config.year)) { - this.addYears(config.year - this.getFullYear()); - } - - /* day has to go last because you can't validate the day without first knowing the month */ - if ($D.validateDay(config.day, this.getFullYear(), this.getMonth())) { - this.addDays(config.day - this.getDate()); - } - - if (config.timezone) { - this.setTimezone(config.timezone); - } - - if (config.timezoneOffset) { - this.setTimezoneOffset(config.timezoneOffset); - } - - if (config.week && validate(config.week, 0, 53, "week")) { - this.setWeek(config.week); - } - - return this; - }; - - /** - * Moves the date to the first day of the month. - * @return {Date} this - */ - $P.moveToFirstDayOfMonth = function () { - return this.set({ day: 1 }); - }; - - /** - * Moves the date to the last day of the month. - * @return {Date} this - */ - $P.moveToLastDayOfMonth = function () { - return this.set({ day: $D.getDaysInMonth(this.getFullYear(), this.getMonth())}); - }; - - /** - * Moves the date to the next n'th occurrence of the dayOfWeek starting from the beginning of the month. The number (-1) is a magic number and will return the last occurrence of the dayOfWeek in the month. - * @param {Number} The dayOfWeek to move to - * @param {Number} The n'th occurrence to move to. Use (-1) to return the last occurrence in the month - * @return {Date} this - */ - $P.moveToNthOccurrence = function (dayOfWeek, occurrence) { - var shift = 0; - if (occurrence > 0) { - shift = occurrence - 1; - } - else if (occurrence === -1) { - this.moveToLastDayOfMonth(); - if (this.getDay() !== dayOfWeek) { - this.moveToDayOfWeek(dayOfWeek, -1); - } - return this; - } - return this.moveToFirstDayOfMonth().addDays(-1).moveToDayOfWeek(dayOfWeek, +1).addWeeks(shift); - }; - - /** - * Move to the next or last dayOfWeek based on the orient value. - * @param {Number} The dayOfWeek to move to - * @param {Number} Forward (+1) or Back (-1). Defaults to +1. [Optional] - * @return {Date} this - */ - $P.moveToDayOfWeek = function (dayOfWeek, orient) { - var diff = (dayOfWeek - this.getDay() + 7 * (orient || +1)) % 7; - return this.addDays((diff === 0) ? diff += 7 * (orient || +1) : diff); - }; - - /** - * Move to the next or last month based on the orient value. - * @param {Number} The month to move to. 0 = January, 11 = December - * @param {Number} Forward (+1) or Back (-1). Defaults to +1. [Optional] - * @return {Date} this - */ - $P.moveToMonth = function (month, orient) { - var diff = (month - this.getMonth() + 12 * (orient || +1)) % 12; - return this.addMonths((diff === 0) ? diff += 12 * (orient || +1) : diff); - }; - - /** - * Get the Ordinal day (numeric day number) of the year, adjusted for leap year. - * @return {Number} 1 through 365 (366 in leap years) - */ - $P.getOrdinalNumber = function () { - return Math.ceil((this.clone().clearTime() - new Date(this.getFullYear(), 0, 1)) / 86400000) + 1; - }; - - /** - * Get the time zone abbreviation of the current date. - * @return {String} The abbreviated time zone name (e.g. "EST") - */ - $P.getTimezone = function () { - return $D.getTimezoneAbbreviation(this.getUTCOffset()); - }; - - $P.setTimezoneOffset = function (offset) { - var here = this.getTimezoneOffset(), there = Number(offset) * -6 / 10; - return this.addMinutes(there - here); - }; - - $P.setTimezone = function (offset) { - return this.setTimezoneOffset($D.getTimezoneOffset(offset)); - }; - - /** - * Indicates whether Daylight Saving Time is observed in the current time zone. - * @return {Boolean} true|false - */ - $P.hasDaylightSavingTime = function () { - return (Date.today().set({month: 0, day: 1}).getTimezoneOffset() !== Date.today().set({month: 6, day: 1}).getTimezoneOffset()); - }; - - /** - * Indicates whether this Date instance is within the Daylight Saving Time range for the current time zone. - * @return {Boolean} true|false - */ - $P.isDaylightSavingTime = function () { - return Date.today().set({month: 0, day: 1}).getTimezoneOffset() != this.getTimezoneOffset(); - }; - - /** - * Get the offset from UTC of the current date. - * @return {String} The 4-character offset string prefixed with + or - (e.g. "-0500") - */ - $P.getUTCOffset = function () { - var n = this.getTimezoneOffset() * -10 / 6, r; - if (n < 0) { - r = (n - 10000).toString(); - return r.charAt(0) + r.substr(2); - } else { - r = (n + 10000).toString(); - return "+" + r.substr(1); - } - }; - - /** - * Returns the number of milliseconds between this date and date. - * @param {Date} Defaults to now - * @return {Number} The diff in milliseconds - */ - $P.getElapsed = function (date) { - return (date || new Date()) - this; - }; - - if (!$P.toISOString) { - /** - * Converts the current date instance into a string with an ISO 8601 format. The date is converted to it's UTC value. - * @return {String} ISO 8601 string of date - */ - $P.toISOString = function () { - // From http://www.json.org/json.js. Public Domain. - function f(n) { - return n < 10 ? '0' + n : n; - } - - return '"' + this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z"'; - }; - } - - // private - $P._toString = $P.toString; - - /** - * Converts the value of the current Date object to its equivalent string representation. - * Format Specifiers -
-    CUSTOM DATE AND TIME FORMAT STRINGS
-    Format  Description                                                                  Example
-    ------  ---------------------------------------------------------------------------  -----------------------
-     s      The seconds of the minute between 0-59.                                      "0" to "59"
-     ss     The seconds of the minute with leading zero if required.                     "00" to "59"
-     
-     m      The minute of the hour between 0-59.                                         "0"  or "59"
-     mm     The minute of the hour with leading zero if required.                        "00" or "59"
-     
-     h      The hour of the day between 1-12.                                            "1"  to "12"
-     hh     The hour of the day with leading zero if required.                           "01" to "12"
-     
-     H      The hour of the day between 0-23.                                            "0"  to "23"
-     HH     The hour of the day with leading zero if required.                           "00" to "23"
-     
-     d      The day of the month between 1 and 31.                                       "1"  to "31"
-     dd     The day of the month with leading zero if required.                          "01" to "31"
-     ddd    Abbreviated day name. $C.abbreviatedDayNames.                                "Mon" to "Sun" 
-     dddd   The full day name. $C.dayNames.                                              "Monday" to "Sunday"
-     
-     M      The month of the year between 1-12.                                          "1" to "12"
-     MM     The month of the year with leading zero if required.                         "01" to "12"
-     MMM    Abbreviated month name. $C.abbreviatedMonthNames.                            "Jan" to "Dec"
-     MMMM   The full month name. $C.monthNames.                                          "January" to "December"
-
-     yy     The year as a two-digit number.                                              "99" or "08"
-     yyyy   The full four digit year.                                                    "1999" or "2008"
-     
-     t      Displays the first character of the A.M./P.M. designator.                    "A" or "P"
-            $C.amDesignator or $C.pmDesignator
-     tt     Displays the A.M./P.M. designator.                                           "AM" or "PM"
-            $C.amDesignator or $C.pmDesignator
-     
-     S      The ordinal suffix ("st, "nd", "rd" or "th") of the current day.            "st, "nd", "rd" or "th"
-
-|| *Format* || *Description* || *Example* ||
-|| d      || The CultureInfo shortDate Format Pattern                                     || "M/d/yyyy" ||
-|| D      || The CultureInfo longDate Format Pattern                                      || "dddd, MMMM dd, yyyy" ||
-|| F      || The CultureInfo fullDateTime Format Pattern                                  || "dddd, MMMM dd, yyyy h:mm:ss tt" ||
-|| m      || The CultureInfo monthDay Format Pattern                                      || "MMMM dd" ||
-|| r      || The CultureInfo rfc1123 Format Pattern                                       || "ddd, dd MMM yyyy HH:mm:ss GMT" ||
-|| s      || The CultureInfo sortableDateTime Format Pattern                              || "yyyy-MM-ddTHH:mm:ss" ||
-|| t      || The CultureInfo shortTime Format Pattern                                     || "h:mm tt" ||
-|| T      || The CultureInfo longTime Format Pattern                                      || "h:mm:ss tt" ||
-|| u      || The CultureInfo universalSortableDateTime Format Pattern                     || "yyyy-MM-dd HH:mm:ssZ" ||
-|| y      || The CultureInfo yearMonth Format Pattern                                     || "MMMM, yyyy" ||
-     
-
-    STANDARD DATE AND TIME FORMAT STRINGS
-    Format  Description                                                                  Example ("en-US")
-    ------  ---------------------------------------------------------------------------  -----------------------
-     d      The CultureInfo shortDate Format Pattern                                     "M/d/yyyy"
-     D      The CultureInfo longDate Format Pattern                                      "dddd, MMMM dd, yyyy"
-     F      The CultureInfo fullDateTime Format Pattern                                  "dddd, MMMM dd, yyyy h:mm:ss tt"
-     m      The CultureInfo monthDay Format Pattern                                      "MMMM dd"
-     r      The CultureInfo rfc1123 Format Pattern                                       "ddd, dd MMM yyyy HH:mm:ss GMT"
-     s      The CultureInfo sortableDateTime Format Pattern                              "yyyy-MM-ddTHH:mm:ss"
-     t      The CultureInfo shortTime Format Pattern                                     "h:mm tt"
-     T      The CultureInfo longTime Format Pattern                                      "h:mm:ss tt"
-     u      The CultureInfo universalSortableDateTime Format Pattern                     "yyyy-MM-dd HH:mm:ssZ"
-     y      The CultureInfo yearMonth Format Pattern                                     "MMMM, yyyy"
-    
- * @param {String} A format string consisting of one or more format spcifiers [Optional]. - * @return {String} A string representation of the current Date object. - */ - $P.toString = function (format) { - var x = this; - - // Standard Date and Time Format Strings. Formats pulled from CultureInfo file and - // may vary by culture. - if (format && format.length == 1) { - var c = $C.formatPatterns; - x.t = x.toString; - switch (format) { - case "d": - return x.t(c.shortDate); - case "D": - return x.t(c.longDate); - case "F": - return x.t(c.fullDateTime); - case "m": - return x.t(c.monthDay); - case "r": - return x.t(c.rfc1123); - case "s": - return x.t(c.sortableDateTime); - case "t": - return x.t(c.shortTime); - case "T": - return x.t(c.longTime); - case "u": - return x.t(c.universalSortableDateTime); - case "y": - return x.t(c.yearMonth); - } - } - - var ord = function (n) { - switch (n * 1) { - case 1: - case 21: - case 31: - return "st"; - case 2: - case 22: - return "nd"; - case 3: - case 23: - return "rd"; - default: - return "th"; - } - }; - - return format ? format.replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S)/g, - function (m) { - if (m.charAt(0) === "\\") { - return m.replace("\\", ""); - } - x.h = x.getHours; - switch (m) { - case "hh": - return p(x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12)); - case "h": - return x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12); - case "HH": - return p(x.h()); - case "H": - return x.h(); - case "mm": - return p(x.getMinutes()); - case "m": - return x.getMinutes(); - case "ss": - return p(x.getSeconds()); - case "s": - return x.getSeconds(); - case "yyyy": - return p(x.getFullYear(), 4); - case "yy": - return p(x.getFullYear()); - case "dddd": - return $C.dayNames[x.getDay()]; - case "ddd": - return $C.abbreviatedDayNames[x.getDay()]; - case "dd": - return p(x.getDate()); - case "d": - return x.getDate(); - case "MMMM": - return $C.monthNames[x.getMonth()]; - case "MMM": - return $C.abbreviatedMonthNames[x.getMonth()]; - case "MM": - return p((x.getMonth() + 1)); - case "M": - return x.getMonth() + 1; - case "t": - return x.h() < 12 ? $C.amDesignator.substring(0, 1) : $C.pmDesignator.substring(0, 1); - case "tt": - return x.h() < 12 ? $C.amDesignator : $C.pmDesignator; - case "S": - return ord(x.getDate()); - default: - return m; - } - } - ) : this._toString(); - }; -}()); /** - * @version: 1.0 Alpha-1 - * @author: Coolite Inc. http://www.coolite.com/ - * @date: 2008-04-13 - * @copyright: Copyright (c) 2006-2008, Coolite Inc. (http://www.coolite.com/). All rights reserved. - * @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. - * @website: http://www.datejs.com/ - */ - -(function () { - Date.Parsing = { - Exception: function (s) { - this.message = "Parse error at '" + s.substring(0, 10) + " ...'"; - } - }; - - var $P = Date.Parsing; - var _ = $P.Operators = { - // - // Tokenizers - // - rtoken: function (r) { // regex token - return function (s) { - var mx = s.match(r); - if (mx) { - return ([ mx[0], s.substring(mx[0].length) ]); - } else { - throw new $P.Exception(s); - } - }; - }, - token: function (s) { // whitespace-eating token - return function (s) { - return _.rtoken(new RegExp("^\s*" + s + "\s*"))(s); - // Removed .strip() - // return _.rtoken(new RegExp("^\s*" + s + "\s*"))(s).strip(); - }; - }, - stoken: function (s) { // string token - return _.rtoken(new RegExp("^" + s)); - }, - - // - // Atomic Operators - // - - until: function (p) { - return function (s) { - var qx = [], rx = null; - while (s.length) { - try { - rx = p.call(this, s); - } catch (e) { - qx.push(rx[0]); - s = rx[1]; - continue; - } - break; - } - return [ qx, s ]; - }; - }, - many: function (p) { - return function (s) { - var rx = [], r = null; - while (s.length) { - try { - r = p.call(this, s); - } catch (e) { - return [ rx, s ]; - } - rx.push(r[0]); - s = r[1]; - } - return [ rx, s ]; - }; - }, - - // generator operators -- see below - optional: function (p) { - return function (s) { - var r = null; - try { - r = p.call(this, s); - } catch (e) { - return [ null, s ]; - } - return [ r[0], r[1] ]; - }; - }, - not: function (p) { - return function (s) { - try { - p.call(this, s); - } catch (e) { - return [null, s]; - } - throw new $P.Exception(s); - }; - }, - ignore: function (p) { - return p ? - function (s) { - var r = null; - r = p.call(this, s); - return [null, r[1]]; - } : null; - }, - product: function () { - var px = arguments[0], - qx = Array.prototype.slice.call(arguments, 1), rx = []; - for (var i = 0 ; i < px.length ; i++) { - rx.push(_.each(px[i], qx)); - } - return rx; - }, - cache: function (rule) { - var cache = {}, r = null; - return function (s) { - try { - r = cache[s] = (cache[s] || rule.call(this, s)); - } catch (e) { - r = cache[s] = e; - } - if (r instanceof $P.Exception) { - throw r; - } else { - return r; - } - }; - }, - - // vector operators -- see below - any: function () { - var px = arguments; - return function (s) { - var r = null; - for (var i = 0; i < px.length; i++) { - if (px[i] == null) { - continue; - } - try { - r = (px[i].call(this, s)); - } catch (e) { - r = null; - } - if (r) { - return r; - } - } - throw new $P.Exception(s); - }; - }, - each: function () { - var px = arguments; - return function (s) { - var rx = [], r = null; - for (var i = 0; i < px.length ; i++) { - if (px[i] == null) { - continue; - } - try { - r = (px[i].call(this, s)); - } catch (e) { - throw new $P.Exception(s); - } - rx.push(r[0]); - s = r[1]; - } - return [ rx, s]; - }; - }, - all: function () { - var px = arguments, _ = _; - return _.each(_.optional(px)); - }, - - // delimited operators - sequence: function (px, d, c) { - d = d || _.rtoken(/^\s*/); - c = c || null; - - if (px.length == 1) { - return px[0]; - } - return function (s) { - var r = null, q = null; - var rx = []; - for (var i = 0; i < px.length ; i++) { - try { - r = px[i].call(this, s); - } catch (e) { - break; - } - rx.push(r[0]); - try { - q = d.call(this, r[1]); - } catch (ex) { - q = null; - break; - } - s = q[1]; - } - if (!r) { - throw new $P.Exception(s); - } - if (q) { - throw new $P.Exception(q[1]); - } - if (c) { - try { - r = c.call(this, r[1]); - } catch (ey) { - throw new $P.Exception(r[1]); - } - } - return [ rx, (r?r[1]:s) ]; - }; - }, - - // - // Composite Operators - // - - between: function (d1, p, d2) { - d2 = d2 || d1; - var _fn = _.each(_.ignore(d1), p, _.ignore(d2)); - return function (s) { - var rx = _fn.call(this, s); - return [[rx[0][0], r[0][2]], rx[1]]; - }; - }, - list: function (p, d, c) { - d = d || _.rtoken(/^\s*/); - c = c || null; - return (p instanceof Array ? - _.each(_.product(p.slice(0, -1), _.ignore(d)), p.slice(-1), _.ignore(c)) : - _.each(_.many(_.each(p, _.ignore(d))), px, _.ignore(c))); - }, - set: function (px, d, c) { - d = d || _.rtoken(/^\s*/); - c = c || null; - return function (s) { - // r is the current match, best the current 'best' match - // which means it parsed the most amount of input - var r = null, p = null, q = null, rx = null, best = [[], s], last = false; - - // go through the rules in the given set - for (var i = 0; i < px.length ; i++) { - - // last is a flag indicating whether this must be the last element - // if there is only 1 element, then it MUST be the last one - q = null; - p = null; - r = null; - last = (px.length == 1); - - // first, we try simply to match the current pattern - // if not, try the next pattern - try { - r = px[i].call(this, s); - } catch (e) { - continue; - } - - // since we are matching against a set of elements, the first - // thing to do is to add r[0] to matched elements - rx = [[r[0]], r[1]]; - - // if we matched and there is still input to parse and - // we don't already know this is the last element, - // we're going to next check for the delimiter ... - // if there's none, or if there's no input left to parse - // than this must be the last element after all ... - if (r[1].length > 0 && ! last) { - try { - q = d.call(this, r[1]); - } catch (ex) { - last = true; - } - } else { - last = true; - } - - // if we parsed the delimiter and now there's no more input, - // that means we shouldn't have parsed the delimiter at all - // so don't update r and mark this as the last element ... - if (!last && q[1].length === 0) { - last = true; - } - - - // so, if this isn't the last element, we're going to see if - // we can get any more matches from the remaining (unmatched) - // elements ... - if (!last) { - - // build a list of the remaining rules we can match against, - // i.e., all but the one we just matched against - var qx = []; - for (var j = 0; j < px.length ; j++) { - if (i != j) { - qx.push(px[j]); - } - } - - // now invoke recursively set with the remaining input - // note that we don't include the closing delimiter ... - // we'll check for that ourselves at the end - p = _.set(qx, d).call(this, q[1]); - - // if we got a non-empty set as a result ... - // (otw rx already contains everything we want to match) - if (p[0].length > 0) { - // update current result, which is stored in rx ... - // basically, pick up the remaining text from p[1] - // and concat the result from p[0] so that we don't - // get endless nesting ... - rx[0] = rx[0].concat(p[0]); - rx[1] = p[1]; - } - } - - // at this point, rx either contains the last matched element - // or the entire matched set that starts with this element. - - // now we just check to see if this variation is better than - // our best so far, in terms of how much of the input is parsed - if (rx[1].length < best[1].length) { - best = rx; - } - - // if we've parsed all the input, then we're finished - if (best[1].length === 0) { - break; - } - } - - // so now we've either gone through all the patterns trying them - // as the initial match; or we found one that parsed the entire - // input string ... - - // if best has no matches, just return empty set ... - if (best[0].length === 0) { - return best; - } - - // if a closing delimiter is provided, then we have to check it also - if (c) { - // we try this even if there is no remaining input because the pattern - // may well be optional or match empty input ... - try { - q = c.call(this, best[1]); - } catch (ey) { - throw new $P.Exception(best[1]); - } - - // it parsed ... be sure to update the best match remaining input - best[1] = q[1]; - } - - // if we're here, either there was no closing delimiter or we parsed it - // so now we have the best match; just return it! - return best; - }; - }, - forward: function (gr, fname) { - return function (s) { - return gr[fname].call(this, s); - }; - }, - - // - // Translation Operators - // - replace: function (rule, repl) { - return function (s) { - var r = rule.call(this, s); - return [repl, r[1]]; - }; - }, - process: function (rule, fn) { - return function (s) { - var r = rule.call(this, s); - return [fn.call(this, r[0]), r[1]]; - }; - }, - min: function (min, rule) { - return function (s) { - var rx = rule.call(this, s); - if (rx[0].length < min) { - throw new $P.Exception(s); - } - return rx; - }; - } - }; - - - // Generator Operators And Vector Operators - - // Generators are operators that have a signature of F(R) => R, - // taking a given rule and returning another rule, such as - // ignore, which parses a given rule and throws away the result. - - // Vector operators are those that have a signature of F(R1,R2,...) => R, - // take a list of rules and returning a new rule, such as each. - - // Generator operators are converted (via the following _generator - // function) into functions that can also take a list or array of rules - // and return an array of new rules as though the function had been - // called on each rule in turn (which is what actually happens). - - // This allows generators to be used with vector operators more easily. - // Example: - // each(ignore(foo, bar)) instead of each(ignore(foo), ignore(bar)) - - // This also turns generators into vector operators, which allows - // constructs like: - // not(cache(foo, bar)) - - var _generator = function (op) { - return function () { - var args = null, rx = []; - if (arguments.length > 1) { - args = Array.prototype.slice.call(arguments); - } else if (arguments[0] instanceof Array) { - args = arguments[0]; - } - if (args) { - for (var i = 0, px = args.shift() ; i < px.length ; i++) { - args.unshift(px[i]); - rx.push(op.apply(null, args)); - args.shift(); - return rx; - } - } else { - return op.apply(null, arguments); - } - }; - }; - - var gx = "optional not ignore cache".split(/\s/); - - for (var i = 0 ; i < gx.length ; i++) { - _[gx[i]] = _generator(_[gx[i]]); - } - - var _vector = function (op) { - return function () { - if (arguments[0] instanceof Array) { - return op.apply(null, arguments[0]); - } else { - return op.apply(null, arguments); - } - }; - }; - - var vx = "each any all".split(/\s/); - - for (var j = 0 ; j < vx.length ; j++) { - _[vx[j]] = _vector(_[vx[j]]); - } - -}()); - -(function () { - var $D = Date, $P = $D.prototype, $C = $D.CultureInfo; - - var flattenAndCompact = function (ax) { - var rx = []; - for (var i = 0; i < ax.length; i++) { - if (ax[i] instanceof Array) { - rx = rx.concat(flattenAndCompact(ax[i])); - } else { - if (ax[i]) { - rx.push(ax[i]); - } - } - } - return rx; - }; - - $D.Grammar = {}; - - $D.Translator = { - hour: function (s) { - return function () { - this.hour = Number(s); - }; - }, - minute: function (s) { - return function () { - this.minute = Number(s); - }; - }, - second: function (s) { - return function () { - this.second = Number(s); - }; - }, - meridian: function (s) { - return function () { - this.meridian = s.slice(0, 1).toLowerCase(); - }; - }, - timezone: function (s) { - return function () { - var n = s.replace(/[^\d\+\-]/g, ""); - if (n.length) { - this.timezoneOffset = Number(n); - } else { - this.timezone = s.toLowerCase(); - } - }; - }, - day: function (x) { - var s = x[0]; - return function () { - this.day = Number(s.match(/\d+/)[0]); - }; - }, - month: function (s) { - return function () { - this.month = (s.length == 3) ? "jan feb mar apr may jun jul aug sep oct nov dec".indexOf(s)/4 : Number(s) - 1; - }; - }, - year: function (s) { - return function () { - var n = Number(s); - this.year = ((s.length > 2) ? n : - (n + (((n + 2000) < $C.twoDigitYearMax) ? 2000 : 1900))); - }; - }, - rday: function (s) { - return function () { - switch (s) { - case "yesterday": - this.days = -1; - break; - case "tomorrow": - this.days = 1; - break; - case "today": - this.days = 0; - break; - case "now": - this.days = 0; - this.now = true; - break; - } - }; - }, - finishExact: function (x) { - x = (x instanceof Array) ? x : [ x ]; - - for (var i = 0 ; i < x.length ; i++) { - if (x[i]) { - x[i].call(this); - } - } - - var now = new Date(); - - if ((this.hour || this.minute) && (!this.month && !this.year && !this.day)) { - this.day = now.getDate(); - } - - if (!this.year) { - this.year = now.getFullYear(); - } - - if (!this.month && this.month !== 0) { - this.month = now.getMonth(); - } - - if (!this.day) { - this.day = 1; - } - - if (!this.hour) { - this.hour = 0; - } - - if (!this.minute) { - this.minute = 0; - } - - if (!this.second) { - this.second = 0; - } - - if (this.meridian && this.hour) { - if (this.meridian == "p" && this.hour < 12) { - this.hour = this.hour + 12; - } else if (this.meridian == "a" && this.hour == 12) { - this.hour = 0; - } - } - - if (this.day > $D.getDaysInMonth(this.year, this.month)) { - throw new RangeError(this.day + " is not a valid value for days."); - } - - var r = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second); - - if (this.timezone) { - r.set({ timezone: this.timezone }); - } else if (this.timezoneOffset) { - r.set({ timezoneOffset: this.timezoneOffset }); - } - - return r; - }, - finish: function (x) { - x = (x instanceof Array) ? flattenAndCompact(x) : [ x ]; - - if (x.length === 0) { - return null; - } - - for (var i = 0 ; i < x.length ; i++) { - if (typeof x[i] == "function") { - x[i].call(this); - } - } - - var today = $D.today(); - - if (this.now && !this.unit && !this.operator) { - return new Date(); - } else if (this.now) { - today = new Date(); - } - - var expression = !!(this.days && this.days !== null || this.orient || this.operator); - - var gap, mod, orient; - orient = ((this.orient == "past" || this.operator == "subtract") ? -1 : 1); - - if(!this.now && "hour minute second".indexOf(this.unit) != -1) { - today.setTimeToNow(); - } - - if (this.month || this.month === 0) { - if ("year day hour minute second".indexOf(this.unit) != -1) { - this.value = this.month + 1; - this.month = null; - expression = true; - } - } - - if (!expression && this.weekday && !this.day && !this.days) { - var temp = Date[this.weekday](); - this.day = temp.getDate(); - if (!this.month) { - this.month = temp.getMonth(); - } - this.year = temp.getFullYear(); - } - - if (expression && this.weekday && this.unit != "month") { - this.unit = "day"; - gap = ($D.getDayNumberFromName(this.weekday) - today.getDay()); - mod = 7; - this.days = gap ? ((gap + (orient * mod)) % mod) : (orient * mod); - } - - if (this.month && this.unit == "day" && this.operator) { - this.value = (this.month + 1); - this.month = null; - } - - if (this.value != null && this.month != null && this.year != null) { - this.day = this.value * 1; - } - - if (this.month && !this.day && this.value) { - today.set({ day: this.value * 1 }); - if (!expression) { - this.day = this.value * 1; - } - } - - if (!this.month && this.value && this.unit == "month" && !this.now) { - this.month = this.value; - expression = true; - } - - if (expression && (this.month || this.month === 0) && this.unit != "year") { - this.unit = "month"; - gap = (this.month - today.getMonth()); - mod = 12; - this.months = gap ? ((gap + (orient * mod)) % mod) : (orient * mod); - this.month = null; - } - - if (!this.unit) { - this.unit = "day"; - } - - if (!this.value && this.operator && this.operator !== null && this[this.unit + "s"] && this[this.unit + "s"] !== null) { - this[this.unit + "s"] = this[this.unit + "s"] + ((this.operator == "add") ? 1 : -1) + (this.value||0) * orient; - } else if (this[this.unit + "s"] == null || this.operator != null) { - if (!this.value) { - this.value = 1; - } - this[this.unit + "s"] = this.value * orient; - } - - if (this.meridian && this.hour) { - if (this.meridian == "p" && this.hour < 12) { - this.hour = this.hour + 12; - } else if (this.meridian == "a" && this.hour == 12) { - this.hour = 0; - } - } - - if (this.weekday && !this.day && !this.days) { - var temp = Date[this.weekday](); - this.day = temp.getDate(); - if (temp.getMonth() !== today.getMonth()) { - this.month = temp.getMonth(); - } - } - - if ((this.month || this.month === 0) && !this.day) { - this.day = 1; - } - - if (!this.orient && !this.operator && this.unit == "week" && this.value && !this.day && !this.month) { - return Date.today().setWeek(this.value); - } - - if (expression && this.timezone && this.day && this.days) { - this.day = this.days; - } - - return (expression) ? today.add(this) : today.set(this); - } - }; - - var _ = $D.Parsing.Operators, g = $D.Grammar, t = $D.Translator, _fn; - - g.datePartDelimiter = _.rtoken(/^([\s\-\.\,\/\x27]+)/); - g.timePartDelimiter = _.stoken(":"); - g.whiteSpace = _.rtoken(/^\s*/); - g.generalDelimiter = _.rtoken(/^(([\s\,]|at|@|on)+)/); - - var _C = {}; - g.ctoken = function (keys) { - var fn = _C[keys]; - if (! fn) { - var c = $C.regexPatterns; - var kx = keys.split(/\s+/), px = []; - for (var i = 0; i < kx.length ; i++) { - px.push(_.replace(_.rtoken(c[kx[i]]), kx[i])); - } - fn = _C[keys] = _.any.apply(null, px); - } - return fn; - }; - g.ctoken2 = function (key) { - return _.rtoken($C.regexPatterns[key]); - }; - - // hour, minute, second, meridian, timezone - g.h = _.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/), t.hour)); - g.hh = _.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/), t.hour)); - g.H = _.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/), t.hour)); - g.HH = _.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/), t.hour)); - g.m = _.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/), t.minute)); - g.mm = _.cache(_.process(_.rtoken(/^[0-5][0-9]/), t.minute)); - g.s = _.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/), t.second)); - g.ss = _.cache(_.process(_.rtoken(/^[0-5][0-9]/), t.second)); - g.hms = _.cache(_.sequence([g.H, g.m, g.s], g.timePartDelimiter)); - - // _.min(1, _.set([ g.H, g.m, g.s ], g._t)); - g.t = _.cache(_.process(g.ctoken2("shortMeridian"), t.meridian)); - g.tt = _.cache(_.process(g.ctoken2("longMeridian"), t.meridian)); - g.z = _.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/), t.timezone)); - g.zz = _.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/), t.timezone)); - - g.zzz = _.cache(_.process(g.ctoken2("timezone"), t.timezone)); - g.timeSuffix = _.each(_.ignore(g.whiteSpace), _.set([ g.tt, g.zzz ])); - g.time = _.each(_.optional(_.ignore(_.stoken("T"))), g.hms, g.timeSuffix); - - // days, months, years - g.d = _.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/), - _.optional(g.ctoken2("ordinalSuffix"))), t.day)); - g.dd = _.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/), - _.optional(g.ctoken2("ordinalSuffix"))), t.day)); - g.ddd = g.dddd = _.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"), - function (s) { - return function () { - this.weekday = s; - }; - } - )); - g.M = _.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/), t.month)); - g.MM = _.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/), t.month)); - g.MMM = g.MMMM = _.cache(_.process( - g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"), t.month)); - g.y = _.cache(_.process(_.rtoken(/^(\d\d?)/), t.year)); - g.yy = _.cache(_.process(_.rtoken(/^(\d\d)/), t.year)); - g.yyy = _.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/), t.year)); - g.yyyy = _.cache(_.process(_.rtoken(/^(\d\d\d\d)/), t.year)); - - // rolling these up into general purpose rules - _fn = function () { - return _.each(_.any.apply(null, arguments), _.not(g.ctoken2("timeContext"))); - }; - - g.day = _fn(g.d, g.dd); - g.month = _fn(g.M, g.MMM); - g.year = _fn(g.yyyy, g.yy); - - // relative date / time expressions - g.orientation = _.process(g.ctoken("past future"), - function (s) { - return function () { - this.orient = s; - }; - } - ); - g.operator = _.process(g.ctoken("add subtract"), - function (s) { - return function () { - this.operator = s; - }; - } - ); - g.rday = _.process(g.ctoken("yesterday tomorrow today now"), t.rday); - g.unit = _.process(g.ctoken("second minute hour day week month year"), - function (s) { - return function () { - this.unit = s; - }; - } - ); - g.value = _.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/), - function (s) { - return function () { - this.value = s.replace(/\D/g, ""); - }; - } - ); - g.expression = _.set([ g.rday, g.operator, g.value, g.unit, g.orientation, g.ddd, g.MMM ]); - - // pre-loaded rules for different date part order preferences - _fn = function () { - return _.set(arguments, g.datePartDelimiter); - }; - g.mdy = _fn(g.ddd, g.month, g.day, g.year); - g.ymd = _fn(g.ddd, g.year, g.month, g.day); - g.dmy = _fn(g.ddd, g.day, g.month, g.year); - g.date = function (s) { - return ((g[$C.dateElementOrder] || g.mdy).call(this, s)); - }; - - // parsing date format specifiers - ex: "h:m:s tt" - // this little guy will generate a custom parser based - // on the format string, ex: g.format("h:m:s tt") - g.format = _.process(_.many( - _.any( - // translate format specifiers into grammar rules - _.process( - _.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/), - function (fmt) { - if (g[fmt]) { - return g[fmt]; - } else { - throw $D.Parsing.Exception(fmt); - } - } - ), - // translate separator tokens into token rules - _.process( - _.rtoken(/^[^dMyhHmstz]+/), // all legal separators - function (s) { - return _.ignore(_.stoken(s)); - } - ) - )), - // construct the parser ... - function (rules) { - return _.process(_.each.apply(null, rules), t.finishExact); - } - ); - - var _F = { - //"M/d/yyyy": function (s) { - // var m = s.match(/^([0-2]\d|3[0-1]|\d)\/(1[0-2]|0\d|\d)\/(\d\d\d\d)/); - // if (m!=null) { - // var r = [ t.month.call(this,m[1]), t.day.call(this,m[2]), t.year.call(this,m[3]) ]; - // r = t.finishExact.call(this,r); - // return [ r, "" ]; - // } else { - // throw new Date.Parsing.Exception(s); - // } - //} - //"M/d/yyyy": function (s) { return [ new Date(Date._parse(s)), ""]; } - }; - var _get = function (f) { - return _F[f] = (_F[f] || g.format(f)[0]); - }; - - g.formats = function (fx) { - if (fx instanceof Array) { - var rx = []; - for (var i = 0 ; i < fx.length ; i++) { - rx.push(_get(fx[i])); - } - return _.any.apply(null, rx); - } else { - return _get(fx); - } - }; - - // check for these formats first - g._formats = g.formats([ - "\"yyyy-MM-ddTHH:mm:ssZ\"", - "yyyy-MM-ddTHH:mm:ssZ", - "yyyy-MM-ddTHH:mm:ssz", - "yyyy-MM-ddTHH:mm:ss", - "yyyy-MM-ddTHH:mmZ", - "yyyy-MM-ddTHH:mmz", - "yyyy-MM-ddTHH:mm", - "ddd, MMM dd, yyyy H:mm:ss tt", - "ddd MMM d yyyy HH:mm:ss zzz", - "MMddyyyy", - "ddMMyyyy", - "Mddyyyy", - "ddMyyyy", - "Mdyyyy", - "dMyyyy", - "yyyy", - "Mdyy", - "dMyy", - "d" - ]); - - // starting rule for general purpose grammar - g._start = _.process(_.set([ g.date, g.time, g.expression ], - g.generalDelimiter, g.whiteSpace), t.finish); - - // real starting rule: tries selected formats first, - // then general purpose rule - g.start = function (s) { - try { - var r = g._formats.call({}, s); - if (r[1].length === 0) { - return r; - } - } catch (e) {} - return g._start.call({}, s); - }; - - $D._parse = $D.parse; - - /** - * Converts the specified string value into its JavaScript Date equivalent using CultureInfo specific format information. - * - * Example -

-    ///////////
-    // Dates //
-    ///////////
-
-    // 15-Oct-2004
-    var d1 = Date.parse("10/15/2004");
-
-    // 15-Oct-2004
-    var d1 = Date.parse("15-Oct-2004");
-
-    // 15-Oct-2004
-    var d1 = Date.parse("2004.10.15");
-
-    //Fri Oct 15, 2004
-    var d1 = Date.parse("Fri Oct 15, 2004");
-
-    ///////////
-    // Times //
-    ///////////
-
-    // Today at 10 PM.
-    var d1 = Date.parse("10 PM");
-
-    // Today at 10:30 PM.
-    var d1 = Date.parse("10:30 P.M.");
-
-    // Today at 6 AM.
-    var d1 = Date.parse("06am");
-
-    /////////////////////
-    // Dates and Times //
-    /////////////////////
-
-    // 8-July-2004 @ 10:30 PM
-    var d1 = Date.parse("July 8th, 2004, 10:30 PM");
-
-    // 1-July-2004 @ 10:30 PM
-    var d1 = Date.parse("2004-07-01T22:30:00");
-
-    ////////////////////
-    // Relative Dates //
-    ////////////////////
-
-    // Returns today's date. The string "today" is culture specific.
-    var d1 = Date.parse("today");
-
-    // Returns yesterday's date. The string "yesterday" is culture specific.
-    var d1 = Date.parse("yesterday");
-
-    // Returns the date of the next thursday.
-    var d1 = Date.parse("Next thursday");
-
-    // Returns the date of the most previous monday.
-    var d1 = Date.parse("last monday");
-
-    // Returns today's day + one year.
-    var d1 = Date.parse("next year");
-
-    ///////////////
-    // Date Math //
-    ///////////////
-
-    // Today + 2 days
-    var d1 = Date.parse("t+2");
-
-    // Today + 2 days
-    var d1 = Date.parse("today + 2 days");
-
-    // Today + 3 months
-    var d1 = Date.parse("t+3m");
-
-    // Today - 1 year
-    var d1 = Date.parse("today - 1 year");
-
-    // Today - 1 year
-    var d1 = Date.parse("t-1y"); 
-
-
-    /////////////////////////////
-    // Partial Dates and Times //
-    /////////////////////////////
-
-    // July 15th of this year.
-    var d1 = Date.parse("July 15");
-
-    // 15th day of current day and year.
-    var d1 = Date.parse("15");
-
-    // July 1st of current year at 10pm.
-    var d1 = Date.parse("7/1 10pm");
-    
- * - * @param {String} The string value to convert into a Date object [Required] - * @return {Date} A Date object or null if the string cannot be converted into a Date. - */ - $D.parse = function (s) { - var r = null; - if (!s) { - return null; - } - if (s instanceof Date) { - return s; - } - try { - r = $D.Grammar.start.call({}, s.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1")); - } catch (e) { - return null; - } - return ((r[1].length === 0) ? r[0] : null); - }; - - $D.getParseFunction = function (fx) { - var fn = $D.Grammar.formats(fx); - return function (s) { - var r = null; - try { - r = fn.call({}, s); - } catch (e) { - return null; - } - return ((r[1].length === 0) ? r[0] : null); - }; - }; - - /** - * Converts the specified string value into its JavaScript Date equivalent using the specified format {String} or formats {Array} and the CultureInfo specific format information. - * The format of the string value must match one of the supplied formats exactly. - * - * Example -

-    // 15-Oct-2004
-    var d1 = Date.parseExact("10/15/2004", "M/d/yyyy");
-
-    // 15-Oct-2004
-    var d1 = Date.parse("15-Oct-2004", "M-ddd-yyyy");
-
-    // 15-Oct-2004
-    var d1 = Date.parse("2004.10.15", "yyyy.MM.dd");
-
-    // Multiple formats
-    var d1 = Date.parseExact("10/15/2004", ["M/d/yyyy", "MMMM d, yyyy"]);
-    
- * - * @param {String} The string value to convert into a Date object [Required]. - * @param {Object} The expected format {String} or an array of expected formats {Array} of the date string [Required]. - * @return {Date} A Date object or null if the string cannot be converted into a Date. - */ - $D.parseExact = function (s, fx) { - return $D.getParseFunction(fx)(s); - }; + var _ = $D.Parsing.Operators, g = $D.Grammar, t = $D.Translator, _fn; + + g.datePartDelimiter = _.rtoken(/^([\s\-\.\,\/\x27]+)/); + g.timePartDelimiter = _.stoken(":"); + g.whiteSpace = _.rtoken(/^\s*/); + g.generalDelimiter = _.rtoken(/^(([\s\,]|at|@|on)+)/); + + var _C = {}; + g.ctoken = function (keys) { + var fn = _C[keys]; + if (! fn) { + var c = $C.regexPatterns; + var kx = keys.split(/\s+/), px = []; + for (var i = 0; i < kx.length ; i++) { + px.push(_.replace(_.rtoken(c[kx[i]]), kx[i])); + } + fn = _C[keys] = _.any.apply(null, px); + } + return fn; + }; + g.ctoken2 = function (key) { + return _.rtoken($C.regexPatterns[key]); + }; + + // hour, minute, second, meridian, timezone + g.h = _.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/), t.hour)); + g.hh = _.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/), t.hour)); + g.H = _.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/), t.hour)); + g.HH = _.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/), t.hour)); + g.m = _.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/), t.minute)); + g.mm = _.cache(_.process(_.rtoken(/^[0-5][0-9]/), t.minute)); + g.s = _.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/), t.second)); + g.ss = _.cache(_.process(_.rtoken(/^[0-5][0-9]/), t.second)); + g.hms = _.cache(_.sequence([g.H, g.m, g.s], g.timePartDelimiter)); + + // _.min(1, _.set([ g.H, g.m, g.s ], g._t)); + g.t = _.cache(_.process(g.ctoken2("shortMeridian"), t.meridian)); + g.tt = _.cache(_.process(g.ctoken2("longMeridian"), t.meridian)); + g.z = _.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/), t.timezone)); + g.zz = _.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/), t.timezone)); + + g.zzz = _.cache(_.process(g.ctoken2("timezone"), t.timezone)); + g.timeSuffix = _.each(_.ignore(g.whiteSpace), _.set([ g.tt, g.zzz ])); + g.time = _.each(_.optional(_.ignore(_.stoken("T"))), g.hms, g.timeSuffix); + + // days, months, years + g.d = _.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/), + _.optional(g.ctoken2("ordinalSuffix"))), t.day)); + g.dd = _.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/), + _.optional(g.ctoken2("ordinalSuffix"))), t.day)); + g.ddd = g.dddd = _.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"), + function (s) { + return function () { + this.weekday = s; + }; + } + )); + g.M = _.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/), t.month)); + g.MM = _.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/), t.month)); + g.MMM = g.MMMM = _.cache(_.process( + g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"), t.month)); + g.y = _.cache(_.process(_.rtoken(/^(\d\d?)/), t.year)); + g.yy = _.cache(_.process(_.rtoken(/^(\d\d)/), t.year)); + g.yyy = _.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/), t.year)); + g.yyyy = _.cache(_.process(_.rtoken(/^(\d\d\d\d)/), t.year)); + + // rolling these up into general purpose rules + _fn = function () { + return _.each(_.any.apply(null, arguments), _.not(g.ctoken2("timeContext"))); + }; + + g.day = _fn(g.d, g.dd); + g.month = _fn(g.M, g.MMM); + g.year = _fn(g.yyyy, g.yy); + + // relative date / time expressions + g.orientation = _.process(g.ctoken("past future"), + function (s) { + return function () { + this.orient = s; + }; + } + ); + g.operator = _.process(g.ctoken("add subtract"), + function (s) { + return function () { + this.operator = s; + }; + } + ); + g.rday = _.process(g.ctoken("yesterday tomorrow today now"), t.rday); + g.unit = _.process(g.ctoken("second minute hour day week month year"), + function (s) { + return function () { + this.unit = s; + }; + } + ); + g.value = _.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/), + function (s) { + return function () { + this.value = s.replace(/\D/g, ""); + }; + } + ); + g.expression = _.set([ g.rday, g.operator, g.value, g.unit, g.orientation, g.ddd, g.MMM ]); + + // pre-loaded rules for different date part order preferences + _fn = function () { + return _.set(arguments, g.datePartDelimiter); + }; + g.mdy = _fn(g.ddd, g.month, g.day, g.year); + g.ymd = _fn(g.ddd, g.year, g.month, g.day); + g.dmy = _fn(g.ddd, g.day, g.month, g.year); + g.date = function (s) { + return ((g[$C.dateElementOrder] || g.mdy).call(this, s)); + }; + + // parsing date format specifiers - ex: "h:m:s tt" + // this little guy will generate a custom parser based + // on the format string, ex: g.format("h:m:s tt") + g.format = _.process(_.many( + _.any( + // translate format specifiers into grammar rules + _.process( + _.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/), + function (fmt) { + if (g[fmt]) { + return g[fmt]; + } else { + throw $D.Parsing.Exception(fmt); + } + } + ), + // translate separator tokens into token rules + _.process( + _.rtoken(/^[^dMyhHmstz]+/), // all legal separators + function (s) { + return _.ignore(_.stoken(s)); + } + ) + )), + // construct the parser ... + function (rules) { + return _.process(_.each.apply(null, rules), t.finishExact); + } + ); + + var _F = { + //"M/d/yyyy": function (s) { + // var m = s.match(/^([0-2]\d|3[0-1]|\d)\/(1[0-2]|0\d|\d)\/(\d\d\d\d)/); + // if (m!=null) { + // var r = [ t.month.call(this,m[1]), t.day.call(this,m[2]), t.year.call(this,m[3]) ]; + // r = t.finishExact.call(this,r); + // return [ r, "" ]; + // } else { + // throw new Date.Parsing.Exception(s); + // } + //} + //"M/d/yyyy": function (s) { return [ new Date(Date._parse(s)), ""]; } + }; + var _get = function (f) { + return _F[f] = (_F[f] || g.format(f)[0]); + }; + + g.formats = function (fx) { + if (fx instanceof Array) { + var rx = []; + for (var i = 0 ; i < fx.length ; i++) { + rx.push(_get(fx[i])); + } + return _.any.apply(null, rx); + } else { + return _get(fx); + } + }; + + // check for these formats first + g._formats = g.formats([ + "\"yyyy-MM-ddTHH:mm:ssZ\"", + "yyyy-MM-ddTHH:mm:ssZ", + "yyyy-MM-ddTHH:mm:ssz", + "yyyy-MM-ddTHH:mm:ss", + "yyyy-MM-ddTHH:mmZ", + "yyyy-MM-ddTHH:mmz", + "yyyy-MM-ddTHH:mm", + "ddd, MMM dd, yyyy H:mm:ss tt", + "ddd MMM d yyyy HH:mm:ss zzz", + "MMddyyyy", + "ddMMyyyy", + "Mddyyyy", + "ddMyyyy", + "Mdyyyy", + "dMyyyy", + "yyyy", + "Mdyy", + "dMyy", + "d" + ]); + + // starting rule for general purpose grammar + g._start = _.process(_.set([ g.date, g.time, g.expression ], + g.generalDelimiter, g.whiteSpace), t.finish); + + // real starting rule: tries selected formats first, + // then general purpose rule + g.start = function (s) { + try { + var r = g._formats.call({}, s); + if (r[1].length === 0) { + return r; + } + } catch (e) {} + return g._start.call({}, s); + }; + + $D._parse = $D.parse; + + /** + * Converts the specified string value into its JavaScript Date equivalent using CultureInfo specific format information. + * + * Example +

+    ///////////
+    // Dates //
+    ///////////
+
+    // 15-Oct-2004
+    var d1 = Date.parse("10/15/2004");
+
+    // 15-Oct-2004
+    var d1 = Date.parse("15-Oct-2004");
+
+    // 15-Oct-2004
+    var d1 = Date.parse("2004.10.15");
+
+    //Fri Oct 15, 2004
+    var d1 = Date.parse("Fri Oct 15, 2004");
+
+    ///////////
+    // Times //
+    ///////////
+
+    // Today at 10 PM.
+    var d1 = Date.parse("10 PM");
+
+    // Today at 10:30 PM.
+    var d1 = Date.parse("10:30 P.M.");
+
+    // Today at 6 AM.
+    var d1 = Date.parse("06am");
+
+    /////////////////////
+    // Dates and Times //
+    /////////////////////
+
+    // 8-July-2004 @ 10:30 PM
+    var d1 = Date.parse("July 8th, 2004, 10:30 PM");
+
+    // 1-July-2004 @ 10:30 PM
+    var d1 = Date.parse("2004-07-01T22:30:00");
+
+    ////////////////////
+    // Relative Dates //
+    ////////////////////
+
+    // Returns today's date. The string "today" is culture specific.
+    var d1 = Date.parse("today");
+
+    // Returns yesterday's date. The string "yesterday" is culture specific.
+    var d1 = Date.parse("yesterday");
+
+    // Returns the date of the next thursday.
+    var d1 = Date.parse("Next thursday");
+
+    // Returns the date of the most previous monday.
+    var d1 = Date.parse("last monday");
+
+    // Returns today's day + one year.
+    var d1 = Date.parse("next year");
+
+    ///////////////
+    // Date Math //
+    ///////////////
+
+    // Today + 2 days
+    var d1 = Date.parse("t+2");
+
+    // Today + 2 days
+    var d1 = Date.parse("today + 2 days");
+
+    // Today + 3 months
+    var d1 = Date.parse("t+3m");
+
+    // Today - 1 year
+    var d1 = Date.parse("today - 1 year");
+
+    // Today - 1 year
+    var d1 = Date.parse("t-1y");
+
+
+    /////////////////////////////
+    // Partial Dates and Times //
+    /////////////////////////////
+
+    // July 15th of this year.
+    var d1 = Date.parse("July 15");
+
+    // 15th day of current day and year.
+    var d1 = Date.parse("15");
+
+    // July 1st of current year at 10pm.
+    var d1 = Date.parse("7/1 10pm");
+    
+ * + * @param {String} The string value to convert into a Date object [Required] + * @return {Date} A Date object or null if the string cannot be converted into a Date. + */ + $D.parse = function (s) { + var r = null; + if (!s) { + return null; + } + if (s instanceof Date) { + return s; + } + try { + r = $D.Grammar.start.call({}, s.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1")); + } catch (e) { + return null; + } + return ((r[1].length === 0) ? r[0] : null); + }; + + $D.getParseFunction = function (fx) { + var fn = $D.Grammar.formats(fx); + return function (s) { + var r = null; + try { + r = fn.call({}, s); + } catch (e) { + return null; + } + return ((r[1].length === 0) ? r[0] : null); + }; + }; + + /** + * Converts the specified string value into its JavaScript Date equivalent using the specified format {String} or formats {Array} and the CultureInfo specific format information. + * The format of the string value must match one of the supplied formats exactly. + * + * Example +

+    // 15-Oct-2004
+    var d1 = Date.parseExact("10/15/2004", "M/d/yyyy");
+
+    // 15-Oct-2004
+    var d1 = Date.parse("15-Oct-2004", "M-ddd-yyyy");
+
+    // 15-Oct-2004
+    var d1 = Date.parse("2004.10.15", "yyyy.MM.dd");
+
+    // Multiple formats
+    var d1 = Date.parseExact("10/15/2004", ["M/d/yyyy", "MMMM d, yyyy"]);
+    
+ * + * @param {String} The string value to convert into a Date object [Required]. + * @param {Object} The expected format {String} or an array of expected formats {Array} of the date string [Required]. + * @return {Date} A Date object or null if the string cannot be converted into a Date. + */ + $D.parseExact = function (s, fx) { + return $D.getParseFunction(fx)(s); + }; }());/* http://www.JSON.org/json2.js 2008-11-19 @@ -3920,346 +3923,346 @@ replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { // Export module module.exports = _s; - // Integrate with Underscore.js - } else if (typeof root._ !== 'undefined') { - root._.mixin(_s); + // Integrate with Underscore.js + } else if (typeof root._ !== 'undefined') { + root._.mixin(_s); + + // Or define it + } else { + root._ = _s; + } + +}()); +/* + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined + * in FIPS 180-1 + * Version 2.2 Copyright Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for details. + */ + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ +var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_sha1(s) { return rstr2hex(rstr_sha1(str2rstr_utf8(s))); } +function b64_sha1(s) { return rstr2b64(rstr_sha1(str2rstr_utf8(s))); } +function any_sha1(s, e) { return rstr2any(rstr_sha1(str2rstr_utf8(s)), e); } +function hex_hmac_sha1(k, d) + { return rstr2hex(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); } +function b64_hmac_sha1(k, d) + { return rstr2b64(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); } +function any_hmac_sha1(k, d, e) + { return rstr2any(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d)), e); } + +/* + * Perform a simple self-test to see if the VM is working + */ +function sha1_vm_test() +{ + return hex_sha1("abc").toLowerCase() == "a9993e364706816aba3e25717850c26c9cd0d89d"; +} + +/* + * Calculate the SHA1 of a raw string + */ +function rstr_sha1(s) +{ + return binb2rstr(binb_sha1(rstr2binb(s), s.length * 8)); +} + +/* + * Calculate the HMAC-SHA1 of a key and some data (raw strings) + */ +function rstr_hmac_sha1(key, data) +{ + var bkey = rstr2binb(key); + if(bkey.length > 16) bkey = binb_sha1(bkey, key.length * 8); + + var ipad = Array(16), opad = Array(16); + for(var i = 0; i < 16; i++) + { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + var hash = binb_sha1(ipad.concat(rstr2binb(data)), 512 + data.length * 8); + return binb2rstr(binb_sha1(opad.concat(hash), 512 + 160)); +} + +/* + * Convert a raw string to a hex string + */ +function rstr2hex(input) +{ + try { hexcase } catch(e) { hexcase=0; } + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var output = ""; + var x; + for(var i = 0; i < input.length; i++) + { + x = input.charCodeAt(i); + output += hex_tab.charAt((x >>> 4) & 0x0F) + + hex_tab.charAt( x & 0x0F); + } + return output; +} + +/* + * Convert a raw string to a base-64 string + */ +function rstr2b64(input) +{ + try { b64pad } catch(e) { b64pad=''; } + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var output = ""; + var len = input.length; + for(var i = 0; i < len; i += 3) + { + var triplet = (input.charCodeAt(i) << 16) + | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) + | (i + 2 < len ? input.charCodeAt(i+2) : 0); + for(var j = 0; j < 4; j++) + { + if(i * 8 + j * 6 > input.length * 8) output += b64pad; + else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); + } + } + return output; +} + +/* + * Convert a raw string to an arbitrary string encoding + */ +function rstr2any(input, encoding) +{ + var divisor = encoding.length; + var remainders = Array(); + var i, q, x, quotient; + + /* Convert to an array of 16-bit big-endian values, forming the dividend */ + var dividend = Array(Math.ceil(input.length / 2)); + for(i = 0; i < dividend.length; i++) + { + dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); + } + + /* + * Repeatedly perform a long division. The binary array forms the dividend, + * the length of the encoding is the divisor. Once computed, the quotient + * forms the dividend for the next step. We stop when the dividend is zero. + * All remainders are stored for later use. + */ + while(dividend.length > 0) + { + quotient = Array(); + x = 0; + for(i = 0; i < dividend.length; i++) + { + x = (x << 16) + dividend[i]; + q = Math.floor(x / divisor); + x -= q * divisor; + if(quotient.length > 0 || q > 0) + quotient[quotient.length] = q; + } + remainders[remainders.length] = x; + dividend = quotient; + } + + /* Convert the remainders to the output string */ + var output = ""; + for(i = remainders.length - 1; i >= 0; i--) + output += encoding.charAt(remainders[i]); + + /* Append leading zero equivalents */ + var full_length = Math.ceil(input.length * 8 / + (Math.log(encoding.length) / Math.log(2))) + for(i = output.length; i < full_length; i++) + output = encoding[0] + output; + + return output; +} + +/* + * Encode a string as utf-8. + * For efficiency, this assumes the input is valid utf-16. + */ +function str2rstr_utf8(input) +{ + var output = ""; + var i = -1; + var x, y; + + while(++i < input.length) + { + /* Decode utf-16 surrogate pairs */ + x = input.charCodeAt(i); + y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; + if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) + { + x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); + i++; + } + + /* Encode output as utf-8 */ + if(x <= 0x7F) + output += String.fromCharCode(x); + else if(x <= 0x7FF) + output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), + 0x80 | ( x & 0x3F)); + else if(x <= 0xFFFF) + output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), + 0x80 | ((x >>> 6 ) & 0x3F), + 0x80 | ( x & 0x3F)); + else if(x <= 0x1FFFFF) + output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), + 0x80 | ((x >>> 12) & 0x3F), + 0x80 | ((x >>> 6 ) & 0x3F), + 0x80 | ( x & 0x3F)); + } + return output; +} + +/* + * Encode a string as utf-16 + */ +function str2rstr_utf16le(input) +{ + var output = ""; + for(var i = 0; i < input.length; i++) + output += String.fromCharCode( input.charCodeAt(i) & 0xFF, + (input.charCodeAt(i) >>> 8) & 0xFF); + return output; +} + +function str2rstr_utf16be(input) +{ + var output = ""; + for(var i = 0; i < input.length; i++) + output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, + input.charCodeAt(i) & 0xFF); + return output; +} + +/* + * Convert a raw string to an array of big-endian words + * Characters >255 have their high-byte silently ignored. + */ +function rstr2binb(input) +{ + var output = Array(input.length >> 2); + for(var i = 0; i < output.length; i++) + output[i] = 0; + for(var i = 0; i < input.length * 8; i += 8) + output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32); + return output; +} + +/* + * Convert an array of big-endian words to a string + */ +function binb2rstr(input) +{ + var output = ""; + for(var i = 0; i < input.length * 32; i += 8) + output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF); + return output; +} + +/* + * Calculate the SHA-1 of an array of big-endian words, and a bit length + */ +function binb_sha1(x, len) +{ + /* append padding */ + x[len >> 5] |= 0x80 << (24 - len % 32); + x[((len + 64 >> 9) << 4) + 15] = len; + + var w = Array(80); + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + var e = -1009589776; + + for(var i = 0; i < x.length; i += 16) + { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + var olde = e; + + for(var j = 0; j < 80; j++) + { + if(j < 16) w[j] = x[i + j]; + else w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); + var t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), + safe_add(safe_add(e, w[j]), sha1_kt(j))); + e = d; + d = c; + c = bit_rol(b, 30); + b = a; + a = t; + } + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + e = safe_add(e, olde); + } + return Array(a, b, c, d, e); + +} + +/* + * Perform the appropriate triplet combination function for the current + * iteration + */ +function sha1_ft(t, b, c, d) +{ + if(t < 20) return (b & c) | ((~b) & d); + if(t < 40) return b ^ c ^ d; + if(t < 60) return (b & c) | (b & d) | (c & d); + return b ^ c ^ d; +} + +/* + * Determine the appropriate additive constant for the current iteration + */ +function sha1_kt(t) +{ + return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : + (t < 60) ? -1894007588 : -899497514; +} - // Or define it - } else { - root._ = _s; - } +/* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ +function safe_add(x, y) +{ + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} -}()); -/* - * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined - * in FIPS 180-1 - * Version 2.2 Copyright Paul Johnston 2000 - 2009. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for details. - */ - -/* - * Configurable variables. You may need to tweak these to be compatible with - * the server-side, but the defaults work in most cases. - */ -var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ -var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ - -/* - * These are the functions you'll usually want to call - * They take string arguments and return either hex or base-64 encoded strings - */ -function hex_sha1(s) { return rstr2hex(rstr_sha1(str2rstr_utf8(s))); } -function b64_sha1(s) { return rstr2b64(rstr_sha1(str2rstr_utf8(s))); } -function any_sha1(s, e) { return rstr2any(rstr_sha1(str2rstr_utf8(s)), e); } -function hex_hmac_sha1(k, d) - { return rstr2hex(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); } -function b64_hmac_sha1(k, d) - { return rstr2b64(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); } -function any_hmac_sha1(k, d, e) - { return rstr2any(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d)), e); } - -/* - * Perform a simple self-test to see if the VM is working - */ -function sha1_vm_test() -{ - return hex_sha1("abc").toLowerCase() == "a9993e364706816aba3e25717850c26c9cd0d89d"; -} - -/* - * Calculate the SHA1 of a raw string - */ -function rstr_sha1(s) -{ - return binb2rstr(binb_sha1(rstr2binb(s), s.length * 8)); -} - -/* - * Calculate the HMAC-SHA1 of a key and some data (raw strings) - */ -function rstr_hmac_sha1(key, data) -{ - var bkey = rstr2binb(key); - if(bkey.length > 16) bkey = binb_sha1(bkey, key.length * 8); - - var ipad = Array(16), opad = Array(16); - for(var i = 0; i < 16; i++) - { - ipad[i] = bkey[i] ^ 0x36363636; - opad[i] = bkey[i] ^ 0x5C5C5C5C; - } - - var hash = binb_sha1(ipad.concat(rstr2binb(data)), 512 + data.length * 8); - return binb2rstr(binb_sha1(opad.concat(hash), 512 + 160)); -} - -/* - * Convert a raw string to a hex string - */ -function rstr2hex(input) -{ - try { hexcase } catch(e) { hexcase=0; } - var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; - var output = ""; - var x; - for(var i = 0; i < input.length; i++) - { - x = input.charCodeAt(i); - output += hex_tab.charAt((x >>> 4) & 0x0F) - + hex_tab.charAt( x & 0x0F); - } - return output; -} - -/* - * Convert a raw string to a base-64 string - */ -function rstr2b64(input) -{ - try { b64pad } catch(e) { b64pad=''; } - var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - var output = ""; - var len = input.length; - for(var i = 0; i < len; i += 3) - { - var triplet = (input.charCodeAt(i) << 16) - | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) - | (i + 2 < len ? input.charCodeAt(i+2) : 0); - for(var j = 0; j < 4; j++) - { - if(i * 8 + j * 6 > input.length * 8) output += b64pad; - else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); - } - } - return output; -} - -/* - * Convert a raw string to an arbitrary string encoding - */ -function rstr2any(input, encoding) -{ - var divisor = encoding.length; - var remainders = Array(); - var i, q, x, quotient; - - /* Convert to an array of 16-bit big-endian values, forming the dividend */ - var dividend = Array(Math.ceil(input.length / 2)); - for(i = 0; i < dividend.length; i++) - { - dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); - } - - /* - * Repeatedly perform a long division. The binary array forms the dividend, - * the length of the encoding is the divisor. Once computed, the quotient - * forms the dividend for the next step. We stop when the dividend is zero. - * All remainders are stored for later use. - */ - while(dividend.length > 0) - { - quotient = Array(); - x = 0; - for(i = 0; i < dividend.length; i++) - { - x = (x << 16) + dividend[i]; - q = Math.floor(x / divisor); - x -= q * divisor; - if(quotient.length > 0 || q > 0) - quotient[quotient.length] = q; - } - remainders[remainders.length] = x; - dividend = quotient; - } - - /* Convert the remainders to the output string */ - var output = ""; - for(i = remainders.length - 1; i >= 0; i--) - output += encoding.charAt(remainders[i]); - - /* Append leading zero equivalents */ - var full_length = Math.ceil(input.length * 8 / - (Math.log(encoding.length) / Math.log(2))) - for(i = output.length; i < full_length; i++) - output = encoding[0] + output; - - return output; -} - -/* - * Encode a string as utf-8. - * For efficiency, this assumes the input is valid utf-16. - */ -function str2rstr_utf8(input) -{ - var output = ""; - var i = -1; - var x, y; - - while(++i < input.length) - { - /* Decode utf-16 surrogate pairs */ - x = input.charCodeAt(i); - y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; - if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) - { - x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); - i++; - } - - /* Encode output as utf-8 */ - if(x <= 0x7F) - output += String.fromCharCode(x); - else if(x <= 0x7FF) - output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), - 0x80 | ( x & 0x3F)); - else if(x <= 0xFFFF) - output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), - 0x80 | ((x >>> 6 ) & 0x3F), - 0x80 | ( x & 0x3F)); - else if(x <= 0x1FFFFF) - output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), - 0x80 | ((x >>> 12) & 0x3F), - 0x80 | ((x >>> 6 ) & 0x3F), - 0x80 | ( x & 0x3F)); - } - return output; -} - -/* - * Encode a string as utf-16 - */ -function str2rstr_utf16le(input) -{ - var output = ""; - for(var i = 0; i < input.length; i++) - output += String.fromCharCode( input.charCodeAt(i) & 0xFF, - (input.charCodeAt(i) >>> 8) & 0xFF); - return output; -} - -function str2rstr_utf16be(input) -{ - var output = ""; - for(var i = 0; i < input.length; i++) - output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, - input.charCodeAt(i) & 0xFF); - return output; -} - -/* - * Convert a raw string to an array of big-endian words - * Characters >255 have their high-byte silently ignored. - */ -function rstr2binb(input) -{ - var output = Array(input.length >> 2); - for(var i = 0; i < output.length; i++) - output[i] = 0; - for(var i = 0; i < input.length * 8; i += 8) - output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32); - return output; -} - -/* - * Convert an array of big-endian words to a string - */ -function binb2rstr(input) -{ - var output = ""; - for(var i = 0; i < input.length * 32; i += 8) - output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF); - return output; -} - -/* - * Calculate the SHA-1 of an array of big-endian words, and a bit length - */ -function binb_sha1(x, len) -{ - /* append padding */ - x[len >> 5] |= 0x80 << (24 - len % 32); - x[((len + 64 >> 9) << 4) + 15] = len; - - var w = Array(80); - var a = 1732584193; - var b = -271733879; - var c = -1732584194; - var d = 271733878; - var e = -1009589776; - - for(var i = 0; i < x.length; i += 16) - { - var olda = a; - var oldb = b; - var oldc = c; - var oldd = d; - var olde = e; - - for(var j = 0; j < 80; j++) - { - if(j < 16) w[j] = x[i + j]; - else w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); - var t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), - safe_add(safe_add(e, w[j]), sha1_kt(j))); - e = d; - d = c; - c = bit_rol(b, 30); - b = a; - a = t; - } - - a = safe_add(a, olda); - b = safe_add(b, oldb); - c = safe_add(c, oldc); - d = safe_add(d, oldd); - e = safe_add(e, olde); - } - return Array(a, b, c, d, e); - -} - -/* - * Perform the appropriate triplet combination function for the current - * iteration - */ -function sha1_ft(t, b, c, d) -{ - if(t < 20) return (b & c) | ((~b) & d); - if(t < 40) return b ^ c ^ d; - if(t < 60) return (b & c) | (b & d) | (c & d); - return b ^ c ^ d; -} - -/* - * Determine the appropriate additive constant for the current iteration - */ -function sha1_kt(t) -{ - return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : - (t < 60) ? -1894007588 : -899497514; -} - -/* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ -function safe_add(x, y) -{ - var lsw = (x & 0xFFFF) + (y & 0xFFFF); - var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); -} - -/* - * Bitwise rotate a 32-bit number to the left. - */ -function bit_rol(num, cnt) -{ - return (num << cnt) | (num >>> (32 - cnt)); -} +/* + * Bitwise rotate a 32-bit number to the left. + */ +function bit_rol(num, cnt) +{ + return (num << cnt) | (num >>> (32 - cnt)); +} /** * OAuth JavaScript library * Taken from http://oauth.googlecode.com/ @@ -4811,30 +4814,30 @@ OAuth.SignatureMethod.registerMethodClass(["HMAC-SHA1", "HMAC-SHA1-Accessor"], )); OAuth.correctTimestampFromSrc(); -/*jslint +/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc; - + /* * makes relative time out of "Sun Jul 08 19:01:12 +0000 2007" type string * Borrowed from Mike Demers (slightly altered) * https://twitter.pbwiki.com/RelativeTimeScripts - * + * * This requires date.js * http://www.datejs.com/ * @param {string} time_value a string to convert into relative time * @param {object} [labels] labels for text portions of time descriptions * @param {boolean} [use_dateparse] Whether or not to use the Date.parse method to parse the time_value. Default is FALSE */ -sc.helpers.getRelativeTime = function(time_value, labels, use_dateparse) { - +sc.helpers.getRelativeTime = function(time_value, labels, use_dateparse) { + var default_labels = { 'now':'Just now', 'seconds':'sec ago', @@ -4843,22 +4846,22 @@ sc.helpers.getRelativeTime = function(time_value, labels, use_dateparse) { 'hour':'hr ago', 'hours':'hr ago', 'day':'day ago', - 'days':'days ago' + 'days':'days ago' }; - + labels = sch.defaults(default_labels, labels); - + var parsed_date; - + if (use_dateparse === true) { parsed_date = new Date.parse(time_value); } else { parsed_date = new Date(time_value); } - + var now = new Date(); var delta = parseInt( (now.getTime() - parsed_date.getTime()) / 1000, 10); - + if (delta < 10) { return labels.now; } else if(delta < 60) { @@ -4883,87 +4886,87 @@ sc.helpers.getRelativeTime = function(time_value, labels, use_dateparse) { }; /** - * @member sc.helpers + * @member sc.helpers */ sc.helpers.httpTimeToInt = function(entry_date, use_dateparse) { return sc.helpers.dateToInt(entry_date, use_dateparse); }; /** - * this returns milliseconds, not seconds! - * @member sc.helpers + * this returns milliseconds, not seconds! + * @member sc.helpers */ sc.helpers.dateToInt = function(entry_date, use_dateparse) { var parsedDate = new Date(); - + if (use_dateparse === true) { entry_date = new Date.parse(entry_date); } else { entry_date = new Date(entry_date); } - + parsedDate.setTime(entry_date); return parsedDate.getTime(); }; /** - * @member sc.helpers + * @member sc.helpers */ sc.helpers.getTimeAsInt = function() { var now = new Date(); return now.getTime(); }; -/*jslint +/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc; - + /** * add an event listener to a target (element, window, etc). Uses target.addEventListener - * + * * @param {object} target * @param {string} event_type * @param {function} handler a method that will take the event as a param, and "this" refers to target * @param {Object} [scope] the scope to execute the handler within (what "this" refers to) * @param {boolean} [use_capture] defaults to false * @returns {function} the handler that was passed -- or created, if we passed a scope. You can use this to remove the listener later on - * @member sc.helpers + * @member sc.helpers */ sc.helpers.addListener = function(target, event_type, handler, scope, use_capture) { - + if (scope) { sch.warn('scope no longer supported! use a closure or reference "scope" in your event handler'); } if (use_capture) { sch.warn('use_capture no longer supported!'); } - + sch.debug('listening for '+event_type); sch.debug('on target nodeName:'+target.nodeName); - + jQuery(target).bind(event_type, handler); - + }; /** * removes an event listener on a target (element, window, etc). uses Uses target.removeEventListener - * + * * Note that you must match all of the parameters to successfully remove the listener - * + * * @param {object} target * @param {string} event_type * @param {function} handler a method that will take the event as a param, and "this" refers to target * @param {Object} scope the scope to execute the handler * @param {boolean} use_capture defaults to false - * @member sc.helpers + * @member sc.helpers */ sc.helpers.removeListener = function(target, event_type, handler, use_capture) { @@ -4973,75 +4976,75 @@ sc.helpers.removeListener = function(target, event_type, handler, use_capture) { if (use_capture) { sch.warn('use_capture no longer supported!'); } - + jQuery(target).unbind(event_type, handler); }; /** * @param {DOMElement} base_target The base target where the delegated listener will be set-up * @param {string} selector The CSS Selector that will be used to match incoming events. Matching is done with jQuery - * @param {string} event_type The event type + * @param {string} event_type The event type * @param {Function} handler a method that will take the event as a param, and "this" refers to target * @param {Object} [scope] the scope to execute the handler * @param {Boolean} [use_capture] Describe this parameter */ sc.helpers.addDelegatedListener = function(base_target, selector, event_type, handler, scope) { - + sch.warn('scope no longer supported! use a closure or reference "scope" in your event handler'); - + sch.debug('listening for '+event_type); sch.debug('on target nodeName:'+target.nodeName); sch.debug('for selector:'+selector); - + jQuery(base_target).delegate(selector, event_type, handler); - + }; /** * @param {DOMElement} base_target The base target where the delegated listener will be set-up * @param {string} selector The CSS Selector that will be used to match incoming events. Matching is done with jQuery - * @param {string} event_type The event type + * @param {string} event_type The event type * @param {Function} handler a method that will take the event as a param, and "this" refers to target * @param {Object} [scope] the scope to execute the handler */ sc.helpers.removeDelegatedListener = function(base_target, selector, event_type, handler, scope) { sch.warn('scope no longer supported! use a closure or reference "scope" in your event handler'); - + jQuery(base_target).delegate(selector, event_type, handler); - + }; /** * This triggers a custom event using document.createEvent('Events') and target.dispatchEvent() - * + * * @param {string} event_type * @param {DOMElement} target the target for the event (element, window, etc) * @param {object} data data to pass with event. it is always passed as the second parameter to the handler (after the event object) * @param {boolean} bubble whether the event should bubble or not. defaults to true - * @member sc.helpers + * @member sc.helpers */ sc.helpers.triggerCustomEvent = function(event_type, target, data, bubble) { - + sch.debug('EVENT triggering '+event_type); sch.debug('EVENT on target nodeName:'+target.nodeName); - + if (bubble) { sch.warn('bubble is no longer supported!'); } - + if (data) { sch.debug('EVENT data passed'); data = [data]; } - + jQuery(target).trigger(event_type, data); - + }; /** * retrieves the data added to this event object - * @param {DOMEvent} event_obj + * @param {DOMEvent} event_obj * @deprecated */ sc.helpers.getEventData = function(event_obj) { @@ -5050,40 +5053,40 @@ sc.helpers.getEventData = function(event_obj) { }; /** - * Alias for sc.helpers.addListener - * @member sc.helpers + * Alias for sc.helpers.addListener + * @member sc.helpers * @function */ sc.helpers.listen = sc.helpers.addListener; /** * Alias for sc.helpers.removeListener - * @member sc.helpers + * @member sc.helpers * @function */ sc.helpers.unlisten = sc.helpers.removeListener; /** * Alias for sc.helpers.addDelegatedListener - * @member sc.helpers + * @member sc.helpers * @function */ sc.helpers.delegate = sc.helpers.addDelegatedListener; /** * Alias for sc.helpers.removeDelegatedListener - * @member sc.helpers + * @member sc.helpers * @function */ sc.helpers.undelegate = sc.helpers.removeDelegatedListener; /** - * Alias for sc.helpers.triggerCustomEvent - * @member sc.helpers + * Alias for sc.helpers.triggerCustomEvent + * @member sc.helpers * @function */ -sc.helpers.trigger = sc.helpers.triggerCustomEvent;/*jslint +sc.helpers.trigger = sc.helpers.triggerCustomEvent;/*jslint bitwise: false, browser: true, nomen: false, @@ -5095,10 +5098,10 @@ plusplus: false, newcap: false, undef: false, white: false, -onevar: false +onevar: false */ var sc; - + /* We're more lax with JSLint here because this is almost all not our code */ @@ -5271,15 +5274,15 @@ sc.helpers.Base64 = { * @function **/ sc.helpers.crc32 = function (str) { - + function Utf8Encode(string) { string = string.replace(/\r\n/g,"\n"); var utftext = ""; - + for (var n = 0; n < string.length; n++) { - + var c = string.charCodeAt(n); - + if (c < 128) { utftext += String.fromCharCode(c); } @@ -5292,29 +5295,29 @@ sc.helpers.crc32 = function (str) { utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } - + } - + return utftext; } - + str = Utf8Encode(str); - + var table = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D"; - + if (typeof(crc) == "undefined") { crc = 0; } var x = 0; var y = 0; - + crc = crc ^ (-1); for( var i = 0, iTop = str.length; i < iTop; i++ ) { y = ( crc ^ str.charCodeAt( i ) ) & 0xFF; x = "0x" + table.substr( y * 9, 8 ); crc = ( crc >>> 8 ) ^ x; } - + return crc ^ (-1); - + }; @@ -5325,11 +5328,11 @@ sc.helpers.crc32 = function (str) { * @function **/ sc.helpers.MD5 = function (string) { - + function RotateLeft(lValue, iShiftBits) { return (lValue<>>(32-iShiftBits)); } - + function AddUnsigned(lX,lY) { var lX4,lY4,lX8,lY8,lResult; lX8 = (lX & 0x80000000); @@ -5350,32 +5353,32 @@ sc.helpers.MD5 = function (string) { return (lResult ^ lX8 ^ lY8); } } - + function F(x,y,z) { return (x & y) | ((~x) & z); } function G(x,y,z) { return (x & z) | (y & (~z)); } function H(x,y,z) { return (x ^ y ^ z); } function I(x,y,z) { return (y ^ (x | (~z))); } - + function FF(a,b,c,d,x,s,ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b); } - + function GG(a,b,c,d,x,s,ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b); } - + function HH(a,b,c,d,x,s,ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b); } - + function II(a,b,c,d,x,s,ac) { a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac)); return AddUnsigned(RotateLeft(a, s), b); } - + function ConvertToWordArray(string) { var lWordCount; var lMessageLength = string.length; @@ -5398,7 +5401,7 @@ sc.helpers.MD5 = function (string) { lWordArray[lNumberOfWords-1] = lMessageLength>>>29; return lWordArray; } - + function WordToHex(lValue) { var WordToHexValue="",WordToHexValue_temp="",lByte,lCount; for (lCount = 0;lCount<=3;lCount++) { @@ -5408,15 +5411,15 @@ sc.helpers.MD5 = function (string) { } return WordToHexValue; } - + function Utf8Encode(string) { string = string.replace(/\r\n/g,"\n"); var utftext = ""; - + for (var n = 0; n < string.length; n++) { - + var c = string.charCodeAt(n); - + if (c < 128) { utftext += String.fromCharCode(c); } @@ -5429,25 +5432,25 @@ sc.helpers.MD5 = function (string) { utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } - + } - + return utftext; } - + var x=Array(); var k,AA,BB,CC,DD,a,b,c,d; var S11=7, S12=12, S13=17, S14=22; var S21=5, S22=9 , S23=14, S24=20; var S31=4, S32=11, S33=16, S34=23; var S41=6, S42=10, S43=15, S44=21; - + string = Utf8Encode(string); - + x = ConvertToWordArray(string); - + a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; - + for (k=0;k>>(32-s)); return t4; } - + function lsb_hex(val) { var str=""; var i; var vh; var vl; - + for( i=0; i<=6; i+=2 ) { vh = (val>>>(i*4+4))&0x0f; vl = (val>>>(i*4))&0x0f; @@ -5551,28 +5554,28 @@ sc.helpers.SHA1 = function (msg) { } return str; } - + function cvt_hex(val) { var str=""; var i; var v; - + for( i=7; i>=0; i-- ) { v = (val>>>(i*4))&0x0f; str += v.toString(16); } return str; } - - + + function Utf8Encode(string) { string = string.replace(/\r\n/g,"\n"); var utftext = ""; - + for (var n = 0; n < string.length; n++) { - + var c = string.charCodeAt(n); - + if (c < 128) { utftext += String.fromCharCode(c); } @@ -5585,12 +5588,12 @@ sc.helpers.SHA1 = function (msg) { utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } - + } - + return utftext; } - + var blockstart; var i, j; var W = new Array(80); @@ -5601,18 +5604,18 @@ sc.helpers.SHA1 = function (msg) { var H4 = 0xC3D2E1F0; var A, B, C, D, E; var temp; - + msg = Utf8Encode(msg); - + var msg_len = msg.length; - + var word_array = []; for( i=0; i>>29 ); word_array.push( (msg_len<<3)&0x0ffffffff ); - - + + for ( blockstart=0; blockstart> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } - + function S (X, n) { return ( X >>> n ) | (X << (32 - n)); } function R (X, n) { return ( X >>> n ); } function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); } @@ -5728,17 +5731,17 @@ sc.helpers.SHA256 = function (s){ function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); } function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); } function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); } - + function core_sha256 (m, l) { var K = [0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2]; var HASH = [0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19]; var W = [64]; var a, b, c, d, e, f, g, h, i, j; var T1, T2; - + m[l >> 5] |= 0x80 << (24 - l % 32); m[((l + 64 >> 9) << 4) + 15] = l; - + for ( i = 0; i> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } - + } - + return utftext; } - + function binb2hex (binarray) { var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var str = ""; @@ -5825,7 +5828,7 @@ sc.helpers.SHA256 = function (s){ s = Utf8Encode(s); return binb2hex(core_sha256(str2binb(s), s.length * chrsz)); - + }; @@ -5867,7 +5870,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * // No arguments - returns RFC4122, version 4 ID * >>> Math.uuid() * "92329D39-6F5C-4520-ABFC-AAB64544E172" - * + * * // One argument - returns ID of the specified length * >>> Math.uuid(15) // 15 character ID (default base=62) * "VcydxgltxrVZSTV" @@ -5884,7 +5887,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
*/ sc.helpers.UUID = (function() { // Private array of chars to use - var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); + var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); return function (len, radix) { var chars = CHARS, uuid = [], rnd = Math.random; @@ -5916,23 +5919,23 @@ sc.helpers.UUID = (function() { })(); /** - * Checks if the given value is an RFC 4122 UUID + * Checks if the given value is an RFC 4122 UUID * @member sc.helpers 
*/ sc.helpers.isUUID = function(val) { return val.match(/^[0-9A-Z]{8}-[0-9A-Z]{4}-[0-9A-Z]{4}-[0-9A-Z]{4}-[0-9A-Z]{12}$/); }; -/*jslint +/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc, jQuery; - + /* Helpers for fundamental javascript stuff */ @@ -5952,7 +5955,7 @@ sc.helpers.isString = function(thing) { }; /** - * @member sc.helpers + * @member sc.helpers */ sc.helpers.isNumber = function(chk) { return typeof chk === 'number'; @@ -5968,7 +5971,7 @@ sc.helpers.isArray = function(obj) { if (!obj || !obj.constructor) { // short-circuit this if it's falsey return false; } - + if (obj.constructor.toString().indexOf("Array") === -1) { return false; } else { @@ -5985,21 +5988,21 @@ sc.helpers.clone = function(oldObj) { }; /** - * @todo + * @todo * @member sc.helpers */ sc.helpers.each = function(arr, f) { - + }; /** * We use this to do a form of inheritance, where the child inherits * the methods and properties of the supertype - * + * * @link https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Inheritance - * + * * @param {object} child the child type - * @param {object} supertype the parent we inherit from + * @param {object} supertype the parent we inherit from * @member sc.helpers */ sc.helpers.extend = function(child, supertype) @@ -6010,40 +6013,40 @@ sc.helpers.extend = function(child, supertype) /** * Designed to fill in default values for an options argument passed to a * function. Merges the provided defaults with the passed object, using items - * from defaults if they don't exist in passed - * + * from defaults if they don't exist in passed + * * @param {object} defaults the default key/val pairs * @param {object} passed the values provided to the calling method * @returns {object} a set of key/vals that have defaults filled-in * @member sc.helpers */ sc.helpers.defaults = function(defaults, passed) { - + var args = defaults; - + /* override the defaults if necessary */ for (var key in passed) { args[key] = passed[key]; } - + return args; }; -/*jslint +/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc; - + /* A wrapper for JSON.parse() that correct Twitter issues and perform logging if JSON data could not be parsed * which will help to find out what is wrong - * @param {String} text + * @param {String} text * @member sc.helpers */ sc.helpers.deJSON = function(json) { @@ -6053,7 +6056,7 @@ sc.helpers.deJSON = function(json) { // json = json.replace(re, ""); var obj; var done = false; - + try { obj = JSON.parse(json); done = true; @@ -6069,16 +6072,16 @@ sc.helpers.deJSON = function(json) { }; /** - * really just a simple wrapper for JSON.stringify + * really just a simple wrapper for JSON.stringify * @param any js construct * @member sc.helpers 
*/ sc.helpers.enJSON = function(jsobj) { // return JSON.stringify(jsobj); - + var json; var done = false; - + try { json = JSON.stringify(jsobj); done = true; @@ -6096,7 +6099,7 @@ sc.helpers.enJSON = function(jsobj) { /* * Based on jQuery XML to JSON Plugin - * + * * ### jQuery XML to JSON Plugin v1.0 - 2008-07-01 ### * http://www.fyneworks.com/ - diego@fyneworks.com * Dual licensed under the MIT and GPL licenses: @@ -6274,26 +6277,26 @@ sc.helpers.xml2json = function(xml, extended) { }; -/*jslint +/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc; - + /** - * Stub + * Stub * @platformstub * @member sc.helpers 
*/ sc.helpers.getCurrentLocation = function() { - -};/*jslint + +};/*jslint bitwise: false, browser: true, newcap: false, @@ -6303,36 +6306,36 @@ forin: true, plusplus: false, undef: true, white: false, -onevar: false +onevar: false */ var sc; - + /** * determines if a string contains the given screen name prefixed with a @ * this is mainly used for determining if a message should be considered a 'mention' * @param {string} str the string to check * @param {string} sn the screen name to look for - * @return {boolean} + * @return {boolean} * @member sc.helpers 
*/ sc.helpers.containsScreenName = function(str, sn) { - + var re = new RegExp('(?:\\s|\\b|^[[:alnum:]]|^)@('+sn+')(?:\\s|\\b|$)', 'gi'); if ( re.test(str) ) { return true; } return false; - + }; /** * @param {string} str string to search for usernames - * @@param {array} without array of usernames to skip + * @@param {array} without array of usernames to skip */ sc.helpers.extractScreenNames = function(str, without) { str = str.toLowerCase(); // normalize to lowercase - + // var re_uname = /(^|\s|\(\[|,|\.|\()@([a-zA-Z0-9_]+)([^a-zA-Z0-9_]|$)/gi; var re_uname = /(?:^|\s|\(\[|,|\.|\()@([a-zA-Z0-9_]+)/gi; var usernames = []; @@ -6349,12 +6352,12 @@ sc.helpers.extractScreenNames = function(str, without) { ms[x] = ''; } } - + if(ms[1] != ''){ usernames.push(ms[1]); } } - + if (usernames.length > 0) { usernames = _.uniq(usernames); // make unique if (sch.isString(usernames)) { // at least in webOS 1.4.5, if you only had one item it qould return as a string, not an array @@ -6369,18 +6372,18 @@ sc.helpers.extractScreenNames = function(str, without) { usernames = _.without.apply(this, wo_args); } } - + return usernames||[]; }; /** - * find URLs within the given string + * find URLs within the given string * @member sc.helpers 
*/ sc.helpers.extractURLs = function(str) { // var wwwlinks = /(^|\s)((https?|ftp)\:\/\/)?([a-z0-9+!*(),;?&=\$_.-]+(\:[a-z0-9+!*(),;?&=\$_.-]+)?@)?([✪a-z0-9-.]*)\.([a-z]{2,3})(\:[0-9]{2,5})?(\/([a-z0-9+\$_-]\.?)+)*\/?(\?[a-z+&\$_.-][a-z0-9;:@&%=+\/\$_.-]*)?(#[a-z_.-][a-z0-9+\$_.-]*)?(\s|$)/gi; var wwwlinks = /(^|\s|\(|:)(((http(s?):\/\/)|(www\.))([\w✪]+[^\s\)<]+))/gi; - + var ms = []; var URLs = []; while ( (ms = wwwlinks.exec(str)) !== null ) { @@ -6423,7 +6426,7 @@ sc.helpers.replaceMultiple = function(str, map) { * This is a port of the CodeIgniter helper "autolink" to javascript. * It finds and links both web addresses and email addresses. It will ignore * links within HTML (as attributes or between tag pairs) - * + * * @param {string} str * @param {string} type 'email', 'url', or 'both' (default is 'both') * @param {boolean} extra_code a string that will be inserted verbatim into tag @@ -6440,11 +6443,11 @@ sc.helpers.autolink = function(str, type, extra_code, maxlen) { var re_noemail = /(^|[\s\(:。])((http(s?):\/\/)|(www\.))([\w✪]+[^\s\)<]+)/gi; var re_nourl = /(^|\s|\()([a-zA-Z0-9_\.\-\+]+)@([a-zA-Z0-9\-]+)\.([a-zA-Z0-9\-\.]*)([^\s\)<]+)/gi; - + var x, ms, period = ''; if (type !== 'email') - { + { while ((ms = re_nohttpurl.exec(str))) { // look for URLs without a preceding "http://" /* sometimes we can end up with a null instead of a blank string, @@ -6461,7 +6464,7 @@ sc.helpers.autolink = function(str, type, extra_code, maxlen) { } else { extra_code = ''; } - + var desc = ms[3]+ms[4]+ms[5]; if (maxlen && maxlen > 0 && desc.length > maxlen) { @@ -6472,10 +6475,10 @@ sc.helpers.autolink = function(str, type, extra_code, maxlen) { sch.error(newstr); str = str.replace(ms[0], newstr); } - - + + while ((ms = re_noemail.exec(str))) { - + /* sometimes we can end up with a null instead of a blank string, so we need to force the issue in javascript. @@ -6491,7 +6494,7 @@ sc.helpers.autolink = function(str, type, extra_code, maxlen) { } else { extra_code = ''; } - + /* if the last character is one of . , ; ?, we strip it off and stick it on the end of newstr below as "period" @@ -6508,8 +6511,8 @@ sc.helpers.autolink = function(str, type, extra_code, maxlen) { if (maxlen && maxlen > 0 && desc.length > maxlen) { desc = desc.substr(0, maxlen)+'...'; } - - + + var newstr = ms[1]+''+desc+''+period; str = str.replace(ms[0], newstr); } @@ -6524,7 +6527,7 @@ sc.helpers.autolink = function(str, type, extra_code, maxlen) { period = '.'; ms[5] = ms[5].slice(0, -1); } - + /* sometimes we can end up with a null instead of a blank string, so we need to force the issue in javascript. @@ -6547,7 +6550,7 @@ sc.helpers.autolink = function(str, type, extra_code, maxlen) { * turns twitter style username refs ('@username') into links * by default, the template used is @#username# * pass the second param to give it a custom template - * + * * @param {string} str * @param {string} tpl default is '@#username#' * @return {string} @@ -6557,13 +6560,13 @@ sc.helpers.autolinkTwitterScreenname = function(str, tpl) { if (!tpl) { tpl = '@#username#'; } - + var re_uname = /(^|\s|\(\[|,|\.|\()@([a-zA-Z0-9_]+)([^a-zA-Z0-9_]|$)/gi; - + var ms = []; while (ms = re_uname.exec(str)) { - + /* sometimes we can end up with a null instead of a blank string, so we need to force the issue in javascript. @@ -6573,7 +6576,7 @@ sc.helpers.autolinkTwitterScreenname = function(str, tpl) { ms[x] = ''; } } - + var repl_tpl = tpl.replace(/#username#/gi, ms[2]); str = str.replace(ms[0], ms[1]+repl_tpl+ms[3]); @@ -6587,7 +6590,7 @@ sc.helpers.autolinkTwitterScreenname = function(str, tpl) { * turns twitter style hashtags ('#hashtag') into links * by default, the template used is ##hashtag# * pass the second param to give it a custom template - * + * * @param {string} str * @param {string} tpl default is '##hashtag#' * @return {string} @@ -6597,13 +6600,13 @@ sc.helpers.autolinkTwitterHashtag = function(str, tpl) { if (!tpl) { tpl = '##hashtag#'; } - + var re_hashtag = /(^|\s|\()#([a-zA-Z0-9\-_\.+:=]{1,}\w)([^a-zA-Z0-9\-_+]|$)/gi; - + var ms = []; while (ms = re_hashtag.exec(str)) { - + /* sometimes we can end up with a null instead of a blank string, so we need to force the issue in javascript. @@ -6613,7 +6616,7 @@ sc.helpers.autolinkTwitterHashtag = function(str, tpl) { ms[x] = ''; } } - + var repl_tpl = tpl.replace(/#hashtag#/gi, ms[2]); repl_tpl = repl_tpl.replace(/#hashtag_enc#/gi, encodeURIComponent(ms[2])); str = str.replace(ms[0], ms[1]+repl_tpl+ms[3]); @@ -6626,10 +6629,10 @@ sc.helpers.autolinkTwitterHashtag = function(str, tpl) { /** * Applies autolink, autolinkTwitterScreenname, autolinkTwitterHashtag - * + * * @param {string} str * @param {oobject} opts - * + * * Opts structure: * { * 'autolink': { @@ -6648,25 +6651,25 @@ sc.helpers.autolinkTwitterHashtag = function(str, tpl) { 
*/ sc.helpers.makeClickable = function(str, opts) { var autolink_type, autolink_extra_code, autolink_maxlen, screenname_tpl, hashtag_tpl; - + if (!opts) { opts = {}; } - + if (opts.autolink) { var autolink_type = opts.autolink.type || null; var autolink_extra_code = opts.autolink.extra_code || null; var autolink_maxlen = opts.autolink.maxlen || null; } - + if (opts.screenname) { var screenname_tpl = opts.screenname.tpl || null; } - + if (opts.hashtag) { var hashtag_tpl = opts.hashtag.tpl || null; } - + str = sc.helpers.autolink(str, autolink_type, autolink_extra_code, autolink_maxlen); str = sc.helpers.autolinkTwitterScreenname(str, screenname_tpl); str = sc.helpers.autolinkTwitterHashtag(str, hashtag_tpl); @@ -6727,7 +6730,7 @@ sc.helpers.htmlspecialchars = function(string, quote_style) { // first, do & tmp_str = tmp_str.split('&').join(histogram['&']); - + // then do the rest for (symbol in histogram) { if (symbol != '&') { @@ -6754,19 +6757,19 @@ sc.helpers.htmlentities = function(string, quote_style) { // * returns 1: 'Kevin & van Zonneveld' // * example 2: htmlentities("foo'bar","ENT_QUOTES"); // * returns 2: 'foo'bar' - + var histogram = {}, symbol = '', tmp_str = '', entity = ''; tmp_str = string.toString(); - + if (false === (histogram = sc.helpers._get_html_translation_table('HTML_ENTITIES', quote_style))) { return false; } - + for (symbol in histogram) { entity = histogram[symbol]; tmp_str = tmp_str.split(symbol).join(entity); } - + return tmp_str; }; @@ -6785,21 +6788,21 @@ sc.helpers._get_html_translation_table = function(table, quote_style) { // % note: Table from http://www.the-art-of-web.com/html/character-codes/ // * example 1: get_html_translation_table('HTML_SPECIALCHARS'); // * returns 1: {'"': '"', '&': '&', '<': '<', '>': '>'} - + var entities = [], histogram = {}, decimal = 0, symbol = ''; var constMappingTable = {}, constMappingQuoteStyle = {}; var useTable = {}, useQuoteStyle = {}; - + useTable = (table ? table.toUpperCase() : 'HTML_SPECIALCHARS'); useQuoteStyle = (quote_style ? quote_style.toUpperCase() : 'ENT_COMPAT'); - + // Translate arguments constMappingTable[0] = 'HTML_SPECIALCHARS'; constMappingTable[1] = 'HTML_ENTITIES'; constMappingQuoteStyle[0] = 'ENT_NOQUOTES'; constMappingQuoteStyle[2] = 'ENT_COMPAT'; constMappingQuoteStyle[3] = 'ENT_QUOTES'; - + // Map numbers to strings for compatibilty with PHP constants if (!isNaN(useTable)) { useTable = constMappingTable[useTable]; @@ -6807,7 +6810,7 @@ sc.helpers._get_html_translation_table = function(table, quote_style) { if (!isNaN(useQuoteStyle)) { useQuoteStyle = constMappingQuoteStyle[useQuoteStyle]; } - + if (useTable === 'HTML_SPECIALCHARS') { // ascii decimals for better compatibility entities.push({'code':38, 'entity':'&'}); @@ -6929,13 +6932,13 @@ sc.helpers._get_html_translation_table = function(table, quote_style) { } else { throw Error("Table: "+useTable+' not supported'); } - + // ascii decimals to real symbols for (var i=0; i < entities.length; i++) { symbol = String.fromCharCode(entities[i].code); histogram[symbol] = entities[i].entity; } - + return histogram; }; @@ -6949,16 +6952,16 @@ sc.helpers._get_html_translation_table = function(table, quote_style) { * @namespace **/ sc.helpers.Utf8 = { - + /** @function public method for url encoding */ encode : function (string) { string = string.replace(/\r\n/g,"\n"); var utftext = ""; - + for (var n = 0; n < string.length; n++) { - + var c = string.charCodeAt(n); - + if (c < 128) { utftext += String.fromCharCode(c); } @@ -6971,22 +6974,22 @@ sc.helpers.Utf8 = { utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } - + } - + return utftext; }, - + /** @function public method for url decoding */ decode : function (utftext) { var string = ""; var i = 0; var c = 0, c1 = 0, c2 = 0, c3 = 0; - + while ( i < utftext.length ) { - + c = utftext.charCodeAt(i); - + if (c < 128) { string += String.fromCharCode(c); i++; @@ -7002,12 +7005,12 @@ sc.helpers.Utf8 = { string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); i += 3; } - + } - + return string; } - + }; @@ -7020,16 +7023,16 @@ sc.helpers.Utf8 = { * http://www.webtoolkit.info/ * **/ - + sc.helpers.trim = function (str, chars) { return sc.helpers.ltrim(sc.helpers.rtrim(str, chars), chars); }; - + sc.helpers.ltrim = function (str, chars) { chars = chars || "\\s"; return str.replace(new RegExp("^[" + chars + "]+", "g"), ""); }; - + sc.helpers.rtrim = function (str, chars) { chars = chars || "\\s"; return str.replace(new RegExp("[" + chars + "]+$", "g"), ""); @@ -7040,7 +7043,7 @@ sc.helpers.rtrim = function (str, chars) { * @param {string} input the input string * @param {number} pad_length the length to pad the string * @param {string} pad_string the string to pad with - * @param {string} pad_type STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH. Default is STR_PAD_RIGHT + * @param {string} pad_type STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH. Default is STR_PAD_RIGHT * @member sc.helpers 
*/ sc.helpers.pad = function (input, pad_length, pad_string, pad_type) { @@ -7067,7 +7070,7 @@ sc.helpers.pad = function (input, pad_length, pad_string, pad_type) { input += ''; pad_string = pad_string !== undefined ? pad_string : ' '; - + if (pad_type != 'STR_PAD_LEFT' && pad_type != 'STR_PAD_RIGHT' && pad_type != 'STR_PAD_BOTH') { pad_type = 'STR_PAD_RIGHT'; } if ((pad_to_go = pad_length - input.length) > 0) { if (pad_type == 'STR_PAD_LEFT') { input = str_pad_repeater(pad_string, pad_to_go) + input; } @@ -7083,8 +7086,8 @@ sc.helpers.pad = function (input, pad_length, pad_string, pad_type) { }; /** - * truncate a string to a certain length, if it exceeds that length - * + * truncate a string to a certain length, if it exceeds that length + * * @param {string} str * @param {Number} limit the max length of the string * @param {string} [suffix] a suffix to append to the string if it is over limit. Does not count against the limit @@ -7099,7 +7102,7 @@ sc.helpers.truncate = function(str, limit, suffix) { } } - return str; + return str; }; @@ -7111,91 +7114,91 @@ sc.helpers.truncate = function(str, limit, suffix) { * @member sc.helpers 
*/ sc.helpers.nl2br = function(str, breaktag) { - + breaktag = breaktag || '
'; - + str = str.replace(/(\r\n|\n\r|\r|\n)/g, breaktag+'$1'); return str; -};/*jslint +};/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc; - + /** * These are system-oriented functions, mostly utilizing AIR apis * to interact with the OS - * + * * NOTE: to use all these helpers, you must additionally load a platform-specific definition file! */ /** - * @constant + * @constant */ var SPAZCORE_PLATFORM_AIR = 'AIR'; /** - * @constant + * @constant */ var SPAZCORE_PLATFORM_WEBOS = 'webOS'; /** - * @constant + * @constant */ var SPAZCORE_PLATFORM_TITANIUM = 'Titanium'; /** - * @constant + * @constant */ var SPAZCORE_PLATFORM_UNKNOWN = '__UNKNOWN'; /** - * @constant + * @constant */ var SPAZCORE_OS_WINDOWS = 'Windows'; /** - * @constant + * @constant */ var SPAZCORE_OS_LINUX = 'Linux'; /** - * @constant + * @constant */ var SPAZCORE_OS_MACOS = 'MacOS'; /** - * @constant + * @constant */ var SPAZCORE_OS_UNKNOWN = '__OS_UNKNOWN'; /** - * error reporting levels + * error reporting levels */ /** - * @constant + * @constant */ var SPAZCORE_DUMPLEVEL_DEBUG = 4; /** - * @constant + * @constant */ var SPAZCORE_DUMPLEVEL_NOTICE = 3; /** - * @constant + * @constant */ var SPAZCORE_DUMPLEVEL_WARNING = 2; /** - * @constant + * @constant */ var SPAZCORE_DUMPLEVEL_ERROR = 1; /** - * @constant + * @constant */ var SPAZCORE_DUMPLEVEL_NONE = 0; // this means "never ever dump anything!" /** - * @constant + * @constant */ var SPAZCORE_DUMP_MAXLEN = 512; @@ -7203,9 +7206,9 @@ var SPAZCORE_DUMP_MAXLEN = 512; /** * Returns a string identifier for the platform. -* +* * Right now these checks are really, really basic -* +* * @return {String} an identifier for the platform * @member sc.helpers */ @@ -7224,11 +7227,11 @@ sc.helpers.getPlatform = function() { /** * checks to see if current platform is the one passed in -* +* * use one of the defined constants, like SPAZCORE_PLATFORM_AIR -* +* * @param {String} str the platform you're checking for -* +* * @member sc.helpers */ sc.helpers.isPlatform = function(str) { @@ -7241,21 +7244,21 @@ sc.helpers.isPlatform = function(str) { }; /** - * @member sc.helpers + * @member sc.helpers */ sc.helpers.isAIR = function() { return sc.helpers.isPlatform(SPAZCORE_PLATFORM_AIR); }; /** - * @member sc.helpers + * @member sc.helpers */ sc.helpers.iswebOS = function() { return sc.helpers.isPlatform(SPAZCORE_PLATFORM_WEBOS); }; /** - * @member sc.helpers + * @member sc.helpers */ sc.helpers.isTitanium = function() { return sc.helpers.isPlatform(SPAZCORE_PLATFORM_TITANIUM); @@ -7264,7 +7267,7 @@ sc.helpers.isTitanium = function() { /** - * Helper to send a debug dump + * Helper to send a debug dump * @member sc.helpers 
*/ sc.helpers.debug = function(obj) { @@ -7272,7 +7275,7 @@ sc.helpers.debug = function(obj) { }; /** - * helper to send a notice dump + * helper to send a notice dump * @member sc.helpers 
*/ sc.helpers.note = function(obj) { @@ -7280,7 +7283,7 @@ sc.helpers.note = function(obj) { }; /** - * helper to send a warn dump + * helper to send a warn dump * @member sc.helpers 
*/ sc.helpers.warn = function(obj) { @@ -7288,7 +7291,7 @@ sc.helpers.warn = function(obj) { }; /** - * helper to send an error dump + * helper to send an error dump * @member sc.helpers 
*/ sc.helpers.error = function(obj) { @@ -7304,17 +7307,17 @@ sc.helpers.error = function(obj) { sc.helpers.dump = function(obj, level, cb) { if (!level) { level = SPAZCORE_DUMPLEVEL_DEBUG; } - + if (sc.dumplevel < level ) { return; } - + if (sc.helpers.isString(obj)) { obj = sch.truncate(obj, SPAZCORE_DUMP_MAXLEN, '…[TRUNC]'); } - + console.log(obj); - + if (cb) { cb(obj, level); } @@ -7408,7 +7411,7 @@ sc.helpers.getAppStoreDir = function() { /** * Get the preferences file - * @TODO this should be removed and we rely on the preferences lib + * @TODO this should be removed and we rely on the preferences lib * @member sc.helpers 
*/ sc.helpers.getPreferencesFile = function(name, create) { @@ -7428,7 +7431,7 @@ sc.helpers.init_file = function(path, overwrite) { /** * Returns a string identifier for the OS. -* +* * @return {String} an identifier for the OS. See the SPAZCORE_OS_* variables */ sc.helpers.getOS = function() { @@ -7438,7 +7441,7 @@ sc.helpers.getOS = function() { /** * checks to see if current platform is the one passed in. Use one of the defined constants, like SPAZCORE_OS_WINDOWS -* +* * @param {String} str the platform you're checking for * @member sc.helpers */ @@ -7451,32 +7454,32 @@ sc.helpers.isOS = function(str) { }; /** - * @member sc.helpers + * @member sc.helpers */ sc.helpers.isWindows = function() { return sc.helpers.isOS(SPAZCORE_OS_WINDOWS); }; /** - * @member sc.helpers + * @member sc.helpers */ sc.helpers.isLinux = function() { return sc.helpers.isOS(SPAZCORE_OS_LINUX); }; /** - * @member sc.helpers + * @member sc.helpers */ sc.helpers.isMacOS = function() { return sc.helpers.isOS(SPAZCORE_OS_MACOS); }; /** - * Takes a key/val pair object and returns a query string - * @member sc.helpers + * Takes a key/val pair object and returns a query string + * @member sc.helpers */ sc.helpers.objectToQueryString = function(object) { var query_string, key, val, pieces = []; - + for(key in object) { val = object[key]; pieces.push(encodeURIComponent(key)+'='+encodeURIComponent(val)); @@ -7488,12 +7491,12 @@ sc.helpers.objectToQueryString = function(object) { /** - * takes a username and service, and returns the profile URL on that service + * takes a username and service, and returns the profile URL on that service */ sc.helpers.getServiceBaseUrl = function(service) { - + var url = null; - + switch(service) { case SPAZCORE_SERVICE_TWITTER: url = SPAZCORE_BASEURL_TWITTER; @@ -7505,19 +7508,19 @@ sc.helpers.getServiceBaseUrl = function(service) { url = SPAZCORE_BASEURL_FREELISHUS; break; } - + return url; - + }; /** - * takes a username and service, and returns the profile URL on that service + * takes a username and service, and returns the profile URL on that service */ sc.helpers.getServiceProfileUrl = function(username, service) { - + var url = null; - + switch(service) { case SPAZCORE_SERVICE_TWITTER: url = SPAZCORE_BASEURL_TWITTER+"/"+username; @@ -7529,17 +7532,17 @@ sc.helpers.getServiceProfileUrl = function(username, service) { url = SPAZCORE_BASEURL_FREELISHUS+"/"+username; break; } - + return url; - + }; /** - * takes a status id, username and service, and returns the status URL on that service + * takes a status id, username and service, and returns the status URL on that service */ sc.helpers.getStatusUrl = function(id, username, service) { - + var url = null; switch(service) { @@ -7553,37 +7556,37 @@ sc.helpers.getStatusUrl = function(id, username, service) { url = SPAZCORE_BASEURL_FREELISHUS+'notice/'+id; break; } - + return url; - + }; -/*jslint +/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc, jQuery; - + /** * View helper methods for Twitter apps - * + * */ /** * This removes any extra items from a set of elements. Intended to be used for * limiting the size of timelines - * + * * This does NOT remove bound event listeners in order to increase speed. Be careful! - * + * * @param {string} item_selector a jquery-compatible selector to get items * @param {integer} max_items the max # of item we should have * @param {boolean} remove_from_top whether or not to remove extra items from the top. default is FALSE * @requires jQuery - * @member sc.helpers + * @member sc.helpers */ sc.helpers.removeExtraElements = function(item_selector, max_items, remove_from_top) { @@ -7596,7 +7599,7 @@ sc.helpers.removeExtraElements = function(item_selector, max_items, remove_from_ var parent = jqitems.parent().get(0); var diff = jqitems.length - max_items; - + sch.debug('removing extra elements from '+item_selector); sch.debug('matching item count '+jqitems.length); sch.debug('max_items: '+max_items); @@ -7622,11 +7625,11 @@ sc.helpers.removeExtraElements = function(item_selector, max_items, remove_from_ /** * This removes any duplicate items from a series of elements. Intended to be used for * limiting the sice of timelines - * + * * @param {string} item_selector a jquery-compatible selector to get items * @param {boolean} remove_from_top whether or not to remove extra items from the top. default is FALSE * @TODO - * @member sc.helpers + * @member sc.helpers */ sc.helpers.removeDuplicateElements = function(item_selector, remove_from_top) { sc.helpers.dump('removeDuplicateElements TODO'); @@ -7638,11 +7641,11 @@ sc.helpers.removeDuplicateElements = function(item_selector, remove_from_top) { /** * This updates relative times in elements. Each element has to have an attribute * that contains the created_at value provided by Twitter - * + * * @param {string} item_selector the jQuery selector for the elements which will contain the relative times * @param {string} time_attribute the attribute of the element that contains the created_at value * @requires jQuery - * @member sc.helpers + * @member sc.helpers */ sc.helpers.updateRelativeTimes = function(item_selector, time_attribute) { jQuery(item_selector).each(function(i) { @@ -7656,22 +7659,22 @@ sc.helpers.updateRelativeTimes = function(item_selector, time_attribute) { /** * this marks all items in the selected set of elements as read. It does this by removing * the 'new' class - * + * * @param {string} item_selector * @requires jQuery - * @member sc.helpers + * @member sc.helpers */ sc.helpers.markAllAsRead = function(item_selector) { jQuery(item_selector).removeClass('new'); }; -/*jslint +/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc, DOMParser; @@ -7695,54 +7698,54 @@ sc.helpers.createXMLFromString = function (string) { /** - * "constants" for account types + * "constants" for account types */ /** - * @constant + * @constant */ var SPAZCORE_ACCOUNT_TWITTER = 'twitter'; /** - * @constant + * @constant */ var SPAZCORE_ACCOUNT_IDENTICA = 'identi.ca'; /** - * @constant + * @constant */ var SPAZCORE_ACCOUNT_FREELISHUS = 'freelish.us'; /** - * @constant + * @constant */ var SPAZCORE_ACCOUNT_STATUSNET = 'StatusNet'; /** - * @constant + * @constant */ var SPAZCORE_ACCOUNT_FLICKR = 'flickr'; /** - * @constant + * @constant */ var SPAZCORE_ACCOUNT_WORDPRESS = 'wordpress.com'; /** - * @constant + * @constant */ var SPAZCORE_ACCOUNT_WORDPRESS_TWITTER = 'wordpress-twitter'; /** - * @constant + * @constant */ var SPAZCORE_ACCOUNT_TUMBLR = 'tumblr'; /** - * @constant + * @constant */ var SPAZCORE_ACCOUNT_TUMBLR_TWITTER = 'tumblr-twitter'; /** - * @constant + * @constant */ var SPAZCORE_ACCOUNT_FACEBOOK = 'facebook'; /** - * @constant + * @constant */ var SPAZCORE_ACCOUNT_FRIENDFEED = 'friendfeed'; /** - * @constant + * @constant */ var SPAZCORE_ACCOUNT_CUSTOM = 'custom'; @@ -7758,7 +7761,7 @@ var SpazAccounts = function(prefsObj) { this.prefs = new SpazPrefs(); this.prefs.load(); } - + /* load existing accounts */ @@ -7767,24 +7770,24 @@ var SpazAccounts = function(prefsObj) { }; /** - * the key used inside the prefs object + * the key used inside the prefs object */ SpazAccounts.prototype.prefskey = 'users'; /** - * loads the accounts array from the prefs object + * loads the accounts array from the prefs object */ -SpazAccounts.prototype.load = function() { +SpazAccounts.prototype.load = function() { var accjson = this.prefs.get(this.prefskey); - + sch.debug("accjson:'"+accjson+"'"); - + try { this._accounts = sch.deJSON(this.prefs.get(this.prefskey)); } catch(e) { sch.error(e.message); this._accounts = []; - } + } /* sanity check @@ -7792,13 +7795,13 @@ SpazAccounts.prototype.load = function() { if (!sch.isArray(this._accounts)) { this._accounts = []; } - + sch.debug("this._accounts:'"+this._accounts+"'"); - + }; /** - * saves the accounts array to the prefs obj + * saves the accounts array to the prefs obj */ SpazAccounts.prototype.save = function() { this.prefs.set(this.prefskey, sch.enJSON(this._accounts)); @@ -7806,7 +7809,7 @@ SpazAccounts.prototype.save = function() { for (var x in this._accounts) { sch.debug(this._accounts[x].id); }; - + sch.debug('THE ACCOUNTS:'); sch.debug(sch.enJSON(this._accounts)); @@ -7817,7 +7820,7 @@ SpazAccounts.prototype.save = function() { /** * returns the array of accounts - * @returns {array} the accounts + * @returns {array} the accounts */ SpazAccounts.prototype.getAll = function() { return this._accounts; @@ -7873,7 +7876,7 @@ SpazAccounts.prototype.initAccounts = function() { * @returns {object} the account object just added */ SpazAccounts.prototype.add = function(username, auth, type) { - + if (!type) { sch.error("Type must be set"); return false; @@ -7895,11 +7898,11 @@ SpazAccounts.prototype.add = function(username, auth, type) { /** - * @param {string} id the UUID of the account to delete + * @param {string} id the UUID of the account to delete */ SpazAccounts.prototype.remove = function(id) { sch.error("Deleting '"+id+"'…"); - + var index = this._findUserIndex(id); if (index !== false) { var deleted = this._accounts.splice(index, 1); @@ -7919,13 +7922,13 @@ SpazAccounts.prototype.remove = function(id) { */ SpazAccounts.prototype.getByType = function(type) { var matches = []; - + for (var i=0; i < this._accounts.length; i++) { if (this._accounts[i].type === type) { matches.push(this._accounts[i]); } }; - + return matches; }; @@ -7941,7 +7944,7 @@ SpazAccounts.prototype.getByUsername = function(username) { matches.push(this._accounts[i]); } }; - + return matches; }; @@ -7958,27 +7961,27 @@ SpazAccounts.prototype.getByUsernameAndType = function(username, type) { matches.push(this._accounts[i]); } }; - + return matches; - + }; /** * retrives the user object by user and type * @param {string} id the user id UUID - * @param {string} type + * @param {string} type */ SpazAccounts.prototype.get = function(id) { var index = this._findUserIndex(id); if (index !== false) { - return this._accounts[i]; + return this._accounts[i]; } - + return false; - + }; @@ -7990,47 +7993,47 @@ SpazAccounts.prototype.set = SpazAccounts.prototype.update; SpazAccounts.prototype.getLabel = function(id) { - + var index = this._findUserIndex(id); var label = ''; - + if (index !== false) { label = this._accounts[i].username+'@'+this._accounts[i].type; if (this._accounts[i].type === SPAZCORE_ACCOUNT_STATUSNET || this._accounts[i].type === SPAZCORE_ACCOUNT_CUSTOM) { - + } return label; } return false; - + }; /** * a private function to find the user's array index by their UUID * @param {string} id the user's UUID - * @returns {number|boolen} returns the array index or false if DNE + * @returns {number|boolen} returns the array index or false if DNE */ SpazAccounts.prototype._findUserIndex = function(id) { - + for (i=0; i 0) { return matches; } else { return null; } - + }; /** * find the image service URLs that work with our defined APIs in a given string * @param {object} matches * @return {object|null} fullurl:thumburl key:val pairs - * + * */ SpazImageURL.prototype.getThumbsForMatches = function(matches) { var x, service, api, thumburl, thumburls = {}, num_urls = 0; - + for (service in matches) { sch.dump('SERVICE:'+service); api = this.getAPI(service); @@ -8693,8 +8696,8 @@ SpazImageURL.prototype.getThumbsForMatches = function(matches) { } sch.dump('num_urls:'+num_urls); - sch.dump(thumburls); - + sch.dump(thumburls); + if (num_urls > 0) { return thumburls; } else { @@ -8716,7 +8719,7 @@ SpazImageURL.prototype.getThumbsForUrls = function(str) { } else { return null; } - + }; /** @@ -8742,7 +8745,7 @@ SpazImageURL.prototype.getThumbForUrl = function(url) { */ SpazImageURL.prototype.getImagesForMatches = function(matches) { var x, service, api, imageurl, imageurls = {}, num_urls = 0; - + for (service in matches) { sch.dump('SERVICE:'+service); api = this.getAPI(service); @@ -8756,8 +8759,8 @@ SpazImageURL.prototype.getImagesForMatches = function(matches) { } sch.dump('num_urls:'+num_urls); - sch.dump(imageurls); - + sch.dump(imageurls); + if (num_urls > 0) { return imageurls; } else { @@ -8795,24 +8798,24 @@ SpazImageURL.prototype.getImageForUrl = function(url) { return null; } }; -/*jslint +/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc, DOMParser, jQuery; /** - * A file uploader class for SpazCore + * A file uploader class for SpazCore */ /** - * Events used by this library + * Events used by this library */ if (!sc.events) { sc.events = {}; } sc.events.fileUploadStart = 'fileUploadStart'; @@ -8823,20 +8826,20 @@ sc.events.fileUploadFailure = 'fileUploadFailure'; /** * A File uploader class - * + * * opts = { * api:'', * startEvent:'', * successEvent:'', * failureEvent:'', * eventTarget:DOMElement - * } + * } * @constructor */ function SpazFileUploader(opts) { if (!opts) { opts = {}; } - + if (opts.api) { this.setAPI(opts.api); } @@ -8845,14 +8848,14 @@ function SpazFileUploader(opts) { this.failureEvent = opts.failureEvent || sc.events.fileUploadFailure; this.eventTarget = opts.eventTarget || document; this.auth = opts.auth || null; - + this.apis = this.getAPIs(); } /** * returns an array of API labels - * @return array + * @return array */ SpazFileUploader.prototype.getAPILabels = function() { var labels = []; @@ -8876,7 +8879,7 @@ SpazFileUploader.prototype.getAPIs = function() { 'post_url' : 'http://drippic.com/drippic/upload/tweet', 'processResult': function(event, apiobj) { var loader = event.target; - + sch.debug('PROCESSING: EVENT'); sch.debug(event); @@ -8887,7 +8890,7 @@ SpazFileUploader.prototype.getAPIs = function() { if (rspAttr.getNamedItem("stat").nodeValue === 'ok') { returnobj['mediaurl'] = jQuery(xmldoc).find('mediaurl').text(); - } + } else { returnobj['errMsg'] = jQuery(xmldoc).find('error').text(); @@ -8902,7 +8905,7 @@ SpazFileUploader.prototype.getAPIs = function() { 'api_key_field': 'api_key', // setting this to non-empty means we MUST set an api key 'processResult': function(event, apiobj) { var loader = event.target; - + var returnobj = {}; var parser=new DOMParser(); @@ -8912,7 +8915,7 @@ SpazFileUploader.prototype.getAPIs = function() { if (rspAttr.getNamedItem("stat").nodeValue === 'ok') { returnobj['mediaurl'] = jQuery(xmldoc).find('mediaurl').text(); - } + } else { returnobj['errAttributes'] = xmldoc.getElementsByTagName("err")[0].attributes; @@ -8935,7 +8938,7 @@ SpazFileUploader.prototype.getAPIs = function() { if (rspAttr.getNamedItem("stat").nodeValue === 'ok') { returnobj['mediaurl'] = jQuery(xmldoc).find('mediaurl').text(); - } + } else { returnobj['errAttributes'] = xmldoc.getElementsByTagName("err")[0].attributes; @@ -8950,7 +8953,7 @@ SpazFileUploader.prototype.getAPIs = function() { 'post_url' : 'http://twitpic.com/api/uploadAndPost', 'processResult': function(event, apiobj) { var loader = event.target; - + sch.debug('PROCESSING: EVENT'); sch.debug(event); @@ -8961,7 +8964,7 @@ SpazFileUploader.prototype.getAPIs = function() { if (rspAttr.getNamedItem("stat").nodeValue === 'ok') { returnobj['mediaurl'] = jQuery(xmldoc).find('mediaurl').text(); - } + } else { returnobj['errAttributes'] = xmldoc.getElementsByTagName("err")[0].attributes; @@ -8976,7 +8979,7 @@ SpazFileUploader.prototype.getAPIs = function() { 'post_url' : 'http://posterous.com/api/uploadAndPost', 'processResult': function(event, apiobj) { var loader = event.target; - + sch.debug('PROCESSING: EVENT'); sch.debug(event); @@ -8987,7 +8990,7 @@ SpazFileUploader.prototype.getAPIs = function() { if (rspAttr.getNamedItem("stat").nodeValue === 'ok') { returnobj['mediaurl'] = jQuery(xmldoc).find('mediaurl').text(); - } + } else { returnobj['errAttributes'] = xmldoc.getElementsByTagName("err")[0].attributes; @@ -9010,7 +9013,7 @@ SpazFileUploader.prototype.getAPIs = function() { if (rspAttr.getNamedItem("stat").nodeValue === 'ok') { returnobj['mediaurl'] = jQuery(xmldoc).find('mediaurl').text(); - } + } else { returnobj['errAttributes'] = xmldoc.getElementsByTagName("err")[0].attributes; @@ -9027,27 +9030,27 @@ SpazFileUploader.prototype.getAPIs = function() { // 'upload_url' : 'http://tweetphotoapi.com/api/tpapi.svc/upload2', // 'api_key_field': 'TPAPIKEY', // this means we need to set the api key // 'onBeforeSend' : function(extraParams, api.upload_url, file_url) { - // + // // }, // 'processResult': function(event, apiobj) { // var loader = event.target; - // + // // var parser=new DOMParser(); // var xmldoc = parser.parseFromString(loader.data,"text/xml"); - // + // // if (jQuery(xmldoc).find('Status').text().toLowerCase() === 'ok') // { // var mediaurl = jQuery(xmldoc).find('MediaUrl').text(); - // } + // } // else // { // sch.error('There was an error uploading to TweetPhoto') // var errAttributes = xmldoc.getElementsByTagName("err")[0].attributes; // var errMsg = errAttributes.getNamedItem("msg").nodeValue; // } - // } + // } // } - + }; return apis; @@ -9056,7 +9059,7 @@ SpazFileUploader.prototype.getAPIs = function() { /** * Pass the api you want to use as a string - * @param {string} apilabel + * @param {string} apilabel */ SpazFileUploader.prototype.setAPI = function(apilabel) { this.api = this.apis[apilabel]; @@ -9094,18 +9097,18 @@ SpazFileUploader.prototype.getAPIKey = function() { * 'password':'xxx', * 'source':'xxx', * 'message':'' - * - * } - * + * + * } + * * This uploads a file located at the given file_url. It uses the * sc.helpers.HTTPUploadFile as defined for your given platform. Events are * raised as set in the constructor on start, success and failure. - * + * * Note that in the webOS implementation, success events are raised every time * progress is reported, NOT just when completion happens. Check for the * "completed" boolean property in the response object. This may change in the * future. - * + * * @param {string} post_url the url we're uploading the file to * @param {string} file_url the local url of the file we're uploading * @param {object} opts a set of key/val pairs @@ -9124,12 +9127,12 @@ SpazFileUploader.prototype.uploadFile = function(post_url, file_url, opts) { sch.error('Must set the API before uploading'); return; } - + var username = opts.username || null; var password = opts.password || null; var source = opts.source || null; var message = opts.message || null; - + /* platform opts are for platform-specific options. For now we're using this because webOS requires the scene controller to call the service @@ -9145,9 +9148,9 @@ SpazFileUploader.prototype.uploadFile = function(post_url, file_url, opts) { "source": source, "message": message }; - + /** - * if we have an API key field, then we need the api key + * if we have an API key field, then we need the api key */ if ( (api.api_key_field) ) { extraParams[api.api_key_field] = this.getAPIKey(); @@ -9159,12 +9162,12 @@ SpazFileUploader.prototype.uploadFile = function(post_url, file_url, opts) { if (api.onBeforeSend) { api.onBeforeSend.call(api, extraParams, api.upload_url, file_url); } - + /* trigger upload start event */ sc.helpers.triggerCustomEvent(thisSFU.startEvent, thisSFU.eventTarget); - + // upload the file sc.helpers.HTTPUploadFile({ 'extra' : extraParams, @@ -9176,7 +9179,7 @@ SpazFileUploader.prototype.uploadFile = function(post_url, file_url, opts) { function(event) { sch.debug('UPLOAD SUCCESS, PROCESSING'); /* - For now we're not using the processResult methods, as the + For now we're not using the processResult methods, as the implementation can vary by platform. For now, process response externally. */ @@ -9187,7 +9190,7 @@ SpazFileUploader.prototype.uploadFile = function(post_url, file_url, opts) { function(event) { sch.debug('UPLOAD FAILURE, PROCESSING'); /* - For now we're not using the processResult methods, as the + For now we're not using the processResult methods, as the implementation can vary by platform. For now, process response externally. */ @@ -9201,11 +9204,11 @@ SpazFileUploader.prototype.uploadFile = function(post_url, file_url, opts) { /** - * a wrapper for uploadFile that uses the post_url from the API definition + * a wrapper for uploadFile that uses the post_url from the API definition */ SpazFileUploader.prototype.uploadAndPost = function(file_url, opts) { var api; - + if (opts.api) { api = this.apis.api; } else if (this.api) { @@ -9214,18 +9217,18 @@ SpazFileUploader.prototype.uploadAndPost = function(file_url, opts) { sch.error('Must set the API before uploading'); return; } - + this.uploadFile(api.post_url, file_url, opts); - + }; /** - * a wrapper for uploadFile that uses the upload_url from the API definition + * a wrapper for uploadFile that uses the upload_url from the API definition */ SpazFileUploader.prototype.upload = function(file_url, opts) { - + var api; - + if (opts.api) { api = this.apis.api; } else if (this.api) { @@ -9234,29 +9237,29 @@ SpazFileUploader.prototype.upload = function(file_url, opts) { sch.error('Must set the API before uploading'); return; } - + this.uploadFile(api.upload_url, file_url, opts); - + }; /** * The SpazFilterChain is intended to create a chain of filters for processing some input. * There are no restrictions on the type of input, but all filter functions must expect * the same type of input, and return the same type of output - * + * * All filter functions must be synchronous -- they need to take input and return the * modified version - * - * @constructor + * + * @constructor */ var SpazFilterChain = function (opts) { - + opts = sch.defaults({ filters:null }, opts); this._filters = []; - + /* if we have filters, process them */ @@ -9277,21 +9280,21 @@ SpazFilterChain.prototype.addFilter = function(label, func, position) { 'label':label, 'func':func }; - + if (position) { this._filters.splice(position, 0, filter_obj); } else { this._filters.push(filter_obj); } - + sch.debug('added filter "'+label+'"'); }; /** - * remove a filter from the chain + * remove a filter from the chain */ SpazFilterChain.prototype.removeFilter = function(label) { - + var i = this.getFilterIndex(label); var removed = this._filters.splice(i,1); sch.debug('removed filter "'+label+'": '+removed); @@ -9299,7 +9302,7 @@ SpazFilterChain.prototype.removeFilter = function(label) { /** - * removes all filters in the chain + * removes all filters in the chain */ SpazFilterChain.prototype.nukeFilters = function() { this._filters = []; @@ -9322,7 +9325,7 @@ SpazFilterChain.prototype.makeFilterFirst = function(label) { /** * takes a filter label and moves that filter to last in the chain - * @param {string} label the label for a filter in the chain + * @param {string} label the label for a filter in the chain */ SpazFilterChain.prototype.makeFilterLast = function(label) { var i = this.getFilterIndex(label); @@ -9335,7 +9338,7 @@ SpazFilterChain.prototype.makeFilterLast = function(label) { /** * Returns an array of all the labels of filters in the chain - * @returns {array} + * @returns {array} */ SpazFilterChain.prototype.getFilterList = function() { var filter_list = []; @@ -9349,7 +9352,7 @@ SpazFilterChain.prototype.getFilterList = function() { /** * takes input and processes it through each filter in the chain, returning the final result * @param {Mixed} input The input - * @returns {Mixed} the output + * @returns {Mixed} the output */ SpazFilterChain.prototype.process = function(input) { var filter_obj; @@ -9368,7 +9371,7 @@ SpazFilterChain.prototype.process = function(input) { */ SpazFilterChain.prototype.processArray = function(input_array) { var filter_obj; - + for (var i=0; i < input_array.length; i++) { for (var k=0; k < this._filters.length; k++) { filter_obj = this._filters[k]; @@ -9379,7 +9382,7 @@ SpazFilterChain.prototype.processArray = function(input_array) { } } } - + // remove stuff set to null, so we can use filters that remove items by returning null; input_array = _.compact(input_array); return input_array; @@ -9388,7 +9391,7 @@ SpazFilterChain.prototype.processArray = function(input_array) { /** * find the array index of a given filter * @param {string} label the label for a filter in the chain - * @returns {Number|Boolean} the position of the filter, or FALSE if not found + * @returns {Number|Boolean} the position of the filter, or FALSE if not found */ SpazFilterChain.prototype.getFilterIndex = function(label) { for (var i=0; i < this._filters.length; i++) { @@ -9397,14 +9400,14 @@ SpazFilterChain.prototype.getFilterIndex = function(label) { } } return false; -};/*jslint +};/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc, DOMParser, jQuery; @@ -9427,7 +9430,7 @@ var SpazImageUploader = function(opts) { /** - * this lets us set options after instantiation + * this lets us set options after instantiation * @param {object} opts options hash * @param {object} [opts.auth_obj] A SpazAuth object that's filled with proper authentication info * @param {string} [opts.username] a username, in case we're doing that kind of thing @@ -9448,7 +9451,7 @@ SpazImageUploader.prototype.setOpts = function(opts) { }; /** - * returns an array of labels for the services + * returns an array of labels for the services * @return array */ SpazImageUploader.prototype.getServiceLabels = function() { @@ -9469,14 +9472,14 @@ SpazImageUploader.prototype.services = { 'drippic' : { 'url' : 'http://drippic.com/drippic2/upload', 'parseResponse': function(data) { - + var parser=new DOMParser(); xmldoc = parser.parseFromString(data,"text/xml"); - + var status; var rspAttr; var errMsg; - + try { rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes; status = rspAttr.getNamedItem("stat").nodeValue; @@ -9484,9 +9487,9 @@ SpazImageUploader.prototype.services = { errMsg = 'Unknown error uploading image'; return {'error':errMsg}; } - + if (status == 'ok') { - var mediaurl = xmldoc.getElementsByTagName("mediaurl")[0].childNodes[0].nodeValue; + var mediaurl = xmldoc.getElementsByTagName("mediaurl")[0].childNodes[0].nodeValue; return {'url':mediaurl}; } else { if (xmldoc.getElementsByTagName("err")[0]) { @@ -9494,7 +9497,7 @@ SpazImageUploader.prototype.services = { } else { errMsg = xmldoc.getElementsByTagName("error")[0].childNodes[0].nodeValue; } - + sch.error(errMsg); return {'error':errMsg}; } @@ -9509,7 +9512,7 @@ SpazImageUploader.prototype.services = { 'parseResponse': function(data) { var parser=new DOMParser(); xmldoc = parser.parseFromString(data,"text/xml"); - + var status; var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes; if (rspAttr.getNamedItem("status")) { @@ -9519,7 +9522,7 @@ SpazImageUploader.prototype.services = { } else { status = 'fuck I wish they would use the same goddamn nodenames'; } - + if (status == 'ok') { var mediaurl = xmldoc.getElementsByTagName("mediaurl")[0].childNodes[0].nodeValue; return {'url':mediaurl}; @@ -9530,7 +9533,7 @@ SpazImageUploader.prototype.services = { } else { errAttributes = xmldoc.getElementsByTagName("error")[0].attributes; } - + sch.error(errAttributes); errMsg = errAttributes.getNamedItem("msg").nodeValue; sch.error(errMsg); @@ -9548,16 +9551,16 @@ SpazImageUploader.prototype.services = { // 'key':'579HINUYe8d826dd61808f2580cbda7f13433310' // }, // 'parseResponse': function(data) { - // + // // var parser=new DOMParser(); // xmldoc = parser.parseFromString(data,"text/xml"); - // + // // var status; // var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes; // status = rspAttr.getNamedItem("stat").nodeValue; - // + // // if (status == 'ok') { - // var mediaurl = xmldoc.getElementsByTagName("mediaurl")[0].childNodes[0].nodeValue; + // var mediaurl = xmldoc.getElementsByTagName("mediaurl")[0].childNodes[0].nodeValue; // return {'url':mediaurl}; // } else { // var errAttributes; @@ -9566,13 +9569,13 @@ SpazImageUploader.prototype.services = { // } else { // errAttributes = xmldoc.getElementsByTagName("error")[0].attributes; // } - // + // // sch.error(errAttributes); // errMsg = errAttributes.getNamedItem("msg").nodeValue; // sch.error(errMsg); // return {'error':errMsg}; // } - // + // // } // }, 'twitpic' : { @@ -9581,17 +9584,17 @@ SpazImageUploader.prototype.services = { 'key':'3d8f511397248dc913193a6195c4a018' }, 'parseResponse': function(data) { - + if (sch.isString(data)) { data = sch.deJSON(data); } - + if (data.url) { return {'url':data.url}; } else { return {'error':'unknown error'}; } - + } }, 'twitgoo' : { @@ -9602,7 +9605,7 @@ SpazImageUploader.prototype.services = { 'source_url':'http://getspaz.com' }, 'parseResponse': function(data) { - + var parser=new DOMParser(); xmldoc = parser.parseFromString(data,"text/xml"); @@ -9611,7 +9614,7 @@ SpazImageUploader.prototype.services = { status = rspAttr.getNamedItem("status").nodeValue; if (status == 'ok') { - var mediaurl = xmldoc.getElementsByTagName("mediaurl")[0].childNodes[0].nodeValue; + var mediaurl = xmldoc.getElementsByTagName("mediaurl")[0].childNodes[0].nodeValue; return {'url':mediaurl}; } else { var errAttributes; @@ -9626,22 +9629,22 @@ SpazImageUploader.prototype.services = { sch.error(errMsg); return {'error':errMsg}; } - + } }, 'identi.ca' : { 'url' : 'https://identi.ca/api/statusnet/media/upload', 'parseResponse': function(data) { - + var parser=new DOMParser(); xmldoc = parser.parseFromString(data,"text/xml"); var status; var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes; status = rspAttr.getNamedItem("stat").nodeValue; - + if (status == 'ok') { - var mediaurl = xmldoc.getElementsByTagName("mediaurl")[0].childNodes[0].nodeValue; + var mediaurl = xmldoc.getElementsByTagName("mediaurl")[0].childNodes[0].nodeValue; return {'url':mediaurl}; } else { var errMsg; @@ -9650,7 +9653,7 @@ SpazImageUploader.prototype.services = { } else { errMsg = xmldoc.getElementsByTagName("error")[0].childNodes[0].nodeValue; } - + sch.error(errMsg); return {'error':errMsg}; } @@ -9672,7 +9675,7 @@ SpazImageUploader.prototype.services = { var status; var rspAttr = xmldoc.getElementsByTagName("rsp")[0].attributes; status = rspAttr.getNamedItem("stat").nodeValue; - + if (status == 'ok') { var mediaurl = xmldoc.getElementsByTagName("mediaurl")[0].childNodes[0].nodeValue; return {'url':mediaurl}; @@ -9683,28 +9686,28 @@ SpazImageUploader.prototype.services = { } else { errMsg = xmldoc.getElementsByTagName("error")[0].childNodes[0].nodeValue; } - + sch.error(errMsg); return {'error':errMsg}; } - + } } }; /** - * Retrieves the auth_header + * Retrieves the auth_header */ SpazImageUploader.prototype.getAuthHeader = function() { - + var opts = sch.defaults({ 'getEchoHeaderOpts':{} }, this.opts); - + var auth_header; var user = opts.username; var pass = opts.password; - + if (opts.auth_method === 'echo') { // this is Twitter. hopefully var twit = new SpazTwit({'auth':opts.auth_obj}); @@ -9713,7 +9716,7 @@ SpazImageUploader.prototype.getAuthHeader = function() { } else { auth_header = opts.auth_obj.signRequest(); // returns basic auth header } - + sch.error(auth_header); return auth_header; @@ -9721,14 +9724,14 @@ SpazImageUploader.prototype.getAuthHeader = function() { /** - * this actually does the upload. Well, really it preps the data and uses sc.helpers.HTTPFileUpload + * this actually does the upload. Well, really it preps the data and uses sc.helpers.HTTPFileUpload */ SpazImageUploader.prototype.upload = function() { var opts = sch.defaults({ extra:{} }, this.opts); - + var srvc = this.services[opts.service]; if (srvc.prepForUpload) { @@ -9742,7 +9745,7 @@ SpazImageUploader.prototype.upload = function() { if (srvc.extra) { opts.extra = jQuery.extend(opts.extra, srvc.extra); } - + var onSuccess, rs; if (srvc.parseResponse) { /** @ignore */ @@ -9760,41 +9763,41 @@ SpazImageUploader.prototype.upload = function() { } else { onSuccess = opts.onSuccess; } - + /* get auth stuff */ var auth_header; if (opts.service === 'yfrog') { - verify_url = 'https://api.twitter.com/1/account/verify_credentials.xml'; + verify_url = 'https://api.twitter.com/' + SPAZCORE_APIVERSION_TWITTER + '/account/verify_credentials.xml'; auth_header = this.getAuthHeader({ 'getEchoHeaderOpts': { 'verify_url':verify_url } }); } else { - verify_url = 'https://api.twitter.com/1/account/verify_credentials.json'; + verify_url = 'https://api.twitter.com/' + SPAZCORE_APIVERSION_TWITTER + '/account/verify_credentials.json'; auth_header = this.getAuthHeader(); } - + if (auth_header.indexOf('Basic ') === 0) { - + opts.username = this.opts.auth_obj.getUsername(); opts.password = this.opts.auth_obj.getPassword(); - + if (!opts.headers) { opts.headers = {}; } opts.headers['Authorization'] = auth_header; } else { - + if (!opts.headers) { opts.headers = {}; } opts.headers['X-Auth-Service-Provider'] = verify_url; opts.headers['X-Verify-Credentials-Authorization'] = auth_header; } - + sc.helpers.HTTPUploadFile(opts, onSuccess, opts.onFailure); - -};/*jslint + +};/*jslint browser: true, nomen: false, debug: true, @@ -9803,17 +9806,17 @@ sub: true, plusplus: true, undef: true, white: false, -onevar: false +onevar: false */ var sc, jQuery; /** - * @constructor + * @constructor */ function SpazPhotoMailer(opts) { this.apis = this.getAPIs(); - + } SpazPhotoMailer.prototype.getAPILabels = function() { @@ -9825,9 +9828,9 @@ SpazPhotoMailer.prototype.getAPILabels = function() { }; SpazPhotoMailer.prototype.getAPIs = function() { - + var thisSPM = this; - + var apis = { "yfrog": { "email_tpl" :"{{username}}.??????@yfrog.com", @@ -9849,7 +9852,7 @@ SpazPhotoMailer.prototype.getAPIs = function() { return thisSPM.apis['posterous'].email_tpl; } }, - + "pikchur": { "email_tpl" :"{{username}}.???@pikchur.com", "message_in" :"subject", @@ -9893,67 +9896,67 @@ SpazPhotoMailer.prototype.getAPIs = function() { return thisSPM.apis['tweetphoto'].email_tpl.replace('{{username}}', username); }, 'retrievePostingAddress': function(username, password, success, failure) { - + function getTweetPhotoProfile(username, password) { - + var url = "http://tweetphotoapi.com/api/tpapi.svc/json/users/"+username; var TPAPI_header = 'TPAPI: '+username+","+password; - + jQuery.ajax({ 'dataType':'text', - + 'success':function(data, textStatus) { var profile = sc.helpers.deJSON(data); - + }, - + 'error':function(xhr, testStatus, errorThrown) { failure(xhr, testStatus, errorThrown); }, - + 'beforeSend':function(xhr){ xhr.setRequestHeader("TPAPI", username+","+password); }, - + 'url':url - - + + }); - + } - + function getTweetPhoto(username, password, settings_url) { var TPAPI_header = 'TPAPI: '+username+","+password; - + jQuery.ajax({ 'dataType':'text', - + 'success':function(data, textStatus) { var settings = sc.helpers.deJSON(data); success(settings.Email); }, - + 'error':function(xhr, testStatus, errorThrown) { failure(xhr, testStatus, errorThrown); }, - + 'beforeSend':function(xhr){ xhr.setRequestHeader("TPAPI", username+","+password); }, - + 'url':settings_url - + }); - + } - - - + + + } } }; - + return apis; }; @@ -9963,42 +9966,42 @@ SpazPhotoMailer.prototype.setAPI = function(apilabel) { }; SpazPhotoMailer.prototype.send = function(api, photo_url, message) { - + }; -/*jslint +/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc, Titanium, air, jQuery, Mojo; /** - * @constant + * @constant */ var SPAZCORE_PREFS_TI_KEY = 'preferences.json'; /** - * @constant + * @constant */ var SPAZCORE_PREFS_AIR_FILENAME = 'preferences.json'; /** - * @constant + * @constant */ var SPAZCORE_PREFS_MOJO_COOKIENAME = 'preferences.json'; /** - * @constant + * @constant */ var SPAZCORE_PREFS_STANDARD_COOKIENAME = 'preferences_json'; - + /** * A preferences lib for AIR JS apps. This requires the json2.js library - * + * * @param {object} defaults a JS object of key:value pairs used for the pref defaults. Example: * { * foo:124545, @@ -10016,21 +10019,21 @@ var SPAZCORE_PREFS_STANDARD_COOKIENAME = 'preferences_json'; * onSet:function(key, value) {}; * } * } - * + * * events raised: * 'spazprefs_loaded' - * + * * @TODO we need to pull out the platform-specifc stuff into the /platforms/... hierarchy * @class SpazPrefs * @constructor */ -function SpazPrefs(defaults, id, sanity_methods) { +function SpazPrefs(defaults, id, sanity_methods) { /* init prefs */ this._prefs = {}; - + /* init sanity check methods we use: @@ -10044,16 +10047,16 @@ function SpazPrefs(defaults, id, sanity_methods) { sch.debug('adding sanity methods to prefs'); this._sanity_methods = sanity_methods; } - + if (id) { this.id = id; } - + if (defaults) { this.setDefaults(defaults); this._applyDefaults(); } - + this.loaded = false; } @@ -10061,7 +10064,7 @@ function SpazPrefs(defaults, id, sanity_methods) { /** * sets the passed object of key:val pairs as the default preferences * @param {object} defaults - */ + */ SpazPrefs.prototype.setDefaults = function(defaults) { this._defaults = defaults; }; @@ -10080,10 +10083,10 @@ SpazPrefs.prototype._applyDefaults = function() { }; /** - * resets all prefs to defaults and saves + * resets all prefs to defaults and saves */ SpazPrefs.prototype.resetPrefs = function() { - + this._applyDefaults(); this.save(); }; @@ -10096,7 +10099,7 @@ SpazPrefs.prototype.resetPrefs = function() { */ SpazPrefs.prototype.get = function(key, encrypted) { var value; - + if (encrypted) { value = this.getEncrypted(key); } else { @@ -10109,12 +10112,12 @@ SpazPrefs.prototype.get = function(key, encrypted) { value = undefined; } } - + if (this._sanity_methods[key] && this._sanity_methods[key].onGet) { sc.helpers.debug("Calling "+key+".onGet()"); value = this._sanity_methods[key].onGet.call(this, key, value); } - + return value; }; @@ -10123,22 +10126,22 @@ SpazPrefs.prototype.get = function(key, encrypted) { * set a preference and save automatically */ SpazPrefs.prototype.set = function(key, val, encrypted) { - + sc.helpers.debug('Setting and saving "'+key+'" to "'+val+'" ('+typeof(val)+')'); - + if (this._sanity_methods[key] && this._sanity_methods[key].onSet) { sc.helpers.debug("Calling "+key+".onSet()"); val = this._sanity_methods[key].onSet.call(this, key, val); } - + if (encrypted) { this.setEncrypted(key, val); } else { this._prefs[key] = val; } - - + + this.save(); }; @@ -10154,17 +10157,17 @@ SpazPrefs.prototype.set = function(key, val, encrypted) { * @param {function} method the method definition */ SpazPrefs.prototype.setSanityMethod = function(key, type, method) { - + if (type !== 'onGet' && type !== 'onSet') { sch.error('sanity method type must be onGet or onSet'); } - + if (!this._sanity_methods[key]) { this._sanity_methods[key] = {}; } - + this._sanity_methods[key][type] = method; - + }; @@ -10207,7 +10210,7 @@ SpazPrefs.prototype.load = function(name) { SpazPrefs.prototype.save = function() { - + }; @@ -10218,40 +10221,40 @@ SpazPrefs.prototype.save = function() { if (sc) { var scPrefs = SpazPrefs; } -/*jslint +/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc; /** - * A library to shorten text + * A library to shorten text * @constructor */ function SpazShortText() { this.map = {}; - + this.genBaseMaps(); this.processBaseMaps(); - + } /** - * internal function to generate the default long -> short maps + * internal function to generate the default long -> short maps */ SpazShortText.prototype.genBaseMaps = function() { - + this.basemap = { - + /* txtspeak type stuff */ @@ -10314,7 +10317,7 @@ SpazShortText.prototype.genBaseMaps = function() { 'weeks' :'wks', 'with' :'w', 'without' :'w/o', - + 'that' :'tht', 'what' :'wht', 'have' :'hv', @@ -10625,7 +10628,7 @@ SpazShortText.prototype.genBaseMaps = function() { 'talked' :'tlkd', 'hundred' :'hndrd', 'changed' :'chgd', - 'completely' :'cmpltly', + 'completely' :'cmpltly', 'explain' :'exp', 'playing' :'plyg', 'relationship' :'rlshp', @@ -10754,8 +10757,8 @@ SpazShortText.prototype.genBaseMaps = function() { 'mommy' :'mom', 'possibly' :'pssbly', 'worst' :'wrst', - - + + /* contractions */ @@ -10812,7 +10815,7 @@ SpazShortText.prototype.genBaseMaps = function() { 'That will' :'That\'ll', 'That had' :'That\'d', 'That would' :'That\'d', - + 'are not' :'aren\'t', 'can not' :'can\'t', 'could not' :'couldn\'t', @@ -10829,7 +10832,7 @@ SpazShortText.prototype.genBaseMaps = function() { 'were not' :'weren\'t', 'will not' :'won\'t', 'would not' :'wouldn\'t', - + /* numbers */ @@ -10846,10 +10849,10 @@ SpazShortText.prototype.genBaseMaps = function() { 'eleven' :'11', 'twelve' :'12', 'twenty' :'20' - + }; - - + + /* these mappings aren't to be altered at all when processed into regexes */ @@ -10869,11 +10872,11 @@ SpazShortText.prototype.genBaseMaps = function() { /** - * This processes the base maps into the this.map object of regexes and replacements + * This processes the base maps into the this.map object of regexes and replacements */ SpazShortText.prototype.processBaseMaps = function() { var key, val, regex, israw; - + for (key in this.basemap) { val = this.basemap[key]; regex = new RegExp('(\\b)'+key+'(\\b)', 'gi'); @@ -10882,7 +10885,7 @@ SpazShortText.prototype.processBaseMaps = function() { 'regex':regex }; } - + /* take the rawmap stuff and glob it into this.map, so we only have one to worry about */ @@ -10894,45 +10897,45 @@ SpazShortText.prototype.processBaseMaps = function() { 'regex':regex }; } - - + + }; /** * shortens the given text according to the map - * + * * @param {string} text - * @return {string} + * @return {string} */ SpazShortText.prototype.shorten = function(text) { - + for (var key in this.map) { var re = this.map[key].regex; var rp = this.map[key]["short"]; text = text.replace(re, rp); } - + return text; - + }; /** * this adds a new mapping to the basemaps and processes the base maps into regexes again - * @param {string} search + * @param {string} search * @param {string} replase * @param {boolean} israw is true, this mapping won't be altered at all when processed into a regex */ SpazShortText.prototype.addMap = function(search, replace, israw) { israw = israw || false; - + if (israw) { this.baserawmap[search] = replace; } else { this.basemap[search] = replace; } - + this.processBaseMaps(); }; @@ -10940,51 +10943,51 @@ SpazShortText.prototype.addMap = function(search, replace, israw) { /** * returns the map - * @return {object} + * @return {object} */ SpazShortText.prototype.getMaps = function() { return this.map; -};/*jslint +};/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc, jQuery; /** - * A library to do url shortening + * A library to do url shortening */ /** - * Constants to refer to services + * Constants to refer to services */ /** - * @constant + * @constant */ var SPAZCORE_SHORTURL_SERVICE_ISGD = 'is.gd'; /** - * @constant + * @constant */ var SPAZCORE_SHORTURL_SERVICE_BITLY = 'bit.ly'; /** - * @constant + * @constant */ var SPAZCORE_SHORTURL_SERVICE_JMP = 'j.mp'; /** - * @constant + * @constant */ var SPAZCORE_SHORTURL_SERVICE_GOOGLE = 'goo.gl'; /** - * @constant + * @constant */ var SPAZCORE_SHORTURL_SERVICE_GOLOOKAT = 'go.ly'; /** - * @constant + * @constant */ var SPAZCORE_EXPANDABLE_DOMAINS = [ "bit.ly", @@ -11076,7 +11079,7 @@ var SPAZCORE_EXPANDABLE_DOMAINS = [ /** - * events raised here + * events raised here */ if (!sc.events) { sc.events = {}; } sc.events.newShortURLSuccess = 'newShortURLSuccess'; @@ -11092,17 +11095,17 @@ sc.events.newExpandURLFailure = 'recoverLongURLFailure'; * @constructor */ function SpazShortURL(service) { - + this.api = this.getAPIObj(service); - - + + this.expanded_cache = {}; - + } SpazShortURL.prototype.services = {}; - + SpazShortURL.prototype.services[SPAZCORE_SHORTURL_SERVICE_BITLY] = { 'url' : 'http://api.bit.ly/v3/shorten', 'getData' : function(longurl, opts) { @@ -11182,7 +11185,7 @@ SpazShortURL.prototype.services[SPAZCORE_SHORTURL_SERVICE_GOOGLE] = { }, 'processResult' : function(data, longurl) { var result = sc.helpers.deJSON(data); - + if (result.longUrl && result.id) { result.longurl = longurl; // google re-encodes characters so we need to use the original we passed result.shorturl = result.id; @@ -11196,7 +11199,7 @@ SpazShortURL.prototype.services[SPAZCORE_SHORTURL_SERVICE_GOOGLE] = { /** - * returns an array of labels for the services + * returns an array of labels for the services * @return array */ SpazShortURL.prototype.getServiceLabels = function() { @@ -11212,9 +11215,9 @@ SpazShortURL.prototype.getServiceLabels = function() { SpazShortURL.prototype.getAPIObj = function(service) { - - + + return this.services[service]; }; @@ -11229,9 +11232,9 @@ SpazShortURL.prototype.getAPIObj = function(service) { * @param {Function} [opts.onError] */ SpazShortURL.prototype.shorten = function(longurl, opts) { - + var shortener = this; - + if (!opts) { opts = {}; } /* @@ -11245,13 +11248,13 @@ SpazShortURL.prototype.shorten = function(longurl, opts) { if (sch.isString(longurl)) { longurl = [longurl]; } - - + + for (var i=0; i < longurl.length; i++) { longurl[i]; - + /* we call getData now in case it needs to override anything */ @@ -11260,13 +11263,13 @@ SpazShortURL.prototype.shorten = function(longurl, opts) { if (sc.helpers.getMojoURL) { this.api.url = sc.helpers.getMojoURL(this.api.url); } - + getShortURL(longurl[i], shortener, apidata, opts, this); - + } - + function getShortURL(longurl, shortener, apidata, opts, self) { - + jQuery.ajax({ 'traditional':true, // so we don't use square brackets on arrays in data. Bit.ly doesn't like it 'dataType':'text', @@ -11288,7 +11291,7 @@ SpazShortURL.prototype.shorten = function(longurl, opts) { if (opts.onError) { opts.onError(errobj); } - + }, success:function(data) { // var shorturl = trim(data); @@ -11312,9 +11315,9 @@ SpazShortURL.prototype.shorten = function(longurl, opts) { 'contentType':self.api.contentType || "application/x-www-form-urlencoded", 'url' :self.api.url, 'data':apidata - }); + }); } - + }; SpazShortURL.prototype._onShortenResponseSuccess = function(data, target) { @@ -11325,19 +11328,19 @@ SpazShortURL.prototype._onShortenResponseFailure = function(errobj, target) { }; /** - * @TODO + * @TODO */ SpazShortURL.prototype.expand = function(shorturl, opts) { - + var shortener = this; var longurl; - + if (!opts) { opts = {}; } - + opts.event_target = opts.event_target || document; - + /* Do a lookup in the cache first */ @@ -11350,7 +11353,7 @@ SpazShortURL.prototype.expand = function(shorturl, opts) { ); return; } - + /* if not cached, do query to look it up */ @@ -11360,9 +11363,9 @@ SpazShortURL.prototype.expand = function(shorturl, opts) { }, 'error':function(xhr, msg, exc) { sc.helpers.dump(this.url + ' error:'+msg); - + var errobj = {'url':this.url, 'xhr':null, 'msg':null}; - + if (xhr) { errobj.xhr = xhr; sc.helpers.dump("Error:"+xhr.status+" from "+ this.url); @@ -11374,22 +11377,22 @@ SpazShortURL.prototype.expand = function(shorturl, opts) { if (opts.onError) { opts.onError(errobj); } - + }, success:function(data) { data = sch.deJSON(data); var longurl = data['final_url']; - + /* save it to cache */ shortener.saveExpandedURLToCache(shorturl, longurl); - + var resp = { 'shorturl':shorturl, 'longurl' :longurl }; - + shortener._onExpandResponseSuccess(resp, opts.event_target); if (opts.onSuccess) { opts.onSuccess(resp); @@ -11403,14 +11406,14 @@ SpazShortURL.prototype.expand = function(shorturl, opts) { }; /** - * @TODO + * @TODO */ SpazShortURL.prototype._onExpandResponseSuccess = function(data, target) { sc.helpers.triggerCustomEvent(sc.events.newExpandURLSuccess, target, data); }; /** - * @TODO + * @TODO */ SpazShortURL.prototype._onExpandResponseFailure = function(errobj, target) { sc.helpers.triggerCustomEvent(sc.events.newExpandURLFailure, target, errobj); @@ -11419,9 +11422,9 @@ SpazShortURL.prototype._onExpandResponseFailure = function(errobj, target) { SpazShortURL.prototype.findExpandableURLs = function(str) { var x, i, j, matches = [], key, thisdomain, thisregex, regexes = []; - + var all_urls = sch.extractURLs(str); - + for (i=0; i < SPAZCORE_EXPANDABLE_DOMAINS.length; i++) { thisdomain = SPAZCORE_EXPANDABLE_DOMAINS[i]; if (thisdomain == 'ff.im') { @@ -11433,19 +11436,19 @@ SpazShortURL.prototype.findExpandableURLs = function(str) { } else { regexes.push(new RegExp("http://"+thisdomain+"/([a-zA-Z0-9-_]+)", "gi")); } - + }; - + sch.debug("looking for "+regexes+ " in '"+str+"'"); for (i=0; i < regexes.length; i++) { thisregex = regexes[i]; while( (re_matches = thisregex.exec(sch.trim(str))) != null) { matches.push(re_matches[0]); - } + } }; - + sch.debug('Matches: '+matches); - + if (matches.length > 0) { return matches; } else { @@ -11467,8 +11470,8 @@ SpazShortURL.prototype.expandURLs = function(urls, target, onSuccess, onFailure) /** * @param {string} str the string to replace the URLs in - * @param {string} shorturl - * @param {string} longurl + * @param {string} shorturl + * @param {string} longurl */ SpazShortURL.prototype.replaceExpandableURL = function(str, shorturl, longurl) { str = str.replace(shorturl, longurl, 'gi'); @@ -11488,7 +11491,7 @@ SpazShortURL.prototype.getExpandedURLFromCache = function(shortURL) { SpazShortURL.prototype.saveExpandedURLToCache = function(shortURL, longURL) { this.expanded_cache[shortURL] = longURL; -};/*jslint +};/*jslint browser: true, nomen: false, debug: true, @@ -11496,20 +11499,20 @@ forin: true, plusplus: false, undef: true, white: false, -onevar: false +onevar: false */ var sc; /** - * SpazTemplate + * SpazTemplate * designed for fast templating functions * @class SpazTemplate * @constructor */ function SpazTemplate() { - + this._tpls = {}; - + } /** @@ -11523,12 +11526,12 @@ SpazTemplate.prototype.addTemplateMethod = function(name, method) { /** * @param string methodname the template method to call. - * @param mixed data data to be used by the template method + * @param mixed data data to be used by the template method * @return string; */ SpazTemplate.prototype.parseTemplate = function(methodname, data) { var parsed = this._tpls[methodname](data); - + return parsed; }; @@ -11544,7 +11547,7 @@ SpazTemplate.prototype.parseArray = function(methodname, data_array) { } return parsed; }; -/*jslint +/*jslint browser: true, nomen: false, debug: true, @@ -11552,7 +11555,7 @@ forin: true, plusplus: false, undef: true, white: false, -onevar: false +onevar: false */ var sc, jQuery; @@ -11563,15 +11566,15 @@ var sc, jQuery; /** - * This object provides an API for managing the content of a timeline + * This object provides an API for managing the content of a timeline * Currently this requires jQuery, but that could change or be overwritten * on a per-app basis * @requires jQuery * @constructor */ var SpazTimeline = function(opts) { - - var thisTL = this; + + var thisTL = this; /** * This is a wrapper function for the refresher interval * we define this here and use a closure to solve a scope issue when the interval fires @@ -11581,29 +11584,29 @@ var SpazTimeline = function(opts) { sch.debug('Refreshing timeline'); thisTL.requestData.call(thisTL); }; - - + + /** - * Again, due to scope issues, we define this here to take advantage of the closure + * Again, due to scope issues, we define this here to take advantage of the closure */ this.onSuccess = function(e, data) { sch.debug('onSuccess timeline'); thisTL.data_success.call(thisTL, e, data); - thisTL.startRefresher(); + thisTL.startRefresher(); }; /** - * Again, due to scope issues, we define this here to take advantage of the closure + * Again, due to scope issues, we define this here to take advantage of the closure */ this.onFailure = function(e, data) { sch.debug('onFailure timeline'); thisTL.data_failure.call(thisTL, e, data); - thisTL.startRefresher(); + thisTL.startRefresher(); }; - - + + /* - By breaking this out, we can more easily override the + By breaking this out, we can more easily override the constructor process */ this._init(opts); @@ -11611,28 +11614,28 @@ var SpazTimeline = function(opts) { SpazTimeline.prototype._init = function(opts) { - + opts = opts || {}; - - this.max_items = opts.max_items || 100; + + this.max_items = opts.max_items || 100; this.refresh_time = opts.refresh_time || 1000*60*2; // mseconds - + this.timeline_container_selector = opts.timeline_container_selector || '#timeline'; this.timeline_item_selector = opts.timeline_item_selector || 'div.timeline-entry'; // this.entry_relative_time_selector= opts.entry_relative_time_selector|| '.date'; this.event_target = opts.event_target || jQuery(this.timeline_container_selector).get(0); - + this.add_method = opts.add_method || 'prepend'; // prepend or append - + this.success_event = opts.success_event || 'timeline-success'; this.failure_event = opts.failure_event || 'timeline-failure'; - + this.renderer = opts.renderer || null; // required this.request_data = opts.request_data || null; // required this.data_success = opts.data_success || null; // required this.data_failure = opts.data_failure || null; this.refresher = opts.refresher || null; - + if (!this.renderer) { throw new Error ("renderer is required"); } @@ -11649,17 +11652,17 @@ SpazTimeline.prototype._init = function(opts) { }; /** - * the timeline + * the timeline */ SpazTimeline.prototype.last_id = -1; /** - * an array of data items that are represented in the timeline + * an array of data items that are represented in the timeline */ SpazTimeline.prototype.model = []; /** - * call this after initialization + * call this after initialization */ SpazTimeline.prototype.start = function() { sch.debug('Starting timeline'); @@ -11668,19 +11671,19 @@ SpazTimeline.prototype.start = function() { /** - * This is the method that gets data from the model and calls addItems() on what is returned - * + * This is the method that gets data from the model and calls addItems() on what is returned + * * @todo needs to be written to handle async call */ SpazTimeline.prototype.requestData = function() { sch.debug('Requesting data timeline'); this.stopRefresher(); - + this.stopListening(); this.startListening(); - + // call an appropriate model function - var items = this.request_data(); + var items = this.request_data(); }; @@ -11702,7 +11705,7 @@ SpazTimeline.prototype.stopListening = function() { SpazTimeline.prototype.startRefresher = function() { this.stopRefresher(); - + sc.helpers.debug('Starting refresher'); if (this.refresh_time > 1000) { // the minimum refresh is 1000ms. Otherwise we don't auto-refresh sc.helpers.debug('Refresh time is '+this.refresh_time+'ms'); @@ -11725,7 +11728,7 @@ SpazTimeline.prototype.stopRefresher = function() { /** * Stuff we should do when we're done using this, including - * removing event listeners an stopping the refresher + * removing event listeners an stopping the refresher */ SpazTimeline.prototype.cleanup = function() { sch.debug('Cleaning up timeline'); @@ -11739,14 +11742,14 @@ SpazTimeline.prototype.cleanup = function() { */ SpazTimeline.prototype.addItems = function(items) { sch.debug('Adding items to timeline'); - + var items_html = []; var timeline_html = ''; - + for (var x=0; x'; @@ -11757,31 +11760,31 @@ SpazTimeline.prototype.addItems = function(items) { timeline_html = items_html.join(''); this.prepend(timeline_html); } - + this.removeExtraItems(); - + }; SpazTimeline.prototype.renderItem = function(item, templatefunc) { sch.debug('Rendering item in timeline'); - + var html = templatefunc(item); - + return html; - + }; SpazTimeline.prototype.removeExtraItems = function() { - + sch.debug('Removing extra items in timeline'); - + if (this.add_method === 'append') { var remove_from_top = true; } else { remove_from_top = false; } - + sc.helpers.removeExtraElements(this.getEntrySelector(), this.max_items, remove_from_top); }; @@ -11793,50 +11796,50 @@ SpazTimeline.prototype.removeItem = function(selector) {}; /** * @param {string} selector - * @return {boolean} + * @return {boolean} */ SpazTimeline.prototype.itemExists = function(selector) { - + sch.debug('Checking it item ('+selector+') exists in timeline'); - + var items = this.select(selector); if (items.length>0) { return true; } else { return false; } - + }; SpazTimeline.prototype.hideItems = function(selector) { sch.debug('Hiding items in timeline'); - + this.filterItems(selector, 'blacklist'); }; SpazTimeline.prototype.showItems = function(selector) { sch.debug('Showing items in timeline'); - + this.filterItems(selector, 'whitelist'); }; /** - * @param {string} selector + * @param {string} selector * @param {string} type "whitelist" or "blacklist" */ SpazTimeline.prototype.filterItems = function(selector, type) {}; /** - * sorts the elements in the timeline according to the sorting function + * sorts the elements in the timeline according to the sorting function */ SpazTimeline.prototype.sortItems = function(selector, sortfunc) { - + sch.debug('Sorting items in timeline'); - + var items = this.select(selector); items.sort(sortfunc); }; @@ -11844,8 +11847,8 @@ SpazTimeline.prototype.sortItems = function(selector, sortfunc) { /** - * This is a wrapper for the selector engine, so someone could swap in - * their own recipe if necessary. By default we use jQuery, and return the + * This is a wrapper for the selector engine, so someone could swap in + * their own recipe if necessary. By default we use jQuery, and return the * array of HTML elements (not the jQuery object) * @type DOMelement[] */ @@ -11857,7 +11860,7 @@ SpazTimeline.prototype.select = function(selector, container) { }; /** - * wrapper for prepending to timeline + * wrapper for prepending to timeline */ SpazTimeline.prototype.prepend = function(htmlitem) { jQuery(this.timeline_container_selector).prepend(htmlitem); @@ -11869,24 +11872,24 @@ SpazTimeline.prototype.append = function(htmlitem) { SpazTimeline.prototype.getEntrySelector = function() { return this.timeline_container_selector + ' ' + this.timeline_item_selector; }; -/*jslint +/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc, DOMParser, jQuery, sch; - + /** - * A library to interact with the API for theMovieDB.org + * A library to interact with the API for theMovieDB.org * @see The API docs */ /** - * events raised here + * events raised here */ if (!sc.events) { sc.events = {}; } sc.events.tmdbMethodSuccess = 'tmdbMethodSuccess'; @@ -11917,7 +11920,7 @@ sc.events.tmdbHashGetInfoFailure = 'tmdbHashGetInfoFailure'; * @param {DOMElement} [opts.eventTarget] what to target triggered events with. default is the document element */ function SpazTMDB(opts) { - + /* set defaults */ @@ -11927,19 +11930,19 @@ function SpazTMDB(opts) { 'format':'json', 'eventTarget':document }, opts); - + this.apikey = opts.apikey; this.lang = opts.lang; this.format = opts.format; this.eventTarget = opts.eventTarget; - + this.baseURL = 'http://api.themoviedb.org/2.1/'; - + } /** * Sets the API key - * @param {string} apikey the api key used to access the API + * @param {string} apikey the api key used to access the API */ SpazTMDB.prototype.setAPIKey = function(apikey) { this.apikey = apikey; @@ -11947,7 +11950,7 @@ SpazTMDB.prototype.setAPIKey = function(apikey) { /** * Gets the API key - * @returns {string} the api key that was previously set + * @returns {string} the api key that was previously set */ SpazTMDB.prototype.getAPIKey = function() { return this.apikey; @@ -11956,8 +11959,8 @@ SpazTMDB.prototype.getAPIKey = function() { /** * Search for movies by title * @param {string} value the value passed to the search method - * @param {function} [onSuccess] a callback - * @param {function} [onFailure] a callback + * @param {function} [onSuccess] a callback + * @param {function} [onFailure] a callback */ SpazTMDB.prototype.movieSearch = function(value, onSuccess, onFailure) { this.callMethod({ @@ -11975,8 +11978,8 @@ SpazTMDB.prototype.movieSearch = function(value, onSuccess, onFailure) { /** * Get info for a movie * @param {string|number} id The id of the movie (numeric) - * @param {function} [onSuccess] a callback - * @param {function} [onFailure] a callback + * @param {function} [onSuccess] a callback + * @param {function} [onFailure] a callback */ SpazTMDB.prototype.movieInfo = function(id, onSuccess, onFailure) { this.callMethod({ @@ -11994,8 +11997,8 @@ SpazTMDB.prototype.movieInfo = function(id, onSuccess, onFailure) { /** * Get images for a movie * @param {string|number} id The id of the movie (numeric) - * @param {function} [onSuccess] a callback - * @param {function} [onFailure] a callback + * @param {function} [onSuccess] a callback + * @param {function} [onFailure] a callback */ SpazTMDB.prototype.movieImages = function(id, onSuccess, onFailure) { this.callMethod({ @@ -12013,8 +12016,8 @@ SpazTMDB.prototype.movieImages = function(id, onSuccess, onFailure) { /** * Lookup a movie by IMDB id * @param {string} id The IMDB id of the movie. ex "tt0137523" - * @param {function} [onSuccess] a callback - * @param {function} [onFailure] a callback + * @param {function} [onSuccess] a callback + * @param {function} [onFailure] a callback */ SpazTMDB.prototype.movieInfoIMDB = function(id, onSuccess, onFailure) { this.callMethod({ @@ -12032,8 +12035,8 @@ SpazTMDB.prototype.movieInfoIMDB = function(id, onSuccess, onFailure) { /** * Search for a person * @param {string|number} id The id of the person (numeric) - * @param {function} [onSuccess] a callback - * @param {function} [onFailure] a callback + * @param {function} [onSuccess] a callback + * @param {function} [onFailure] a callback */ SpazTMDB.prototype.personInfo = function(id, onSuccess, onFailure) { this.callMethod({ @@ -12051,8 +12054,8 @@ SpazTMDB.prototype.personInfo = function(id, onSuccess, onFailure) { /** * Search for a person * @param {string} name The name to search for - * @param {function} [onSuccess] a callback - * @param {function} [onFailure] a callback + * @param {function} [onSuccess] a callback + * @param {function} [onFailure] a callback */ SpazTMDB.prototype.personSearch = function(name, onSuccess, onFailure) { this.callMethod({ @@ -12071,8 +12074,8 @@ SpazTMDB.prototype.personSearch = function(name, onSuccess, onFailure) { /** * Get movie info by file hash * @param {string} hash The hash corresponding to the movie - * @param {function} [onSuccess] a callback - * @param {function} [onFailure] a callback + * @param {function} [onSuccess] a callback + * @param {function} [onFailure] a callback * @see Hash Source Codes */ SpazTMDB.prototype.movieInfoHash = function(hash, onSuccess, onFailure) { @@ -12094,7 +12097,7 @@ SpazTMDB.prototype.movieInfoHash = function(hash, onSuccess, onFailure) { /** * Method to construct an API URL from the passed method and value strings * @param {string} method the string for this parameter. See API docs for list - * @param {string} value the value we're passing to the API method. This will be encoded using encodeURIComponent() + * @param {string} value the value we're passing to the API method. This will be encoded using encodeURIComponent() * @returns {string} the URL string */ SpazTMDB.prototype.getURL = function(method, value) { @@ -12116,11 +12119,11 @@ SpazTMDB.prototype.getURL = function(method, value) { * @param {string} [opts.failureEvent] the type of event to raise on failure. default is {@link sc.events.tmdbMethodFailure} * @param {function} [opts.onSuccess] a callback function called on success. takes args data, textStatus * @param {function} [opts.onFailure] a callback function called on failure. takes args xhr, msg, exc - * + * */ SpazTMDB.prototype.callMethod = function(opts) { var that = this; - + opts = sch.defaults({ 'method' :'Movie.search', 'value' :'Road House', @@ -12129,9 +12132,9 @@ SpazTMDB.prototype.callMethod = function(opts) { 'onSuccess' :null, // callback on success 'onFailure' :null // callback on failure }, opts); - + var url = this.getURL(opts.method, opts.value); - + jQuery.ajax({ 'url' :url, 'type':'GET', @@ -12153,7 +12156,7 @@ SpazTMDB.prototype.callMethod = function(opts) { //= require //= require -/*jslint +/*jslint browser: true, nomen: false, debug: true, @@ -12163,7 +12166,7 @@ regexp: false, sub: true, undef: true, white: false, -onevar: false +onevar: false */ var sc, jQuery, Mojo, use_palmhost_proxy; @@ -12171,72 +12174,72 @@ var sc, jQuery, Mojo, use_palmhost_proxy; * various constant definitions */ /** - * @constant + * @constant */ var SPAZCORE_SECTION_FRIENDS = 'friends'; /** - * @constant + * @constant */ var SPAZCORE_SECTION_HOME = 'home'; /** - * @constant + * @constant */ var SPAZCORE_SECTION_REPLIES = 'replies'; /** - * @constant + * @constant */ var SPAZCORE_SECTION_DMS = 'dms'; /** - * @constant + * @constant */ var SPAZCORE_SECTION_FAVORITES = 'favorites'; /** - * @constant + * @constant */ var SPAZCORE_SECTION_COMBINED = 'combined'; /** - * @constant + * @constant */ var SPAZCORE_SECTION_PUBLIC = 'public'; /** - * @constant + * @constant */ var SPAZCORE_SECTION_SEARCH = 'search'; /** - * @constant + * @constant */ var SPAZCORE_SECTION_USER = 'user-timeline'; /** - * @constant + * @constant */ var SPAZCORE_SECTION_FRIENDLIST = 'friendslist'; /** - * @constant + * @constant */ var SPAZCORE_SECTION_FOLLOWERSLIST = 'followerslist'; /** - * @constant + * @constant */ var SPAZCORE_SECTION_USERLISTS = 'userlists'; /** - * @constant + * @constant */ -var SPAZCORE_SERVICEURL_TWITTER = 'https://api.twitter.com/1/'; +var SPAZCORE_SERVICEURL_TWITTER = 'https://api.twitter.com/' + SPAZCORE_APIVERSION_TWITTER + '/'; /** - * @constant + * @constant */ var SPAZCORE_SERVICEURL_IDENTICA = 'https://identi.ca/api/'; /** - * @constant + * @constant */ var SPAZCORE_SERVICEURL_FREELISHUS = 'http://freelish.us/api/'; /** - * @constant + * @constant */ var SPAZCORE_SERVICEURL_WORDPRESS_TWITTER = 'https://twitter-api.wordpress.com/'; /** - * @constant + * @constant */ var SPAZCORE_SERVICEURL_TUMBLR_TWITTER = 'http://www.tumblr.com/'; @@ -12244,10 +12247,10 @@ var SPAZCORE_SERVICEURL_TUMBLR_TWITTER = 'http://www.tumblr.com/'; /** * A Twitter API library for Javascript - * - * + * + * * jQuery events raised by this library - * + * *
    *
  • 'spaztwit_ajax_error'
  • *
  • 'new_public_timeline_data' (data)
  • @@ -12302,7 +12305,7 @@ var SPAZCORE_SERVICEURL_TUMBLR_TWITTER = 'http://www.tumblr.com/'; *
  • 'destroy_dm_succeeded'
  • *
  • 'destroy_dm_failed'
  • *
- * + * * @param {Object} opts various options * @param {Object} [opts.auth] SpazAuth object * @param {String} [opts.event_mode] The event mode to use ('jquery' or 'DOM'). Defaults to 'DOM' @@ -12312,7 +12315,7 @@ var SPAZCORE_SERVICEURL_TUMBLR_TWITTER = 'http://www.tumblr.com/'; * @constructor */ function SpazTwit(opts) { - + this.opts = sch.defaults({ auth: null, username: null, @@ -12320,16 +12323,16 @@ function SpazTwit(opts) { event_target: document, timeout: this.DEFAULT_TIMEOUT }, opts); - - + + this.auth = this.opts.auth; - + this.setSource('SpazCore'); - + this.initializeData(); - + this.initializeCombinedTracker(); - + /* Cache for one-shot users and posts. Not sure what we'll do with it yet */ @@ -12337,14 +12340,14 @@ function SpazTwit(opts) { users:{}, posts:{} }; - + this.me = {}; - + this.setBaseURL(SPAZCORE_SERVICEURL_TWITTER); /** - * remap dump calls as appropriate + * remap dump calls as appropriate */ if (sc && sc.helpers && sc.helpers.dump) { window.dump = sc.helpers.dump; @@ -12356,7 +12359,7 @@ function SpazTwit(opts) { } /** - * the default timeout value (60 seconds) + * the default timeout value (60 seconds) */ SpazTwit.prototype.DEFAULT_TIMEOUT = 1000*60; @@ -12460,19 +12463,19 @@ SpazTwit.prototype.initializeData = function() { /** - * resets the combined_finished progress tracker + * resets the combined_finished progress tracker */ SpazTwit.prototype.initializeCombinedTracker = function() { this.combined_finished = {}; this.combined_finished[SPAZCORE_SECTION_HOME] = false; this.combined_finished[SPAZCORE_SECTION_REPLIES] = false; this.combined_finished[SPAZCORE_SECTION_DMS] = false; - + this.combined_errors = []; }; /** - * Checks to see if the combined timeline is finished + * Checks to see if the combined timeline is finished * @return {boolean} */ SpazTwit.prototype.combinedTimelineFinished = function() { @@ -12485,7 +12488,7 @@ SpazTwit.prototype.combinedTimelineFinished = function() { }; /** - * Checks to see if the combined timeline is finished + * Checks to see if the combined timeline is finished * @return {boolean} */ SpazTwit.prototype.combinedTimelineHasErrors = function() { @@ -12545,24 +12548,24 @@ SpazTwit.prototype.combinedNewItemsRemoveUpdates = function() { * @param {string} newurl */ SpazTwit.prototype.setBaseURL= function(newurl) { - + var lastchar = newurl.charAt(newurl.length -1); if (lastchar !== '/') { newurl = newurl + '/'; } - + this.baseurl = newurl; }; /** * sets the base URL by the service type - * @param {string} service see SPAZCORE_SERVICE_* + * @param {string} service see SPAZCORE_SERVICE_* */ SpazTwit.prototype.setBaseURLByService= function(service) { - + var baseurl = ''; - + switch (service) { case SPAZCORE_SERVICE_TWITTER: baseurl = SPAZCORE_SERVICEURL_TWITTER; @@ -12583,7 +12586,7 @@ SpazTwit.prototype.setBaseURLByService= function(service) { baseurl = SPAZCORE_SERVICEURL_TWITTER; break; } - + this.baseurl = baseurl; }; @@ -12592,7 +12595,7 @@ SpazTwit.prototype.getServiceFromBaseURL = function(baseurl) { var service; if (!baseurl) { baseurl = this.baseurl; } - + switch (baseurl) { case SPAZCORE_SERVICEURL_TWITTER: service = SPAZCORE_SERVICE_TWITTER; @@ -12613,9 +12616,9 @@ SpazTwit.prototype.getServiceFromBaseURL = function(baseurl) { service = SPAZCORE_SERVICE_CUSTOM; break; } - + return service; - + }; @@ -12627,8 +12630,8 @@ SpazTwit.prototype.setCredentials = function(auth_obj) { /** * set the source string we will pass on updates - * - * @param {string} new_source + * + * @param {string} new_source */ SpazTwit.prototype.setSource = function(new_source) { this.source = new_source; @@ -12651,7 +12654,7 @@ SpazTwit.prototype.getAPIURL = function(key, urldata) { urls.friends_timeline = "statuses/friends_timeline.json"; urls.home_timeline = "statuses/home_timeline.json"; urls.user_timeline = "statuses/user_timeline.json"; - urls.replies_timeline = "statuses/replies.json"; + urls.replies_timeline = "statuses/mentions_timeline.json"; urls.show = "statuses/show/{{ID}}.json"; urls.show_related = "related_results/show/{{ID}}.json"; urls.favorites = "favorites.json"; @@ -12705,28 +12708,28 @@ SpazTwit.prototype.getAPIURL = function(key, urldata) { urls.trends_current = "trends/current.json"; urls.trends_daily = "trends/daily.json"; urls.trends_weekly = "trends/weekly.json"; - + //retweet urls.retweet = "statuses/retweet/{{ID}}.json"; urls.retweets = "statuses/retweets/{{ID}}.json"; urls.retweeted_by_me = "statuses/retweeted_by_me.json"; urls.retweeted_to_me = "statuses/retweeted_to_me.json"; urls.retweets_of_me = "statuses/retweets_of_me.json"; - + urls.search = "search.json"; // misc urls.test = "help/test.json"; urls.downtime_schedule = "help/downtime_schedule.json"; - + if (urls[key].indexOf('{{ID}}') > -1) { if (typeof(urldata) === 'string') { urls[key] = urls[key].replace('{{ID}}', urldata); } else if (urldata && typeof(urldata) === 'object') { urls[key] = urls[key].replace('{{ID}}', urldata.id); } - + } // Token replacement for user lists @@ -12743,15 +12746,14 @@ SpazTwit.prototype.getAPIURL = function(key, urldata) { } if (urls[key]) { - + if (urldata && typeof urldata !== "string") { urldata = '?'+jQuery.param(urldata); } else { urldata = ''; } - return this._postProcessURL(this.baseurl + urls[key] + urldata); - + } else { return false; } @@ -12763,11 +12765,11 @@ SpazTwit.prototype.getAPIURL = function(key, urldata) { /* - * Verify authentication credentials. + * Verify authentication credentials. */ SpazTwit.prototype.verifyCredentials = function(onSuccess, onFailure) { var url = this.getAPIURL('verify_credentials'); - + var opts = { 'url':url, 'process_callback': this._processAuthenticatedUser, @@ -12782,35 +12784,35 @@ SpazTwit.prototype.verifyCredentials = function(onSuccess, onFailure) { Perform a request and get true or false back */ var xhr = this._callMethod(opts); - + }; /** * This takes data retrieved from the verifyCredentials method and stores it * in this.me. it then fires off the event specified in finished_event - * + * * @param {object} data the data returned by a successful call to the verifyCredentials API method - * @param {string} finished_event the type of event to fire + * @param {string} finished_event the type of event to fire * @private */ SpazTwit.prototype._processAuthenticatedUser = function(data, opts) { this.me = data; this.initializeData(); - + if (opts.success_callback) { opts.success_callback(this.me); } this.triggerEvent(opts.success_event_type, this.me); - + }; /** - * Initiates retrieval of the public timeline. + * Initiates retrieval of the public timeline. */ SpazTwit.prototype.getPublicTimeline = function(onSuccess, onFailure) { var url = this.getAPIURL('public_timeline'); - + var xhr = this._getTimeline({ 'url':url, 'success_callback':onSuccess, @@ -12822,13 +12824,13 @@ SpazTwit.prototype.getPublicTimeline = function(onSuccess, onFailure) { /** * Initiates retrieval of the home timeline (all the people you are following) - * + * * @param {string} since_id default is 1. If a negative number value is passed, the '-' prefix is removed and the string is used as the max_id - * @param {integer} count default is 200 + * @param {integer} count default is 200 * @param {integer} page default is null (ignored if null) */ SpazTwit.prototype.getHomeTimeline = function(since_id, count, page, processing_opts, onSuccess, onFailure) { - + if (!page) { page = null;} if (!count) { count = 50;} if (!since_id) { @@ -12838,15 +12840,15 @@ SpazTwit.prototype.getHomeTimeline = function(since_id, count, page, processing_ since_id = 1; } } - + if (!processing_opts) { processing_opts = {}; } - + if (processing_opts.combined) { processing_opts.section = SPAZCORE_SECTION_HOME; } - + var data = {}; if (since_id[0] == '-') { data['max_id'] = since_id.replace('-', ''); @@ -12857,8 +12859,8 @@ SpazTwit.prototype.getHomeTimeline = function(since_id, count, page, processing_ if (page) { data['page'] = page; } - - + + var url = this.getAPIURL('home_timeline', data); this._getTimeline({ 'url':url, @@ -12883,13 +12885,13 @@ SpazTwit.prototype._processHomeTimeline = function(ret_items, opts, processing_o /** * Initiates retrieval of the friends timeline (all the people you are following) - * + * * @param {string} since_id default is 1 - * @param {integer} count default is 200 + * @param {integer} count default is 200 * @param {integer} page default is null (ignored if null) */ SpazTwit.prototype.getFriendsTimeline = function(since_id, count, page, processing_opts, onSuccess, onFailure) { - + if (!page) { page = null;} if (!count) { count = 50;} if (!since_id) { @@ -12899,23 +12901,23 @@ SpazTwit.prototype.getFriendsTimeline = function(since_id, count, page, processi since_id = 1; } } - + if (!processing_opts) { processing_opts = {}; } - + if (processing_opts.combined) { processing_opts.section = SPAZCORE_SECTION_FRIENDS; } - + var data = {}; data['since_id'] = since_id; data['count'] = count; if (page) { data['page'] = page; } - - + + var url = this.getAPIURL('friends_timeline', data); this._getTimeline({ 'url':url, @@ -12938,9 +12940,9 @@ SpazTwit.prototype._processFriendsTimeline = function(ret_items, opts, processin /** - * + * */ -SpazTwit.prototype.getReplies = function(since_id, count, page, processing_opts, onSuccess, onFailure) { +SpazTwit.prototype.getReplies = function(since_id, count, page, processing_opts, onSuccess, onFailure) { if (!page) { page = null;} if (!count) { count = null;} if (!since_id) { @@ -12950,16 +12952,16 @@ SpazTwit.prototype.getReplies = function(since_id, count, page, processing_opts, since_id = 1; } } - + if (!processing_opts) { processing_opts = {}; } - + if (processing_opts.combined) { processing_opts.section = SPAZCORE_SECTION_REPLIES; } - - + + var data = {}; if (since_id[0] == '-') { data['max_id'] = since_id.replace('-', ''); @@ -12972,7 +12974,7 @@ SpazTwit.prototype.getReplies = function(since_id, count, page, processing_opts, if (count) { data['count'] = count; } - + var url = this.getAPIURL('replies_timeline', data); this._getTimeline({ 'url':url, @@ -12996,7 +12998,7 @@ SpazTwit.prototype._processRepliesTimeline = function(ret_items, opts, processin }; /** - * + * */ SpazTwit.prototype.getDirectMessages = function(since_id, count, page, processing_opts, onSuccess, onFailure) { if (!page) { page = null;} @@ -13008,15 +13010,15 @@ SpazTwit.prototype.getDirectMessages = function(since_id, count, page, processin since_id = 1; } } - + if (!processing_opts) { processing_opts = {}; } - + if (processing_opts.combined) { processing_opts.section = SPAZCORE_SECTION_DMS; } - + var data = {}; if (since_id[0] == '-') { data['max_id'] = since_id.replace('-', ''); @@ -13029,7 +13031,7 @@ SpazTwit.prototype.getDirectMessages = function(since_id, count, page, processin if (count) { data['count'] = count; } - + var url = this.getAPIURL('dm_timeline', data); this._getTimeline({ 'url':url, @@ -13038,9 +13040,9 @@ SpazTwit.prototype.getDirectMessages = function(since_id, count, page, processin 'failure_callback':onFailure, 'success_event_type': 'new_dms_timeline_data', 'failure_event_type': 'error_dms_timeline_data', - 'processing_opts':processing_opts + 'processing_opts':processing_opts }); - + }; /** @@ -13052,19 +13054,19 @@ SpazTwit.prototype._processDMTimeline = function(ret_items, opts, processing_opt }; /** - * + * */ -SpazTwit.prototype.getFavorites = function(page, processing_opts, onSuccess, onFailure) { +SpazTwit.prototype.getFavorites = function(page, processing_opts, onSuccess, onFailure) { if (!page) { page = null;} if (!processing_opts) { processing_opts = {}; } - + var data = {}; if (page) { data['page'] = page; } - + var url = this.getAPIURL('favorites', data); this._getTimeline({ @@ -13118,10 +13120,10 @@ SpazTwit.prototype.getUserTimeline = function(id, count, page, onSuccess, onFail if (opts.page) { data['page'] = opts.page; } - - + + var url = this.getAPIURL('user_timeline', data); - + this._getTimeline({ 'url':url, 'process_callback' : this._processUserTimeline, @@ -13144,21 +13146,21 @@ SpazTwit.prototype._processUserTimeline = function(ret_items, opts, processing_o /** * this retrieves three different timelines. the event "new_combined_timeline_data" - * does not fire until ALL async ajax calls are made - * - * + * does not fire until ALL async ajax calls are made + * + * */ SpazTwit.prototype.getCombinedTimeline = function(com_opts, onSuccess, onFailure) { - var home_count, friends_count, replies_count, dm_count, + var home_count, friends_count, replies_count, dm_count, home_since, friends_since, dm_since, replies_since, home_page, friends_page, dm_page, replies_page; var opts = { 'combined':true }; - + if (com_opts) { - + if (com_opts.friends_count) { friends_count = com_opts.friends_count; } @@ -13171,7 +13173,7 @@ SpazTwit.prototype.getCombinedTimeline = function(com_opts, onSuccess, onFailure if (com_opts.dm_count) { dm_count = com_opts.dm_count; // this is not used yet } - + if (com_opts.home_since) { home_since = com_opts.home_since; } @@ -13184,7 +13186,7 @@ SpazTwit.prototype.getCombinedTimeline = function(com_opts, onSuccess, onFailure if (com_opts.dm_since) { dm_since = com_opts.dm_since; } - + if (com_opts.home_page) { home_page = com_opts.home_page; } @@ -13197,19 +13199,19 @@ SpazTwit.prototype.getCombinedTimeline = function(com_opts, onSuccess, onFailure if (com_opts.dm_page) { dm_page = com_opts.dm_page; } - + /* we might still only pass in friends_* opts, so we translate those to home_* */ if (!home_count) { home_count = friends_count; } if (!home_since) { home_since = friends_since; } if (!home_page) { home_page = friends_page; } - + if (com_opts.force) { opts.force = true; } } - + this.getHomeTimeline(home_since, home_count, home_page, opts, onSuccess, onFailure); this.getReplies(replies_since, replies_count, replies_page, opts, onSuccess, onFailure); this.getDirectMessages(dm_since, dm_count, dm_page, opts, onSuccess, onFailure); @@ -13229,8 +13231,8 @@ SpazTwit.prototype.search = function(query, since_id, results_per_page, page, la if (!results_per_page) { results_per_page = 100; } - - + + var data = {}; data['q'] = query; data['rpp'] = results_per_page; @@ -13248,7 +13250,7 @@ SpazTwit.prototype.search = function(query, since_id, results_per_page, page, la if (geocode) { data['geocode'] = geocode; } - + var url = this.getAPIURL('search', data); this._getTimeline({ 'url':url, @@ -13258,15 +13260,15 @@ SpazTwit.prototype.search = function(query, since_id, results_per_page, page, la 'success_event_type': 'new_search_timeline_data', 'failure_event_type': 'error_search_timeline_data' }); - + }; /** * @private */ -SpazTwit.prototype._processSearchTimeline = function(search_result, opts, processing_opts) { +SpazTwit.prototype._processSearchTimeline = function(search_result, opts, processing_opts) { /* - Search is different enough that we need to break it out and + Search is different enough that we need to break it out and write a custom alternative to _processTimeline */ if (!processing_opts) { processing_opts = {}; } @@ -13275,12 +13277,12 @@ SpazTwit.prototype._processSearchTimeline = function(search_result, opts, proces reset .newitems data properties */ this.data[SPAZCORE_SECTION_SEARCH].newitems = []; - + /* put these results in the lastresultdata property */ this.data[SPAZCORE_SECTION_SEARCH].lastresultdata = search_result; - + /* grab the array of items */ @@ -13298,10 +13300,10 @@ SpazTwit.prototype._processSearchTimeline = function(search_result, opts, proces sort items */ ret_items.sort(this._sortItemsAscending); - + /* set lastid - */ + */ var lastid = ret_items[ret_items.length-1].id; this.data[SPAZCORE_SECTION_SEARCH].lastid = lastid; sc.helpers.dump('this.data['+SPAZCORE_SECTION_SEARCH+'].lastid:'+this.data[SPAZCORE_SECTION_SEARCH].lastid); @@ -13315,7 +13317,7 @@ SpazTwit.prototype._processSearchTimeline = function(search_result, opts, proces concat new items onto data.items array */ this.data[SPAZCORE_SECTION_SEARCH].items = this.data[SPAZCORE_SECTION_SEARCH].items.concat(this.data[SPAZCORE_SECTION_SEARCH].newitems); - + this.data[SPAZCORE_SECTION_SEARCH].items = this.removeDuplicates(this.data[SPAZCORE_SECTION_SEARCH].items); sch.debug('NOT removing extras from search -- we don\'t do that anymore'); // this.data[SPAZCORE_SECTION_SEARCH].items = this.removeExtraElements(this.data[SPAZCORE_SECTION_SEARCH].items, this.data[SPAZCORE_SECTION_SEARCH].max); @@ -13331,42 +13333,42 @@ SpazTwit.prototype._processSearchTimeline = function(search_result, opts, proces 'page' : search_result.page, 'query' : search_result.query }; - + if (opts.success_callback) { opts.success_callback(this.data[SPAZCORE_SECTION_SEARCH].newitems, search_info); } this.triggerEvent(opts.success_event_type, [this.data[SPAZCORE_SECTION_SEARCH].newitems, search_info]); - + } else { // no new items, but we should fire off success anyway - + if (opts.success_callback) { opts.success_callback(null, []); } this.triggerEvent(opts.success_event_type, []); } - + }; SpazTwit.prototype._processSearchItem = function(item, section_name) { - + // remove snowflakeyness item = this.deSnowFlake(item); - + // set service data item.SC_service_baseurl = this.baseurl; item.SC_service = this.getServiceFromBaseURL(this.baseurl); - - + + item.SC_timeline_from = section_name; if (this.username) { item.SC_user_received_by = this.username; } // sc.helpers.dump(item); - + item.SC_is_search = true; /* @@ -13375,30 +13377,30 @@ SpazTwit.prototype._processSearchItem = function(item, section_name) { if (!item.SC_created_at_unixtime) { item.SC_created_at_unixtime = sc.helpers.httpTimeToInt(item.created_at); } - + /* add raw text .SC_raw_text for unmodified text */ if (!item.SC_text_raw) { item.SC_text_raw = item.text; } - + /* add "in_reply_to_screen_name" if it does not exist */ if (!item.in_reply_to_screen_name && item.in_reply_to_user_id) { /** - * @todo get this from the Spaz code + * @todo get this from the Spaz code */ } - + /* add .SC_retrieved_unixtime */ if (!item.SC_retrieved_unixtime) { item.SC_retrieved_unixtime = sc.helpers.getTimeAsInt(); } - + /* normalize so we have as much user data in this object as possible */ @@ -13407,13 +13409,13 @@ SpazTwit.prototype._processSearchItem = function(item, section_name) { 'screen_name':item.from_user, 'id':item.from_user_id }; - + /* The source info here is encoded differently */ item.source = sc.helpers.fromHTMLSpecialChars(item.source); - - + + return item; }; @@ -13437,7 +13439,7 @@ SpazTwit.prototype.getTrends = function(onSuccess, onFailure) { SpazTwit.prototype._processTrends = function(trends_result, opts, processing_opts) { if (!processing_opts) { processing_opts = {}; } - + /* grab the array of items */ @@ -13452,23 +13454,23 @@ SpazTwit.prototype._processTrends = function(trends_result, opts, processing_opt } } // jQuery().trigger(finished_event, [ret_items]); - + if (opts.success_callback) { opts.success_callback(ret_items); } this.triggerEvent(opts.success_event_type, ret_items); - + } }; /** * this is a general wrapper for timeline methods - * @param {obj} opts a set of options for this method + * @param {obj} opts a set of options for this method * @private */ SpazTwit.prototype._getTimeline = function(opts) { - + opts = sch.defaults({ 'method':'GET', 'timeout':this.DEFAULT_TIMEOUT, @@ -13481,22 +13483,22 @@ SpazTwit.prototype._getTimeline = function(opts) { 'success_callback':null, 'failure_callback':null }, opts); - + /* for closure references */ var stwit = this; - + sch.error('_getTimeline opts:'); sch.error(opts); - + var xhr = jQuery.ajax({ 'timeout' :opts.timeout, 'complete':function(xhr, msg){ sch.error(opts.url + ' complete:'+msg); if (msg === 'timeout') { // jQuery().trigger(opts.failure_event_type, [{'url':opts.url, 'xhr':xhr, 'msg':msg}]); - stwit.triggerEvent(opts.failure_event_type, {'url':opts.url, 'xhr':xhr, 'msg':msg}); + stwit.triggerEvent(opts.failure_event_type, {'url':opts.url, 'xhr':xhr, 'msg':msg}); } }, 'error':function(xhr, msg, exc) { @@ -13530,9 +13532,9 @@ SpazTwit.prototype._getTimeline = function(opts) { sc.helpers.dump("opts.failure_event_type:"+opts.failure_event_type); // jQuery().trigger(opts.failure_event_type, [{'url':opts.url, 'xhr':xhr, 'msg':msg}]); stwit.triggerEvent(opts.failure_event_type, {'url':opts.url, 'xhr':xhr, 'msg':msg}); - + } - + } else { sc.helpers.dump("Error:Unknown from "+opts['url']); if (opts.failure_callback) { @@ -13541,12 +13543,12 @@ SpazTwit.prototype._getTimeline = function(opts) { if (opts.failure_event_type) { // jQuery().trigger(opts.failure_event_type, [{'url':opts.url, 'xhr':null, 'msg':'Unknown Error'}]); stwit.triggerEvent(opts.failure_event_type, {'url':opts.url, 'xhr':xhr, 'msg':'Unknown Error'}); - + } } // jQuery().trigger('spaztwit_ajax_error', [{'url':opts.url, 'xhr':xhr, 'msg':msg}]); stwit.triggerEvent('spaztwit_ajax_error', {'url':opts.url, 'xhr':xhr, 'msg':msg}); - + if (opts.processing_opts && opts.processing_opts.combined) { sc.helpers.dump('adding to combined processing errors'); if (xhr && xhr.readyState > 3) { @@ -13554,7 +13556,7 @@ SpazTwit.prototype._getTimeline = function(opts) { } else { stwit.combined_errors.push( {'url':opts.url, 'xhr':null, 'msg':msg, 'section':opts.processing_opts.section} ); } - + stwit.combined_finished[opts.processing_opts.section] = true; sc.helpers.dump(stwit.combined_errors); sc.helpers.dump(stwit.combined_finished); @@ -13562,12 +13564,12 @@ SpazTwit.prototype._getTimeline = function(opts) { opts.process_callback.call(stwit, [], opts, opts.processing_opts); } } - + }, 'success':function(data) { // sc.helpers.dump("Success! \n\n" + data); sch.error(opts.url + ' success!'+" data:"+data); - + try { data = sc.helpers.deJSON(data); } catch(e) { @@ -13588,7 +13590,7 @@ SpazTwit.prototype._getTimeline = function(opts) { } // jQuery().trigger(opts.success_event_type, [data]); stwit.triggerEvent(opts.success_event_type, data); - } + } }, 'beforeSend':function(xhr){ sc.helpers.dump(opts.url + ' beforesend'); @@ -13604,20 +13606,20 @@ SpazTwit.prototype._getTimeline = function(opts) { 'data': opts.data, 'dataType':'text' }); - + return xhr; }; /** - * general processor for timeline data + * general processor for timeline data * @private */ SpazTwit.prototype._processTimeline = function(section_name, ret_items, opts, processing_opts) { - + sch.debug(opts); - + if (!processing_opts) { processing_opts = {}; } if (section_name !== SPAZCORE_SECTION_USER) { // the user timeline section isn't persistent @@ -13625,19 +13627,19 @@ SpazTwit.prototype._processTimeline = function(section_name, ret_items, opts, pr reset .newitems data properties */ this.data[section_name].newitems = []; - + } - - + + if (ret_items == undefined) { sch.error('ret_items is undefined!'); } - + if (ret_items && ret_items.length > 0){ - + var proc_items = []; - + /* we process each item, adding some attributes and generally making it cool */ @@ -13654,8 +13656,8 @@ SpazTwit.prototype._processTimeline = function(section_name, ret_items, opts, pr sort items */ ret_items.sort(this._sortItemsAscending); - - + + if (section_name === SPAZCORE_SECTION_USER) { // special case -- we don't keep this data, just parse and fire it off if (opts.success_callback) { @@ -13663,9 +13665,9 @@ SpazTwit.prototype._processTimeline = function(section_name, ret_items, opts, pr } this.triggerEvent(opts.success_event_type, ret_items); - + } else { // this is a "normal" timeline that we want to be persistent - + if (opts.is_update_item) { /* we do not want this to be the lastid, instead remember it in combined.updates @@ -13693,24 +13695,24 @@ SpazTwit.prototype._processTimeline = function(section_name, ret_items, opts, pr Fire off the new section data event */ if (!processing_opts.combined) { - + if (opts.success_callback) { opts.success_callback(this.data[section_name].newitems); } - + this.triggerEvent(opts.success_event_type, this.data[section_name].items); } else { this.combined_finished[section_name] = true; sc.helpers.dump("this.combined_finished["+section_name+"]:"+this.combined_finished[section_name]); } - + /* add on to newitems array for combined section */ this.data[SPAZCORE_SECTION_COMBINED].newitems = this.data[SPAZCORE_SECTION_COMBINED].newitems.concat(this.data[section_name].newitems); - + } @@ -13721,17 +13723,17 @@ SpazTwit.prototype._processTimeline = function(section_name, ret_items, opts, pr opts.success_callback(); } this.triggerEvent(opts.success_event_type); - + } else { this.combined_finished[section_name] = true; } } - + /* Fire off the new combined data event */ if (this.combinedTimelineFinished()) { - + /* Remove those updates from combined newitems */ @@ -13740,24 +13742,24 @@ SpazTwit.prototype._processTimeline = function(section_name, ret_items, opts, pr /* we do this stuff here to avoid processing repeatedly */ - + this._addToSectionItems(SPAZCORE_SECTION_COMBINED, this.data[SPAZCORE_SECTION_COMBINED].newitems, this._sortItemsByDateAsc); - + // sort these items -- the timelines can be out of order when combined - + // sc.helpers.dump('Removing duplicates in '+SPAZCORE_SECTION_COMBINED+' newitems'); - // + // this.data[SPAZCORE_SECTION_COMBINED].newitems = this._cleanupItemArray(this.data[SPAZCORE_SECTION_COMBINED].newitems, this.data[SPAZCORE_SECTION_COMBINED].max, this._sortItemsByDateAsc); - + if (this.combinedTimelineHasErrors()) { if (opts.failure_callback) { opts.failure_callback(this.combined_errors); } - + this.triggerEvent('error_combined_timeline_data', this.combined_errors); } - + if (opts.success_callback) { opts.success_callback(this.data[SPAZCORE_SECTION_COMBINED].newitems); } @@ -13774,7 +13776,7 @@ SpazTwit.prototype._processTimeline = function(section_name, ret_items, opts, pr * removes dupes, extras, and optionally sorts the section items * @param {string} section_name * @param {array} arr an array of items - * @param {function} sortfunc - optional + * @param {function} sortfunc - optional */ SpazTwit.prototype._addToSectionItems = function(section_name, arr, sortfunc) { // concat new items onto data.items array @@ -13785,12 +13787,12 @@ SpazTwit.prototype._addToSectionItems = function(section_name, arr, sortfunc) { /** * Sorts (optionally), removes dupes, and removes extra items from a given * array of section items - * + * * @param {array} arr * @param {max} integer * @param {func} sortfunc - optional - * - * @return {array} + * + * @return {array} */ SpazTwit.prototype._cleanupItemArray = function(arr, max, sortfunc) { if (sortfunc) { @@ -13805,23 +13807,23 @@ SpazTwit.prototype._cleanupItemArray = function(arr, max, sortfunc) { /** * This modifies a Twitter post, adding some properties. All new properties are * prepended with "SC_" - * - * this executes within the jQuery.each scope, so this === the item + * + * this executes within the jQuery.each scope, so this === the item */ SpazTwit.prototype._processItem = function(item, section_name) { - + // remove snowflakeyness item = this.deSnowFlake(item); - + // set service data item.SC_service_baseurl = this.baseurl; item.SC_service = this.getServiceFromBaseURL(this.baseurl); - + item.SC_timeline_from = section_name; if (this.username) { item.SC_user_received_by = this.username; } - + /* is reply? Then add .SC_is_reply */ @@ -13830,80 +13832,80 @@ SpazTwit.prototype._processItem = function(item, section_name) { item.SC_is_reply = true; } } - + /* is an official API retweet? then add .SC_is_retweet */ if ( item.retweeted_status ) { item.SC_is_retweet = true; } - + /* If it comes from the replies timeline, it's a reply (aka a mention) */ if (section_name === SPAZCORE_SECTION_REPLIES) { item.SC_is_reply = true; } - + /* Does it contain my name? then it's a reply */ if (this.username && sc.helpers.containsScreenName(item.text, this.username) ) { item.SC_is_reply = true; } - + if (item.user) { item.user = this._processUser(item.user); } - - + + /* is dm? */ if (item.recipient_id && item.sender_id) { item.SC_is_dm = true; - + if (item.sender) { item.sender = this._processUser(item.sender); } if (item.recipient) { item.recipient = this._processUser(item.recipient); } - - + + } - - + + /* add unix timestamp .SC_created_at_unixtime for easier date comparison */ if (!item.SC_created_at_unixtime) { item.SC_created_at_unixtime = sc.helpers.httpTimeToInt(item.created_at); } - + /* add raw text .SC_raw_text for unmodified text */ if (!item.SC_text_raw) { item.SC_text_raw = item.text; } - + /* add "in_reply_to_screen_name" if it does not exist */ if (!item.in_reply_to_screen_name && item.in_reply_to_user_id) { /** - * @todo get this from the Spaz code + * @todo get this from the Spaz code */ } - + /* add .SC_retrieved_unixtime */ if (!item.SC_retrieved_unixtime) { item.SC_retrieved_unixtime = sc.helpers.getTimeAsInt(); } - + return item; }; @@ -13912,46 +13914,46 @@ SpazTwit.prototype._processItem = function(item, section_name) { /** * This modifies a Twitter post, adding some properties. All new properties are * prepended with "SC_" - * - * this executes within the jQuery.each scope, so this === the item + * + * this executes within the jQuery.each scope, so this === the item */ SpazTwit.prototype._processUser = function(item, section_name) { - + // remove snowflakeyness item = this.deSnowFlake(item); - + // set service data item.SC_service_baseurl = this.baseurl; item.SC_service = this.getServiceFromBaseURL(this.baseurl); - - + + item.SC_timeline_from = section_name; if (this.username) { item.SC_user_received_by = this.username; } - - + + if (section_name === SPAZCORE_SECTION_FOLLOWERSLIST) { item.SC_is_follower; } if (section_name === SPAZCORE_SECTION_FRIENDLIST) { item.SC_is_followed; } - + /* add unix timestamp .SC_created_at_unixtime for easier date comparison */ if (!item.SC_created_at_unixtime) { item.SC_created_at_unixtime = sc.helpers.httpTimeToInt(item.created_at)/1000; } - + /* add .SC_retrieved_unixtime */ if (!item.SC_retrieved_unixtime) { item.SC_retrieved_unixtime = sc.helpers.getTimeAsInt()/1000; } - + return item; }; @@ -13966,7 +13968,7 @@ SpazTwit.prototype.getEchoHeader = function(opts) { } else { url = this.getAPIURL('verify_credentials'); } - + var method = 'GET'; var auth_header = this.auth.signRequest(method, url, null); @@ -13977,9 +13979,9 @@ SpazTwit.prototype.getEchoHeader = function(opts) { /** * this is a general wrapper for non-timeline methods on the Twitter API. We - * use this to call methods that will return a single response - * - * @param {obj} opts a set of options for this method + * use this to call methods that will return a single response + * + * @param {obj} opts a set of options for this method * @param {string} opts.url The url for the request * @param {string} [opts.method] the HTTP method to use. default is POST * @param {number} [opts.timeout] the timeout for the request. default is 60 seconds @@ -13993,7 +13995,7 @@ SpazTwit.prototype.getEchoHeader = function(opts) { * @param {function} [opts.failure_callback] a callback to fire on failure */ SpazTwit.prototype._callMethod = function(opts) { - + opts = sch.defaults({ 'method':'POST', 'timeout':this.DEFAULT_TIMEOUT, @@ -14005,20 +14007,20 @@ SpazTwit.prototype._callMethod = function(opts) { 'success_callback':null, 'failure_callback':null }, opts); - + var method; - + /* for closure references */ var stwit = this; - + if (opts.method) { method = opts.method; } else { method = 'POST'; } - + var xhr = jQuery.ajax({ 'timeout' :this.opts.timeout, 'complete':function(xhr, msg){ @@ -14045,7 +14047,7 @@ SpazTwit.prototype._callMethod = function(opts) { // jQuery().trigger(opts.failure_event_type, [{'url':opts.url, 'xhr':xhr, 'msg':msg}]); stwit.triggerEvent(opts.failure_event_type, {'url':opts.url, 'xhr':xhr, 'msg':msg}); } - + } else { sc.helpers.dump("Error:Unknown from "+opts['url']); if (opts.failure_callback) { @@ -14076,7 +14078,7 @@ SpazTwit.prototype._callMethod = function(opts) { } // jQuery().trigger(opts.success_event_type, [data]); stwit.triggerEvent(opts.success_event_type, data); - + } }, 'beforeSend':function(xhr){ @@ -14107,9 +14109,9 @@ SpazTwit.prototype.getUser = function(user_id, onSuccess, onFailure) { } else { data.user_id = user_id; } - + var url = this.getAPIURL('show_user'); - + var opts = { 'url':url, 'data':data, @@ -14180,7 +14182,7 @@ SpazTwit.prototype._processFriendsList = function(ret_items, opts, processing_op SpazTwit.prototype.getFollowersList = function(user_id, cursor, onSuccess, onFailure) { var url = this.getAPIURL('followerslist'); - + var data = {}; if (sch.isString(user_id) && user_id.indexOf('@') === 0) { @@ -14188,7 +14190,7 @@ SpazTwit.prototype.getFollowersList = function(user_id, cursor, onSuccess, onFai } else { data.user_id = user_id; } - + if (cursor) { data.cursor = cursor; } else { @@ -14222,9 +14224,9 @@ SpazTwit.prototype._processFollowersList = function(ret_items, opts, processing_ * @private */ SpazTwit.prototype._processUserList = function(section_name, ret_items, opts, processing_opts) { - + var users = [], next = -1, prev = -1; - + if (!processing_opts) { processing_opts = {}; } if (ret_items.users) { @@ -14243,8 +14245,8 @@ SpazTwit.prototype._processUserList = function(section_name, ret_items, opts, pr users[k] = this._processUser(users[k], section_name); sch.dump(users[k]); } - - + + // set lastid var lastid = users[users.length-1].id; this.data[section_name].lastid = lastid; @@ -14273,9 +14275,9 @@ SpazTwit.prototype._processUserList = function(section_name, ret_items, opts, pr SpazTwit.prototype.addFriend = function(user_id, onSuccess, onFailure) { var data = {}; data['id'] = user_id; - + var url = this.getAPIURL('friendship_create', data); - + var opts = { 'url':url, 'success_event_type':'create_friendship_succeeded', @@ -14293,9 +14295,9 @@ SpazTwit.prototype.addFriend = function(user_id, onSuccess, onFailure) { SpazTwit.prototype.removeFriend = function(user_id, onSuccess, onFailure) { var data = {}; data['id'] = user_id; - + var url = this.getAPIURL('friendship_destroy', data); - + var opts = { 'url':url, 'success_event_type':'destroy_friendship_succeeded', @@ -14313,32 +14315,32 @@ SpazTwit.prototype.removeFriend = function(user_id, onSuccess, onFailure) { }; /** - * @param {string|number} target_id the target user id, or screen name if prefixed with a "@" - * @param {string|number} [source_id] the surce user id, or screen name if prefixed with a "@" + * @param {string|number} target_id the target user id, or screen name if prefixed with a "@" + * @param {string|number} [source_id] the surce user id, or screen name if prefixed with a "@" * @param {function} [onSuccess] success callback * @param {function} [onFailure] failure callback */ SpazTwit.prototype.showFriendship = function(target_id, source_id, onSuccess, onFailure) { var data = {}; - + if (sch.isString(target_id) && target_id.indexOf('@')===0) { data['target_screen_name'] = target_id.substr(1); } else { data['target_id'] = target_id; } - + if (source_id) { if (sch.isString(source_id) && source_id.indexOf('@')===0) { data['source_screen_name'] = source_id.substr(1); } else { data['source_id'] = source_id; } - + } - - + + var url = this.getAPIURL('friendship_show', data); - + var opts = { 'url':url, 'method':'GET', @@ -14362,9 +14364,9 @@ SpazTwit.prototype.getIncomingFriendships = function(cursor, onSuccess, onFailur cursor = -1; } data['cursor'] = cursor; - + var url = this.getAPIURL('friendship_incoming', data); - + var opts = { 'url':url, 'method':'GET', @@ -14388,9 +14390,9 @@ SpazTwit.prototype.getOutgoingFriendships = function(cursor, onSuccess, onFailur cursor = -1; } data['cursor'] = cursor; - + var url = this.getAPIURL('friendship_outgoing', data); - + var opts = { 'url':url, 'method':'GET', @@ -14415,9 +14417,9 @@ SpazTwit.prototype.getFriendsGraph = function(user_id, cursor, onSuccess, onFail } data['cursor'] = cursor; data['user_id'] = user_id; - + var url = this.getAPIURL('graph_friends', data); - + var opts = { 'url':url, 'method':'GET', @@ -14442,9 +14444,9 @@ SpazTwit.prototype.getFollowersGraph = function(user_id, cursor, onSuccess, onFa } data['cursor'] = cursor; data['user_id'] = user_id; - + var url = this.getAPIURL('graph_followers', data); - + var opts = { 'url':url, 'method':'GET', @@ -14465,9 +14467,9 @@ SpazTwit.prototype.getFollowersGraph = function(user_id, cursor, onSuccess, onFa SpazTwit.prototype.block = function(user_id, onSuccess, onFailure) { var data = {}; data['id'] = user_id; - + var url = this.getAPIURL('block_create', data); - + var opts = { 'url':url, 'success_event_type':'create_block_succeeded', @@ -14486,9 +14488,9 @@ SpazTwit.prototype.block = function(user_id, onSuccess, onFailure) { SpazTwit.prototype.unblock = function(user_id, onSuccess, onFailure) { var data = {}; data['id'] = user_id; - + var url = this.getAPIURL('block_destroy', data); - + var opts = { 'url':url, 'success_event_type':'destroy_block_succeeded', @@ -14508,9 +14510,9 @@ SpazTwit.prototype.unblock = function(user_id, onSuccess, onFailure) { SpazTwit.prototype.follow = function(user_id, onSuccess, onFailure) { // to add notification var data = {}; data['id'] = user_id; - + var url = this.getAPIURL('follow', data); - + var opts = { 'url':url, 'username':this.username, @@ -14526,15 +14528,15 @@ SpazTwit.prototype.follow = function(user_id, onSuccess, onFailure) { // to add Perform a request and get true or false back */ var xhr = this._callMethod(opts); - + }; SpazTwit.prototype.unfollow = function(user_id, onSuccess, onFailure) { // to remove notification var data = {}; data['id'] = user_id; - + var url = this.getAPIURL('unfollow', data); - + var opts = { 'url':url, 'username':this.username, @@ -14550,14 +14552,14 @@ SpazTwit.prototype.unfollow = function(user_id, onSuccess, onFailure) { // to re Perform a request and get true or false back */ var xhr = this._callMethod(opts); - + }; SpazTwit.prototype.update = function(status, source, in_reply_to_status_id, onSuccess, onFailure) { var url = this.getAPIURL('update'); - + var data = {}; if (in_reply_to_status_id) { data.in_reply_to_status_id = in_reply_to_status_id; @@ -14568,7 +14570,7 @@ SpazTwit.prototype.update = function(status, source, in_reply_to_status_id, onSu data.source = this.source; } data.status = status; - + var opts = { 'url':url, 'data':data, @@ -14584,35 +14586,35 @@ SpazTwit.prototype.update = function(status, source, in_reply_to_status_id, onSu */ var xhr = this._callMethod(opts); - + }; SpazTwit.prototype._processUpdateReturn = function(data, opts) { - + /* Add this to the HOME section and fire off the event when done - */ + */ opts.is_update_item = true; this._processTimeline(SPAZCORE_SECTION_HOME, [data], opts); }; /** - * @param {string|number} user_id a string or number. if a screen name, prefix with '@'; else assumed to be a numeric user_id + * @param {string|number} user_id a string or number. if a screen name, prefix with '@'; else assumed to be a numeric user_id * @param {string} text the message to send to the user_id */ SpazTwit.prototype.sendDirectMessage = function(user_id, text, onSuccess, onFailure) { var url = this.getAPIURL('dm_new'); - + var data = {}; - + if (sch.isString(user_id) && user_id.indexOf('@') === 0) { data.screen_name = user_id.substr(1); } else { data.user_id = user_id; } - + data.text = text; - + var opts = { 'url':url, 'data':data, @@ -14631,14 +14633,14 @@ SpazTwit.prototype.sendDirectMessage = function(user_id, text, onSuccess, onFail /** * destroy/delete a status - * @param {Number|String} id the id of the status + * @param {Number|String} id the id of the status */ SpazTwit.prototype.destroy = function(id, onSuccess, onFailure) { var data = {}; data['id'] = id; - + var url = this.getAPIURL('destroy_status', data); - + var opts = { 'url':url, 'data':data, @@ -14656,14 +14658,14 @@ SpazTwit.prototype.destroy = function(id, onSuccess, onFailure) { /** * destroy/delete a direct message - * @param {Number|String} id the id of the status + * @param {Number|String} id the id of the status */ SpazTwit.prototype.destroyDirectMessage = function(id, onSuccess, onFailure) { var data = {}; data['id'] = id; - + var url = this.getAPIURL('dm_destroy', data); - + var opts = { 'url':url, 'data':data, @@ -14683,9 +14685,9 @@ SpazTwit.prototype.destroyDirectMessage = function(id, onSuccess, onFailure) { SpazTwit.prototype.getOne = function(id, onSuccess, onFailure) { var data = {}; data['id'] = id; - + var url = this.getAPIURL('show', data); - + var opts = { 'url':url, 'process_callback': this._processOneItem, @@ -14704,7 +14706,7 @@ SpazTwit.prototype.getOne = function(id, onSuccess, onFailure) { SpazTwit.prototype._processOneItem = function(data, opts) { - + /* this item needs to be added to the friends timeline so we can avoid dupes @@ -14714,14 +14716,14 @@ SpazTwit.prototype._processOneItem = function(data, opts) { opts.success_callback(data); } this.triggerEvent(opts.success_event_type, data); - + }; /** * get related messages to the given message id - * + * * @param {string|number} id message id * @param {function} onSuccess callback function(data) * @param {function} onFailure callback function(xhr, message, exc) @@ -14729,9 +14731,9 @@ SpazTwit.prototype._processOneItem = function(data, opts) { SpazTwit.prototype.getRelated = function(id, onSuccess, onFailure) { var data = {}; data['id'] = id; - + var url = this.getAPIURL('show_related', data); - + var opts = { 'url':url, 'success_event_type':'get_related_success', @@ -14757,13 +14759,13 @@ SpazTwit.prototype.getRelated = function(id, onSuccess, onFailure) { * Retweets a tweet. * id: the numeric id of a tweet */ - + SpazTwit.prototype.retweet = function(id, onSuccess, onFailure) { var data = {}; data['id'] = id; - + var url = this.getAPIURL('retweet', data); - + var opts = { 'url' : url, 'username' : this.username, @@ -14774,7 +14776,7 @@ SpazTwit.prototype.retweet = function(id, onSuccess, onFailure) { 'failure_callback' : onFailure, 'data' : data }; - + var xhr = this._callMethod(opts); }; @@ -14789,7 +14791,7 @@ SpazTwit.prototype.getRetweets = function(id, count) { 'id' : id, 'count' : count }); - + var opts = { 'url' : url, 'username' : this.username, @@ -14798,7 +14800,7 @@ SpazTwit.prototype.getRetweets = function(id, count) { 'failure_event_Type' : 'get_retweets_failed', 'method' : 'GET' }; - + var xhr = this._getTimeline(opts); }; @@ -14809,7 +14811,7 @@ SpazTwit.prototype.getRetweets = function(id, count) { * count: the number of tweets to return. Cannot be over 200. * page: the page of results to return. */ - + SpazTwit.prototype.retweetedByMe = function(since, max, count, page){ var params = {}; if(since != null){ @@ -14827,7 +14829,7 @@ SpazTwit.prototype.retweetedByMe = function(since, max, count, page){ } params['page'] = page; var url = this.getAPIURL('retweeted_by_me', params); - + var opts = { 'url' : url, 'username' : this.username, @@ -14836,7 +14838,7 @@ SpazTwit.prototype.retweetedByMe = function(since, max, count, page){ 'failure_event_type' : 'retweeted_by_me_failed', 'method' : 'GET' }; - + var xhr = this._getTimeline(opts); }; @@ -14847,7 +14849,7 @@ SpazTwit.prototype.retweetedByMe = function(since, max, count, page){ * count: the number of tweets to return. Cannot be over 200. * page: the page of results to return. */ - + SpazTwit.prototype.retweetedToMe = function(since, max, count, page){ var params = {}; if(since != null){ @@ -14865,7 +14867,7 @@ SpazTwit.prototype.retweetedToMe = function(since, max, count, page){ } params['page'] = page; var url = this.getAPIURL('retweeted_to_me', params); - + var opts = { 'url' : url, 'username' : this.username, @@ -14874,7 +14876,7 @@ SpazTwit.prototype.retweetedToMe = function(since, max, count, page){ 'failure_event_type' : 'retweeted_to_me_failed', 'method' : 'GET' }; - + var xhr = this._getTimeline(opts); }; @@ -14885,7 +14887,7 @@ SpazTwit.prototype.retweetedToMe = function(since, max, count, page){ * count: the number of tweets to return. Cannot be over 200. * page: the page of results to return. */ - + SpazTwit.prototype.retweetsOfMe = function(since, max, count, page){ var params = {}; if(since != null){ @@ -14903,7 +14905,7 @@ SpazTwit.prototype.retweetsOfMe = function(since, max, count, page){ } params['page'] = page; var url = this.getAPIURL('retweets_of_me', params); - + var opts = { 'url' : url, 'username' : this.username, @@ -14912,16 +14914,16 @@ SpazTwit.prototype.retweetsOfMe = function(since, max, count, page){ 'failure_event_type' : 'retweets_of_me_failed', 'method' : 'GET' }; - + var xhr = this._getTimeline(opts); }; SpazTwit.prototype.favorite = function(id, onSuccess, onFailure) { var data = {}; data['id'] = id; - + var url = this.getAPIURL('favorites_create', data); - + var opts = { 'url':url, 'success_event_type':'create_favorite_succeeded', @@ -14940,9 +14942,9 @@ SpazTwit.prototype.favorite = function(id, onSuccess, onFailure) { SpazTwit.prototype.unfavorite = function(id, onSuccess, onFailure) { var data = {}; data['id'] = id; - + var url = this.getAPIURL('favorites_destroy', data); - + var opts = { 'url':url, 'success_event_type':'destroy_favorite_succeeded', @@ -14964,11 +14966,11 @@ SpazTwit.prototype.unfavorite = function(id, onSuccess, onFailure) { SpazTwit.prototype.updateLocation = function(location_str, onSuccess, onFailure) { var data = {}; data.location = location_str; - + this.setBaseURL(SPAZCORE_SERVICEURL_TWITTER); - + var url = this.getAPIURL('update_profile'); - + var opts = { 'url':url, 'success_event_type':'update_location_succeeded', @@ -14985,20 +14987,20 @@ SpazTwit.prototype.updateLocation = function(location_str, onSuccess, onFailure) }; SpazTwit.prototype.updateProfile = function(name, email, url, location, description) { - + }; /** * get the current rate limit status - * @param {Function} onSuccess callback for success - * @param {Function} onFailure callback for failure + * @param {Function} onSuccess callback for success + * @param {Function} onFailure callback for failure */ SpazTwit.prototype.getRateLimitStatus = function(onSuccess, onFailure) { - + var url = this.getAPIURL('ratelimit_status'); - + var opts = { 'method':'GET', 'url':url, @@ -15012,29 +15014,29 @@ SpazTwit.prototype.getRateLimitStatus = function(onSuccess, onFailure) { Perform a request and get true or false back */ var xhr = this._callMethod(opts); - + }; SpazTwit.prototype.test = function() {}; /** - * @private + * @private */ SpazTwit.prototype._postProcessURL = function(url) { - - if (typeof Mojo !== "undefined") { // we're in webOS + + if (typeof Mojo !== "undefined") { // we're in webOS if (use_palmhost_proxy) { // we are not on an emu or device, so proxy calls var re = /https?:\/\/.[^\/:]*(?::[0-9]+)?/; var match = url.match(re); if (match && match[0] !== Mojo.hostingPrefix) { url = "/proxy?url=" + encodeURIComponent(url); } - return url; + return url; } else { return url; } - + } else { return url; } @@ -15043,8 +15045,8 @@ SpazTwit.prototype._postProcessURL = function(url) { /** * sorting function for an array of tweets. Asc by ID. - * - * Example: itemsarray.sort(this._sortItemsAscending) + * + * Example: itemsarray.sort(this._sortItemsAscending) * @param {object} a a twitter message object * @param {object} b a twitter message object * @return {integer} @@ -15064,8 +15066,8 @@ SpazTwit.prototype._sortItemsAscending = function(a,b) { /** * sorting function for an array of tweets. Desc by ID. - * - * Example: itemsarray.sort(this._sortItemsDescending) + * + * Example: itemsarray.sort(this._sortItemsDescending) * @param {object} a a twitter message object * @param {object} b a twitter message object * @return {integer} @@ -15088,10 +15090,10 @@ SpazTwit.prototype._sortItemsDescending = function(a,b) { /** * sorting function for an array of tweets. Asc by date. - * + * * requires SpazCore helpers/datetime.js for httpTimeToInt() - * - * Example: itemsarray.sort(this._sortItemsByDateAsc) + * + * Example: itemsarray.sort(this._sortItemsByDateAsc) * @param {object} a a twitter message object * @param {object} b a twitter message object * @return {integer} @@ -15105,12 +15107,12 @@ SpazTwit.prototype._sortItemsByDateAsc = function(a,b) { /** * sorting function for an array of tweets. Desc by date. - * + * * requires SpazCore helpers/datetime.js for httpTimeToInt() - * + * * Example: itemsarray.sort(this._sortItemsByDateDesc) * @param {object} a a twitter message object - * @param {object} b a twitter message object + * @param {object} b a twitter message object * @return {integer} * @private */ @@ -15123,20 +15125,20 @@ SpazTwit.prototype._sortItemsByDateDesc = function(a,b) { /** * this takes an array of messages and returns one with any duplicates removed - * + * * This is based on the jQuery.unique() method - * + * * @param {array} array an array of Twitter message objects * @return {array} */ SpazTwit.prototype.removeDuplicates = function(arr) { - + var ret = [], done = {}, length = arr.length; try { for ( var i = 0; i < length; i++ ) { var id = arr[i].id; - + if ( !done[ id ] ) { done[ id ] = true; ret.push( arr[ i ] ); @@ -15150,7 +15152,7 @@ SpazTwit.prototype.removeDuplicates = function(arr) { ret = arr; } return ret; - + }; @@ -15158,17 +15160,17 @@ SpazTwit.prototype.removeDuplicates = function(arr) { * removes extra elements from a timeline array. * @param {array} items the timeline array * @param {integer} max the max # of items we should have - * @param {boolean} remove_from_top whether or not to remove extra items from the top. default is FALSE + * @param {boolean} remove_from_top whether or not to remove extra items from the top. default is FALSE */ SpazTwit.prototype.removeExtraElements = function(items, max, remove_from_top) { - + if (!remove_from_top) { remove_from_top = false; } - + var diff = items.length - max; if (diff > 0) { - + if (!remove_from_top) { sc.helpers.dump("array length is " + items.length + " > " + max + "; removing last " + diff + " entries"); items.splice(diff * -1, diff); @@ -15177,17 +15179,17 @@ SpazTwit.prototype.removeExtraElements = function(items, max, remove_from_top) { items.splice(0, diff); } } - + return items; }; /** - * gets the saved searches the authenticating user has + * gets the saved searches the authenticating user has */ SpazTwit.prototype.getSavedSearches = function(onSuccess, onFailure) { var url = this.getAPIURL('saved_searches'); - + var opts = { 'url':url, 'success_event_type':'new_saved_searches_data', @@ -15205,12 +15207,12 @@ SpazTwit.prototype.getSavedSearches = function(onSuccess, onFailure) { /** * Saves the search query to the Twitter servers - * - * @param {String} search_query + * + * @param {String} search_query */ SpazTwit.prototype.addSavedSearch = function(search_query, onSuccess, onFailure) { var url = this.getAPIURL('saved_searches_create'); - + var opts = { 'url':url, 'success_event_type':'create_saved_search_succeeded', @@ -15225,17 +15227,17 @@ SpazTwit.prototype.addSavedSearch = function(search_query, onSuccess, onFailure) Perform a request and get true or false back */ var xhr = this._callMethod(opts); - + }; /** * Delete the saved search corresponding to the given ID - * + * * @param {String} search_id Note that this is converted to a string via search_id.toString() */ SpazTwit.prototype.removeSavedSearch = function(search_id, onSuccess, onFailure) { var url = this.getAPIURL('saved_searches_destroy', search_id.toString()); - + var opts = { 'url':url, 'success_event_type':'destroy_saved_search_succeeded', @@ -15245,7 +15247,7 @@ SpazTwit.prototype.removeSavedSearch = function(search_id, onSuccess, onFailure) 'data':{'id':search_id}, 'method':'POST' }; - + sch.debug('opts for removeSavedSearch'); sch.debug(opts); @@ -15253,14 +15255,14 @@ SpazTwit.prototype.removeSavedSearch = function(search_id, onSuccess, onFailure) Perform a request and get true or false back */ var xhr = this._callMethod(opts); - + }; /** - * retrieves the list of lists + * retrieves the list of lists */ SpazTwit.prototype.getLists = function(user, onSuccess, onFailure) { if (!user && !this.username) { @@ -15272,7 +15274,7 @@ SpazTwit.prototype.getLists = function(user, onSuccess, onFailure) { var url = this.getAPIURL('lists', { 'user':user }); - + var opts = { 'url':url, 'success_event_type':'get_lists_succeeded', @@ -15293,7 +15295,7 @@ SpazTwit.prototype.getLists = function(user, onSuccess, onFailure) { * @private */ SpazTwit.prototype._processUserLists = function(section_name, ret_items, opts, processing_opts) { - + if (!processing_opts) { processing_opts = {}; } if (ret_items.length > 0){ @@ -15326,7 +15328,7 @@ SpazTwit.prototype._processUserLists = function(section_name, ret_items, opts, p this.triggerEvent(opts.success_event_type, this.data[section_name].newitems ); } else { // no new items, but we should fire off success anyway - + if (opts.success_callback) { opts.success_callback(); } @@ -15337,38 +15339,38 @@ SpazTwit.prototype._processUserLists = function(section_name, ret_items, opts, p /** * This modifies a Twitter user list, adding some properties. All new properties are * prepended with "SC_" - * - * this executes within the jQuery.each scope, so this === the item + * + * this executes within the jQuery.each scope, so this === the item */ -SpazTwit.prototype._processList = function(item, section_name) { +SpazTwit.prototype._processList = function(item, section_name) { /* add .SC_retrieved_unixtime */ if (!item.SC_retrieved_unixtime) { item.SC_retrieved_unixtime = sc.helpers.getTimeAsInt(); } - + return item; }; /** * retrieves a given list timeline - * @param {string} list + * @param {string} list */ SpazTwit.prototype.getListInfo = function(list, user, onSuccess, onFailure) { if (!user && !this.username) { sch.error('must pass a username or have one set to get list'); return; } - + user = user || this.username; var url = this.getAPIURL('lists_list', { 'user':user, 'slug':list }); - + var opts = { 'url':url, 'success_event_type':'get_list_succeeded', @@ -15384,7 +15386,7 @@ SpazTwit.prototype.getListInfo = function(list, user, onSuccess, onFailure) { /** * retrieves a given list timeline - * @param {string} list + * @param {string} list * @param {string} user the user who owns this list * @param {function} [onSuccess] function to call on success * @param {function} [onFailure] function to call on failure @@ -15394,14 +15396,14 @@ SpazTwit.prototype.getListTimeline = function(list, user, onSuccess, onFailure) sch.error('must pass a username or have one set to get list'); return; } - + user = user || this.username; var url = this.getAPIURL('lists_timeline', { 'user':user, 'slug':list }); - + var opts = { 'url':url, 'success_event_type':'get_list_timeline_succeeded', @@ -15422,21 +15424,21 @@ SpazTwit.prototype.getListTimeline = function(list, user, onSuccess, onFailure) SpazTwit.prototype._processListTimeline = function(data, opts, processing_opts) { if (!processing_opts) { processing_opts = {}; } - + var user = processing_opts.user || null; var slug = processing_opts.slug || null; - + var rdata = { 'statuses':data, 'user':user, 'slug':slug }; - + /* grab the array of items */ // jQuery().trigger(finished_event, [ret_items]); - + if (opts.success_callback) { opts.success_callback(rdata); } @@ -15445,21 +15447,21 @@ SpazTwit.prototype._processListTimeline = function(data, opts, processing_opts) /** * retrieves a given list's members - * @param {string} list + * @param {string} list */ SpazTwit.prototype.getListMembers = function(list, user) { if (!user && !this.username) { sch.error('must pass a username or have one set to get list'); return; } - + user = user || this.username; var url = this.getAPIURL('lists_members', { 'user':user, 'slug':list }); - + var opts = { 'url':url, 'success_event_type':'get_list_members_succeeded', @@ -15486,11 +15488,11 @@ SpazTwit.prototype.addList = function(list, visibility, description) { data['name'] = list; data['mode'] = visibility; data['description'] = description; - + var url = this.getAPIURL('lists', { 'user': this.username }); - + var opts = { 'url':url, 'success_event_type':'create_list_succeeded', @@ -15499,7 +15501,7 @@ SpazTwit.prototype.addList = function(list, visibility, description) { 'failure_callback':null, 'data':data }; - + var xhr = this._callMethod(opts); }; @@ -15508,12 +15510,12 @@ SpazTwit.prototype.updateList = function(list, name, visibility, description){ data['name'] = name; data['mode'] = visibility; data['description'] = description; - + var url = this.getAPIURL('lists_list', { 'user': this.username, 'slug': list }); - + var opts = { 'url':url, 'username':this.username, @@ -15522,35 +15524,35 @@ SpazTwit.prototype.updateList = function(list, name, visibility, description){ 'failure_event_type':'update_list_failed', 'data':data }; - + var xhr = this._callMethod(opts); }; /** * delete a list - * @param {string} list The list name + * @param {string} list The list name */ SpazTwit.prototype.removeList = function(list, user) { - + if (!user && !this.username) { sch.error('must pass a username or have one set to remove list'); return; } - + user = user || this.username; - + var url = this.getAPIURL('lists_list', { 'user': user, 'slug':list }); - + var opts = { 'url':url, 'success_event_type':'remove_list_succeeded', 'failure_event_type':'remove_list_failed', 'method':'DELETE' }; - + var xhr = this._callMethod(opts); }; @@ -15561,51 +15563,51 @@ SpazTwit.prototype.addUserToList = function(user, list, list_user) { var data = {}; data['list_id'] = list; data['id'] = list_user; - - + + if (!user && !this.username) { sch.error('must pass a username or have one set to add a user to a list'); return; } - + user = user || this.username; - + var url = this.getAPIURL('lists_members', { 'user': user, 'slug': list }); - + var opts = { 'url':url, 'success_event_type':'add_list_user_succeeded', 'failure_event_type':'add_list_user_failed', 'data':data }; - + var xhr = this._callMethod(opts); }; /** - * delete a user from a list + * delete a user from a list */ SpazTwit.prototype.removeUserFromList = function(user, list, list_user) { var data = {}; data['list_id'] = list; data['id'] = list_user; - - + + if (!user && !this.username) { sch.error('must pass a username or have one set to remove a user from a list'); return; } - + user = user || this.username; - + var url = this.getAPIURL('lists_members', { 'user': user, 'slug': list }); - + var opts = { 'url':url, 'success_event_type':'create_list_succeeded', @@ -15615,7 +15617,7 @@ SpazTwit.prototype.removeUserFromList = function(user, list, list_user) { 'data':data, 'method':'DELETE' }; - + var xhr = this._callMethod(opts); }; @@ -15625,13 +15627,13 @@ SpazTwit.prototype.listsSubscribedTo = function(user) { sch.error('must pass a username or have one set to retrieve subscribed lists'); return false; } - + user = user || this.username; - + var url = this.getAPIURL('lists_subscriptions', { 'user': user }); - + var opts = { 'url':url, 'username': this.username, @@ -15639,7 +15641,7 @@ SpazTwit.prototype.listsSubscribedTo = function(user) { 'success_event_type':'get_subscriptions_succeeded', 'failure_event_type':'get_subscriptions_failed' }; - + var xhr = this._callMethod(opts); }; @@ -15648,13 +15650,13 @@ SpazTwit.prototype.listMemberships = function(user) { sch.error('must pass a username or have one set to retrieve list memberships'); return false; } - + user = user || this.username; - + var url = this.getAPIURL('lists_memberships', { 'user': user }); - + var opts = { 'url':url, 'username': this.username, @@ -15662,7 +15664,7 @@ SpazTwit.prototype.listMemberships = function(user) { 'success_event_type':'get_list_memberships_succeeded', 'failure_event_type':'get_list_memberships_failed' }; - + var xhr = this._callMethod(opts); }; @@ -15671,14 +15673,14 @@ SpazTwit.prototype.getListSubscribers = function(list, user){ sch.error('must pass a username or have one set to retrieve list subscribers'); return false; } - + user = user || this.username; - + var url = this.getAPIURL('lists_subscribers', { 'user': user, 'slug': list }); - + var opts = { 'url':url, 'username': this.username, @@ -15687,7 +15689,7 @@ SpazTwit.prototype.getListSubscribers = function(list, user){ 'failure_event_type':'get_list_subscribers_failed', 'method':'GET' }; - + var xhr = this._callMethod(opts); }; @@ -15696,15 +15698,15 @@ SpazTwit.prototype.isSubscribed = function(list, list_user, user){ sch.error('must pass a username or have one set to retrieve list subscribers'); return false; } - + user = user || this.username; - + var url = this.getAPIURL('lists_check_subscriber', { 'user': user, 'slug': list, 'id': list_user }); - + var opts = { 'url':url, 'username': this.username, @@ -15713,7 +15715,7 @@ SpazTwit.prototype.isSubscribed = function(list, list_user, user){ 'failure_event_type':'check_list_subscribers_failed', 'method':'GET' }; - + var xhr = this._callMethod(opts); }; @@ -15722,14 +15724,14 @@ SpazTwit.prototype.subscribe = function(list, user){ sch.error('must pass a username or have one set to subscribe to a list'); return false; } - + user = user || this.username; - + var url = this.getAPIURL('lists_subscribers', { 'user': user, 'slug': list }); - + var opts = { 'url':url, 'username': this.username, @@ -15738,7 +15740,7 @@ SpazTwit.prototype.subscribe = function(list, user){ 'failure_event_type':'list_subscribe_failed', 'method':'POST' }; - + var xhr = this._callMethod(opts); }; @@ -15747,15 +15749,15 @@ SpazTwit.prototype.unsubscribe = function(list, user){ sch.error('must pass a username or have one set to unsubscribe'); return false; } - + user = user || this.username; - + var url = this.getAPIURL('lists_subscribers', { 'user': user, 'slug': list, 'id': list_user }); - + var opts = { 'url':url, 'username': this.username, @@ -15764,7 +15766,7 @@ SpazTwit.prototype.unsubscribe = function(list, user){ 'failure_event_type':'list_unsubscribe_failed', 'method':'DELETE' }; - + var xhr = this._callMethod(opts); }; @@ -15773,15 +15775,15 @@ SpazTwit.prototype.isMember = function(list, list_user, user){ sch.error('must pass a username or have one set to retrieve list memberships'); return false; } - + user = user || this.username; - + var url = this.getAPIURL('lists_check_member', { 'user': user, 'slug': list, 'id': list_user }); - + var opts = { 'url':url, 'username': this.username, @@ -15790,7 +15792,7 @@ SpazTwit.prototype.isMember = function(list, list_user, user){ 'failure_event_type':'check_list_members_failed', 'method':'GET' }; - + var xhr = this._callMethod(opts); }; @@ -15802,10 +15804,10 @@ SpazTwit.prototype.isMember = function(list, list_user, user){ */ SpazTwit.prototype.reportSpam = function(user_id, onSuccess, onFailure) { var url = this.getAPIURL('report_spam'); - + var data = {}; data['user_id'] = user_id; - + var opts = { 'url':url, 'username': this.username, @@ -15817,7 +15819,7 @@ SpazTwit.prototype.reportSpam = function(user_id, onSuccess, onFailure) { 'method':'POST', 'data':data }; - + var xhr = this._callMethod(opts); }; @@ -15830,7 +15832,7 @@ SpazTwit.prototype.openUserStream = function(onData, onFailure) { close existing stream */ this.closeUserStream(); - + /* open new stream */ @@ -15842,7 +15844,7 @@ SpazTwit.prototype.openUserStream = function(onData, onFailure) { if (data) { sch.debug('new stream data:'+data); item = sch.deJSON(data); - + if (item.source && item.user && item.text) { // is "normal" status item = that._processItem(item, SPAZCORE_SECTION_HOME); if (onData) { @@ -15856,7 +15858,7 @@ SpazTwit.prototype.openUserStream = function(onData, onFailure) { onData(item); } } - + } } }); @@ -15883,23 +15885,23 @@ SpazTwit.prototype.userStreamExists = function() { /** - * scans an object for _str values and assigns them back to the non-string id properties + * scans an object for _str values and assigns them back to the non-string id properties */ SpazTwit.prototype.deSnowFlake = function(obj) { - + if (obj.id_str) { obj.id = obj.id_str; } - + if (obj.in_reply_to_user_id_str) { obj.in_reply_to_user_id = obj.in_reply_to_user_id_str; } - + if (obj.in_reply_to_status_id_str) { obj.in_reply_to_status_id = obj.in_reply_to_status_id_str; } - - // search item stuff + + // search item stuff if (obj.to_user_id_str) { obj.to_user_id = obj.to_user_id_str; } @@ -15907,49 +15909,49 @@ SpazTwit.prototype.deSnowFlake = function(obj) { if (obj.from_user_id_str) { obj.from_user_id = obj.from_user_id_str; } - + // descend into the underworld if (obj.user) { obj.user = this.deSnowFlake(obj.user); } - + if (obj.recipient) { obj.recipient = this.deSnowFlake(obj.recipient); } - + if (obj.sender) { obj.sender = this.deSnowFlake(obj.sender); } - + if (obj.retweeted_status) { obj.retweeted_status = this.deSnowFlake(obj.retweeted_status); } - + return obj; }; /** - * + * */ SpazTwit.prototype.triggerEvent = function(type, data) { var target = this.opts.event_target || document; data = data || null; - + sc.helpers.dump('TriggerEvent: target:'+target.toString()+ ' type:'+type+ ' data:'+data); - + if (this.opts.event_mode === 'jquery') { data = [data]; jQuery(target).trigger(type, data); } else { - sc.helpers.trigger(type, target, data); + sc.helpers.trigger(type, target, data); } - + }; /** * shortcut for SpazTwit if the SpazCore libraries are being used - * + * */ if (sc) { var scTwit = SpazTwit; @@ -15957,11 +15959,11 @@ if (sc) { /** * THIS IS NOT FINISHED - * + * * returns the current geocode location as a string and the full object as second param - * + * * raises events: 'location_retrieved_success', 'location_retrieved_error' - * + * * @param {Object} controller a Mojo scene controller * @param {Function} onsuccess * @param {Function} onerror @@ -15994,14 +15996,14 @@ sc.helpers.getCurrentLocation = function(onsuccess, onerror) { onFailure:error } ); -};/*jslint +};/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc, Mojo, use_palmhost_proxy; @@ -16015,13 +16017,13 @@ var sc, Mojo, use_palmhost_proxy; * sceneAssistant:{} // REQ; the sceneAssistant we're firing the service req from * } * extra:{...} // extra post fields (text/plain only atm) - * } - * @param Function onSuccess + * } + * @param Function onSuccess */ sc.helpers.HTTPUploadFile = function(opts, onSuccess, onFailure) { - + sch.debug('in HTTPUploadFile ================!!!!!!!!!!!!!!'); - + opts = sch.defaults({ 'method':'POST', 'content_type':'img', @@ -16033,7 +16035,7 @@ sc.helpers.HTTPUploadFile = function(opts, onSuccess, onFailure) { 'username':null, 'password':null }, opts); - + var key, val, postparams = [], customHttpHeaders = []; var file_url = opts.file_url || null; var url = opts.url || null; @@ -16046,29 +16048,29 @@ sc.helpers.HTTPUploadFile = function(opts, onSuccess, onFailure) { postparams.push({ 'key' :key, 'data':val, contentType:'text/plain' }); } } - + if (opts.username) { postparams.push({ 'key' :'username', 'data':opts.username, contentType:'text/plain' }); } if (opts.password) { postparams.push({ 'key' :'password', 'data':opts.password, contentType:'text/plain' }); } - - + + if (opts.platform) { var sceneAssistant = opts.platform.sceneAssistant; } else { sch.error('You must pass the opts.platform.sceneAssistant argument to upload on webOS'); return; } - + var headers = []; if (opts.headers) { for(key in opts.headers) { customHttpHeaders.push( key + ': ' + opts.headers[key] ); } } - + sch.debug('OPTS ============='); sch.debug(opts); sch.debug('OPTS.EXTRA ============='); @@ -16084,16 +16086,16 @@ sc.helpers.HTTPUploadFile = function(opts, onSuccess, onFailure) { var onSuccessCheck = function(resp) { if (resp.completed) { // we're actually done - onSuccess(resp); + onSuccess(resp); } else { // fire a progress event jQuery(document).trigger('spazcore_upload_progress', [resp]); } }; - + sceneAssistant.controller.serviceRequest('palm://com.palm.downloadmanager/', { - method: 'upload', + method: 'upload', parameters: { 'url' : url, 'contentType': content_type, @@ -16102,12 +16104,12 @@ sc.helpers.HTTPUploadFile = function(opts, onSuccess, onFailure) { 'postParameters': postparams, cookies : {}, // optional customHttpHeaders: customHttpHeaders, // optional - subscribe : true + subscribe : true }, 'onSuccess' : onSuccessCheck, 'onFailure' : onFailure }); -};/*jslint +};/*jslint browser: true, nomen: false, debug: true, @@ -16115,13 +16117,13 @@ forin: true, regexp: false, undef: true, white: false, -onevar: false +onevar: false */ var sc, Mojo, use_palmhost_proxy; - - + + /** - * This should contain definitions for all methods from helpers/sys.js tagged @platformstub + * This should contain definitions for all methods from helpers/sys.js tagged @platformstub */ /** @@ -16129,18 +16131,18 @@ var sc, Mojo, use_palmhost_proxy; */ sc.helpers.dump = function(obj, level, cb) { var dumper; - + if (!level) { level = SPAZCORE_DUMPLEVEL_DEBUG; } - + if (sc.dumplevel < level ) { return; } - + if (sc.helpers.isString(obj)) { obj = sch.truncate(obj, SPAZCORE_DUMP_MAXLEN, '…[TRUNC]'); } - - + + if (sc.helpers.isString(obj) || sc.helpers.isNumber(obj) || !obj) { dumper = Mojo.Log.info; } else { @@ -16158,7 +16160,7 @@ sc.helpers.dump = function(obj, level, cb) { } else { // this is an object. we hope. dumper(obj); } - + if (cb) { cb(obj, level); } @@ -16184,11 +16186,11 @@ sc.helpers.openInBrowser = function(url) { /** - * this is specific to webOS, for retrieving the proper URL prefixed with the Palm Host proxy if needed + * this is specific to webOS, for retrieving the proper URL prefixed with the Palm Host proxy if needed * @param {string} url */ sc.helpers.getMojoURL = function(url) { - if (typeof Mojo !== "undefined") { // we're in webOS + if (typeof Mojo !== "undefined") { // we're in webOS /* I would like to apologize for using a global here. ick. */ @@ -16198,7 +16200,7 @@ sc.helpers.getMojoURL = function(url) { if (match && match[0] !== Mojo.hostingPrefix) { url = "/proxy?url=" + encodeURIComponent(url); } - return url; + return url; } else { return url; } @@ -16206,30 +16208,30 @@ sc.helpers.getMojoURL = function(url) { } else { return url; } - + }; -/*jslint +/*jslint browser: true, nomen: false, debug: true, forin: true, undef: true, white: false, -onevar: false +onevar: false */ var sc, Mojo; /** * WEBOS - * platform-specific definitions for prefs lib + * platform-specific definitions for prefs lib */ SpazPrefs.prototype.load = function(callback) { - + var thisPrefs = this; - - + + sc.helpers.dump('this is webOS'); if (!this.mojoCookie) { sc.helpers.dump('making cookie'); @@ -16243,12 +16245,12 @@ SpazPrefs.prototype.load = function(callback) { thisPrefs._prefs[key] = loaded_prefs[key]; } } - + jQuery(document).trigger('spazprefs_loaded'); if( typeof callback == 'function' ) callback(this); - + }; @@ -16257,24 +16259,24 @@ SpazPrefs.prototype.save = function(callback) { if (!this.mojoCookie) { this.mojoCookie = new Mojo.Model.Cookie(SPAZCORE_PREFS_MOJO_COOKIENAME); } - + this.mojoCookie.put(this._prefs); } - + if( typeof callback == 'function' ) callback(this); }; /** - * @todo + * @todo */ SpazPrefs.prototype.getEncrypted = function(key) { }; /** - * @todo + * @todo */ SpazPrefs.prototype.setEncrypted = function(key, val) { From 8d0fcd1ee11589fc515821396d4e8d24814bdb24 Mon Sep 17 00:00:00 2001 From: MetaView Date: Tue, 16 Jul 2013 16:38:55 +0200 Subject: [PATCH 2/2] make friends, followers and searches working again --- app/assistants/friends-followers-assistant.js | 124 +++++----- app/assistants/preferences-assistant.js | 94 ++++---- app/assistants/search-twitter-assistant.js | 226 +++++++++--------- spazcore/spazcore-webos.js | 46 ++-- 4 files changed, 253 insertions(+), 237 deletions(-) diff --git a/app/assistants/friends-followers-assistant.js b/app/assistants/friends-followers-assistant.js index 8009d26..fd12866 100644 --- a/app/assistants/friends-followers-assistant.js +++ b/app/assistants/friends-followers-assistant.js @@ -1,10 +1,10 @@ function FriendsFollowersAssistant() { - /* this is the creator function for your scene assistant object. It will be passed all the + /* this is the creator function for your scene assistant object. It will be passed all the additional parameters (after the scene name) that were passed to pushScene. The reference to the scene controller (this.controller) has not be established yet, so any initialization that needs the scene controller should be done in the setup function below. */ scene_helpers.addCommonSceneMethods(this); - + /* this connects App to this property of the appAssistant */ @@ -17,7 +17,7 @@ FriendsFollowersAssistant.prototype.setup = function() { var thisA = this; this.mode = 'friends'; - + this.scroller = this.controller.getSceneScroller(); this.initAppMenu({ 'items':LOGGEDIN_APPMENU_ITEMS }); this.initTwit('DOM'); @@ -43,7 +43,7 @@ FriendsFollowersAssistant.prototype.setup = function() { toggleCmd:'friends-followers', items: [ {label:$L('My Timeline'), icon:'conversation', command:'filter-timeline-all', shortcut:'T', 'class':"palm-header left"}, - {label:'@', icon:'at', command:'filter-timeline-replies'}, + {label:'@', icon:'at', command:'filter-timeline-replies'}, {label:$L('DM'), icon: 'dms', secondaryIconPath:'', command:'filter-timeline-dms'}, {label:$L('Favorites'), icon:'favorite', command:'favorites', shortcut:'F'}, {label:$L('Friends and Followers'), icon:'friends-followers', command:'friends-followers', shortcut:'L'}, @@ -53,33 +53,33 @@ FriendsFollowersAssistant.prototype.setup = function() { {} ] }); - + this.setCommand('friends-followers_friends', function(e) { thisA.mode = 'friends'; thisA.resetState(); thisA.refresh(); }); - + this.setCommand('friends-followers_followers', function(e) { thisA.mode = 'followers'; thisA.resetState(); thisA.refresh(); }); - - + + /* this function is for setup tasks that have to happen when the scene is first created */ - + /* use Luna.View.render to render view templates and add them to the scene, if needed. */ - + /* setup widgets here */ - + /* add event handlers to listen to events from widgets */ - + this.setupInlineSpinner('activity-spinner-friends-followers'); - + this.refreshOnActivate = true; - - + + this.controller.setupWidget("friends-followers-timeline", this.timeline_attributes = { itemTemplate: 'timeline-entry', @@ -99,7 +99,7 @@ FriendsFollowersAssistant.prototype.setup = function() { } ); this.timeline_list = this.controller.get('friends-followers-timeline'); - + /* more button */ @@ -112,41 +112,41 @@ FriendsFollowersAssistant.prototype.setup = function() { "buttonClass" : 'Primary' }; this.controller.setupWidget('more-friends-followers-button', this.moreButtonAttributes, this.moreButtonModel); - + this.listenForMetaTapScroll(); - + }; FriendsFollowersAssistant.prototype.activate = function(event) { /* put in event handlers here that should only be in effect when this scene is active. For example, key handlers that are observing the document */ - + // this.addPostPopup(); var thisA = this; // for closures below - + var tts = App.prefs.get('timeline-text-size'); this.setTimelineTextSize('#friends-followers-timeline', tts); - - + + /* Prepare for timeline entry taps */ this._handleTap = this.handleTap.bindAsEventListener(this); this.controller.listen('friends-followers-timeline', Mojo.Event.listTap, this._handleTap); - + /* - start the friends-followers timeline + start the friends-followers timeline */ if (this.refreshOnActivate) { this.refresh(); this.refreshOnActivate = false; } - - - + + + }; @@ -155,11 +155,11 @@ FriendsFollowersAssistant.prototype.deactivate = function(event) { stop listening for timeline entry taps */ this.controller.stopListening('friends-followers-timeline', Mojo.Event.listTap, this._handleTap); - + }; FriendsFollowersAssistant.prototype.cleanup = function(event) { - jQuery('#more-friends-followers-button').unbind(Mojo.Event.tap); + jQuery('#more-friends-followers-button').unbind(Mojo.Event.tap); }; @@ -171,24 +171,24 @@ FriendsFollowersAssistant.prototype.getEntryElementByStatusId = function(id) { FriendsFollowersAssistant.prototype.refresh = function(event) { var thisA = this; - + var method_name = 'getFriendsList'; - + var cursor = -1; if (event !== null && (sch.isNumber(event) || sch.isString(event))) { cursor = event; } - + Mojo.Log.error('CURSOR:%s', cursor); - + this.showInlineSpinner('activity-spinner-friends-followers', $L('Loading users…')); - + /* reset scrollstate to avoid white flash */ var scrollstate = this.scroller.mojo.getState(); this.scroller.mojo.setState(scrollstate, false); - + if (this.mode === 'friends') { method_name = 'getFriendsList'; } else if (this.mode === 'followers') { @@ -197,13 +197,13 @@ FriendsFollowersAssistant.prototype.refresh = function(event) { Mojo.Log.error('Invalid mode:%s', this.mode); return; } - - + + this.twit[method_name]( '@'+App.username, cursor, function(data, cursor_obj) { - + /* if mode is wrong, don't add */ @@ -214,12 +214,12 @@ FriendsFollowersAssistant.prototype.refresh = function(event) { thisA.hideInlineSpinner('activity-spinner-friends-followers'); return; } - + if (sch.isArray(data)) { - + // data = data.reverse(); var no_dupes = []; - + for (var i=0; i < data.length; i++) { // Mojo.Log.error('data[i]: %s', data[i].id); /* @@ -229,25 +229,25 @@ FriendsFollowersAssistant.prototype.refresh = function(event) { App.Tweets.saveUser(data[i]); no_dupes.push(data[i]); } - + }; - + Mojo.Log.error('no_dupes.length:%s', no_dupes.length); - + thisA.addItems(no_dupes); - + } - + if (cursor_obj && cursor_obj.next) { thisA.friends_more_cursor = cursor_obj.next; } - + thisA.hideInlineSpinner('activity-spinner-friends-followers'); }, function(xhr, msg, exc) { Mojo.Log.error('EROROR in getFriends'); Mojo.Log.error("%j , %j , %j", xhr, msg, exc); - + var err_msg = $L("There was an error retrieving users"); thisA.displayErrorInfo(err_msg, null); @@ -257,16 +257,16 @@ FriendsFollowersAssistant.prototype.refresh = function(event) { thisA.hideInlineSpinner('activity-spinner-friends-followers'); } ); - + }; FriendsFollowersAssistant.prototype.loadMore = function(event) { - + // if (this.timeline_model && this.timeline_model.items && this.timeline_model.items.length) { // this.friends_more_cursor = this.timeline_model.items[this.timeline_model.items.length-1].id; // } Mojo.Log.error('this.friends_more_cursor: %s', this.friends_more_cursor); - + this.refresh(this.friends_more_cursor); }; @@ -275,10 +275,10 @@ FriendsFollowersAssistant.prototype.loadMore = function(event) { redefine addItems to work with list model */ FriendsFollowersAssistant.prototype.addItems = function(new_items) { - + // now we have all the existing items from the model var model_items = this.timeline_model.items.clone(); - + var model_item; for (var i=0; i < new_items.length; i++) { model_item = { @@ -289,19 +289,19 @@ FriendsFollowersAssistant.prototype.addItems = function(new_items) { // add each item to the model model_items.push(model_item); } - + // sort // model_items.sort(function(a,b){ // Mojo.Log.error('a.created %s, b.created %s', a.created, b.created); // return a.created - b.created; // newest first // }); - + // re-assign the cloned items back to the model object this.timeline_model.items = model_items; - + // tell the controller it's changed to update list widget this.controller.modelChanged(this.timeline_model); - + /* reset scrollstate to avoid white flash */ @@ -311,7 +311,7 @@ FriendsFollowersAssistant.prototype.addItems = function(new_items) { FriendsFollowersAssistant.prototype.renderItem = function(obj) { - + var html = ''; Mojo.Timing.resume("timing_friends-followers-timeline.renderer"); @@ -319,20 +319,20 @@ FriendsFollowersAssistant.prototype.renderItem = function(obj) { html = App.tpl.parseTemplate('follower_row', obj); Mojo.Timing.pause("timing_friends-followers-timeline.renderer"); return html; - + } catch(err) { sch.error("There was an error rendering the object: "+sch.enJSON(obj)); sch.error("Error:"+sch.enJSON(err)); Mojo.Timing.pause("timing_friends-followers-timeline.renderer"); - + return ''; } - + }; FriendsFollowersAssistant.prototype.itemExistsInModel = function(obj) { - + for (var i=0; i < this.timeline_model.items.length; i++) { if (this.timeline_model.items[i].id == obj.id) { sch.error(obj.id +' exists in model'); diff --git a/app/assistants/preferences-assistant.js b/app/assistants/preferences-assistant.js index 57c9890..b30c361 100644 --- a/app/assistants/preferences-assistant.js +++ b/app/assistants/preferences-assistant.js @@ -1,11 +1,11 @@ function PreferencesAssistant() { - /* this is the creator function for your scene assistant object. It will be passed all the + /* this is the creator function for your scene assistant object. It will be passed all the additional parameters (after the scene name) that were passed to pushScene. The reference to the scene controller (this.controller) has not be established yet, so any initialization that needs the scene controller should be done in the setup function below. */ - + scene_helpers.addCommonSceneMethods(this); - + /* this connects App to this property of the appAssistant */ @@ -17,11 +17,11 @@ PreferencesAssistant.prototype.aboutToActivate = function(callback){ }; PreferencesAssistant.prototype.setup = function() { - + var thisA = this; this.scroller = this.controller.getSceneScroller(); - + this.initAppMenu({ 'items':[ Mojo.Menu.editItem, { label: $L('New Search Card'), command: 'new-search-card' }, @@ -30,19 +30,19 @@ PreferencesAssistant.prototype.setup = function() { { label: $L('Help...'), command:Mojo.Menu.helpCmd }, { label: $L('Donate...'), command:'donate' } ]}); - + this.setupCommonMenus({ viewMenuItems: [ { items:[ - {label: $L("Preferences"), command:'scroll-top', 'class':"palm-header left", width:320} + {label: $L("Preferences"), command:'scroll-top', 'class':"palm-header left", width:320} ] } ] }); - - + + /* note that these property keys MUST match a preference key */ @@ -69,14 +69,14 @@ PreferencesAssistant.prototype.setup = function() { 'post-rt-cursor-position': App.prefs.get('post-rt-cursor-position'), 'post-send-on-enter': App.prefs.get('post-send-on-enter'), 'timeline-absolute-timestamps': App.prefs.get('timeline-absolute-timestamps') - + }; - - + + /* Setup checkboxes */ - + /* temporarily disabling sound and vibration prefs until we can sort out how to tell if sound is off */ @@ -115,7 +115,7 @@ PreferencesAssistant.prototype.setup = function() { }, this.model ); - + /* Notification preferences @@ -168,7 +168,7 @@ PreferencesAssistant.prototype.setup = function() { }, this.model ); - + this.controller.setupWidget("checkbox-post-send-on-enter", this.soundEnabledAtts = { fieldName: 'post-send-on-enter', @@ -177,7 +177,7 @@ PreferencesAssistant.prototype.setup = function() { }, this.model ); - + this.controller.setupWidget("checkbox-timeline-absolute-timestamps", this.soundEnabledAtts = { fieldName: 'timeline-absolute-timestamps', @@ -186,7 +186,7 @@ PreferencesAssistant.prototype.setup = function() { }, this.model ); - + /* temporarily disabling sound and vibration prefs until we can sort out how to tell if sound is off */ @@ -204,7 +204,7 @@ PreferencesAssistant.prototype.setup = function() { /* - Setup refresh rate widgets + Setup refresh rate widgets */ this.setupChoices(); @@ -258,8 +258,8 @@ PreferencesAssistant.prototype.setup = function() { this.controller.listen('timeline-friends-getcount', Mojo.Event.propertyChange, this.saveSettings.bindAsEventListener(this)); this.controller.listen('timeline-replies-getcount', Mojo.Event.propertyChange, this.saveSettings.bindAsEventListener(this)); this.controller.listen('timeline-dm-getcount', Mojo.Event.propertyChange, this.saveSettings.bindAsEventListener(this)); - - + + this.controller.setupWidget('timeline-text-size', { label: $L('Timeline Text Size'), @@ -292,7 +292,7 @@ PreferencesAssistant.prototype.setup = function() { this.controller.listen('post-rt-cursor-position', Mojo.Event.propertyChange, this.saveSettings.bindAsEventListener(this)); - + this.controller.setupWidget('image-uploader', { label: $L('service'), @@ -302,7 +302,7 @@ PreferencesAssistant.prototype.setup = function() { this.model ); this.controller.listen('image-uploader', Mojo.Event.propertyChange, this.saveSettings.bindAsEventListener(this)); - + /* clear cache button */ @@ -319,7 +319,7 @@ PreferencesAssistant.prototype.setup = function() { * saves the current values of the selectors */ PreferencesAssistant.prototype.saveSettings = function(event) { - + for (var key in this.model) { App.prefs.set(key, this.model[key]); if (this.onSave[key]) { @@ -329,7 +329,7 @@ PreferencesAssistant.prototype.saveSettings = function(event) { }; /** - * a hash of functions to call on save for certain prefs + * a hash of functions to call on save for certain prefs */ PreferencesAssistant.prototype.onSave = { 'network-refreshinterval' : function(e, val) { @@ -354,11 +354,11 @@ PreferencesAssistant.prototype.onSave = { //function declares & initializes our choice arrays PreferencesAssistant.prototype.setupChoices = function(){ - + // Options for list selector choices: this.validTimes = [ - {label:$L('Never'), value:0}, - {label:$L('5min'), value:300000}, + {label:$L('Never'), value:0}, + {label:$L('5min'), value:300000}, {label:$L('10min'), value:600000}, {label:$L('15min'), value:900000}, {label:$L('30min'), value:1800000}, @@ -367,7 +367,7 @@ PreferencesAssistant.prototype.setupChoices = function(){ {label:$L('4hr'), value:14400000}, {label:$L('8hr'), value:28800000} ]; - + this.validInitialLoads = [ {label:$L('2'), value:2}, {label:$L('5'), value:5}, @@ -378,7 +378,7 @@ PreferencesAssistant.prototype.setupChoices = function(){ {label:$L('100'), value:100}, {label:$L('200'), value:200} ]; - + this.validInitialLoadsDmReply = [ {label:$L('2'), value:2}, {label:$L('5'), value:5}, @@ -387,25 +387,25 @@ PreferencesAssistant.prototype.setupChoices = function(){ {label:$L('40'), value:40}, {label:$L('60'), value:60}, {label:$L('100'), value:100}, - {label:$L('200'), value:200} + {label:$L('200'), value:200} ]; - + this.validTimelineTextSizes = [ - {label:$L('Tall'), value:'tall'}, - {label:$L('Grande'),value:'grande'}, - {label:$L('Venti'), value:'venti'} + {label:$L('Tall'), value:'tall'}, + {label:$L('Grande'),value:'grande'}, + {label:$L('Venti'), value:'venti'} ]; - + this.validAppThemes = []; for(var tkey in AppThemes) { this.validAppThemes.push({label:tkey, value:tkey}); } - + this.validRTCursorPositions = [ - {label:$L('Beginning'), value:'beginning'}, + {label:$L('Beginning'), value:'beginning'}, {label:$L('End'),value:'end'} ]; - + var image_uploader = new SpazImageUploader(); this.validImageUploaders = []; for (var key in image_uploader.services) { @@ -414,6 +414,8 @@ PreferencesAssistant.prototype.setupChoices = function(){ } }; +PreferencesAssistant.prototype.refresh = function() { +}; PreferencesAssistant.prototype.activate = function(event) { @@ -428,10 +430,10 @@ PreferencesAssistant.prototype.deactivate = function(event) { }; PreferencesAssistant.prototype.cleanup = function(event) { - /* this function should do any cleanup needed before the scene is destroyed as + /* this function should do any cleanup needed before the scene is destroyed as a result of being popped off the scene stack */ - - + + this.controller.stopListening('network-refreshinterval', Mojo.Event.propertyChange, this.saveSettings); this.controller.stopListening('network-searchrefreshinterval', Mojo.Event.propertyChange, this.saveSettings); this.controller.stopListening('timeline-friends-getcount', Mojo.Event.propertyChange, this.saveSettings); @@ -444,7 +446,7 @@ PreferencesAssistant.prototype.cleanup = function(event) { Mojo.Event.stopListening(jQuery('#clear-cache-button')[0], Mojo.Event.tap, function(e) { thisA.clearTimelineCache(); }); - + /* temporarily disabling sound and vibration prefs until we can sort out how to tell if sound is off */ @@ -457,12 +459,12 @@ PreferencesAssistant.prototype.cleanup = function(event) { this.controller.stopListening('checkbox-notify-mentions', Mojo.Event.propertyChange, this.saveSettings); this.controller.stopListening('checkbox-notify-dms', Mojo.Event.propertyChange, this.saveSettings); this.controller.stopListening('checkbox-notify-searchresults', Mojo.Event.propertyChange, this.saveSettings); - + }; -PreferencesAssistant.prototype.considerForNotification = function(params){ +PreferencesAssistant.prototype.considerForNotification = function(params){ Mojo.Log.error('NOTIFICATION RECEIVED in PreferencesAssistant:%j', params); - - return params; + + return params; }; diff --git a/app/assistants/search-twitter-assistant.js b/app/assistants/search-twitter-assistant.js index ec28414..51007bb 100644 --- a/app/assistants/search-twitter-assistant.js +++ b/app/assistants/search-twitter-assistant.js @@ -1,21 +1,21 @@ /** * events raised here: - * 'search_timeline_refresh' + * 'search_timeline_refresh' */ function SearchTwitterAssistant(args) { - /* this is the creator function for your scene assistant object. It will be passed all the + /* this is the creator function for your scene assistant object. It will be passed all the additional parameters (after the scene name) that were passed to pushScene. The reference to the scene controller (this.controller) has not be established yet, so any initialization that needs the scene controller should be done in the setup function below. */ - + scene_helpers.addCommonSceneMethods(this); - + /* this connects App to this property of the appAssistant */ App = Spaz.getAppObj(); - + if (args && args.searchterm) { this.passedSearch = args.searchterm; } @@ -23,10 +23,10 @@ function SearchTwitterAssistant(args) { /* we may be in a new stage, so need to init prefs if they don't exist */ - + this.lightweight = true; } - + if (args && args.saved_id > 0) { this.isSavedSearch = true; this.saved_id = args.saved_id; @@ -34,12 +34,12 @@ function SearchTwitterAssistant(args) { this.isSavedSearch = false; this.saved_id = null; } - + /* this property will hold the setInterval return */ this.refresher = null; - + this.lastQuery = ''; } @@ -49,19 +49,19 @@ SearchTwitterAssistant.prototype.aboutToActivate = function(callback){ SearchTwitterAssistant.prototype.setup = function() { /* this function is for setup tasks that have to happen when the scene is first created */ - + /* use Mojo.View.render to render view templates and add them to the scene, if needed. */ var thisA = this; this.scroller = this.controller.getSceneScroller(); - + this.initTwit(); - + this.trackStageActiveState(); - - + + /* view and command menus */ @@ -70,7 +70,7 @@ SearchTwitterAssistant.prototype.setup = function() { viewMenuItems: [ { items:[ - {label: $L("Search & Explore"), command:'scroll-top', 'class':"palm-header left", width:320} + {label: $L("Search & Explore"), command:'scroll-top', 'class':"palm-header left", width:320} ] } @@ -82,29 +82,29 @@ SearchTwitterAssistant.prototype.setup = function() { {label:$L('Compose'), icon:'compose', command:'compose', shortcut:'N'}, {}, {label:$L('Save search'), icon:'favorite-outline', command:'save-search', shortcut:'S'}, - {label:$L('Refresh'), icon:'sync', command:'refresh', shortcut:'R'} + {label:$L('Refresh'), icon:'sync', command:'refresh', shortcut:'R'} ] }); - - this.initAppMenu({ 'items':LOGGEDIN_APPMENU_ITEMS }); + + this.initAppMenu({ 'items':LOGGEDIN_APPMENU_ITEMS }); } else { this.setupCommonMenus({ viewMenuItems: [ { items:[ - {label: $L("Search & Explore"), command:'scroll-top', 'class':"palm-header left", width:320} + {label: $L("Search & Explore"), command:'scroll-top', 'class':"palm-header left", width:320} ] } ], cmdMenuItems: [ {}, - {label:$L('Refresh'), icon:'sync', command:'refresh', shortcut:'R'} + {label:$L('Refresh'), icon:'sync', command:'refresh', shortcut:'R'} ] - + }); - - this.initAppMenu(); + + this.initAppMenu(); } @@ -134,14 +134,14 @@ SearchTwitterAssistant.prototype.setup = function() { jQuery('#submit-search-button').bind(Mojo.Event.tap, function() { thisA.search.call(thisA, thisA.searchBoxModel.value, null, 1); }); - + this.searchButtonAttributes = { "type": Mojo.Widget.activityButton }; this.searchButtonModel = { "buttonLabel" : "Search", "buttonClass" : 'Primary' - }; + }; this.controller.setupWidget('submit-search-button', this.searchButtonAttributes, this.searchButtonModel); @@ -162,31 +162,33 @@ SearchTwitterAssistant.prototype.setup = function() { this.timeline_model = { items : [] } - ); + ); this.timeline_list = this.controller.get('search-timeline'); // this.refresh(); - + if (this.isSavedSearch) { this.fillStar(true); } else { this.fillStar(false); } - + /* more button */ jQuery('#more-search-button').bind(Mojo.Event.tap, function() { thisA.loadMore.call(thisA); }); - this.moreButtonAttributes = {}; + this.moreButtonAttributes = { + "type": Mojo.Widget.activityButton + }; this.moreButtonModel = { "buttonLabel" : "More", "buttonClass" : 'Primary' }; this.controller.setupWidget('more-search-button', this.moreButtonAttributes, this.moreButtonModel); - + this.listenForMetaTapScroll(); }; @@ -197,49 +199,49 @@ SearchTwitterAssistant.prototype.activate = function(event) { var thisA = this; // for closures - + if (event && event.searchterm) { this.passedSearch = event.searchterm; } - - + + if (this.passedSearch) { this.searchBoxModel.value = this.passedSearch.replace(/"/gi, '"'); // convert the entities back into "'s this.controller.modelChanged(this.searchBoxModel); this.search(this.passedSearch); this.passedSearch = null; // eliminate this so it isn't used anymore } - - + + var tts = App.prefs.get('timeline-text-size'); this.setTimelineTextSize('#search-timeline', tts); - - - + + + jQuery(document).bind('search_timeline_refresh', function(e) { thisA.markAllAsRead(); thisA.refresh(); }); - + this.listenForEnter('search-twitter-textfield', function() { thisA.controller.get('submit-search-button').mojo.activate(); thisA.search(thisA.searchBoxModel.value, null, 1); }); - + /* Prepare for timeline entry taps */ this.bindTimelineEntryTaps('search-timeline'); - + }; SearchTwitterAssistant.prototype.deactivate = function(event) { - jQuery(document).unbind('search_timeline_refresh'); - + jQuery(document).unbind('search_timeline_refresh'); + Mojo.Log.error('DEACTIVATE'); - + /* stop listening for timeline entry taps */ @@ -249,50 +251,48 @@ SearchTwitterAssistant.prototype.deactivate = function(event) { SearchTwitterAssistant.prototype.cleanup = function(event) { jQuery('#submit-search-button').unbind(Mojo.Event.tap); - + jQuery('#more-search-button').unbind(Mojo.Event.tap); - + this.stopListeningForEnter('search-twitter-textfield'); - + this.stopTrackingStageActiveState(); - + }; -SearchTwitterAssistant.prototype.search = function(e, type, page) { +SearchTwitterAssistant.prototype.search = function(e, type, since_id) { var thisA = this; var search_string; - - if (type && type.toLowerCase() == 'refresh') { // empty unless this is a refresh + + type = type ? type.toLowerCase() : ""; + + if (type == 'refresh') { // empty unless this is a refresh this.scrollToTop(); this.markAllAsRead(); - } else if (type && type.toLowerCase() == 'loadmore') { + } else if (type == 'loadmore') { this.markAllAsRead(); } else { - this.clear(); + this.clear(); } - + if (sch.isString(e)) { search_string = e; } else if (e.value && sch.isString(e.value)) { search_string = e.value; } - - if (!page) { - page = 1; - } - + Mojo.Log.info("Searching for: %s", search_string); - + /* clear any existing results */ if (search_string !== this.lastQuery) { this.clear(); } - + this.lastQuery = sch.fromHTMLSpecialChars(search_string); Mojo.Log.info('refresh()'); @@ -301,8 +301,8 @@ SearchTwitterAssistant.prototype.search = function(e, type, page) { thisA.markAllAsRead(); } - this.activateSpinner(); - + this.activateSpinner(type); + /* reset scrollstate to avoid white flash */ @@ -315,16 +315,17 @@ SearchTwitterAssistant.prototype.search = function(e, type, page) { thisA.twit.search( thisA.lastQuery, // query - null, // since_id - 100, // results_per_page - page, // page + since_id ? ('-' + since_id) : null, // since_id -> max_id + 10, // results_per_page + null, // page null, // lang null, // , geocode function(data, searchinfo) { // onSuccess - + Mojo.Log.error('searchinfo: %j', searchinfo); Mojo.Log.error('data: %j', data); - + thisA.max_id = searchinfo.max_id; + /* reverse the tweets for collection rendering (faster) */ @@ -344,10 +345,10 @@ SearchTwitterAssistant.prototype.search = function(e, type, page) { } } } - + thisA.addItems(no_dupes); - thisA.deactivateSpinner(); + thisA.deactivateSpinner(type); /* show a banner if need be @@ -363,7 +364,7 @@ SearchTwitterAssistant.prototype.search = function(e, type, page) { function(xhr, msg, exc) { // onFailure var err_msg = $L("There was an error loading the search results"); thisA.displayErrorInfo(err_msg, null); - thisA.deactivateSpinner(); + thisA.deactivateSpinner(type); } ); @@ -378,27 +379,21 @@ SearchTwitterAssistant.prototype.search = function(e, type, page) { */ this.checkInternetStatus( getSearchTimeline ); - + }; SearchTwitterAssistant.prototype.refresh = function(event) { var page = 1; - + if (event && sch.isNumber(event)) { page = event; } this.search(this.searchBoxModel.value, 'refresh', page); }; SearchTwitterAssistant.prototype.loadMore = function(event) { - if (this.search_more_page) { - this.search_more_page++; - } else { - this.search_more_page = 2; - } - - this.search(this.searchBoxModel.value, 'loadmore', this.search_more_page); + this.search(this.searchBoxModel.value, 'loadmore', this.max_id); }; @@ -413,12 +408,12 @@ SearchTwitterAssistant.prototype.clear = function() { redefine addItems to work with list model */ SearchTwitterAssistant.prototype.addItems = function(new_items) { - + Mojo.Log.error("addItems"); - + // now we have all the existing items from the model var model_items = this.timeline_model.items.clone(); - + var model_item; for (var i=0; i < new_items.length; i++) { model_item = { @@ -427,20 +422,20 @@ SearchTwitterAssistant.prototype.addItems = function(new_items) { }; // add each item to the model model_items.push(model_item); - + } - + // sort, in reverse model_items.sort(function(a,b){ return b.data.SC_created_at_unixtime - a.data.SC_created_at_unixtime; // newest first }); - + // re-assign the cloned items back to the model object this.timeline_model.items = model_items; - + // this filters and updates the model this.controller.modelChanged(this.timeline_model); - + /* reset scrollstate to avoid white flash */ @@ -450,7 +445,7 @@ SearchTwitterAssistant.prototype.addItems = function(new_items) { SearchTwitterAssistant.prototype.renderItem = function(obj) { - + var html = ''; Mojo.Timing.resume("timing_SearchTwitterAssistant.renderer"); @@ -462,19 +457,19 @@ SearchTwitterAssistant.prototype.renderItem = function(obj) { } Mojo.Timing.pause("timing_SearchTwitterAssistant.renderer"); return html; - + } catch(err) { sch.error("There was an error rendering the object: "+sch.enJSON(obj)); sch.error("Error:"+sch.enJSON(err)); Mojo.Timing.pause("timing_SearchTwitterAssistant.renderer"); - + return ''; } - + }; SearchTwitterAssistant.prototype.itemExistsInModel = function(obj) { - + for (var i=0; i < this.timeline_model.items.length; i++) { if (this.timeline_model.items[i].id == obj.id) { @@ -492,36 +487,46 @@ SearchTwitterAssistant.prototype.itemExistsInModel = function(obj) { * loop through items in timeline_model and set Spaz_is_new = false, Spaz_is_read = true */ SearchTwitterAssistant.prototype.markAllAsRead = function() { - + Mojo.Log.error("markAllAsRead"); - + Mojo.Timing.resume("timing_html_markAllAsRead"); - + for (var i=0; i < this.timeline_model.items.length; i++) { this.timeline_model.items[i].data.Spaz_is_new = false; this.timeline_model.items[i].data.Spaz_is_read = true; } - + Mojo.Timing.pause("timing_html_markAllAsRead"); - + Mojo.Log.error(Mojo.Timing.createTimingString("timing_html", "Updating HTML element times")); - + this.controller.modelChanged(this.timeline_model); }; -SearchTwitterAssistant.prototype.activateSpinner = function() { - this.buttonWidget = this.controller.get('submit-search-button'); - this.buttonWidget.mojo.activate(); +SearchTwitterAssistant.prototype.activateSpinner = function(type) { + if (type == 'loadmore') { + var buttonWidget = this.controller.get('more-search-button'); + buttonWidget.mojo.activate(); + } else { + var buttonWidget = this.controller.get('submit-search-button'); + buttonWidget.mojo.activate(); + } }; -SearchTwitterAssistant.prototype.deactivateSpinner = function() { - this.buttonWidget = this.controller.get('submit-search-button'); - this.buttonWidget.mojo.deactivate(); +SearchTwitterAssistant.prototype.deactivateSpinner = function(type) { + if (type == 'loadmore') { + var buttonWidget = this.controller.get('more-search-button'); + buttonWidget.mojo.deactivate(); + } else { + var buttonWidget = this.controller.get('submit-search-button'); + buttonWidget.mojo.deactivate(); + } }; SearchTwitterAssistant.prototype.saveSearch = function(searchstr) { - + var thisA = this; jQuery(document).bind('create_saved_search_succeeded', {thisAssistant:this}, function(e, resp) { @@ -532,14 +537,14 @@ SearchTwitterAssistant.prototype.saveSearch = function(searchstr) { thisA.twit.getSavedSearches(); // this will force a refresh on any listeners jQuery(document).unbind('create_saved_search_succeeded'); }); - + this.twit.addSavedSearch(searchstr); - + }; SearchTwitterAssistant.prototype.removeSearch = function(searchstr) { - + var thisA = this; jQuery(document).bind('destroy_saved_search_succeeded', {thisAssistant:this}, function(e, resp) { @@ -553,7 +558,7 @@ SearchTwitterAssistant.prototype.removeSearch = function(searchstr) { // alert(thisA.saved_id); this.twit.removeSavedSearch(thisA.saved_id); - + }; SearchTwitterAssistant.prototype.fillStar = function(fill) { @@ -566,4 +571,3 @@ SearchTwitterAssistant.prototype.fillStar = function(fill) { this.controller.modelChanged(this.cmdMenuModel); } }; - diff --git a/spazcore/spazcore-webos.js b/spazcore/spazcore-webos.js index d663a85..862ca68 100644 --- a/spazcore/spazcore-webos.js +++ b/spazcore/spazcore-webos.js @@ -12661,8 +12661,8 @@ SpazTwit.prototype.getAPIURL = function(key, urldata) { urls.user_favorites = "favorites/{{ID}}.json"; // use this to retrieve favs of a user other than yourself urls.dm_timeline = "direct_messages.json"; urls.dm_sent = "direct_messages/sent.json"; - urls.friendslist = "statuses/friends.json"; - urls.followerslist = "statuses/followers.json"; + urls.friendslist = "friends/list.json"; + urls.followerslist = "followers/list.json"; urls.show_user = "users/show.json"; urls.featuredlist = "statuses/featured.json"; @@ -12689,7 +12689,7 @@ SpazTwit.prototype.getAPIURL = function(key, urldata) { urls.verify_credentials = "account/verify_credentials.json"; urls.ratelimit_status = "account/rate_limit_status.json"; urls.update_profile = "account/update_profile.json"; - urls.saved_searches = "saved_searches.json"; + urls.saved_searches = "saved_searches/list.json"; urls.report_spam = "report_spam.json"; // User lists URLs @@ -12716,7 +12716,7 @@ SpazTwit.prototype.getAPIURL = function(key, urldata) { urls.retweeted_to_me = "statuses/retweeted_to_me.json"; urls.retweets_of_me = "statuses/retweets_of_me.json"; - urls.search = "search.json"; + urls.search = "search/tweets.json"; // misc urls.test = "help/test.json"; @@ -13235,7 +13235,7 @@ SpazTwit.prototype.search = function(query, since_id, results_per_page, page, la var data = {}; data['q'] = query; - data['rpp'] = results_per_page; + data['count'] = results_per_page; if (since_id) { if (since_id[0] == '-') { data['max_id'] = since_id.replace('-', ''); @@ -13243,7 +13243,7 @@ SpazTwit.prototype.search = function(query, since_id, results_per_page, page, la data['since_id'] = since_id; } } - data['page'] = page; + //data['page'] = page; if (lang) { data['lang'] = lang; } @@ -13252,6 +13252,7 @@ SpazTwit.prototype.search = function(query, since_id, results_per_page, page, la } var url = this.getAPIURL('search', data); + Mojo.Log.error(url); this._getTimeline({ 'url':url, 'process_callback' : this._processSearchTimeline, @@ -13286,7 +13287,7 @@ SpazTwit.prototype._processSearchTimeline = function(search_result, opts, proces /* grab the array of items */ - var ret_items = search_result.results; + var ret_items = search_result.statuses; if (ret_items && ret_items.length > 0){ /* @@ -13323,15 +13324,22 @@ SpazTwit.prototype._processSearchTimeline = function(search_result, opts, proces // this.data[SPAZCORE_SECTION_SEARCH].items = this.removeExtraElements(this.data[SPAZCORE_SECTION_SEARCH].items, this.data[SPAZCORE_SECTION_SEARCH].max); + var metadata = search_result.search_metadata; + if (metadata.next_results) { + var start = metadata.next_results.indexOf("max_id="); + metadata.next_results = metadata.next_results.substr(start + 7); + var end = metadata.next_results.indexOf("&"); + metadata.next_results = metadata.next_results.substr(0, end); + } var search_info = { - 'since_id' : search_result.since_id, - 'max_id' : search_result.max_id, - 'refresh_url' : search_result.refresh_url, - 'results_per_page' : search_result.results_per_page, - 'next_page' : search_result.next_page, - 'completed_in' : search_result.completed_in, - 'page' : search_result.page, - 'query' : search_result.query + 'since_id' : metadata.since_id ? metadata.since_id : 0, + 'max_id' : metadata.next_results ? metadata.next_results : 0, + 'refresh_url' : metadata.refresh_url, + 'results_per_page' : metadata.results_per_page ? metadata.results_per_page : metadata.count, + 'next_page' : '0', + 'completed_in' : metadata.completed_in, + 'page' : '0', + 'query' : metadata.query }; if (opts.success_callback) { @@ -13405,9 +13413,9 @@ SpazTwit.prototype._processSearchItem = function(item, section_name) { normalize so we have as much user data in this object as possible */ item.user = { - 'profile_image_url':item.profile_image_url, - 'screen_name':item.from_user, - 'id':item.from_user_id + 'profile_image_url':item.user.profile_image_url, + 'screen_name':item.user.screen_name, + 'id':item.user.id }; /* @@ -14229,6 +14237,8 @@ SpazTwit.prototype._processUserList = function(section_name, ret_items, opts, pr if (!processing_opts) { processing_opts = {}; } + Mojo.Log.error("%j", ret_items); + if (ret_items.users) { users = ret_items.users; next = ret_items.next_cursor_str;