summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Ostler <sostler@deathmachine.local>2010-01-20 01:14:54 -0500
committerScott Ostler <sostler@deathmachine.local>2010-01-20 01:14:54 -0500
commitfaab952a795a1eee1ed6eaca476d56fcb77998aa (patch)
tree5b90a7e345c82583cadac9eda58a6c5d5ec9b9c2
parenta91eb914edb95a5facd62b2eac00186b7b8c63c1 (diff)
parent9b9f1b51d63ee0a46d766d285ffac028d7c40cbb (diff)
Getting up to date
-rwxr-xr-xsrc/site.clj3
-rw-r--r--static/chanbg.pngbin0 -> 218 bytes
-rwxr-xr-xstatic/chat.st92
-rw-r--r--static/date.js507
-rw-r--r--static/datePicker.css129
-rw-r--r--static/door2.gifbin0 -> 323 bytes
-rw-r--r--static/doorway.gifbin0 -> 2354 bytes
-rw-r--r--static/dot.gifbin0 -> 832 bytes
-rw-r--r--static/form_login/front.css146
-rw-r--r--static/form_login/images/.DS_Storebin0 -> 6148 bytes
-rw-r--r--static/form_login/images/bg-btn-blue.pngbin0 -> 380 bytes
-rw-r--r--static/form_login/images/front-bg.gifbin0 -> 78 bytes
-rw-r--r--static/form_login/images/signin-nav-bg-hover-ie.pngbin0 -> 266 bytes
-rw-r--r--static/form_login/images/signin-nav-bg-ie.pngbin0 -> 346 bytes
-rw-r--r--static/form_login/images/toggle_down_light.pngbin0 -> 277 bytes
-rw-r--r--static/form_login/images/toggle_up_dark.pngbin0 -> 288 bytes
-rwxr-xr-xstatic/gritter/css/jquery.gritter.css4
-rwxr-xr-xstatic/gritter/js/jquery.gritter.js2
-rwxr-xr-xstatic/header.css22
-rwxr-xr-xstatic/index.html20
-rw-r--r--static/jewel.gifbin0 -> 2212 bytes
-rw-r--r--static/jewelblu.gifbin0 -> 934 bytes
-rw-r--r--static/jquery.datePicker.js1189
-rwxr-xr-xstatic/js/home.js (renamed from static/home.js)24
-rwxr-xr-xstatic/js/pichat.js (renamed from static/pichat.js)80
-rwxr-xr-xstatic/js/register.js (renamed from static/register.js)0
-rwxr-xr-xstatic/js/sha1.js (renamed from static/sha1.js)0
-rw-r--r--static/js/underscore-min.js16
-rw-r--r--static/js/underscore.js637
-rwxr-xr-xstatic/pichat.css13
-rwxr-xr-xstatic/profile.css121
-rwxr-xr-xstatic/register.html4
-rwxr-xr-xstatic/search/browser.html69
-rw-r--r--static/search/browser.pngbin11865 -> 6563 bytes
-rw-r--r--static/signin.gifbin0 -> 3915 bytes
-rw-r--r--static/talkwith.pngbin0 -> 2698 bytes
-rwxr-xr-xtemplate/banner.st17
-rwxr-xr-xtemplate/browser.st4
-rwxr-xr-xtemplate/chat.st17
-rw-r--r--template/form_login.st44
-rwxr-xr-xtemplate/head.st10
-rwxr-xr-xtemplate/log.st31
-rwxr-xr-xtemplate/profile.st26
43 files changed, 2915 insertions, 312 deletions
diff --git a/src/site.clj b/src/site.clj
index b89215c..653e99a 100755
--- a/src/site.clj
+++ b/src/site.clj
@@ -2,7 +2,6 @@
(:import java.lang.System
java.text.SimpleDateFormat
java.util.Date
- clojure.lang.PersistentQueue
org.apache.commons.codec.digest.DigestUtils
javax.servlet.http.Cookie
org.antlr.stringtemplate.StringTemplateGroup)
@@ -123,7 +122,7 @@
(defn process-message-for-output [d]
{"nick" (encode-html-entities (d :nick))
- "msg_id" (d :message_id)
+ "message_id" (d :message_id)
"created_on" (.format formatter (d :created_on))
"content" (encode-html-entities (d :content))})
diff --git a/static/chanbg.png b/static/chanbg.png
new file mode 100644
index 0000000..331f4eb
--- /dev/null
+++ b/static/chanbg.png
Binary files differ
diff --git a/static/chat.st b/static/chat.st
deleted file mode 100755
index aecf87c..0000000
--- a/static/chat.st
+++ /dev/null
@@ -1,92 +0,0 @@
-<html>
- <head>
- <title>dump.fm</title>
- <link rel="stylesheet" type="text/css" href="/static/reset.css">
- <link rel="stylesheet" type="text/css" href="static/pichat.css">
-
- <link rel="shortcut icon" href="/static/favicon.ico">
- <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
- <script type="text/javascript" src="/static/sha1.js"></script>
- <script type="text/javascript" src="/static/pichat.js"></script>
- <script type="text/javascript" src="/static/scroll.js"></script>
- <script>
- jQuery(document).ready(initChat);
- var Nick = $json_user_nick$;
- </script>
- <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><style type="text/css">
-<!--
-a {
- font-size: 12px;
- color: #000;
-}
-a:link {
- text-decoration: none;
-}
-a:visited {
- text-decoration: none;
- color: #000;
-}
-a:hover {
- text-decoration: none;
- color: #00F;
-}
-a:active {
- text-decoration: none;
- color: #000;
-}
-
--->
-</style></head>
-
-<body>
-
-
- $header()$
-
-<div id="chatrap"><div id="logc">
- <div id="content">
-
- <div id="messagetabs"></div>
- <div id="rapper">
- <div id="loghead"></div>
- </div>
- <div id="userList">
- $users: { u |
- <div class="username"><a href="/u/$u$" class="username"><img src="/static/cat.jpeg" width="50" height="50">$u$</a><br>
- </div>
- }$
- </div>
-
- <div id="messagePane">
- <div id="messageList">
- $messages: { m |
- <div class="msgDiv oldmsg"><b><a href="/u/$m.nick$">$m.nick$</a>: </b>
- <span class="content">$m.content$<span></div>
- }$
- <hr />
- </div></div></div>
- $if(user_nick)$
- <div id="msgInputDiv">
- <input id="msgInput" class="msgInput" type="input" />
- <input id="msgSubmit" type="submit" value="Send Image URL"
- />
- </div>
- $endif$
- </div>
- </div>
-
- </div>
- </div>
- </div>
-
- </div>
-
- </div>
- <div id="footerc">
- <p>
- $footer()$</p>
- <p>
- </p>
- </div>
- </body>
-</html>
diff --git a/static/date.js b/static/date.js
new file mode 100644
index 0000000..2312284
--- /dev/null
+++ b/static/date.js
@@ -0,0 +1,507 @@
+/*
+ * Date prototype extensions. Doesn't depend on any
+ * other code. Doens't overwrite existing methods.
+ *
+ * Adds dayNames, abbrDayNames, monthNames and abbrMonthNames static properties and isLeapYear,
+ * isWeekend, isWeekDay, getDaysInMonth, getDayName, getMonthName, getDayOfYear, getWeekOfYear,
+ * setDayOfYear, addYears, addMonths, addDays, addHours, addMinutes, addSeconds methods
+ *
+ * Copyright (c) 2006 Jörn Zaefferer and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
+ *
+ * Additional methods and properties added by Kelvin Luck: firstDayOfWeek, dateFormat, zeroTime, asString, fromString -
+ * I've added my name to these methods so you know who to blame if they are broken!
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+/**
+ * An Array of day names starting with Sunday.
+ *
+ * @example dayNames[0]
+ * @result 'Sunday'
+ *
+ * @name dayNames
+ * @type Array
+ * @cat Plugins/Methods/Date
+ */
+Date.dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+
+/**
+ * An Array of abbreviated day names starting with Sun.
+ *
+ * @example abbrDayNames[0]
+ * @result 'Sun'
+ *
+ * @name abbrDayNames
+ * @type Array
+ * @cat Plugins/Methods/Date
+ */
+Date.abbrDayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
+
+/**
+ * An Array of month names starting with Janurary.
+ *
+ * @example monthNames[0]
+ * @result 'January'
+ *
+ * @name monthNames
+ * @type Array
+ * @cat Plugins/Methods/Date
+ */
+Date.monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
+
+/**
+ * An Array of abbreviated month names starting with Jan.
+ *
+ * @example abbrMonthNames[0]
+ * @result 'Jan'
+ *
+ * @name monthNames
+ * @type Array
+ * @cat Plugins/Methods/Date
+ */
+Date.abbrMonthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+/**
+ * The first day of the week for this locale.
+ *
+ * @name firstDayOfWeek
+ * @type Number
+ * @cat Plugins/Methods/Date
+ * @author Kelvin Luck
+ */
+Date.firstDayOfWeek = 1;
+
+/**
+ * The format that string dates should be represented as (e.g. 'dd/mm/yyyy' for UK, 'mm/dd/yyyy' for US, 'yyyy-mm-dd' for Unicode etc).
+ *
+ * @name format
+ * @type String
+ * @cat Plugins/Methods/Date
+ * @author Kelvin Luck
+ */
+Date.format = 'dd/mm/yyyy';
+//Date.format = 'mm/dd/yyyy';
+//Date.format = 'yyyy-mm-dd';
+//Date.format = 'dd mmm yy';
+
+/**
+ * The first two numbers in the century to be used when decoding a two digit year. Since a two digit year is ambiguous (and date.setYear
+ * only works with numbers < 99 and so doesn't allow you to set years after 2000) we need to use this to disambiguate the two digit year codes.
+ *
+ * @name format
+ * @type String
+ * @cat Plugins/Methods/Date
+ * @author Kelvin Luck
+ */
+Date.fullYearStart = '20';
+
+(function() {
+
+ /**
+ * Adds a given method under the given name
+ * to the Date prototype if it doesn't
+ * currently exist.
+ *
+ * @private
+ */
+ function add(name, method) {
+ if( !Date.prototype[name] ) {
+ Date.prototype[name] = method;
+ }
+ };
+
+ /**
+ * Checks if the year is a leap year.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.isLeapYear();
+ * @result true
+ *
+ * @name isLeapYear
+ * @type Boolean
+ * @cat Plugins/Methods/Date
+ */
+ add("isLeapYear", function() {
+ var y = this.getFullYear();
+ return (y%4==0 && y%100!=0) || y%400==0;
+ });
+
+ /**
+ * Checks if the day is a weekend day (Sat or Sun).
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.isWeekend();
+ * @result false
+ *
+ * @name isWeekend
+ * @type Boolean
+ * @cat Plugins/Methods/Date
+ */
+ add("isWeekend", function() {
+ return this.getDay()==0 || this.getDay()==6;
+ });
+
+ /**
+ * Check if the day is a day of the week (Mon-Fri)
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.isWeekDay();
+ * @result false
+ *
+ * @name isWeekDay
+ * @type Boolean
+ * @cat Plugins/Methods/Date
+ */
+ add("isWeekDay", function() {
+ return !this.isWeekend();
+ });
+
+ /**
+ * Gets the number of days in the month.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.getDaysInMonth();
+ * @result 31
+ *
+ * @name getDaysInMonth
+ * @type Number
+ * @cat Plugins/Methods/Date
+ */
+ add("getDaysInMonth", function() {
+ return [31,(this.isLeapYear() ? 29:28),31,30,31,30,31,31,30,31,30,31][this.getMonth()];
+ });
+
+ /**
+ * Gets the name of the day.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.getDayName();
+ * @result 'Saturday'
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.getDayName(true);
+ * @result 'Sat'
+ *
+ * @param abbreviated Boolean When set to true the name will be abbreviated.
+ * @name getDayName
+ * @type String
+ * @cat Plugins/Methods/Date
+ */
+ add("getDayName", function(abbreviated) {
+ return abbreviated ? Date.abbrDayNames[this.getDay()] : Date.dayNames[this.getDay()];
+ });
+
+ /**
+ * Gets the name of the month.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.getMonthName();
+ * @result 'Janurary'
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.getMonthName(true);
+ * @result 'Jan'
+ *
+ * @param abbreviated Boolean When set to true the name will be abbreviated.
+ * @name getDayName
+ * @type String
+ * @cat Plugins/Methods/Date
+ */
+ add("getMonthName", function(abbreviated) {
+ return abbreviated ? Date.abbrMonthNames[this.getMonth()] : Date.monthNames[this.getMonth()];
+ });
+
+ /**
+ * Get the number of the day of the year.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.getDayOfYear();
+ * @result 11
+ *
+ * @name getDayOfYear
+ * @type Number
+ * @cat Plugins/Methods/Date
+ */
+ add("getDayOfYear", function() {
+ var tmpdtm = new Date("1/1/" + this.getFullYear());
+ return Math.floor((this.getTime() - tmpdtm.getTime()) / 86400000);
+ });
+
+ /**
+ * Get the number of the week of the year.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.getWeekOfYear();
+ * @result 2
+ *
+ * @name getWeekOfYear
+ * @type Number
+ * @cat Plugins/Methods/Date
+ */
+ add("getWeekOfYear", function() {
+ return Math.ceil(this.getDayOfYear() / 7);
+ });
+
+ /**
+ * Set the day of the year.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.setDayOfYear(1);
+ * dtm.toString();
+ * @result 'Tue Jan 01 2008 00:00:00'
+ *
+ * @name setDayOfYear
+ * @type Date
+ * @cat Plugins/Methods/Date
+ */
+ add("setDayOfYear", function(day) {
+ this.setMonth(0);
+ this.setDate(day);
+ return this;
+ });
+
+ /**
+ * Add a number of years to the date object.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.addYears(1);
+ * dtm.toString();
+ * @result 'Mon Jan 12 2009 00:00:00'
+ *
+ * @name addYears
+ * @type Date
+ * @cat Plugins/Methods/Date
+ */
+ add("addYears", function(num) {
+ this.setFullYear(this.getFullYear() + num);
+ return this;
+ });
+
+ /**
+ * Add a number of months to the date object.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.addMonths(1);
+ * dtm.toString();
+ * @result 'Tue Feb 12 2008 00:00:00'
+ *
+ * @name addMonths
+ * @type Date
+ * @cat Plugins/Methods/Date
+ */
+ add("addMonths", function(num) {
+ var tmpdtm = this.getDate();
+
+ this.setMonth(this.getMonth() + num);
+
+ if (tmpdtm > this.getDate())
+ this.addDays(-this.getDate());
+
+ return this;
+ });
+
+ /**
+ * Add a number of days to the date object.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.addDays(1);
+ * dtm.toString();
+ * @result 'Sun Jan 13 2008 00:00:00'
+ *
+ * @name addDays
+ * @type Date
+ * @cat Plugins/Methods/Date
+ */
+ add("addDays", function(num) {
+ //this.setDate(this.getDate() + num);
+ this.setTime(this.getTime() + (num*86400000) );
+ return this;
+ });
+
+ /**
+ * Add a number of hours to the date object.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.addHours(24);
+ * dtm.toString();
+ * @result 'Sun Jan 13 2008 00:00:00'
+ *
+ * @name addHours
+ * @type Date
+ * @cat Plugins/Methods/Date
+ */
+ add("addHours", function(num) {
+ this.setHours(this.getHours() + num);
+ return this;
+ });
+
+ /**
+ * Add a number of minutes to the date object.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.addMinutes(60);
+ * dtm.toString();
+ * @result 'Sat Jan 12 2008 01:00:00'
+ *
+ * @name addMinutes
+ * @type Date
+ * @cat Plugins/Methods/Date
+ */
+ add("addMinutes", function(num) {
+ this.setMinutes(this.getMinutes() + num);
+ return this;
+ });
+
+ /**
+ * Add a number of seconds to the date object.
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.addSeconds(60);
+ * dtm.toString();
+ * @result 'Sat Jan 12 2008 00:01:00'
+ *
+ * @name addSeconds
+ * @type Date
+ * @cat Plugins/Methods/Date
+ */
+ add("addSeconds", function(num) {
+ this.setSeconds(this.getSeconds() + num);
+ return this;
+ });
+
+ /**
+ * Sets the time component of this Date to zero for cleaner, easier comparison of dates where time is not relevant.
+ *
+ * @example var dtm = new Date();
+ * dtm.zeroTime();
+ * dtm.toString();
+ * @result 'Sat Jan 12 2008 00:01:00'
+ *
+ * @name zeroTime
+ * @type Date
+ * @cat Plugins/Methods/Date
+ * @author Kelvin Luck
+ */
+ add("zeroTime", function() {
+ this.setMilliseconds(0);
+ this.setSeconds(0);
+ this.setMinutes(0);
+ this.setHours(0);
+ return this;
+ });
+
+ /**
+ * Returns a string representation of the date object according to Date.format.
+ * (Date.toString may be used in other places so I purposefully didn't overwrite it)
+ *
+ * @example var dtm = new Date("01/12/2008");
+ * dtm.asString();
+ * @result '12/01/2008' // (where Date.format == 'dd/mm/yyyy'
+ *
+ * @name asString
+ * @type Date
+ * @cat Plugins/Methods/Date
+ * @author Kelvin Luck
+ */
+ add("asString", function(format) {
+ var r = format || Date.format;
+ if (r.split('mm').length>1) { // ugly workaround to make sure we don't replace the m's in e.g. noveMber
+ r = r.split('mmmm').join(this.getMonthName(false))
+ .split('mmm').join(this.getMonthName(true))
+ .split('mm').join(_zeroPad(this.getMonth()+1))
+ } else {
+ r = r.split('m').join(this.getMonth()+1);
+ }
+ r = r.split('yyyy').join(this.getFullYear())
+ .split('yy').join((this.getFullYear() + '').substring(2))
+ .split('dd').join(_zeroPad(this.getDate()))
+ .split('d').join(this.getDate());
+ return r;
+ });
+
+ /**
+ * Returns a new date object created from the passed String according to Date.format or false if the attempt to do this results in an invalid date object
+ * (We can't simple use Date.parse as it's not aware of locale and I chose not to overwrite it incase it's functionality is being relied on elsewhere)
+ *
+ * @example var dtm = Date.fromString("12/01/2008");
+ * dtm.toString();
+ * @result 'Sat Jan 12 2008 00:00:00' // (where Date.format == 'dd/mm/yyyy'
+ *
+ * @name fromString
+ * @type Date
+ * @cat Plugins/Methods/Date
+ * @author Kelvin Luck
+ */
+ Date.fromString = function(s)
+ {
+ var f = Date.format;
+
+ var d = new Date('01/01/1970');
+
+ if (s == '') return d;
+
+ s = s.toLowerCase();
+ var matcher = '';
+ var order = [];
+ var r = /(dd?d?|mm?m?|yy?yy?)+([^(m|d|y)])?/g;
+ var results;
+ while ((results = r.exec(f)) != null)
+ {
+ switch (results[1]) {
+ case 'd':
+ case 'dd':
+ case 'm':
+ case 'mm':
+ case 'yy':
+ case 'yyyy':
+ matcher += '(\\d+\\d?\\d?\\d?)+';
+ order.push(results[1].substr(0, 1));
+ break;
+ case 'mmm':
+ matcher += '([a-z]{3})';
+ order.push('M');
+ break;
+ }
+ if (results[2]) {
+ matcher += results[2];
+ }
+
+ }
+ var dm = new RegExp(matcher);
+ var result = s.match(dm);
+ for (var i=0; i<order.length; i++) {
+ var res = result[i+1];
+ switch(order[i]) {
+ case 'd':
+ d.setDate(res);
+ break;
+ case 'm':
+ d.setMonth(Number(res)-1);
+ break;
+ case 'M':
+ for (var j=0; j<Date.abbrMonthNames.length; j++) {
+ if (Date.abbrMonthNames[j].toLowerCase() == res) break;
+ }
+ d.setMonth(j);
+ break;
+ case 'y':
+ d.setYear(res);
+ break;
+ }
+ }
+
+ return d;
+ };
+
+ // utility method
+ var _zeroPad = function(num) {
+ var s = '0'+num;
+ return s.substring(s.length-2)
+ //return ('0'+num).substring(-2); // doesn't work on IE :(
+ };
+
+})(); \ No newline at end of file
diff --git a/static/datePicker.css b/static/datePicker.css
new file mode 100644
index 0000000..0361bc6
--- /dev/null
+++ b/static/datePicker.css
@@ -0,0 +1,129 @@
+
+
+table.jCalendar {
+ border: 1px solid #000;
+ background: #aaa;
+ border-collapse: separate;
+ border-spacing: 2px;
+}
+table.jCalendar th {
+ background: #333;
+ color: #fff;
+ font-weight: bold;
+ padding: 3px 5px;
+}
+
+table.jCalendar td {
+ background: #ccc;
+ color: #000;
+ padding: 3px 5px;
+ text-align: center;
+}
+table.jCalendar td.other-month {
+ background: #ddd;
+ color: #aaa;
+}
+table.jCalendar td.today {
+ background: #666;
+ color: #fff;
+}
+table.jCalendar td.selected {
+ background: #f66;
+ color: #fff;
+}
+table.jCalendar td.selected.dp-hover {
+ background: #f33;
+ color: #fff;
+}
+table.jCalendar td.dp-hover,
+table.jCalendar tr.activeWeekHover td {
+ background: #fff;
+ color: #000;
+}
+table.jCalendar tr.selectedWeek td {
+ background: #f66;
+ color: #fff;
+}
+table.jCalendar td.disabled, table.jCalendar td.disabled.dp-hover {
+ background: #bbb;
+ color: #888;
+}
+table.jCalendar td.unselectable,
+table.jCalendar td.unselectable:hover,
+table.jCalendar td.unselectable.dp-hover {
+ background: #bbb;
+ color: #888;
+}
+
+/* For the popup */
+
+/* NOTE - you will probably want to style a.dp-choose-date - see how I did it in demo.css */
+
+div.dp-popup {
+ position: relative;
+ background: #ccc;
+ font-size: 10px;
+ font-family: arial, sans-serif;
+ padding: 2px;
+ width: 171px;
+ line-height: 1.2em;
+}
+div#dp-popup {
+ position: absolute;
+ z-index: 199;
+}
+div.dp-popup h2 {
+ font-size: 12px;
+ text-align: center;
+ margin: 2px 0;
+ padding: 0;
+}
+a#dp-close {
+ font-size: 11px;
+ padding: 4px 0;
+ text-align: center;
+ display: block;
+}
+a#dp-close:hover {
+ text-decoration: underline;
+}
+div.dp-popup a {
+ color: #000;
+ text-decoration: none;
+ padding: 3px 2px 0;
+}
+div.dp-popup div.dp-nav-prev {
+ position: absolute;
+ top: 2px;
+ left: 4px;
+ width: 100px;
+}
+div.dp-popup div.dp-nav-prev a {
+ float: left;
+}
+/* Opera needs the rules to be this specific otherwise it doesn't change the cursor back to pointer after you have disabled and re-enabled a link */
+div.dp-popup div.dp-nav-prev a, div.dp-popup div.dp-nav-next a {
+ cursor: pointer;
+}
+div.dp-popup div.dp-nav-prev a.disabled, div.dp-popup div.dp-nav-next a.disabled {
+ cursor: default;
+}
+div.dp-popup div.dp-nav-next {
+ position: absolute;
+ top: 2px;
+ right: 4px;
+ width: 100px;
+}
+div.dp-popup div.dp-nav-next a {
+ float: right;
+}
+div.dp-popup a.disabled {
+ cursor: default;
+ color: #aaa;
+}
+div.dp-popup td {
+ cursor: pointer;
+}
+div.dp-popup td.disabled {
+ cursor: default;
+} \ No newline at end of file
diff --git a/static/door2.gif b/static/door2.gif
new file mode 100644
index 0000000..da0cca1
--- /dev/null
+++ b/static/door2.gif
Binary files differ
diff --git a/static/doorway.gif b/static/doorway.gif
new file mode 100644
index 0000000..15e1c94
--- /dev/null
+++ b/static/doorway.gif
Binary files differ
diff --git a/static/dot.gif b/static/dot.gif
new file mode 100644
index 0000000..339faf7
--- /dev/null
+++ b/static/dot.gif
Binary files differ
diff --git a/static/form_login/front.css b/static/form_login/front.css
new file mode 100644
index 0000000..ea767b0
--- /dev/null
+++ b/static/form_login/front.css
@@ -0,0 +1,146 @@
+#login-container {
+ float: right;
+ /*width:780px;
+ margin:0 auto;*/
+right:2;
+color:#fff;
+ position: relative;
+top:-6;
+filter:alpha(opacity=90);
+ -moz-opacity:0.9;
+ -khtml-opacity: 0.9;
+ opacity: 0.9;
+
+}
+
+#login-container a:link, a:visited {
+ color:#f0e;
+ text-decoration:none;
+}
+#login-container .topnav {
+ padding:10px 0px 12px;
+ font-size:11px;
+ line-height:23px;
+ text-align:right;
+
+}
+#login-container .topnav a.signin {
+
+ padding:4px 3 3px 6px;
+ text-decoration:none;
+border:1px solid #;
+background-color:#f0e;
+ font-weight:;
+ color:#fff;
+ -webkit-border-radius:4px;
+ -moz-border-radius:4px;
+ border-radius:4px;
+ *background:transparent url("images/signin-nav-bg-ie.png") no-repeat 0 0;
+ *padding:4px 12px 6px; filter:alpha(opacity=80);
+
+
+}
+#login-container .topnav a.signin:hover {
+ background:#59B;
+ *background:transparent url("images/signin-nav-bg-hover-ie.png") no-repeat 0 0;
+ *padding:4px 12px 6px;
+}
+#login-container .topnav a.signin, #login-container .topnav a.signin:hover {
+ *background-position:0 3px!important;
+}
+
+a.signin {
+ position:relative;
+ margin-left:3px;
+}
+a.signin span {
+ background-image:url("images/toggle_down_light.png");
+ background-repeat:no-repeat;
+ background-position:100% 50%;
+ padding:4px 16px 6px 0;
+}
+#login-container .topnav a.menu-open {
+ background:#ddeef6!important;
+ color:#666!important;
+ outline:none;box-shadow: 3px 2px 2px #ccc;
+-webkit-box-shadow: 3px 2px 2px #ccc;
+-moz-box-shadow: 3px 2px 2px #ccc;
+filter: progid:DXImageTransform.Microsoft.dropShadow(color=#ccc, offX=3, offY=4, positive=true);
+
+}
+
+a.signin.menu-open span {
+ background-image:url("images/toggle_up_dark.png");
+ color:#789;
+}
+
+#signin_menu {
+ -moz-border-radius-topleft:5px;
+ -moz-border-radius-bottomleft:5px;
+ -moz-border-radius-bottomright:5px;
+ -webkit-border-top-left-radius:5px;
+ -webkit-border-bottom-left-radius:5px;
+ -webkit-border-bottom-right-radius:5px;
+ display:none;
+ background-color:#ddeef6;
+ position:absolute;
+ width:210px;
+ z-index:100;
+ border:1px transparent;
+ text-align:left;
+ padding:12px;
+ top: 24.5px;
+ right: 0px;
+ margin-top:5px;
+ margin-right: 0px;
+ *margin-right: -1px;
+ color:#789;
+ font-size:11px; box-shadow: 3px 2px 2px #ccc;
+-webkit-box-shadow: 3px 2px 2px #ccc;
+-moz-box-shadow: 3px 2px 2px #ccc;
+filter: progid:DXImageTransform.Microsoft.dropShadow(color=#ccc, offX=3, offY=4, positive=true);
+}
+
+#signin_menu input[type=text], #signin_menu input[type=password] {
+ display:block;
+ -moz-border-radius:4px;
+ -webkit-border-radius:4px;
+ border:1px solid #ACE;
+ font-size:13px;
+ margin:0 0 5px;
+ padding:5px;
+ width:203px;
+}
+#signin_menu p {
+ margin:0;
+}
+#signin_menu a {
+ color:#6AC;
+}
+#signin_menu label {
+ font-weight:normal;
+}
+
+#signin_menu p a {
+ color:#27B!important;
+}
+#loginSubmit {
+ -moz-border-radius:4px;
+ -webkit-border-radius:4px;
+ background:#39d url('images/bg-btn-blue.png') repeat-x scroll 0 0;
+ border:1px solid #39D;
+ color:#fff;
+ text-shadow:0 -1px 0 #39d;
+ padding:4px 10px 5px;
+ font-size:11px;
+ margin:0 5px 0 0;
+ font-weight:bold;
+}
+#loginSubmit::-moz-focus-inner {
+padding:0;
+border:0;
+}
+#loginSubmit:hover, #loginSubmit:focus {
+ background-position:0 -5px;
+ cursor:pointer;
+} \ No newline at end of file
diff --git a/static/form_login/images/.DS_Store b/static/form_login/images/.DS_Store
new file mode 100644
index 0000000..5008ddf
--- /dev/null
+++ b/static/form_login/images/.DS_Store
Binary files differ
diff --git a/static/form_login/images/bg-btn-blue.png b/static/form_login/images/bg-btn-blue.png
new file mode 100644
index 0000000..058f726
--- /dev/null
+++ b/static/form_login/images/bg-btn-blue.png
Binary files differ
diff --git a/static/form_login/images/front-bg.gif b/static/form_login/images/front-bg.gif
new file mode 100644
index 0000000..dcd3ba9
--- /dev/null
+++ b/static/form_login/images/front-bg.gif
Binary files differ
diff --git a/static/form_login/images/signin-nav-bg-hover-ie.png b/static/form_login/images/signin-nav-bg-hover-ie.png
new file mode 100644
index 0000000..a89bb69
--- /dev/null
+++ b/static/form_login/images/signin-nav-bg-hover-ie.png
Binary files differ
diff --git a/static/form_login/images/signin-nav-bg-ie.png b/static/form_login/images/signin-nav-bg-ie.png
new file mode 100644
index 0000000..f0a0d2b
--- /dev/null
+++ b/static/form_login/images/signin-nav-bg-ie.png
Binary files differ
diff --git a/static/form_login/images/toggle_down_light.png b/static/form_login/images/toggle_down_light.png
new file mode 100644
index 0000000..d354161
--- /dev/null
+++ b/static/form_login/images/toggle_down_light.png
Binary files differ
diff --git a/static/form_login/images/toggle_up_dark.png b/static/form_login/images/toggle_up_dark.png
new file mode 100644
index 0000000..951d903
--- /dev/null
+++ b/static/form_login/images/toggle_up_dark.png
Binary files differ
diff --git a/static/gritter/css/jquery.gritter.css b/static/gritter/css/jquery.gritter.css
index 0d23e04..3189eb2 100755
--- a/static/gritter/css/jquery.gritter.css
+++ b/static/gritter/css/jquery.gritter.css
@@ -24,7 +24,7 @@
#gritter-notice-wrapper {
position:fixed;
top:70px;
- right:20px;
+ right:40px;
width:301px;
@@ -66,7 +66,7 @@ float:right;
display:block;
background:url(../images/gritter.png0) no-repeat left -40px;
background-color:#eee;
- color:#ccc;
+ color:#000;
height:auto;
padding:7px 15px 11px 11px;
font-size: 11px;
diff --git a/static/gritter/js/jquery.gritter.js b/static/gritter/js/jquery.gritter.js
index 60305ba..b673f8f 100755
--- a/static/gritter/js/jquery.gritter.js
+++ b/static/gritter/js/jquery.gritter.js
@@ -22,7 +22,7 @@
$.gritter.options = {
fade_in_speed: 'medium', // how fast notifications fade in
fade_out_speed: 1000, // how fast the notices fade out
- time: 2500 // hang on the screen for...
+ time: 4500 // hang on the screen for...
}
/**
diff --git a/static/header.css b/static/header.css
index 4b03c2c..a128095 100755
--- a/static/header.css
+++ b/static/header.css
@@ -9,6 +9,10 @@
font-size:16px;
color: #fff;
}
+#strapline{position:absolute;
+top:6;
+right:20%;
+}
.white a:hover {
text-decoration: none;
text-shadow: -1px 1px 1px #;
@@ -42,27 +46,32 @@ filter: progid:DXImageTransform.Microsoft.dropShadow(color=#036aca, offX=3, offY
}
#bar7{
- top:28px;
+ top:25px;
position:absolute;
font-family: Arial, Helvetica, sans-serif;
- font-size: 18px;
+ font-size: 16px;
left: 170px;
- margin-left: 2%;
+ margin-left: 1%;
margin-right: 8%;
letter-spacing: -1px;
z-index: 999;
}
#logout7{
- top:5px;
+ top:2px;
position:relative;
font-size:12px;
- margin-right: 10px;
+ margin-right: 5px;
float:right;
z-index: 999;
+ line-height:1.5;
font-family: Arial, Helvetica, sans-serif;
font-weight: normal;
}
+#logout7 a{font-size:12px;
+}
+#logout7 a:hover{font-size:12px;
+}
#logo7{
top:20px;
margin-left: 15px;
@@ -251,9 +260,8 @@ border:0;
.btnav { border: 0px #000000 solid;}
body {
- background-color:#e3e3e3;
- background-position:center;
+
z-index:0;
}
diff --git a/static/index.html b/static/index.html
index df36408..f80e5da 100755
--- a/static/index.html
+++ b/static/index.html
@@ -1,9 +1,9 @@
</html><head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
- <script type="text/javascript" src="/static/jquery-1.3.2.min.js"></script>
- <script type="text/javascript" src="static/sha1.js"></script>
- <script type="text/javascript" src="static/home.js"></script>
- <script type="text/javascript" src="static/background.js"></script>
+ <script type="text/javascript" src="/static/js/underscore-min.js"></script>
+ <script type="text/javascript" src="/static/js/sha1.js"></script>
+ <script type="text/javascript" src="/static/js/home.js"></script>
+ <script type="text/javascript" src="static/background.js"></script>
<script>
$(document).ready(initHome);
</script>
@@ -198,17 +198,9 @@ body {
<p align="center" class="line">Talk with pictures. </p>
<h1 align="center">&nbsp;</h1>
<h1 align="center"><br />
- u
- <input type="text" class="feild"id="nickInput" size="17" name="txt"
-onfocus="if(this.beenchanged!=true){ this.value = ''}"
-onblur="if(this.beenchanged!=true) { this.value='username' }"
-onchange="this.beenchanged = true;"/>
+ <input type="text" class="feild"id="nickInput" size="17" name="txt" />
<br />
- p
- <input type="password" class="feild" id="passwordInput" size="17"name="txt"
-onfocus="if(this.beenchanged!=true){ this.value = ''}"
-onblur="if(this.beenchanged!=true) { this.value='passwordpasswordd' }"
-onchange="this.beenchanged = true;"/>
+ <input type="password" class="feild" id="passwordInput" size="17"name="txt" />
</h1>
<h1 align="center"> <br />
<input type="submit" class="submit" id="loginSubmit" value="Log In" />
diff --git a/static/jewel.gif b/static/jewel.gif
new file mode 100644
index 0000000..8acdebf
--- /dev/null
+++ b/static/jewel.gif
Binary files differ
diff --git a/static/jewelblu.gif b/static/jewelblu.gif
new file mode 100644
index 0000000..9868b02
--- /dev/null
+++ b/static/jewelblu.gif
Binary files differ
diff --git a/static/jquery.datePicker.js b/static/jquery.datePicker.js
new file mode 100644
index 0000000..4bb82e0
--- /dev/null
+++ b/static/jquery.datePicker.js
@@ -0,0 +1,1189 @@
+/**
+ * Copyright (c) 2008 Kelvin Luck (http://www.kelvinluck.com/)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ * .
+ * $Id: jquery.datePicker.js 84 2009-08-05 17:54:35Z kelvin.luck@gmail.com $
+ **/
+
+(function($){
+
+ $.fn.extend({
+/**
+ * Render a calendar table into any matched elements.
+ *
+ * @param Object s (optional) Customize your calendars.
+ * @option Number month The month to render (NOTE that months are zero based). Default is today's month.
+ * @option Number year The year to render. Default is today's year.
+ * @option Function renderCallback A reference to a function that is called as each cell is rendered and which can add classes and event listeners to the created nodes. Default is no callback.
+ * @option Number showHeader Whether or not to show the header row, possible values are: $.dpConst.SHOW_HEADER_NONE (no header), $.dpConst.SHOW_HEADER_SHORT (first letter of each day) and $.dpConst.SHOW_HEADER_LONG (full name of each day). Default is $.dpConst.SHOW_HEADER_SHORT.
+ * @option String hoverClass The class to attach to each cell when you hover over it (to allow you to use hover effects in IE6 which doesn't support the :hover pseudo-class on elements other than links). Default is dp-hover. Pass false if you don't want a hover class.
+ * @type jQuery
+ * @name renderCalendar
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('#calendar-me').renderCalendar({month:0, year:2007});
+ * @desc Renders a calendar displaying January 2007 into the element with an id of calendar-me.
+ *
+ * @example
+ * var testCallback = function($td, thisDate, month, year)
+ * {
+ * if ($td.is('.current-month') && thisDate.getDay() == 4) {
+ * var d = thisDate.getDate();
+ * $td.bind(
+ * 'click',
+ * function()
+ * {
+ * alert('You clicked on ' + d + '/' + (Number(month)+1) + '/' + year);
+ * }
+ * ).addClass('thursday');
+ * } else if (thisDate.getDay() == 5) {
+ * $td.html('Friday the ' + $td.html() + 'th');
+ * }
+ * }
+ * $('#calendar-me').renderCalendar({month:0, year:2007, renderCallback:testCallback});
+ *
+ * @desc Renders a calendar displaying January 2007 into the element with an id of calendar-me. Every Thursday in the current month has a class of "thursday" applied to it, is clickable and shows an alert when clicked. Every Friday on the calendar has the number inside replaced with text.
+ **/
+ renderCalendar : function(s)
+ {
+ var dc = function(a)
+ {
+ return document.createElement(a);
+ };
+
+ s = $.extend({}, $.fn.datePicker.defaults, s);
+
+ if (s.showHeader != $.dpConst.SHOW_HEADER_NONE) {
+ var headRow = $(dc('tr'));
+ for (var i=Date.firstDayOfWeek; i<Date.firstDayOfWeek+7; i++) {
+ var weekday = i%7;
+ var day = Date.dayNames[weekday];
+ headRow.append(
+ jQuery(dc('th')).attr({'scope':'col', 'abbr':day, 'title':day, 'class':(weekday == 0 || weekday == 6 ? 'weekend' : 'weekday')}).html(s.showHeader == $.dpConst.SHOW_HEADER_SHORT ? day.substr(0, 1) : day)
+ );
+ }
+ };
+
+ var calendarTable = $(dc('table'))
+ .attr(
+ {
+ 'cellspacing':2
+ }
+ )
+ .addClass('jCalendar')
+ .append(
+ (s.showHeader != $.dpConst.SHOW_HEADER_NONE ?
+ $(dc('thead'))
+ .append(headRow)
+ :
+ dc('thead')
+ )
+ );
+ var tbody = $(dc('tbody'));
+
+ var today = (new Date()).zeroTime();
+ today.setHours(12);
+
+ var month = s.month == undefined ? today.getMonth() : s.month;
+ var year = s.year || today.getFullYear();
+
+ var currentDate = (new Date(year, month, 1, 12, 0, 0));
+
+
+ var firstDayOffset = Date.firstDayOfWeek - currentDate.getDay() + 1;
+ if (firstDayOffset > 1) firstDayOffset -= 7;
+ var weeksToDraw = Math.ceil(( (-1*firstDayOffset+1) + currentDate.getDaysInMonth() ) /7);
+ currentDate.addDays(firstDayOffset-1);
+
+ var doHover = function(firstDayInBounds)
+ {
+ return function()
+ {
+ if (s.hoverClass) {
+ var $this = $(this);
+ if (!s.selectWeek) {
+ $this.addClass(s.hoverClass);
+ } else if (firstDayInBounds && !$this.is('.disabled')) {
+ $this.parent().addClass('activeWeekHover');
+ }
+ }
+ }
+ };
+ var unHover = function()
+ {
+ if (s.hoverClass) {
+ var $this = $(this);
+ $this.removeClass(s.hoverClass);
+ $this.parent().removeClass('activeWeekHover');
+ }
+ };
+
+ var w = 0;
+ while (w++<weeksToDraw) {
+ var r = jQuery(dc('tr'));
+ var firstDayInBounds = s.dpController ? currentDate > s.dpController.startDate : false;
+ for (var i=0; i<7; i++) {
+ var thisMonth = currentDate.getMonth() == month;
+ var d = $(dc('td'))
+ .text(currentDate.getDate() + '')
+ .addClass((thisMonth ? 'current-month ' : 'other-month ') +
+ (currentDate.isWeekend() ? 'weekend ' : 'weekday ') +
+ (thisMonth && currentDate.getTime() == today.getTime() ? 'today ' : '')
+ )
+ .data('datePickerDate', currentDate.asString())
+ .hover(doHover(firstDayInBounds), unHover)
+ ;
+ r.append(d);
+ if (s.renderCallback) {
+ s.renderCallback(d, currentDate, month, year);
+ }
+ // addDays(1) fails in some locales due to daylight savings. See issue 39.
+ //currentDate.addDays(1);
+ // set the time to midday to avoid any weird timezone issues??
+ currentDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate()+1, 12, 0, 0);
+ }
+ tbody.append(r);
+ }
+ calendarTable.append(tbody);
+
+ return this.each(
+ function()
+ {
+ $(this).empty().append(calendarTable);
+ }
+ );
+ },
+/**
+ * Create a datePicker associated with each of the matched elements.
+ *
+ * The matched element will receive a few custom events with the following signatures:
+ *
+ * dateSelected(event, date, $td, status)
+ * Triggered when a date is selected. event is a reference to the event, date is the Date selected, $td is a jquery object wrapped around the TD that was clicked on and status is whether the date was selected (true) or deselected (false)
+ *
+ * dpClosed(event, selected)
+ * Triggered when the date picker is closed. event is a reference to the event and selected is an Array containing Date objects.
+ *
+ * dpMonthChanged(event, displayedMonth, displayedYear)
+ * Triggered when the month of the popped up calendar is changed. event is a reference to the event, displayedMonth is the number of the month now displayed (zero based) and displayedYear is the year of the month.
+ *
+ * dpDisplayed(event, $datePickerDiv)
+ * Triggered when the date picker is created. $datePickerDiv is the div containing the date picker. Use this event to add custom content/ listeners to the popped up date picker.
+ *
+ * @param Object s (optional) Customize your date pickers.
+ * @option Number month The month to render when the date picker is opened (NOTE that months are zero based). Default is today's month.
+ * @option Number year The year to render when the date picker is opened. Default is today's year.
+ * @option String startDate The first date date can be selected.
+ * @option String endDate The last date that can be selected.
+ * @option Boolean inline Whether to create the datePicker as inline (e.g. always on the page) or as a model popup. Default is false (== modal popup)
+ * @option Boolean createButton Whether to create a .dp-choose-date anchor directly after the matched element which when clicked will trigger the showing of the date picker. Default is true.
+ * @option Boolean showYearNavigation Whether to display buttons which allow the user to navigate through the months a year at a time. Default is true.
+ * @option Boolean closeOnSelect Whether to close the date picker when a date is selected. Default is true.
+ * @option Boolean displayClose Whether to create a "Close" button within the date picker popup. Default is false.
+ * @option Boolean selectMultiple Whether a user should be able to select multiple dates with this date picker. Default is false.
+ * @option Number numSelectable The maximum number of dates that can be selected where selectMultiple is true. Default is a very high number.
+ * @option Boolean clickInput If the matched element is an input type="text" and this option is true then clicking on the input will cause the date picker to appear.
+ * @option Boolean rememberViewedMonth Whether the datePicker should remember the last viewed month and open on it. If false then the date picker will always open with the month for the first selected date visible.
+ * @option Boolean selectWeek Whether to select a complete week at a time...
+ * @option Number verticalPosition The vertical alignment of the popped up date picker to the matched element. One of $.dpConst.POS_TOP and $.dpConst.POS_BOTTOM. Default is $.dpConst.POS_TOP.
+ * @option Number horizontalPosition The horizontal alignment of the popped up date picker to the matched element. One of $.dpConst.POS_LEFT and $.dpConst.POS_RIGHT.
+ * @option Number verticalOffset The number of pixels offset from the defined verticalPosition of this date picker that it should pop up in. Default in 0.
+ * @option Number horizontalOffset The number of pixels offset from the defined horizontalPosition of this date picker that it should pop up in. Default in 0.
+ * @option (Function|Array) renderCallback A reference to a function (or an array of seperate functions) that is called as each cell is rendered and which can add classes and event listeners to the created nodes. Each callback function will receive four arguments; a jquery object wrapping the created TD, a Date object containing the date this TD represents, a number giving the currently rendered month and a number giving the currently rendered year. Default is no callback.
+ * @option String hoverClass The class to attach to each cell when you hover over it (to allow you to use hover effects in IE6 which doesn't support the :hover pseudo-class on elements other than links). Default is dp-hover. Pass false if you don't want a hover class.
+ * @type jQuery
+ * @name datePicker
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('input.date-picker').datePicker();
+ * @desc Creates a date picker button next to all matched input elements. When the button is clicked on the value of the selected date will be placed in the corresponding input (formatted according to Date.format).
+ *
+ * @example demo/index.html
+ * @desc See the projects homepage for many more complex examples...
+ **/
+ datePicker : function(s)
+ {
+ if (!$.event._dpCache) $.event._dpCache = [];
+
+ // initialise the date picker controller with the relevant settings...
+ s = $.extend({}, $.fn.datePicker.defaults, s);
+
+ return this.each(
+ function()
+ {
+ var $this = $(this);
+ var alreadyExists = true;
+
+ if (!this._dpId) {
+ this._dpId = $.event.guid++;
+ $.event._dpCache[this._dpId] = new DatePicker(this);
+ alreadyExists = false;
+ }
+
+ if (s.inline) {
+ s.createButton = false;
+ s.displayClose = false;
+ s.closeOnSelect = false;
+ $this.empty();
+ }
+
+ var controller = $.event._dpCache[this._dpId];
+
+ controller.init(s);
+
+ if (!alreadyExists && s.createButton) {
+ // create it!
+ controller.button = $('<a href="#" class="dp-choose-date" title="' + $.dpText.TEXT_CHOOSE_DATE + '">' + $.dpText.TEXT_CHOOSE_DATE + '</a>')
+ .bind(
+ 'click',
+ function()
+ {
+ $this.dpDisplay(this);
+ this.blur();
+ return false;
+ }
+ );
+ $this.after(controller.button);
+ }
+
+ if (!alreadyExists && $this.is(':text')) {
+ $this
+ .bind(
+ 'dateSelected',
+ function(e, selectedDate, $td)
+ {
+ this.value = selectedDate.asString();
+ }
+ ).bind(
+ 'change',
+ function()
+ {
+ if (this.value == '') {
+ controller.clearSelected();
+ } else {
+ var d = Date.fromString(this.value);
+ if (d) {
+ controller.setSelected(d, true, true);
+ }
+ }
+ }
+ );
+ if (s.clickInput) {
+ $this.bind(
+ 'click',
+ function()
+ {
+ // The change event doesn't happen until the input loses focus so we need to manually trigger it...
+ $this.trigger('change');
+ $this.dpDisplay();
+ }
+ );
+ }
+ var d = Date.fromString(this.value);
+ if (this.value != '' && d) {
+ controller.setSelected(d, true, true);
+ }
+ }
+
+ $this.addClass('dp-applied');
+
+ }
+ )
+ },
+/**
+ * Disables or enables this date picker
+ *
+ * @param Boolean s Whether to disable (true) or enable (false) this datePicker
+ * @type jQuery
+ * @name dpSetDisabled
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-picker').datePicker();
+ * $('.date-picker').dpSetDisabled(true);
+ * @desc Prevents this date picker from displaying and adds a class of dp-disabled to it (and it's associated button if it has one) for styling purposes. If the matched element is an input field then it will also set the disabled attribute to stop people directly editing the field.
+ **/
+ dpSetDisabled : function(s)
+ {
+ return _w.call(this, 'setDisabled', s);
+ },
+/**
+ * Updates the first selectable date for any date pickers on any matched elements.
+ *
+ * @param String d A string representing the first selectable date (formatted according to Date.format).
+ * @type jQuery
+ * @name dpSetStartDate
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-picker').datePicker();
+ * $('.date-picker').dpSetStartDate('01/01/2000');
+ * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the first selectable date for each of these to the first day of the millenium.
+ **/
+ dpSetStartDate : function(d)
+ {
+ return _w.call(this, 'setStartDate', d);
+ },
+/**
+ * Updates the last selectable date for any date pickers on any matched elements.
+ *
+ * @param String d A string representing the last selectable date (formatted according to Date.format).
+ * @type jQuery
+ * @name dpSetEndDate
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-picker').datePicker();
+ * $('.date-picker').dpSetEndDate('01/01/2010');
+ * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the last selectable date for each of these to the first Janurary 2010.
+ **/
+ dpSetEndDate : function(d)
+ {
+ return _w.call(this, 'setEndDate', d);
+ },
+/**
+ * Gets a list of Dates currently selected by this datePicker. This will be an empty array if no dates are currently selected or NULL if there is no datePicker associated with the matched element.
+ *
+ * @type Array
+ * @name dpGetSelected
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-picker').datePicker();
+ * alert($('.date-picker').dpGetSelected());
+ * @desc Will alert an empty array (as nothing is selected yet)
+ **/
+ dpGetSelected : function()
+ {
+ var c = _getController(this[0]);
+ if (c) {
+ return c.getSelected();
+ }
+ return null;
+ },
+/**
+ * Selects or deselects a date on any matched element's date pickers. Deselcting is only useful on date pickers where selectMultiple==true. Selecting will only work if the passed date is within the startDate and endDate boundries for a given date picker.
+ *
+ * @param String d A string representing the date you want to select (formatted according to Date.format).
+ * @param Boolean v Whether you want to select (true) or deselect (false) this date. Optional - default = true.
+ * @param Boolean m Whether you want the date picker to open up on the month of this date when it is next opened. Optional - default = true.
+ * @param Boolean e Whether you want the date picker to dispatch events related to this change of selection. Optional - default = true.
+ * @type jQuery
+ * @name dpSetSelected
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-picker').datePicker();
+ * $('.date-picker').dpSetSelected('01/01/2010');
+ * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the selected date on these date pickers to the first Janurary 2010. When the date picker is next opened it will display Janurary 2010.
+ **/
+ dpSetSelected : function(d, v, m, e)
+ {
+ if (v == undefined) v=true;
+ if (m == undefined) m=true;
+ if (e == undefined) e=true;
+ return _w.call(this, 'setSelected', Date.fromString(d), v, m, e);
+ },
+/**
+ * Sets the month that will be displayed when the date picker is next opened. If the passed month is before startDate then the month containing startDate will be displayed instead. If the passed month is after endDate then the month containing the endDate will be displayed instead.
+ *
+ * @param Number m The month you want the date picker to display. Optional - defaults to the currently displayed month.
+ * @param Number y The year you want the date picker to display. Optional - defaults to the currently displayed year.
+ * @type jQuery
+ * @name dpSetDisplayedMonth
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-picker').datePicker();
+ * $('.date-picker').dpSetDisplayedMonth(10, 2008);
+ * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the selected date on these date pickers to the first Janurary 2010. When the date picker is next opened it will display Janurary 2010.
+ **/
+ dpSetDisplayedMonth : function(m, y)
+ {
+ return _w.call(this, 'setDisplayedMonth', Number(m), Number(y), true);
+ },
+/**
+ * Displays the date picker associated with the matched elements. Since only one date picker can be displayed at once then the date picker associated with the last matched element will be the one that is displayed.
+ *
+ * @param HTMLElement e An element that you want the date picker to pop up relative in position to. Optional - default behaviour is to pop up next to the element associated with this date picker.
+ * @type jQuery
+ * @name dpDisplay
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('#date-picker').datePicker();
+ * $('#date-picker').dpDisplay();
+ * @desc Creates a date picker associated with the element with an id of date-picker and then causes it to pop up.
+ **/
+ dpDisplay : function(e)
+ {
+ return _w.call(this, 'display', e);
+ },
+/**
+ * Sets a function or array of functions that is called when each TD of the date picker popup is rendered to the page
+ *
+ * @param (Function|Array) a A function or an array of functions that are called when each td is rendered. Each function will receive four arguments; a jquery object wrapping the created TD, a Date object containing the date this TD represents, a number giving the currently rendered month and a number giving the currently rendered year.
+ * @type jQuery
+ * @name dpSetRenderCallback
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('#date-picker').datePicker();
+ * $('#date-picker').dpSetRenderCallback(function($td, thisDate, month, year)
+ * {
+ * // do stuff as each td is rendered dependant on the date in the td and the displayed month and year
+ * });
+ * @desc Creates a date picker associated with the element with an id of date-picker and then creates a function which is called as each td is rendered when this date picker is displayed.
+ **/
+ dpSetRenderCallback : function(a)
+ {
+ return _w.call(this, 'setRenderCallback', a);
+ },
+/**
+ * Sets the position that the datePicker will pop up (relative to it's associated element)
+ *
+ * @param Number v The vertical alignment of the created date picker to it's associated element. Possible values are $.dpConst.POS_TOP and $.dpConst.POS_BOTTOM
+ * @param Number h The horizontal alignment of the created date picker to it's associated element. Possible values are $.dpConst.POS_LEFT and $.dpConst.POS_RIGHT
+ * @type jQuery
+ * @name dpSetPosition
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('#date-picker').datePicker();
+ * $('#date-picker').dpSetPosition($.dpConst.POS_BOTTOM, $.dpConst.POS_RIGHT);
+ * @desc Creates a date picker associated with the element with an id of date-picker and makes it so that when this date picker pops up it will be bottom and right aligned to the #date-picker element.
+ **/
+ dpSetPosition : function(v, h)
+ {
+ return _w.call(this, 'setPosition', v, h);
+ },
+/**
+ * Sets the offset that the popped up date picker will have from it's default position relative to it's associated element (as set by dpSetPosition)
+ *
+ * @param Number v The vertical offset of the created date picker.
+ * @param Number h The horizontal offset of the created date picker.
+ * @type jQuery
+ * @name dpSetOffset
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('#date-picker').datePicker();
+ * $('#date-picker').dpSetOffset(-20, 200);
+ * @desc Creates a date picker associated with the element with an id of date-picker and makes it so that when this date picker pops up it will be 20 pixels above and 200 pixels to the right of it's default position.
+ **/
+ dpSetOffset : function(v, h)
+ {
+ return _w.call(this, 'setOffset', v, h);
+ },
+/**
+ * Closes the open date picker associated with this element.
+ *
+ * @type jQuery
+ * @name dpClose
+ * @cat plugins/datePicker
+ * @author Kelvin Luck (http://www.kelvinluck.com/)
+ *
+ * @example $('.date-pick')
+ * .datePicker()
+ * .bind(
+ * 'focus',
+ * function()
+ * {
+ * $(this).dpDisplay();
+ * }
+ * ).bind(
+ * 'blur',
+ * function()
+ * {
+ * $(this).dpClose();
+ * }
+ * );
+ * @desc Creates a date picker and makes it appear when the relevant element is focused and disappear when it is blurred.
+ **/
+ dpClose : function()
+ {
+ return _w.call(this, '_closeCalendar', false, this[0]);
+ },
+ // private function called on unload to clean up any expandos etc and prevent memory links...
+ _dpDestroy : function()
+ {
+ // TODO - implement this?
+ }
+ });
+
+ // private internal function to cut down on the amount of code needed where we forward
+ // dp* methods on the jQuery object on to the relevant DatePicker controllers...
+ var _w = function(f, a1, a2, a3, a4)
+ {
+ return this.each(
+ function()
+ {
+ var c = _getController(this);
+ if (c) {
+ c[f](a1, a2, a3, a4);
+ }
+ }
+ );
+ };
+
+ function DatePicker(ele)
+ {
+ this.ele = ele;
+
+ // initial values...
+ this.displayedMonth = null;
+ this.displayedYear = null;
+ this.startDate = null;
+ this.endDate = null;
+ this.showYearNavigation = null;
+ this.closeOnSelect = null;
+ this.displayClose = null;
+ this.rememberViewedMonth= null;
+ this.selectMultiple = null;
+ this.numSelectable = null;
+ this.numSelected = null;
+ this.verticalPosition = null;
+ this.horizontalPosition = null;
+ this.verticalOffset = null;
+ this.horizontalOffset = null;
+ this.button = null;
+ this.renderCallback = [];
+ this.selectedDates = {};
+ this.inline = null;
+ this.context = '#dp-popup';
+ this.settings = {};
+ };
+ $.extend(
+ DatePicker.prototype,
+ {
+ init : function(s)
+ {
+ this.setStartDate(s.startDate);
+ this.setEndDate(s.endDate);
+ this.setDisplayedMonth(Number(s.month), Number(s.year));
+ this.setRenderCallback(s.renderCallback);
+ this.showYearNavigation = s.showYearNavigation;
+ this.closeOnSelect = s.closeOnSelect;
+ this.displayClose = s.displayClose;
+ this.rememberViewedMonth = s.rememberViewedMonth;
+ this.selectMultiple = s.selectMultiple;
+ this.numSelectable = s.selectMultiple ? s.numSelectable : 1;
+ this.numSelected = 0;
+ this.verticalPosition = s.verticalPosition;
+ this.horizontalPosition = s.horizontalPosition;
+ this.hoverClass = s.hoverClass;
+ this.setOffset(s.verticalOffset, s.horizontalOffset);
+ this.inline = s.inline;
+ this.settings = s;
+ if (this.inline) {
+ this.context = this.ele;
+ this.display();
+ }
+ },
+ setStartDate : function(d)
+ {
+ if (d) {
+ this.startDate = Date.fromString(d);
+ }
+ if (!this.startDate) {
+ this.startDate = (new Date()).zeroTime();
+ }
+ this.setDisplayedMonth(this.displayedMonth, this.displayedYear);
+ },
+ setEndDate : function(d)
+ {
+ if (d) {
+ this.endDate = Date.fromString(d);
+ }
+ if (!this.endDate) {
+ this.endDate = (new Date('12/31/2999')); // using the JS Date.parse function which expects mm/dd/yyyy
+ }
+ if (this.endDate.getTime() < this.startDate.getTime()) {
+ this.endDate = this.startDate;
+ }
+ this.setDisplayedMonth(this.displayedMonth, this.displayedYear);
+ },
+ setPosition : function(v, h)
+ {
+ this.verticalPosition = v;
+ this.horizontalPosition = h;
+ },
+ setOffset : function(v, h)
+ {
+ this.verticalOffset = parseInt(v) || 0;
+ this.horizontalOffset = parseInt(h) || 0;
+ },
+ setDisabled : function(s)
+ {
+ $e = $(this.ele);
+ $e[s ? 'addClass' : 'removeClass']('dp-disabled');
+ if (this.button) {
+ $but = $(this.button);
+ $but[s ? 'addClass' : 'removeClass']('dp-disabled');
+ $but.attr('title', s ? '' : $.dpText.TEXT_CHOOSE_DATE);
+ }
+ if ($e.is(':text')) {
+ $e.attr('disabled', s ? 'disabled' : '');
+ }
+ },
+ setDisplayedMonth : function(m, y, rerender)
+ {
+ if (this.startDate == undefined || this.endDate == undefined) {
+ return;
+ }
+ var s = new Date(this.startDate.getTime());
+ s.setDate(1);
+ var e = new Date(this.endDate.getTime());
+ e.setDate(1);
+
+ var t;
+ if ((!m && !y) || (isNaN(m) && isNaN(y))) {
+ // no month or year passed - default to current month
+ t = new Date().zeroTime();
+ t.setDate(1);
+ } else if (isNaN(m)) {
+ // just year passed in - presume we want the displayedMonth
+ t = new Date(y, this.displayedMonth, 1);
+ } else if (isNaN(y)) {
+ // just month passed in - presume we want the displayedYear
+ t = new Date(this.displayedYear, m, 1);
+ } else {
+ // year and month passed in - that's the date we want!
+ t = new Date(y, m, 1)
+ }
+ // check if the desired date is within the range of our defined startDate and endDate
+ if (t.getTime() < s.getTime()) {
+ t = s;
+ } else if (t.getTime() > e.getTime()) {
+ t = e;
+ }
+ var oldMonth = this.displayedMonth;
+ var oldYear = this.displayedYear;
+ this.displayedMonth = t.getMonth();
+ this.displayedYear = t.getFullYear();
+
+ if (rerender && (this.displayedMonth != oldMonth || this.displayedYear != oldYear))
+ {
+ this._rerenderCalendar();
+ $(this.ele).trigger('dpMonthChanged', [this.displayedMonth, this.displayedYear]);
+ }
+ },
+ setSelected : function(d, v, moveToMonth, dispatchEvents)
+ {
+ if (d < this.startDate || d > this.endDate) {
+ // Don't allow people to select dates outside range...
+ return;
+ }
+ var s = this.settings;
+ if (s.selectWeek)
+ {
+ d = d.addDays(- (d.getDay() - Date.firstDayOfWeek + 7) % 7);
+ if (d < this.startDate) // The first day of this week is before the start date so is unselectable...
+ {
+ return;
+ }
+ }
+ if (v == this.isSelected(d)) // this date is already un/selected
+ {
+ return;
+ }
+ if (this.selectMultiple == false) {
+ this.clearSelected();
+ } else if (v && this.numSelected == this.numSelectable) {
+ // can't select any more dates...
+ return;
+ }
+ if (moveToMonth && (this.displayedMonth != d.getMonth() || this.displayedYear != d.getFullYear())) {
+ this.setDisplayedMonth(d.getMonth(), d.getFullYear(), true);
+ }
+ this.selectedDates[d.asString()] = v;
+ this.numSelected += v ? 1 : -1;
+ var selectorString = 'td.' + (d.getMonth() == this.displayedMonth ? 'current-month' : 'other-month');
+ var $td;
+ $(selectorString, this.context).each(
+ function()
+ {
+ if ($(this).data('datePickerDate') == d.asString()) {
+ $td = $(this);
+ if (s.selectWeek)
+ {
+ $td.parent()[v ? 'addClass' : 'removeClass']('selectedWeek');
+ }
+ $td[v ? 'addClass' : 'removeClass']('selected');
+ }
+ }
+ );
+ $('td', this.context).not('.selected')[this.selectMultiple && this.numSelected == this.numSelectable ? 'addClass' : 'removeClass']('unselectable');
+
+ if (dispatchEvents)
+ {
+ var s = this.isSelected(d);
+ $e = $(this.ele);
+ var dClone = Date.fromString(d.asString());
+ $e.trigger('dateSelected', [dClone, $td, s]);
+ $e.trigger('change');
+ }
+ },
+ isSelected : function(d)
+ {
+ return this.selectedDates[d.asString()];
+ },
+ getSelected : function()
+ {
+ var r = [];
+ for(s in this.selectedDates) {
+ if (this.selectedDates[s] == true) {
+ r.push(Date.fromString(s));
+ }
+ }
+ return r;
+ },
+ clearSelected : function()
+ {
+ this.selectedDates = {};
+ this.numSelected = 0;
+ $('td.selected', this.context).removeClass('selected').parent().removeClass('selectedWeek');
+ },
+ display : function(eleAlignTo)
+ {
+ if ($(this.ele).is('.dp-disabled')) return;
+
+ eleAlignTo = eleAlignTo || this.ele;
+ var c = this;
+ var $ele = $(eleAlignTo);
+ var eleOffset = $ele.offset();
+
+ var $createIn;
+ var attrs;
+ var attrsCalendarHolder;
+ var cssRules;
+
+ if (c.inline) {
+ $createIn = $(this.ele);
+ attrs = {
+ 'id' : 'calendar-' + this.ele._dpId,
+ 'class' : 'dp-popup dp-popup-inline'
+ };
+
+ $('.dp-popup', $createIn).remove();
+ cssRules = {
+ };
+ } else {
+ $createIn = $('body');
+ attrs = {
+ 'id' : 'dp-popup',
+ 'class' : 'dp-popup'
+ };
+ cssRules = {
+ 'top' : eleOffset.top + c.verticalOffset,
+ 'left' : eleOffset.left + c.horizontalOffset
+ };
+
+ var _checkMouse = function(e)
+ {
+ var el = e.target;
+ var cal = $('#dp-popup')[0];
+
+ while (true){
+ if (el == cal) {
+ return true;
+ } else if (el == document) {
+ c._closeCalendar();
+ return false;
+ } else {
+ el = $(el).parent()[0];
+ }
+ }
+ };
+ this._checkMouse = _checkMouse;
+
+ c._closeCalendar(true);
+ $(document).bind(
+ 'keydown.datepicker',
+ function(event)
+ {
+ if (event.keyCode == 27) {
+ c._closeCalendar();
+ }
+ }
+ );
+ }
+
+ if (!c.rememberViewedMonth)
+ {
+ var selectedDate = this.getSelected()[0];
+ if (selectedDate) {
+ selectedDate = new Date(selectedDate);
+ this.setDisplayedMonth(selectedDate.getMonth(), selectedDate.getFullYear(), false);
+ }
+ }
+
+ $createIn
+ .append(
+ $('<div></div>')
+ .attr(attrs)
+ .css(cssRules)
+ .append(
+// $('<a href="#" class="selecteee">aaa</a>'),
+ $('<h2></h2>'),
+ $('<div class="dp-nav-prev"></div>')
+ .append(
+ $('<a class="dp-nav-prev-year" href="#" title="' + $.dpText.TEXT_PREV_YEAR + '">&lt;&lt;</a>')
+ .bind(
+ 'click',
+ function()
+ {
+ return c._displayNewMonth.call(c, this, 0, -1);
+ }
+ ),
+ $('<a class="dp-nav-prev-month" href="#" title="' + $.dpText.TEXT_PREV_MONTH + '">&lt;</a>')
+ .bind(
+ 'click',
+ function()
+ {
+ return c._displayNewMonth.call(c, this, -1, 0);
+ }
+ )
+ ),
+ $('<div class="dp-nav-next"></div>')
+ .append(
+ $('<a class="dp-nav-next-year" href="#" title="' + $.dpText.TEXT_NEXT_YEAR + '">&gt;&gt;</a>')
+ .bind(
+ 'click',
+ function()
+ {
+ return c._displayNewMonth.call(c, this, 0, 1);
+ }
+ ),
+ $('<a class="dp-nav-next-month" href="#" title="' + $.dpText.TEXT_NEXT_MONTH + '">&gt;</a>')
+ .bind(
+ 'click',
+ function()
+ {
+ return c._displayNewMonth.call(c, this, 1, 0);
+ }
+ )
+ ),
+ $('<div class="dp-calendar"></div>')
+ )
+ .bgIframe()
+ );
+
+ var $pop = this.inline ? $('.dp-popup', this.context) : $('#dp-popup');
+
+ if (this.showYearNavigation == false) {
+ $('.dp-nav-prev-year, .dp-nav-next-year', c.context).css('display', 'none');
+ }
+ if (this.displayClose) {
+ $pop.append(
+ $('<a href="#" id="dp-close">' + $.dpText.TEXT_CLOSE + '</a>')
+ .bind(
+ 'click',
+ function()
+ {
+ c._closeCalendar();
+ return false;
+ }
+ )
+ );
+ }
+ c._renderCalendar();
+
+ $(this.ele).trigger('dpDisplayed', $pop);
+
+ if (!c.inline) {
+ if (this.verticalPosition == $.dpConst.POS_BOTTOM) {
+ $pop.css('top', eleOffset.top + $ele.height() - $pop.height() + c.verticalOffset);
+ }
+ if (this.horizontalPosition == $.dpConst.POS_RIGHT) {
+ $pop.css('left', eleOffset.left + $ele.width() - $pop.width() + c.horizontalOffset);
+ }
+// $('.selectee', this.context).focus();
+ $(document).bind('mousedown.datepicker', this._checkMouse);
+ }
+
+ },
+ setRenderCallback : function(a)
+ {
+ if (a == null) return;
+ if (a && typeof(a) == 'function') {
+ a = [a];
+ }
+ this.renderCallback = this.renderCallback.concat(a);
+ },
+ cellRender : function ($td, thisDate, month, year) {
+ var c = this.dpController;
+ var d = new Date(thisDate.getTime());
+
+ // add our click handlers to deal with it when the days are clicked...
+
+ $td.bind(
+ 'click',
+ function()
+ {
+ var $this = $(this);
+ if (!$this.is('.disabled')) {
+ c.setSelected(d, !$this.is('.selected') || !c.selectMultiple, false, true);
+ if (c.closeOnSelect) {
+ c._closeCalendar();
+ }
+ // TODO: Instead of this which doesn't work in IE anyway we should find the next focusable element in the document
+ // and pass the focus onto that. That would allow the user to continue on the form as expected...
+ if (!$.browser.msie)
+ {
+ $(c.ele).trigger('focus', [$.dpConst.DP_INTERNAL_FOCUS]);
+ }
+ }
+ }
+ );
+ if (c.isSelected(d)) {
+ $td.addClass('selected');
+ if (c.settings.selectWeek)
+ {
+ $td.parent().addClass('selectedWeek');
+ }
+ } else if (c.selectMultiple && c.numSelected == c.numSelectable) {
+ $td.addClass('unselectable');
+ }
+
+ },
+ _applyRenderCallbacks : function()
+ {
+ var c = this;
+ $('td', this.context).each(
+ function()
+ {
+ for (var i=0; i<c.renderCallback.length; i++) {
+ $td = $(this);
+ c.renderCallback[i].apply(this, [$td, Date.fromString($td.data('datePickerDate')), c.displayedMonth, c.displayedYear]);
+ }
+ }
+ );
+ return;
+ },
+ // ele is the clicked button - only proceed if it doesn't have the class disabled...
+ // m and y are -1, 0 or 1 depending which direction we want to go in...
+ _displayNewMonth : function(ele, m, y)
+ {
+ if (!$(ele).is('.disabled')) {
+ this.setDisplayedMonth(this.displayedMonth + m, this.displayedYear + y, true);
+ }
+ ele.blur();
+ return false;
+ },
+ _rerenderCalendar : function()
+ {
+ this._clearCalendar();
+ this._renderCalendar();
+ },
+ _renderCalendar : function()
+ {
+ // set the title...
+ $('h2', this.context).html((new Date(this.displayedYear, this.displayedMonth, 1)).asString($.dpText.HEADER_FORMAT));
+
+ // render the calendar...
+ $('.dp-calendar', this.context).renderCalendar(
+ $.extend(
+ {},
+ this.settings,
+ {
+ month : this.displayedMonth,
+ year : this.displayedYear,
+ renderCallback : this.cellRender,
+ dpController : this,
+ hoverClass : this.hoverClass
+ })
+ );
+
+ // update the status of the control buttons and disable dates before startDate or after endDate...
+ // TODO: When should the year buttons be disabled? When you can't go forward a whole year from where you are or is that annoying?
+ if (this.displayedYear == this.startDate.getFullYear() && this.displayedMonth == this.startDate.getMonth()) {
+ $('.dp-nav-prev-year', this.context).addClass('disabled');
+ $('.dp-nav-prev-month', this.context).addClass('disabled');
+ $('.dp-calendar td.other-month', this.context).each(
+ function()
+ {
+ var $this = $(this);
+ if (Number($this.text()) > 20) {
+ $this.addClass('disabled');
+ }
+ }
+ );
+ var d = this.startDate.getDate();
+ $('.dp-calendar td.current-month', this.context).each(
+ function()
+ {
+ var $this = $(this);
+ if (Number($this.text()) < d) {
+ $this.addClass('disabled');
+ }
+ }
+ );
+ } else {
+ $('.dp-nav-prev-year', this.context).removeClass('disabled');
+ $('.dp-nav-prev-month', this.context).removeClass('disabled');
+ var d = this.startDate.getDate();
+ if (d > 20) {
+ // check if the startDate is last month as we might need to add some disabled classes...
+ var st = this.startDate.getTime();
+ var sd = new Date(st);
+ sd.addMonths(1);
+ if (this.displayedYear == sd.getFullYear() && this.displayedMonth == sd.getMonth()) {
+ $('.dp-calendar td.other-month', this.context).each(
+ function()
+ {
+ var $this = $(this);
+ if (Date.fromString($this.data('datePickerDate')).getTime() < st) {
+ $this.addClass('disabled');
+ }
+ }
+ );
+ }
+ }
+ }
+ if (this.displayedYear == this.endDate.getFullYear() && this.displayedMonth == this.endDate.getMonth()) {
+ $('.dp-nav-next-year', this.context).addClass('disabled');
+ $('.dp-nav-next-month', this.context).addClass('disabled');
+ $('.dp-calendar td.other-month', this.context).each(
+ function()
+ {
+ var $this = $(this);
+ if (Number($this.text()) < 14) {
+ $this.addClass('disabled');
+ }
+ }
+ );
+ var d = this.endDate.getDate();
+ $('.dp-calendar td.current-month', this.context).each(
+ function()
+ {
+ var $this = $(this);
+ if (Number($this.text()) > d) {
+ $this.addClass('disabled');
+ }
+ }
+ );
+ } else {
+ $('.dp-nav-next-year', this.context).removeClass('disabled');
+ $('.dp-nav-next-month', this.context).removeClass('disabled');
+ var d = this.endDate.getDate();
+ if (d < 13) {
+ // check if the endDate is next month as we might need to add some disabled classes...
+ var ed = new Date(this.endDate.getTime());
+ ed.addMonths(-1);
+ if (this.displayedYear == ed.getFullYear() && this.displayedMonth == ed.getMonth()) {
+ $('.dp-calendar td.other-month', this.context).each(
+ function()
+ {
+ var $this = $(this);
+ var cellDay = Number($this.text());
+ if (cellDay < 13 && cellDay > d) {
+ $this.addClass('disabled');
+ }
+ }
+ );
+ }
+ }
+ }
+ this._applyRenderCallbacks();
+ },
+ _closeCalendar : function(programatic, ele)
+ {
+ if (!ele || ele == this.ele)
+ {
+ $(document).unbind('mousedown.datepicker');
+ $(document).unbind('keydown.datepicker');
+ this._clearCalendar();
+ $('#dp-popup a').unbind();
+ $('#dp-popup').empty().remove();
+ if (!programatic) {
+ $(this.ele).trigger('dpClosed', [this.getSelected()]);
+ }
+ }
+ },
+ // empties the current dp-calendar div and makes sure that all events are unbound
+ // and expandos removed to avoid memory leaks...
+ _clearCalendar : function()
+ {
+ // TODO.
+ $('.dp-calendar td', this.context).unbind();
+ $('.dp-calendar', this.context).empty();
+ }
+ }
+ );
+
+ // static constants
+ $.dpConst = {
+ SHOW_HEADER_NONE : 0,
+ SHOW_HEADER_SHORT : 1,
+ SHOW_HEADER_LONG : 2,
+ POS_TOP : 0,
+ POS_BOTTOM : 1,
+ POS_LEFT : 0,
+ POS_RIGHT : 1,
+ DP_INTERNAL_FOCUS : 'dpInternalFocusTrigger'
+ };
+ // localisable text
+ $.dpText = {
+ TEXT_PREV_YEAR : 'Previous year',
+ TEXT_PREV_MONTH : 'Previous month',
+ TEXT_NEXT_YEAR : 'Next year',
+ TEXT_NEXT_MONTH : 'Next month',
+ TEXT_CLOSE : 'Close',
+ TEXT_CHOOSE_DATE : 'Choose date',
+ HEADER_FORMAT : 'mmmm yyyy'
+ };
+ // version
+ $.dpVersion = '$Id: jquery.datePicker.js 84 2009-08-05 17:54:35Z kelvin.luck@gmail.com $';
+
+ $.fn.datePicker.defaults = {
+ month : undefined,
+ year : undefined,
+ showHeader : $.dpConst.SHOW_HEADER_SHORT,
+ startDate : undefined,
+ endDate : undefined,
+ inline : false,
+ renderCallback : null,
+ createButton : true,
+ showYearNavigation : true,
+ closeOnSelect : true,
+ displayClose : false,
+ selectMultiple : false,
+ numSelectable : Number.MAX_VALUE,
+ clickInput : false,
+ rememberViewedMonth : true,
+ selectWeek : false,
+ verticalPosition : $.dpConst.POS_TOP,
+ horizontalPosition : $.dpConst.POS_LEFT,
+ verticalOffset : 0,
+ horizontalOffset : 0,
+ hoverClass : 'dp-hover'
+ };
+
+ function _getController(ele)
+ {
+ if (ele._dpId) return $.event._dpCache[ele._dpId];
+ return false;
+ };
+
+ // make it so that no error is thrown if bgIframe plugin isn't included (allows you to use conditional
+ // comments to only include bgIframe where it is needed in IE without breaking this plugin).
+ if ($.fn.bgIframe == undefined) {
+ $.fn.bgIframe = function() {return this; };
+ };
+
+
+ // clean-up
+ $(window)
+ .bind('unload', function() {
+ var els = $.event._dpCache || [];
+ for (var i in els) {
+ $(els[i].ele)._dpDestroy();
+ }
+ });
+
+
+})(jQuery);
diff --git a/static/home.js b/static/js/home.js
index 7ced9da..b955d8a 100755
--- a/static/home.js
+++ b/static/js/home.js
@@ -5,6 +5,30 @@ function ifEnter(fn) {
}
function initHome() {
+
+ var defaults = {
+ '#nickInput': "username",
+ "#passwordInput": "not-a-real-password"
+ }
+
+ _.map(defaults, function(value, id){
+
+ // set default values for the login form only if empty
+ if ($(id).val() == "") $(id).val(value);
+
+ // erase the form text when clicked only if it is filler text, otherwise select it
+ $(id).focus(function(){
+ if($(id).val() == value) $(id).val("")
+ else $(id).select()
+ })
+
+ // restore filler text on blur if field is empty
+ $(id).blur(function(){
+ if($(id).val() == "") $(id).val(value);
+ })
+
+ })
+
$('#passwordInput').keyup(ifEnter(login));
$('#loginSubmit').click(login);
}
diff --git a/static/pichat.js b/static/js/pichat.js
index eb0b76f..df79c17 100755
--- a/static/pichat.js
+++ b/static/js/pichat.js
@@ -1,53 +1,43 @@
+var cache = {}
+
function escapeHtml(txt) {
if (!txt) { return ""; }
else { return $("<span>").text(txt).html(); }
}
-// http://stackoverflow.com/questions/37684/replace-url-with-html-links-javascript
function linkify(text) {
- var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi;
- return text.replace(exp,"<a href='$1'>$1</a>");
+ var URLRegex = /((\b(http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi;
+ return text.replace(URLRegex, linkReplace);
}
-
-// http://snippets.dzone.com/posts/show/6995
-var URLRegex = /^((http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/i
-var PicRegex = /\.(jpg|jpeg|png|gif|bmp)$/i;
-function isImage(content) {
- var match = URLRegex.exec(content);
- sansParams = match && match[0].replace(/\?.*$/i, "");
- return sansParams && PicRegex.test(sansParams);
+function linkReplace(match){
+ var PicRegex = /\.(jpg|jpeg|png|gif|bmp)$/i;
+ var matchWithoutParams = match.replace(/\?.*$/i, "")
+ if (PicRegex.test(matchWithoutParams)){
+ return "<a target='_blank' href='" + match + "'><img src='" + match + "'></a>"
+ } else {
+ return "<a target='_blank' href='" + match + "'>" + match + "</a>"
+ }
}
function buildMsgContent(content) {
- if (isImage(content)) {
- return '<a href="' + content + '" target="_blank">'
- + '<img src="'+ content + '" /></a>';
- } else {
- return linkify(escapeHtml(content));
- }
+ return linkify(content)
}
var SpinnerImage = '<img class="spinner" src="/static/spinner.gif" />';
function buildMessageDiv(msg, isLoading) {
var nick = escapeHtml(msg.nick);
- var msgId = 'msg-' + msg.msg_id || 0;
+ var msgId = !isLoading ? 'id="message-' + msg.message_id + '"' : '';
var spinnerHtml = isLoading ? SpinnerImage : '';
- return '<div class="msgDiv" id="' + msgId + '">'
+ var loadingClass = isLoading ? ' loading' : '';
+ return '<div class="msgDiv ' + loadingClass + '" ' + msgId + '>'
+ '<b><a href="/u/' + nick + ' ">' + nick + '</a>: </b>'
+ buildMsgContent(msg.content)
+ spinnerHtml
+ '</div>';
}
-function buildGrowlDataAndPopDatShit(msg) {
- var nick = escapeHtml(msg.nick);
- nick = '<a href="/u/' + nick + ' " style="color:pink">' + nick + '</a>:'
- var msg = buildMsgContent(msg.content)
- growl(nick, msg)
-}
-
function buildUserDiv(user) {
if (user.avatar) {
return '<div class="username">'
@@ -61,6 +51,22 @@ function buildUserDiv(user) {
}
}
+function buildGrowlDataAndPopDatShit(msg) {
+ var nick = escapeHtml(msg.nick);
+ nick = '<a href="/u/' + nick + ' " style="color:pink">' + nick + '</a>:'
+ var msg = buildMsgContent(msg.content)
+ growl(nick, msg)
+}
+
+function growl(user, msg) {
+ $.gritter.add({
+ // (string | mandatory) the heading of the notification
+ title: user,
+ // (string | mandatory) the text inside the notification
+ text: msg
+ });
+}
+
function handleMsgError(resp) {
var respText = resp.responseText ? resp.responseText.trim() : false;
if (respText == 'MUST_LOGIN') {
@@ -82,6 +88,8 @@ function submitMessage() {
var div = addNewMessage(msg, true);
var onSuccess = function(json) {
+ div.attr('id', 'message-' + json)
+ .removeClass('loading').addClass('loaded');
div.find('.spinner').remove();
};
var onError = function(resp, textStatus, errorThrown) {
@@ -98,7 +106,7 @@ function submitMessage() {
dataType: 'json',
success: onSuccess,
error: onError
- });
+ });
}
function ifEnter(fn) {
@@ -148,7 +156,11 @@ function updateUI(msgs, users) {
addNewMessages(msgs);
}
if (users !== null) {
- setUserList(users);
+ var flattened = users.sort().join(",")
+ if (!('userlist' in cache) || flattened != cache.userlist) {
+ $("#userList").html($.map(users, buildUserDiv).join(''));
+ }
+ cache.userlist = flattened
}
}
@@ -260,14 +272,4 @@ function initLog() {
}
-function growl(user, msg) {
- $.gritter.add({
- // (string | mandatory) the heading of the notification
- title: user,
- // (string | mandatory) the text inside the notification
- text: msg
- });
-}
-
-// TODO
-function favoriteImage() {}; \ No newline at end of file
+function favoriteImage() {};
diff --git a/static/register.js b/static/js/register.js
index 89a37fa..89a37fa 100755
--- a/static/register.js
+++ b/static/js/register.js
diff --git a/static/sha1.js b/static/js/sha1.js
index 56418eb..56418eb 100755
--- a/static/sha1.js
+++ b/static/js/sha1.js
diff --git a/static/js/underscore-min.js b/static/js/underscore-min.js
new file mode 100644
index 0000000..9146e08
--- /dev/null
+++ b/static/js/underscore-min.js
@@ -0,0 +1,16 @@
+(function(){var j=this,n=j._,i=function(a){this._wrapped=a},m=typeof StopIteration!=="undefined"?StopIteration:"__break__",b=j._=function(a){return new i(a)};if(typeof exports!=="undefined")exports._=b;var k=Array.prototype.slice,o=Array.prototype.unshift,p=Object.prototype.toString,q=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;b.VERSION="0.5.5";b.each=function(a,c,d){try{if(a.forEach)a.forEach(c,d);else if(b.isArray(a)||b.isArguments(a))for(var e=0,f=a.length;e<f;e++)c.call(d,
+a[e],e,a);else{var g=b.keys(a);f=g.length;for(e=0;e<f;e++)c.call(d,a[g[e]],g[e],a)}}catch(h){if(h!=m)throw h;}return a};b.map=function(a,c,d){if(a&&b.isFunction(a.map))return a.map(c,d);var e=[];b.each(a,function(f,g,h){e.push(c.call(d,f,g,h))});return e};b.reduce=function(a,c,d,e){if(a&&b.isFunction(a.reduce))return a.reduce(b.bind(d,e),c);b.each(a,function(f,g,h){c=d.call(e,c,f,g,h)});return c};b.reduceRight=function(a,c,d,e){if(a&&b.isFunction(a.reduceRight))return a.reduceRight(b.bind(d,e),c);
+var f=b.clone(b.toArray(a)).reverse();b.each(f,function(g,h){c=d.call(e,c,g,h,a)});return c};b.detect=function(a,c,d){var e;b.each(a,function(f,g,h){if(c.call(d,f,g,h)){e=f;b.breakLoop()}});return e};b.select=function(a,c,d){if(a&&b.isFunction(a.filter))return a.filter(c,d);var e=[];b.each(a,function(f,g,h){c.call(d,f,g,h)&&e.push(f)});return e};b.reject=function(a,c,d){var e=[];b.each(a,function(f,g,h){!c.call(d,f,g,h)&&e.push(f)});return e};b.all=function(a,c,d){c=c||b.identity;if(a&&b.isFunction(a.every))return a.every(c,
+d);var e=true;b.each(a,function(f,g,h){(e=e&&c.call(d,f,g,h))||b.breakLoop()});return e};b.any=function(a,c,d){c=c||b.identity;if(a&&b.isFunction(a.some))return a.some(c,d);var e=false;b.each(a,function(f,g,h){if(e=c.call(d,f,g,h))b.breakLoop()});return e};b.include=function(a,c){if(b.isArray(a))return b.indexOf(a,c)!=-1;var d=false;b.each(a,function(e){if(d=e===c)b.breakLoop()});return d};b.invoke=function(a,c){var d=b.rest(arguments,2);return b.map(a,function(e){return(c?e[c]:e).apply(e,d)})};b.pluck=
+function(a,c){return b.map(a,function(d){return d[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);var e={computed:-Infinity};b.each(a,function(f,g,h){g=c?c.call(d,f,g,h):f;g>=e.computed&&(e={value:f,computed:g})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};b.each(a,function(f,g,h){g=c?c.call(d,f,g,h):f;g<e.computed&&(e={value:f,computed:g})});return e.value};b.sortBy=function(a,c,d){return b.pluck(b.map(a,
+function(e,f,g){return{value:e,criteria:c.call(d,e,f,g)}}).sort(function(e,f){e=e.criteria;f=f.criteria;return e<f?-1:e>f?1:0}),"value")};b.sortedIndex=function(a,c,d){d=d||b.identity;for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?(e=g+1):(f=g)}return e};b.toArray=function(a){if(!a)return[];if(a.toArray)return a.toArray();if(b.isArray(a))return a;if(b.isArguments(a))return k.call(a);return b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=function(a,c,d){return c&&!d?k.call(a,
+0,c):a[0]};b.rest=function(a,c,d){return k.call(a,b.isUndefined(c)||d?1:c)};b.last=function(a){return a[a.length-1]};b.compact=function(a){return b.select(a,function(c){return!!c})};b.flatten=function(a){return b.reduce(a,[],function(c,d){if(b.isArray(d))return c.concat(b.flatten(d));c.push(d);return c})};b.without=function(a){var c=b.rest(arguments);return b.select(a,function(d){return!b.include(c,d)})};b.uniq=function(a,c){return b.reduce(a,[],function(d,e,f){if(0==f||(c===true?b.last(d)!=e:!b.include(d,
+e)))d.push(e);return d})};b.intersect=function(a){var c=b.rest(arguments);return b.select(b.uniq(a),function(d){return b.all(c,function(e){return b.indexOf(e,d)>=0})})};b.zip=function(){for(var a=b.toArray(arguments),c=b.max(b.pluck(a,"length")),d=new Array(c),e=0;e<c;e++)d[e]=b.pluck(a,String(e));return d};b.indexOf=function(a,c){if(a.indexOf)return a.indexOf(c);for(var d=0,e=a.length;d<e;d++)if(a[d]===c)return d;return-1};b.lastIndexOf=function(a,c){if(a.lastIndexOf)return a.lastIndexOf(c);for(var d=
+a.length;d--;)if(a[d]===c)return d;return-1};b.range=function(a,c,d){var e=b.toArray(arguments),f=e.length<=1;a=f?0:e[0];c=f?e[0]:e[1];d=e[2]||1;e=Math.ceil((c-a)/d);if(e<=0)return[];e=new Array(e);f=a;for(var g=0;1;f+=d){if((d>0?f-c:c-f)>=0)return e;e[g++]=f}};b.bind=function(a,c){var d=b.rest(arguments,2);return function(){return a.apply(c||j,d.concat(b.toArray(arguments)))}};b.bindAll=function(a){var c=b.rest(arguments);if(c.length==0)c=b.functions(a);b.each(c,function(d){a[d]=b.bind(a[d],a)});
+return a};b.delay=function(a,c){var d=b.rest(arguments,2);return setTimeout(function(){return a.apply(a,d)},c)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(b.rest(arguments)))};b.wrap=function(a,c){return function(){var d=[a].concat(b.toArray(arguments));return c.apply(c,d)}};b.compose=function(){var a=b.toArray(arguments);return function(){for(var c=b.toArray(arguments),d=a.length-1;d>=0;d--)c=[a[d].apply(this,c)];return c[0]}};b.keys=function(a){if(b.isArray(a))return b.range(0,a.length);
+var c=[];for(var d in a)q.call(a,d)&&c.push(d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=function(a){return b.select(b.keys(a),function(c){return b.isFunction(a[c])}).sort()};b.extend=function(a,c){for(var d in c)a[d]=c[d];return a};b.clone=function(a){if(b.isArray(a))return a.slice(0);return b.extend({},a)};b.tap=function(a,c){c(a);return a};b.isEqual=function(a,c){if(a===c)return true;var d=typeof a;if(d!=typeof c)return false;if(a==c)return true;if(!a&&c||a&&!c)return false;
+if(a.isEqual)return a.isEqual(c);if(b.isDate(a)&&b.isDate(c))return a.getTime()===c.getTime();if(b.isNaN(a)&&b.isNaN(c))return true;if(b.isRegExp(a)&&b.isRegExp(c))return a.source===c.source&&a.global===c.global&&a.ignoreCase===c.ignoreCase&&a.multiline===c.multiline;if(d!=="object")return false;if(a.length&&a.length!==c.length)return false;d=b.keys(a);var e=b.keys(c);if(d.length!=e.length)return false;for(var f in a)if(!b.isEqual(a[f],c[f]))return false;return true};b.isEmpty=function(a){return b.keys(a).length==
+0};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=function(a){return!!(a&&a.concat&&a.unshift)};b.isArguments=function(a){return a&&b.isNumber(a.length)&&!b.isArray(a)&&!r.call(a,"length")};b.isFunction=function(a){return!!(a&&a.constructor&&a.call&&a.apply)};b.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};b.isNumber=function(a){return p.call(a)==="[object Number]"};b.isDate=function(a){return!!(a&&a.getTimezoneOffset&&a.setUTCFullYear)};b.isRegExp=function(a){return!!(a&&
+a.test&&a.exec&&(a.ignoreCase||a.ignoreCase===false))};b.isNaN=function(a){return b.isNumber(a)&&isNaN(a)};b.isNull=function(a){return a===null};b.isUndefined=function(a){return typeof a=="undefined"};b.noConflict=function(){j._=n;return this};b.identity=function(a){return a};b.breakLoop=function(){throw m;};var s=0;b.uniqueId=function(a){var c=s++;return a?a+c:c};b.template=function(a,c){a=new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+a.replace(/[\r\t\n]/g,
+" ").replace(/'(?=[^%]*%>)/g,"\t").split("'").join("\\'").split("\t").join("'").replace(/<%=(.+?)%>/g,"',$1,'").split("<%").join("');").split("%>").join("p.push('")+"');}return p.join('');");return c?a(c):a};b.forEach=b.each;b.foldl=b.inject=b.reduce;b.foldr=b.reduceRight;b.filter=b.select;b.every=b.all;b.some=b.any;b.head=b.first;b.tail=b.rest;b.methods=b.functions;var l=function(a,c){return c?b(a).chain():a};b.each(b.functions(b),function(a){var c=b[a];i.prototype[a]=function(){var d=b.toArray(arguments);
+o.call(d,this._wrapped);return l(c.apply(b,d),this._chain)}});b.each(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var c=Array.prototype[a];i.prototype[a]=function(){c.apply(this._wrapped,arguments);return l(this._wrapped,this._chain)}});b.each(["concat","join","slice"],function(a){var c=Array.prototype[a];i.prototype[a]=function(){return l(c.apply(this._wrapped,arguments),this._chain)}});i.prototype.chain=function(){this._chain=true;return this};i.prototype.value=function(){return this._wrapped}})();
diff --git a/static/js/underscore.js b/static/js/underscore.js
new file mode 100644
index 0000000..4385967
--- /dev/null
+++ b/static/js/underscore.js
@@ -0,0 +1,637 @@
+// Underscore.js
+// (c) 2009 Jeremy Ashkenas, DocumentCloud Inc.
+// Underscore is freely distributable under the terms of the MIT license.
+// Portions of Underscore are inspired by or borrowed from Prototype.js,
+// Oliver Steele's Functional, and John Resig's Micro-Templating.
+// For all details and documentation:
+// http://documentcloud.github.com/underscore/
+
+(function() {
+
+ // ------------------------- Baseline setup ---------------------------------
+
+ // Establish the root object, "window" in the browser, or "global" on the server.
+ var root = this;
+
+ // Save the previous value of the "_" variable.
+ var previousUnderscore = root._;
+
+ // If Underscore is called as a function, it returns a wrapped object that
+ // can be used OO-style. This wrapper holds altered versions of all the
+ // underscore functions. Wrapped objects may be chained.
+ var wrapper = function(obj) { this._wrapped = obj; };
+
+ // Establish the object that gets thrown to break out of a loop iteration.
+ var breaker = typeof StopIteration !== 'undefined' ? StopIteration : '__break__';
+
+ // Create a safe reference to the Underscore object for reference below.
+ var _ = root._ = function(obj) { return new wrapper(obj); };
+
+ // Export the Underscore object for CommonJS.
+ if (typeof exports !== 'undefined') exports._ = _;
+
+ // Create quick reference variables for speed access to core prototypes.
+ var slice = Array.prototype.slice,
+ unshift = Array.prototype.unshift,
+ toString = Object.prototype.toString,
+ hasOwnProperty = Object.prototype.hasOwnProperty,
+ propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
+
+ // Current version.
+ _.VERSION = '0.5.5';
+
+ // ------------------------ Collection Functions: ---------------------------
+
+ // The cornerstone, an each implementation.
+ // Handles objects implementing forEach, arrays, and raw objects.
+ _.each = function(obj, iterator, context) {
+ var index = 0;
+ try {
+ if (obj.forEach) {
+ obj.forEach(iterator, context);
+ } else if (_.isArray(obj) || _.isArguments(obj)) {
+ for (var i=0, l=obj.length; i<l; i++) iterator.call(context, obj[i], i, obj);
+ } else {
+ var keys = _.keys(obj), l = keys.length;
+ for (var i=0; i<l; i++) iterator.call(context, obj[keys[i]], keys[i], obj);
+ }
+ } catch(e) {
+ if (e != breaker) throw e;
+ }
+ return obj;
+ };
+
+ // Return the results of applying the iterator to each element. Use JavaScript
+ // 1.6's version of map, if possible.
+ _.map = function(obj, iterator, context) {
+ if (obj && _.isFunction(obj.map)) return obj.map(iterator, context);
+ var results = [];
+ _.each(obj, function(value, index, list) {
+ results.push(iterator.call(context, value, index, list));
+ });
+ return results;
+ };
+
+ // Reduce builds up a single result from a list of values. Also known as
+ // inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.
+ _.reduce = function(obj, memo, iterator, context) {
+ if (obj && _.isFunction(obj.reduce)) return obj.reduce(_.bind(iterator, context), memo);
+ _.each(obj, function(value, index, list) {
+ memo = iterator.call(context, memo, value, index, list);
+ });
+ return memo;
+ };
+
+ // The right-associative version of reduce, also known as foldr. Uses
+ // JavaScript 1.8's version of reduceRight, if available.
+ _.reduceRight = function(obj, memo, iterator, context) {
+ if (obj && _.isFunction(obj.reduceRight)) return obj.reduceRight(_.bind(iterator, context), memo);
+ var reversed = _.clone(_.toArray(obj)).reverse();
+ _.each(reversed, function(value, index) {
+ memo = iterator.call(context, memo, value, index, obj);
+ });
+ return memo;
+ };
+
+ // Return the first value which passes a truth test.
+ _.detect = function(obj, iterator, context) {
+ var result;
+ _.each(obj, function(value, index, list) {
+ if (iterator.call(context, value, index, list)) {
+ result = value;
+ _.breakLoop();
+ }
+ });
+ return result;
+ };
+
+ // Return all the elements that pass a truth test. Use JavaScript 1.6's
+ // filter(), if it exists.
+ _.select = function(obj, iterator, context) {
+ if (obj && _.isFunction(obj.filter)) return obj.filter(iterator, context);
+ var results = [];
+ _.each(obj, function(value, index, list) {
+ iterator.call(context, value, index, list) && results.push(value);
+ });
+ return results;
+ };
+
+ // Return all the elements for which a truth test fails.
+ _.reject = function(obj, iterator, context) {
+ var results = [];
+ _.each(obj, function(value, index, list) {
+ !iterator.call(context, value, index, list) && results.push(value);
+ });
+ return results;
+ };
+
+ // Determine whether all of the elements match a truth test. Delegate to
+ // JavaScript 1.6's every(), if it is present.
+ _.all = function(obj, iterator, context) {
+ iterator = iterator || _.identity;
+ if (obj && _.isFunction(obj.every)) return obj.every(iterator, context);
+ var result = true;
+ _.each(obj, function(value, index, list) {
+ if (!(result = result && iterator.call(context, value, index, list))) _.breakLoop();
+ });
+ return result;
+ };
+
+ // Determine if at least one element in the object matches a truth test. Use
+ // JavaScript 1.6's some(), if it exists.
+ _.any = function(obj, iterator, context) {
+ iterator = iterator || _.identity;
+ if (obj && _.isFunction(obj.some)) return obj.some(iterator, context);
+ var result = false;
+ _.each(obj, function(value, index, list) {
+ if (result = iterator.call(context, value, index, list)) _.breakLoop();
+ });
+ return result;
+ };
+
+ // Determine if a given value is included in the array or object,
+ // based on '==='.
+ _.include = function(obj, target) {
+ if (_.isArray(obj)) return _.indexOf(obj, target) != -1;
+ var found = false;
+ _.each(obj, function(value) {
+ if (found = value === target) _.breakLoop();
+ });
+ return found;
+ };
+
+ // Invoke a method with arguments on every item in a collection.
+ _.invoke = function(obj, method) {
+ var args = _.rest(arguments, 2);
+ return _.map(obj, function(value) {
+ return (method ? value[method] : value).apply(value, args);
+ });
+ };
+
+ // Convenience version of a common use case of map: fetching a property.
+ _.pluck = function(obj, key) {
+ return _.map(obj, function(value){ return value[key]; });
+ };
+
+ // Return the maximum item or (item-based computation).
+ _.max = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
+ var result = {computed : -Infinity};
+ _.each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed >= result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Return the minimum element (or element-based computation).
+ _.min = function(obj, iterator, context) {
+ if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
+ var result = {computed : Infinity};
+ _.each(obj, function(value, index, list) {
+ var computed = iterator ? iterator.call(context, value, index, list) : value;
+ computed < result.computed && (result = {value : value, computed : computed});
+ });
+ return result.value;
+ };
+
+ // Sort the object's values by a criteria produced by an iterator.
+ _.sortBy = function(obj, iterator, context) {
+ return _.pluck(_.map(obj, function(value, index, list) {
+ return {
+ value : value,
+ criteria : iterator.call(context, value, index, list)
+ };
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }), 'value');
+ };
+
+ // Use a comparator function to figure out at what index an object should
+ // be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iterator) {
+ iterator = iterator || _.identity;
+ var low = 0, high = array.length;
+ while (low < high) {
+ var mid = (low + high) >> 1;
+ iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
+ }
+ return low;
+ };
+
+ // Convert anything iterable into a real, live array.
+ _.toArray = function(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ if (_.isArray(iterable)) return iterable;
+ if (_.isArguments(iterable)) return slice.call(iterable);
+ return _.values(iterable);
+ };
+
+ // Return the number of elements in an object.
+ _.size = function(obj) {
+ return _.toArray(obj).length;
+ };
+
+ // -------------------------- Array Functions: ------------------------------
+
+ // Get the first element of an array. Passing "n" will return the first N
+ // values in the array. Aliased as "head". The "guard" check allows it to work
+ // with _.map.
+ _.first = function(array, n, guard) {
+ return n && !guard ? slice.call(array, 0, n) : array[0];
+ };
+
+ // Returns everything but the first entry of the array. Aliased as "tail".
+ // Especially useful on the arguments object. Passing an "index" will return
+ // the rest of the values in the array from that index onward. The "guard"
+ //check allows it to work with _.map.
+ _.rest = function(array, index, guard) {
+ return slice.call(array, _.isUndefined(index) || guard ? 1 : index);
+ };
+
+ // Get the last element of an array.
+ _.last = function(array) {
+ return array[array.length - 1];
+ };
+
+ // Trim out all falsy values from an array.
+ _.compact = function(array) {
+ return _.select(array, function(value){ return !!value; });
+ };
+
+ // Return a completely flattened version of an array.
+ _.flatten = function(array) {
+ return _.reduce(array, [], function(memo, value) {
+ if (_.isArray(value)) return memo.concat(_.flatten(value));
+ memo.push(value);
+ return memo;
+ });
+ };
+
+ // Return a version of the array that does not contain the specified value(s).
+ _.without = function(array) {
+ var values = _.rest(arguments);
+ return _.select(array, function(value){ return !_.include(values, value); });
+ };
+
+ // Produce a duplicate-free version of the array. If the array has already
+ // been sorted, you have the option of using a faster algorithm.
+ _.uniq = function(array, isSorted) {
+ return _.reduce(array, [], function(memo, el, i) {
+ if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo.push(el);
+ return memo;
+ });
+ };
+
+ // Produce an array that contains every item shared between all the
+ // passed-in arrays.
+ _.intersect = function(array) {
+ var rest = _.rest(arguments);
+ return _.select(_.uniq(array), function(item) {
+ return _.all(rest, function(other) {
+ return _.indexOf(other, item) >= 0;
+ });
+ });
+ };
+
+ // Zip together multiple lists into a single array -- elements that share
+ // an index go together.
+ _.zip = function() {
+ var args = _.toArray(arguments);
+ var length = _.max(_.pluck(args, 'length'));
+ var results = new Array(length);
+ for (var i=0; i<length; i++) results[i] = _.pluck(args, String(i));
+ return results;
+ };
+
+ // If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
+ // we need this function. Return the position of the first occurence of an
+ // item in an array, or -1 if the item is not included in the array.
+ _.indexOf = function(array, item) {
+ if (array.indexOf) return array.indexOf(item);
+ for (var i=0, l=array.length; i<l; i++) if (array[i] === item) return i;
+ return -1;
+ };
+
+ // Provide JavaScript 1.6's lastIndexOf, delegating to the native function,
+ // if possible.
+ _.lastIndexOf = function(array, item) {
+ if (array.lastIndexOf) return array.lastIndexOf(item);
+ var i = array.length;
+ while (i--) if (array[i] === item) return i;
+ return -1;
+ };
+
+ // Generate an integer Array containing an arithmetic progression. A port of
+ // the native Python range() function. See:
+ // http://docs.python.org/library/functions.html#range
+ _.range = function(start, stop, step) {
+ var a = _.toArray(arguments);
+ var solo = a.length <= 1;
+ var start = solo ? 0 : a[0], stop = solo ? a[0] : a[1], step = a[2] || 1;
+ var len = Math.ceil((stop - start) / step);
+ if (len <= 0) return [];
+ var range = new Array(len);
+ for (var i = start, idx = 0; true; i += step) {
+ if ((step > 0 ? i - stop : stop - i) >= 0) return range;
+ range[idx++] = i;
+ }
+ };
+
+ // ----------------------- Function Functions: ------------------------------
+
+ // Create a function bound to a given object (assigning 'this', and arguments,
+ // optionally). Binding with arguments is also known as 'curry'.
+ _.bind = function(func, obj) {
+ var args = _.rest(arguments, 2);
+ return function() {
+ return func.apply(obj || root, args.concat(_.toArray(arguments)));
+ };
+ };
+
+ // Bind all of an object's methods to that object. Useful for ensuring that
+ // all callbacks defined on an object belong to it.
+ _.bindAll = function(obj) {
+ var funcs = _.rest(arguments);
+ if (funcs.length == 0) funcs = _.functions(obj);
+ _.each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+ return obj;
+ };
+
+ // Delays a function for the given number of milliseconds, and then calls
+ // it with the arguments supplied.
+ _.delay = function(func, wait) {
+ var args = _.rest(arguments, 2);
+ return setTimeout(function(){ return func.apply(func, args); }, wait);
+ };
+
+ // Defers a function, scheduling it to run after the current call stack has
+ // cleared.
+ _.defer = function(func) {
+ return _.delay.apply(_, [func, 1].concat(_.rest(arguments)));
+ };
+
+ // Returns the first function passed as an argument to the second,
+ // allowing you to adjust arguments, run code before and after, and
+ // conditionally execute the original function.
+ _.wrap = function(func, wrapper) {
+ return function() {
+ var args = [func].concat(_.toArray(arguments));
+ return wrapper.apply(wrapper, args);
+ };
+ };
+
+ // Returns a function that is the composition of a list of functions, each
+ // consuming the return value of the function that follows.
+ _.compose = function() {
+ var funcs = _.toArray(arguments);
+ return function() {
+ var args = _.toArray(arguments);
+ for (var i=funcs.length-1; i >= 0; i--) {
+ args = [funcs[i].apply(this, args)];
+ }
+ return args[0];
+ };
+ };
+
+ // ------------------------- Object Functions: ------------------------------
+
+ // Retrieve the names of an object's properties.
+ _.keys = function(obj) {
+ if(_.isArray(obj)) return _.range(0, obj.length);
+ var keys = [];
+ for (var key in obj) if (hasOwnProperty.call(obj, key)) keys.push(key);
+ return keys;
+ };
+
+ // Retrieve the values of an object's properties.
+ _.values = function(obj) {
+ return _.map(obj, _.identity);
+ };
+
+ // Return a sorted list of the function names available in Underscore.
+ _.functions = function(obj) {
+ return _.select(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort();
+ };
+
+ // Extend a given object with all of the properties in a source object.
+ _.extend = function(destination, source) {
+ for (var property in source) destination[property] = source[property];
+ return destination;
+ };
+
+ // Create a (shallow-cloned) duplicate of an object.
+ _.clone = function(obj) {
+ if (_.isArray(obj)) return obj.slice(0);
+ return _.extend({}, obj);
+ };
+
+ // Invokes interceptor with the obj, and then returns obj.
+ // The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
+ _.tap = function(obj, interceptor) {
+ interceptor(obj);
+ return obj;
+ };
+
+ // Perform a deep comparison to check if two objects are equal.
+ _.isEqual = function(a, b) {
+ // Check object identity.
+ if (a === b) return true;
+ // Different types?
+ var atype = typeof(a), btype = typeof(b);
+ if (atype != btype) return false;
+ // Basic equality test (watch out for coercions).
+ if (a == b) return true;
+ // One is falsy and the other truthy.
+ if ((!a && b) || (a && !b)) return false;
+ // One of them implements an isEqual()?
+ if (a.isEqual) return a.isEqual(b);
+ // Check dates' integer values.
+ if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
+ // Both are NaN?
+ if (_.isNaN(a) && _.isNaN(b)) return true;
+ // Compare regular expressions.
+ if (_.isRegExp(a) && _.isRegExp(b))
+ return a.source === b.source &&
+ a.global === b.global &&
+ a.ignoreCase === b.ignoreCase &&
+ a.multiline === b.multiline;
+ // If a is not an object by this point, we can't handle it.
+ if (atype !== 'object') return false;
+ // Check for different array lengths before comparing contents.
+ if (a.length && (a.length !== b.length)) return false;
+ // Nothing else worked, deep compare the contents.
+ var aKeys = _.keys(a), bKeys = _.keys(b);
+ // Different object sizes?
+ if (aKeys.length != bKeys.length) return false;
+ // Recursive comparison of contents.
+ for (var key in a) if (!_.isEqual(a[key], b[key])) return false;
+ return true;
+ };
+
+ // Is a given array or object empty?
+ _.isEmpty = function(obj) {
+ return _.keys(obj).length == 0;
+ };
+
+ // Is a given value a DOM element?
+ _.isElement = function(obj) {
+ return !!(obj && obj.nodeType == 1);
+ };
+
+ // Is a given value an array?
+ _.isArray = function(obj) {
+ return !!(obj && obj.concat && obj.unshift);
+ };
+
+ // Is a given variable an arguments object?
+ _.isArguments = function(obj) {
+ return obj && _.isNumber(obj.length) && !_.isArray(obj) && !propertyIsEnumerable.call(obj, 'length');
+ };
+
+ // Is a given value a function?
+ _.isFunction = function(obj) {
+ return !!(obj && obj.constructor && obj.call && obj.apply);
+ };
+
+ // Is a given value a string?
+ _.isString = function(obj) {
+ return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
+ };
+
+ // Is a given value a number?
+ _.isNumber = function(obj) {
+ return toString.call(obj) === '[object Number]';
+ };
+
+ // Is a given value a date?
+ _.isDate = function(obj) {
+ return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
+ };
+
+ // Is the given value a regular expression?
+ _.isRegExp = function(obj) {
+ return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
+ };
+
+ // Is the given value NaN -- this one is interesting. NaN != NaN, and
+ // isNaN(undefined) == true, so we make sure it's a number first.
+ _.isNaN = function(obj) {
+ return _.isNumber(obj) && isNaN(obj);
+ };
+
+ // Is a given value equal to null?
+ _.isNull = function(obj) {
+ return obj === null;
+ };
+
+ // Is a given variable undefined?
+ _.isUndefined = function(obj) {
+ return typeof obj == 'undefined';
+ };
+
+ // -------------------------- Utility Functions: ----------------------------
+
+ // Run Underscore.js in noConflict mode, returning the '_' variable to its
+ // previous owner. Returns a reference to the Underscore object.
+ _.noConflict = function() {
+ root._ = previousUnderscore;
+ return this;
+ };
+
+ // Keep the identity function around for default iterators.
+ _.identity = function(value) {
+ return value;
+ };
+
+ // Break out of the middle of an iteration.
+ _.breakLoop = function() {
+ throw breaker;
+ };
+
+ // Generate a unique integer id (unique within the entire client session).
+ // Useful for temporary DOM ids.
+ var idCounter = 0;
+ _.uniqueId = function(prefix) {
+ var id = idCounter++;
+ return prefix ? prefix + id : id;
+ };
+
+ // JavaScript templating a-la ERB, pilfered from John Resig's
+ // "Secrets of the JavaScript Ninja", page 83.
+ // Single-quote fix from Rick Strahl's version.
+ _.template = function(str, data) {
+ var fn = new Function('obj',
+ 'var p=[],print=function(){p.push.apply(p,arguments);};' +
+ 'with(obj){p.push(\'' +
+ str.replace(/[\r\t\n]/g, " ")
+ .replace(/'(?=[^%]*%>)/g,"\t")
+ .split("'").join("\\'")
+ .split("\t").join("'")
+ .replace(/<%=(.+?)%>/g, "',$1,'")
+ .split("<%").join("');")
+ .split("%>").join("p.push('")
+ + "');}return p.join('');");
+ return data ? fn(data) : fn;
+ };
+
+ // ------------------------------- Aliases ----------------------------------
+
+ _.forEach = _.each;
+ _.foldl = _.inject = _.reduce;
+ _.foldr = _.reduceRight;
+ _.filter = _.select;
+ _.every = _.all;
+ _.some = _.any;
+ _.head = _.first;
+ _.tail = _.rest;
+ _.methods = _.functions;
+
+ // ------------------------ Setup the OOP Wrapper: --------------------------
+
+ // Helper function to continue chaining intermediate results.
+ var result = function(obj, chain) {
+ return chain ? _(obj).chain() : obj;
+ };
+
+ // Add all of the Underscore functions to the wrapper object.
+ _.each(_.functions(_), function(name) {
+ var method = _[name];
+ wrapper.prototype[name] = function() {
+ var args = _.toArray(arguments);
+ unshift.call(args, this._wrapped);
+ return result(method.apply(_, args), this._chain);
+ };
+ });
+
+ // Add all mutator Array functions to the wrapper.
+ _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+ var method = Array.prototype[name];
+ wrapper.prototype[name] = function() {
+ method.apply(this._wrapped, arguments);
+ return result(this._wrapped, this._chain);
+ };
+ });
+
+ // Add all accessor Array functions to the wrapper.
+ _.each(['concat', 'join', 'slice'], function(name) {
+ var method = Array.prototype[name];
+ wrapper.prototype[name] = function() {
+ return result(method.apply(this._wrapped, arguments), this._chain);
+ };
+ });
+
+ // Start chaining a wrapped Underscore object.
+ wrapper.prototype.chain = function() {
+ this._chain = true;
+ return this;
+ };
+
+ // Extracts the result from a wrapped and chained object.
+ wrapper.prototype.value = function() {
+ return this._wrapped;
+ };
+
+})();
diff --git a/static/pichat.css b/static/pichat.css
index 40720b7..0e5fb5f 100755
--- a/static/pichat.css
+++ b/static/pichat.css
@@ -4,6 +4,10 @@ body {
background-color:#e3e3e3;
margin:0;
+ background-color:#ffffee;
+ background-image:url(/static/chanbg.png);
+ background-repeat:repeat-x;
+ background-position:top;
}
@@ -29,7 +33,7 @@ body {
position:fixed;
width:100%;
bottom:0px;
-line-height:2.5;
+line-height:3.1;
font-size:11px;
word-spacing:8px;
height:28px;
@@ -55,15 +59,12 @@ color:000;
#messagePane {
border: 2px solid #c8cbce;
-
-
top:56px;
bottom:65px;
position:fixed;
width: 99%;
background-color:#FFF;
left:0.3%;
-
z-index:5;
}
@@ -164,7 +165,7 @@ top:15px;
position: absolute;
padding: 5px;
top:85px;
- min-width: 150px;
+ min-width: 160px;
width:11%;
float:right;
right: 6%;
@@ -184,6 +185,8 @@ top:15px;
-webkit-border-bottom-right-radius:5px;
-moz-border-radius-bottomleft:5px;
-moz-border-radius-bottomright:5px;
+border-right:2px solid #c8cbce;
+border-bottom:2px solid #c8cbce;
max-height:450px;
box-shadow: 3px 4px 4px #c8cbce;
-webkit-box-shadow: 3px 4px 4px #c8cbce;
diff --git a/static/profile.css b/static/profile.css
index 7605fc7..91e5b92 100755
--- a/static/profile.css
+++ b/static/profile.css
@@ -1,40 +1,26 @@
#profile {
float: right;
padding: 20px;
- width: 180px;
+width:180;
position:absolute;
- top:17px;
- left:560;
- margin-top:9px;
- background-color:#f5f5f5;
+ top:30px;
+ left:642;
+ margin-top:34px;
+background-color:#fff;
background-image:url(/static/spexx.png);
- border:solid 1px #999;
+
text-overflow: ellipsis-word;
background-position:top;
z-index:999;
min-height:600px;
- border-top-left-radius:5px;
- border-top-right-radius:5px;
- -webkit-border-top-left-radius:5px;
- -webkit-border-top-right-radius:5px;
- -moz-border-radius-topleft:5px;
- -moz-border-radius-topright:5px;
- border-bottom-left-radius:5px;
- border-bottom-right-radius:5px;
- -webkit-border-bottom-left-radius:5px;
- -webkit-border-bottom-right-radius:5px;
- -moz-border-radius-bottomleft:5px;
- -moz-border-radius-bottomright:5px;
- box-shadow: 10px 3px 10px #c8cbce;
--webkit-box-shadow:10px 3px 10px #c8cbce;
--moz-box-shadow:10px 3px 10px #c8cbce;
+
- line-height:1.6;
+ line-height:1.5;
}
#chatrap{
- width:600 ;
+ width:800;
- margin-left: 18%;
+ margin-left:auto;
margin-right: auto ;
@@ -42,38 +28,44 @@
}
#pnav{position:absolute;
-background:#fff;
-height:25px;
+
+height:45px;
padding-left:11;
font-size:20px;
-margin-top:-28;
-background-image:url(/static/bgnav.jpg);
+margin-top:-40;
background-position:top;
font-weight:bold;
-width:260;
+width:600;
+margin-left:35;
text-align:left;
-border:1px solid #087cff;
-left:-70;
+
+
letter-spacing:2px;
- border-top-left-radius:5px;
- border-top-right-radius:5px;
- -webkit-border-top-left-radius:5px;
- -webkit-border-top-right-radius:5px;
- -moz-border-radius-topleft:5px;
- -moz-border-radius-topright:5px;
- border-bottom-left-radius:5px;
- border-bottom-right-radius:5px;
- -webkit-border-bottom-left-radius:5px;
- -webkit-border-bottom-right-radius:5px;
- -moz-border-radius-bottomleft:5px;
- -moz-border-radius-bottomright:5px;
- box-shadow: 15px 15px 10px #c8cbce;
--webkit-box-shadow: 15px 15px 10px #c8cbce;
--moz-box-shadow: 15px 15px 10px #c8cbce;
+
+
+}
+#pnavo{
+margin-top:20;
+background:#fff;
+width:240;
+
+height:35;
+
+}
+#pnavn{
+position:absolute;
+top:20;
+left:280;
+background:#fff;
+width:270;
+height:35;
+
+
+
}
#pnav a {
- font-size: 12px;
- color:#444;
+ font-size: 30px;
+ color:#000;
}
pnav a:link {
text-decoration: none;
@@ -85,7 +77,8 @@ a:visited {
}
#pnav a:hover {
text-decoration: none;
- color: #f0e;
+ color: #fff;
+background:#f0e;
}
a:active {
text-decoration: none;
@@ -108,10 +101,10 @@ height:28px;
{
position:absolute;
- top:50px;
+ top:70px;
margin-right:5px;
padding-top: 25px;
- min-height: 800px;
+
}
@@ -135,14 +128,26 @@ height:28px;
text-overflow: ellipsis-word;
- padding: 15px;
+ padding: 18px;
font-family: Arial, Helvetica, sans-serif;
font-size: 12px;
text-transform: uppercase;
line-height:15px;
background-color:#fff;
-border:1px solid #999;
-margin-top:-2;
+border:1px solid #eee;
+ border-top-left-radius:15px;
+ border-top-right-radius:15px;
+ -webkit-border-top-left-radius:15px;
+ -webkit-border-top-right-radius:15px;
+ -moz-border-radius-topleft:15px;
+ -moz-border-radius-topright:15px;
+ border-bottom-left-radius:15px;
+ border-bottom-right-radius:15px;
+ -webkit-border-bottom-left-radius:15px;
+ -webkit-border-bottom-right-radius:15px;
+ -moz-border-radius-bottomleft:15px;
+ -moz-border-radius-bottomright:15px;
+margin-top:20;
z-index:4;
width:600;
line-height:20px;
@@ -240,6 +245,12 @@ padding:20;
}
body,td,th {
font-family: Arial, Helvetica, sans-serif;
+ background-color:#ffffee;
+ background-image:url(/static/chanbg.png);
+ background-repeat:repeat-x;
+ background-position:top;
+
+
-}@charset "UTF-8";
+}@charset "UTF-8"; \ No newline at end of file
diff --git a/static/register.html b/static/register.html
index e2ead5f..3cddffa 100755
--- a/static/register.html
+++ b/static/register.html
@@ -4,8 +4,8 @@
<link rel="shortcut icon" href="static/favicon.ico">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
- <script type="text/javascript" src="static/sha1.js"></script>
- <script type="text/javascript" src="static/register.js"></script>
+ <script type="text/javascript" src="static/js/sha1.js"></script>
+ <script type="text/javascript" src="static/js/register.js"></script>
<script>
$(document).ready(initRegister);
</script>
diff --git a/static/search/browser.html b/static/search/browser.html
index 99e4710..917294f 100755
--- a/static/search/browser.html
+++ b/static/search/browser.html
@@ -4,6 +4,8 @@
<title>dump.fm - image search</title>
<style type="text/css">
+
+
<!--
a {
font-size: 12px;
@@ -29,6 +31,8 @@ a:active {
body {
font-size:13;
font-family:"Trebuchet MS", Arial, Helvetica, sans-serif;
+ margin:50;
+
}
@@ -43,48 +47,35 @@ a:active {
width: 1200px;
}
#description {display:none;width:790px;}
- #description div, .post, .result {margin: -px 270px;width:470px;}
- #description p > p,#description p {margin:0;line-height:.1;width:600;}
- #description img {float:left;margin:0 12px 32px 0;}
-table.search{font-family:Verdana,Arial,Helvetica,sans-serif;text-align:left;font-size:11px;color:#333}.gsc-trailing-more-results,.gsc-resultsHeader,.gsc-search-box{display:none}.gsc-results{padding-left:20px}#searchControl .gsc-control{width:550px;padding:10px;padding-left:20;}select, label{font:bold 11px Arial,Helvetica,sans-serif;color:#003;text-transform:uppercase;margin-right:5px;line-height:.1;}input#q{font:bold 11px Arial,Helvetica,sans-serif;color:#F00;height:2em;padding:3px;border-top:2px solid #999;border-right:2px solid #999;border-bottom:1px solid #999;border-left:1px solid #999;}
-#logo{padding-left:20;}
-.gsc-control img{
- max-width:500px;
- width: expression(this.width > 500 ? 500: true);
- max-height:400px;
- height: expression(this.width > 500 ? 500: true);
-
- #submit {
+ #description div, .post, .result {}
+ #description p > p,#description p {margin:0;line-height:1;width:800;}
+ #description img {float:left;margin:0 12px 12px 0;}
+table.search{font-family:Verdana,Arial,Helvetica,sans-serif;text-align:left;font-size:11px;color:#333}
+.gsc-trailing-more-results,.gsc-resultsHeader,
+.gsc-search-box{display:none;}
+.gsc-results{padding-left:0px;}
+#searchControl
+.gsc-control{width:600;height:30;padding:0px;padding-left:0;}select, label{font:bold 11px Arial,Helvetica,sans-serif;color:#003;text-transform:uppercase;margin-right:5px;}
+input#q{width:400;height:25px;font:bold Arial,Helvetica,sans-serif;color:#F00;}
+input#submit{
- position:absolute;
- display:inline-block;
- width:120px;
-height:35px;
-right:0px;
+ width:100px;
+height:28px;
font-size:20px;
background-image:url(/static/bg-btn-blue.png);
-top:15px;
text-align:center;
z-index:100;
cursor:pointer;
background-color:#087cff;
- border-top-right-radius:10px;
- -webkit-border-top-right-radius:5px;
- -moz-border-radius-topright:5px;
- border-bottom-right-radius:5px;
- -webkit-border-bottom-right-radius:5px;
- -moz-border-radius-bottomright:5px;
- border-radius:2px;
font-size:12px;
color:#fff;
text-shadow:1px 1px 3px rgba(0,0,0,0.5);
}
+#logo{padding-left:20;}
+
+#ish{width:800;}
+
-#ish{
- top:30%;
- left:20%;
- width: 300px;
-}
</style>
@@ -101,19 +92,17 @@ top:15px;
<div id="ish">
<form onSubmit="searchImages(); return false;" >
<div align="left">
-
- <tr>
- <td colspan="2"><p align="left"><img src="browser.png" width="141" height="64"></p>
-
- <div align="left">
- <input name="q" type="text" id="q" onChange="searchImages();" size="30%">
+ browser tool
+
+ <tr>
+ <td colspan="2"><br>
+ <input name="q" type="text" id="q" onChange="searchImages();" size="10%">
<input type="submit" name="submit" id="submit" class="msgSubmit"value="Search Images">
- </div>
+
<label>
</label>
- </p> </td>
- </tr>
- <div align="center">
+ </td>
+ <div align="left">
<div align="left">
<table class="search" width="425" border="0" cellpadding="5" cellspacing="0">
diff --git a/static/search/browser.png b/static/search/browser.png
index a2e22c0..1ae3413 100644
--- a/static/search/browser.png
+++ b/static/search/browser.png
Binary files differ
diff --git a/static/signin.gif b/static/signin.gif
new file mode 100644
index 0000000..5ab623b
--- /dev/null
+++ b/static/signin.gif
Binary files differ
diff --git a/static/talkwith.png b/static/talkwith.png
new file mode 100644
index 0000000..7642fca
--- /dev/null
+++ b/static/talkwith.png
Binary files differ
diff --git a/template/banner.st b/template/banner.st
index 3998ff0..9e92d8c 100755
--- a/template/banner.st
+++ b/template/banner.st
@@ -2,26 +2,29 @@
<div id="header7">
<div id="logo7">
<div align="center"><a href="/chat" onMouseOut="MM_swapImgRestore()" onMouseOver="MM_swapImage('Image2','','/static/mouseover.gif',1)"><img src="/static/wordlogo2.gif" name="Image2" width="153" height="73" border="0"></a></div>
+
+ <div id="strapline"><img src="/static/talkwith.png" width="179" height="53" /></div>
</div>
<div class="white">
<div id="bar7">
<div style="float: left;">
<div align="center">$if(user_nick)$&nbsp;
- <a href="/u/$user_nick$">&#x2605; Profile &#x2605;</a> |
- $else$ <a href="/register">Register</a> |
+ <a href="/u/$user_nick$"> Profile </a> <img src="/static/jewelblu.gif">
+ $else$ <a href="/register">Register </a><img src="/static/jewelblu.gif">
$endif$
- <a href="/chat">Room A</a> |
- <a href="/log">Log</a>
- $if(isadmin)$
- | <a href="/VIP/chat"> &#x2605; VIP &#x2605;</a>
+ <a href="/chat">Room A </a><img src="/static/jewelblu.gif">
+ <a href="/log">Log </a>
+ <img src="/static/jewelblu.gif"><a href="/browser">Browser Tool </a>
+ $if(isadmin)$
+ <img src="/static/jewelblu.gif"><a href="/VIP/chat"> &#x2605; VIP &#x2605; </a>
$endif$
</div>
</div>
</div>
</div>
<div id="logout7" class="white">
- <div align="center">$if(user_nick)$ <a href="/logout">Logout</a> $else$ <a href="/" class="btnav">Log In</a>$endif$
+ <div align="center">$if(user_nick)$ <a href="/logout"><img src="/static/door2.gif" width="16" height="16" /> Logout</a> $else$ $form_login()$ $endif$
</div>
</div>
<div align="center"><br />
diff --git a/template/browser.st b/template/browser.st
index 93da34d..33c6ba1 100755
--- a/template/browser.st
+++ b/template/browser.st
@@ -42,14 +42,14 @@
</div>
<div id="messagePane">
<div id="messageList">
- <iframe src="/static/search/browser.html" style="width:100%;height:100%;padding:0px;background-color: #fff; position:absolute; top:0px; left:0px; border:none; allowtransparency="true" scrolling="yes" ></iframe>
+ <iframe src="/static/search/browser.html" style="width:100%;height:100%;padding:0px;background-color: #fff; position:absolute; top:0px; left:0px; border:none; allowtransparency="true" scrolling="auto" ></iframe>
</div>
$if(user_nick)$
<div id="msgInputDiv">
<input id="msgInput" class="msgInput" type="input" />
- <input id="msgSubmit" type="submit" value="Send Text"
+ <input id="msgSubmit" type="submit" value="Send Image URL"
/>
</div>
$endif$
diff --git a/template/chat.st b/template/chat.st
index 4b65aa7..7c723d7 100755
--- a/template/chat.st
+++ b/template/chat.st
@@ -49,7 +49,7 @@
<div id="messagePane">
<div id="messageList">
$messages: { m |
- <div class="msgDiv oldmsg"><b><a href="/u/$m.nick$">$m.nick$</a>: </b>
+ <div class="msgDiv oldmsg" id="message-$m.message_id$"><b><a href="/u/$m.nick$">$m.nick$</a>: </b>
<span class="content">$m.content$<span></div>
}$
<hr />
@@ -64,17 +64,12 @@
</div>
</div>
</div>
+ </div>
+ <div id="footerc">
+ <p>
+ $footer()$
+ <p>
</div>
-</div>
-</div>
-
- </div>
- <div id="footerc">
- <p>
- $footer()$</p>
- <p>
- </p>
- </div>
</body>
</html>
diff --git a/template/form_login.st b/template/form_login.st
new file mode 100644
index 0000000..aee9283
--- /dev/null
+++ b/template/form_login.st
@@ -0,0 +1,44 @@
+<div id="login-container">
+ <div class="topnav"> Have an account? <a href="login" class="signin"><span>Sign in</span></a> </div>
+ <fieldset id="signin_menu">
+ <form onsubmit="return false">
+ </p>
+<img src="/static/signin.gif">
+ </p>
+ </p><br>
+ </p>
+
+ <input id="nickInput" name="nickInput" value="" title="username" tabindex="4" type="text">
+ </p>
+ <p>
+ <input id="passwordInput" name="passwordInput" value="" title="password" tabindex="5" type="password">
+ </p>
+ <p class="remember">
+ <input id="loginSubmit" value="Sign in" tabindex="6" type="submit">
+ </p>
+ </form>
+ </fieldset>
+</div>
+<script src="/static/js/home.js" type="text/javascript"></script>
+<script type="text/javascript">
+ jQuery(document).ready(function() {
+
+ initHome();
+
+ jQuery(".signin").click(function(e) {
+ e.preventDefault();
+ jQuery("fieldset#signin_menu").toggle();
+ jQuery(".signin").toggleClass("menu-open");
+ });
+
+ jQuery("fieldset#signin_menu").mouseup(function() {
+ return false
+ });
+ jQuery(document).mouseup(function(e) {
+ if(jQuery(e.target).parent("a.signin").length==0) {
+ jQuery(".signin").removeClass("menu-open");
+ jQuery("fieldset#signin_menu").hide();
+ }
+ });
+});
+</script> \ No newline at end of file
diff --git a/template/head.st b/template/head.st
index 66f8fb1..a9bb0f0 100755
--- a/template/head.st
+++ b/template/head.st
@@ -1,12 +1,16 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
-<script type="text/javascript" src="/static/jquery-1.3.2.min.js"></script>
-<script type="text/javascript" src="/static/sha1.js"></script>
-<script type="text/javascript" src="/static/pichat.js"></script>
+<!-- <script type="text/javascript" src="/static/jquery-1.3.2.min.js"></script> -->
+<script type="text/javascript" src="/static/js/underscore-min.js"></script>
+<script type="text/javascript" src="/static/js/sha1.js"></script>
+<script type="text/javascript" src="/static/js/pichat.js"></script>
<link rel="stylesheet" type="text/css" href="/static/reset.css">
<link rel="stylesheet" type="text/css" href="/static/header.css">
+$if(!user_nick)$
+<link href="/static/form_login/front.css" media="screen, projection" rel="stylesheet" type="text/css">
+$endif$
<link rel="shortcut icon" href="/static/favicon.ico">
<script type="text/javascript">
diff --git a/template/log.st b/template/log.st
index 60eb3d5..abc0477 100755
--- a/template/log.st
+++ b/template/log.st
@@ -20,16 +20,7 @@
</div>
<br>
- <div id="pnav">
- $if(next)$
- <a href="/$roomkey$/log/$next$"><- OLD DUMPS</a>
- $endif$
- &nbsp;&nbsp;
- $if(prev)$
- <a href="/$roomkey$/log/$prev$">NEW DUMPS -></a>
- $endif$
- </div>
<div id="posts">
$if(dumps)$
@@ -37,16 +28,20 @@
$else$
No dumps!
$endif$
- <div id="pnav">
+ <div id="pnav">
+ <div id="pnavo">
+ $if(next)$
+ <a href="/$roomkey$/log/$next$"><- OLD DUMPS</a>
+ $endif$
+ </div>
+ <div id="pnavn">
+ &nbsp;&nbsp;
+ $if(prev)$
+ <a href="/$roomkey$/log/$prev$">NEW DUMPS -></a>
+ $endif$
- $if(next)$
- <a href="/$roomkey$/log/$next$"><- OLD DUMPS</a>
- $endif$
- &nbsp;&nbsp;
- $if(prev)$
- <a href="/$roomkey$/log/$prev$">NEW DUMPS -></a>
- $endif$
- </div>
+ <br><br>
+</div></div>
diff --git a/template/profile.st b/template/profile.st
index 91ca683..6204e27 100755
--- a/template/profile.st
+++ b/template/profile.st
@@ -3,11 +3,17 @@
<title>$nick$'s dump.fm</title>
$head()$
<link rel="stylesheet" type="text/css" media="screen" href="/static/profile.css">
+
<script type="text/javascript" src="/static/jquery.editinplace.1.0.1.packed.js"></script>
+
<script>
jQuery(document).ready(initProfile);
- </script>
+
+
+ </script>
+
+
</head>
<body>
$banner()$
@@ -19,15 +25,7 @@
</div>
<br>
- <div id="pnav">
- $if(next)$
- <a href="/u/$nick$/$next$"><- OLD DUMPS</a>
- $endif$
- &nbsp;&nbsp;
- $if(prev)$
- <a href="/u/$nick$/$prev$">NEW DUMPS -></a>
- $endif$
- </div>
+
<div id="posts">
@@ -49,16 +47,19 @@
$endif$
<p>&nbsp;</p>
<div id="pnav">
+ <div id="pnavo">
$if(next)$
<a href="/u/$nick$/$next$"><- OLD DUMPS</a>
$endif$
+ </div>
+ <div id="pnavn">
&nbsp;&nbsp;
$if(prev)$
<a href="/u/$nick$/$prev$">NEW DUMPS -></a>
$endif$
<br><br>
-</div>
+</div></div>
</div>
@@ -82,7 +83,8 @@
<h3>personal info</h3>
<div id="bio" $if(is_home)$class="editable"$endif$>$bio$</div>
- <br>
+ <br><br><br>
+
</div>
<div id="footer">