diff options
author | 藍挺瑋 <lantw44@gmail.com> | 2012-11-25 16:39:20 +0800 |
---|---|---|
committer | lantw44 <lantw44@gmail.com> | 2012-11-26 19:13:18 +0800 |
commit | d9f2dee9c6857cbbbe04dcf4d12b8450362e7812 (patch) | |
tree | 1078efc2f1b0de1c4fdc8d95bae1a01c5b3a5edf | |
download | inccalendar-d9f2dee9c6857cbbbe04dcf4d12b8450362e7812.tar.gz inccalendar-d9f2dee9c6857cbbbe04dcf4d12b8450362e7812.tar.zst inccalendar-d9f2dee9c6857cbbbe04dcf4d12b8450362e7812.zip |
Initial commit - upload all filesv0
-rw-r--r-- | .gitignore | 6 | ||||
-rw-r--r-- | app.yaml | 22 | ||||
-rw-r--r-- | css/format.css | 51 | ||||
-rw-r--r-- | jinhtml/month.html | 89 | ||||
-rw-r--r-- | jinhtml/welcome.html | 19 | ||||
-rw-r--r-- | js/cookie.js | 28 | ||||
-rw-r--r-- | js/month.js | 95 | ||||
-rw-r--r-- | js/shortcut.js | 223 | ||||
-rw-r--r-- | main.py | 39 |
9 files changed, 572 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cf9916f --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/datastore +/.project +/.pydevproject +*.pyc +*.swp +*.swo diff --git a/app.yaml b/app.yaml new file mode 100644 index 0000000..ed977e9 --- /dev/null +++ b/app.yaml @@ -0,0 +1,22 @@ +application: inccalender +version: 1 +runtime: python27 +api_version: 1 +threadsafe: false + +libraries: +- name: jinja2 + version: latest + +handlers: +- url: /css + static_dir: css + +- url: /js + static_dir: js + +- url: /access/.* + script: access/\1.app + +- url: /.* + script: main.app diff --git a/css/format.css b/css/format.css new file mode 100644 index 0000000..479321f --- /dev/null +++ b/css/format.css @@ -0,0 +1,51 @@ +body{ + margin: 0px; +} +div#topprodname{ + color: rgb(203, 203, 203); + background-color: black; + text-align: center; + font-size: 18px; + padding-top: 4px; + padding-bottom: 4px; +} +div#controlpanel{ + margin: 4px; + height: 28px; +} +div#controlpanel input{ + background-color: blue; + color: white; + border-width: thin; + border-radius: 4px; + padding: 4px 8px; + font-size: large; +} +div#controlpanel input.selected{ + border-style: inset; + background-color: navy; +} +div#controlleft{ + width: 50%; + float: left; + position: relative; + left: 2px; + text-align: left; +} +div#controlright{ + width: 50%; + float: left; + position: relative; + right: 2px; + text-align: right; +} +div#statusbar{ + position: fixed; + left: 0px; + bottom: 0px; + padding-top: 2px; + padding-bottom: 2px; + width: 100%; + border-top-style: dotted; + border-top-width: 2px; +}
\ No newline at end of file diff --git a/jinhtml/month.html b/jinhtml/month.html new file mode 100644 index 0000000..65becd0 --- /dev/null +++ b/jinhtml/month.html @@ -0,0 +1,89 @@ +<!DOCTYPE html> +<html> + <head> + <meta http-equiv="Content-type" content="text/html; charset=UTF-8"> + <title>{{ productname }}</title> + <link rel="stylesheet" href="css/format.css" type="text/css"> + <style type="text/css"> + div#timeselect{ + margin-top: 20px; + margin-bottom: 20px; + font-size: x-large; + text-align: center; + } + div#timeselect input{ + vertical-align: text-top; + } + table#cal{ + min-width: 800px; + width: 100%; + } + tbody#calbody{ + border-width: 2px; + border-style: solid; + height: 100px; + } + #timeedit_month, #timeedit_year, #timeedit_apply, #timeedit_cancel{ + display: none; + } + #timeedit_month, #timeedit_year{ + width: 50px; + } + </style> + <script src="js/cookie.js" type="text/javascript"></script> + <script src="js/month.js" type="text/javascript"></script> + <script type="text/javascript"> + function google_logout(){ + window.location = "{{ logouturl }}"; + } + </script> + </head> + <body onload="setyearmonth(); createcaltable(); setmonthcal();"> + <div id="topprodname"> + {{ googleuser }} - {{ productname }} + </div> + <div id="controlpanel"> + <div id="controlleft"> + <input type="button" value="月曆" id="switchmonth" class="selected"> + <input type="button" value="清單" id="switchlist"> + </div> + <div id="controlright"> + <input type="button" value="匯入" id="buttonimport"> + <input type="button" value="匯出" id="buttonexport"> + <input type="button" value="登出" onclick="google_logout()" style="background-color: darkgray"> + </div> + </div> + <div id="statusbar"> + 載入中...... + </div> + <div id="timeselect"> + <input type="button" value="<" id="timeselect_prev" onclick="timeselect_prev()"> + <span id="timeselect_year" onclick="timeselect_direct()">XXXX</span> + <input type="text" maxlength="4" id="timeedit_year"> + 年 + <span id="timeselect_month" onclick="timeselect_direct()">XX</span> + <input type="text" maxlength="4" id="timeedit_month"> + 月 + <input type="button" value=">" id="timeselect_fwd" onclick="timeselect_fwd()"> + <input type="button" value="確定" id="timeedit_apply" onclick="timeedit_apply()"> + <input type="button" value="取消" id="timeedit_cancel" onclick="timeedit_cancel()"> + </div> + <div id="monthcal"> + <table id="cal"> + <thead> + <tr> + <td>週日</td> + <td>週一</td> + <td>週二</td> + <td>週三</td> + <td>週四</td> + <td>週五</td> + <td>週六</td> + </tr> + </thead> + <tbody id="calbody"> + </tbody> + </table> + </div> + </body> +</html>
\ No newline at end of file diff --git a/jinhtml/welcome.html b/jinhtml/welcome.html new file mode 100644 index 0000000..cb18c9d --- /dev/null +++ b/jinhtml/welcome.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> + <head> + <meta http-equiv="content-type" content="text/html; charset=UTF-8"> + <title>{{ productname }}</title> + <style type="text/css"> + h1, p{ + text-align: center; + } + </style> + </head> + <body> + <h1>歡迎使用 {{ productname}}!</h1> + <p>請使用您的 Google 帳號 + <a href="{{ loginurl }}">登入</a> + 以使用本應用程式 + </p> + </body> +</html>
\ No newline at end of file diff --git a/js/cookie.js b/js/cookie.js new file mode 100644 index 0000000..8310e3e --- /dev/null +++ b/js/cookie.js @@ -0,0 +1,28 @@ +function getcookievalue(vname){ + var cookiearr = document.cookie.split(";"); + var rval = ""; + var i; + for(i=0;i<cookiearr.length;i++){ + if((cookiearr[i].substr(0, cookiearr[i].indexOf("="))).replace(" ", "") == vname){ + rval = unescape(cookiearr[i].substr(cookiearr[i].indexOf("=") + 1)); + } + } + return rval; +} + +function setcookievalue(vname, val){ + document.cookie = vname + "=" + escape(val); +} + +function cookie_exists(vname){ + var cookiearr = document.cookie.split(";"); + var yes = 0; + var i; + for(i=0;i<cookiearr.length;i++){ + if((cookiearr[i].substr(0, cookiearr[i].indexOf("="))).replace(" ", "") == vname){ + yes = 1; + break; + } + } + return yes; +} diff --git a/js/month.js b/js/month.js new file mode 100644 index 0000000..2dd4db0 --- /dev/null +++ b/js/month.js @@ -0,0 +1,95 @@ +var cookie_year = "inccal_year"; +var cookie_month = "inccal_month"; +var value_year; +var value_month; +var objyear; +var objmonth; + +function setyearmonth(){ + var useryear = parseInt(getcookievalue(cookie_year)); + var usermonth = parseInt(getcookievalue(cookie_month)); + /* 初始化 objyear 和 objmonth,其他函式中不用在做同樣的動作 */ + objyear = document.getElementById("timeselect_year"); + objmonth = document.getElementById("timeselect_month"); + if(useryear > 0 && usermonth >= 1 && usermonth <= 12){ + value_year = useryear; + value_month = usermonth; + }else{ + var today = new Date(); + value_year = today.getFullYear(); + value_month = today.getMonth(); + } +} + +function timeselect_prev(){ + if(value_month <= 1){ + if(value_year > 1){ + value_year--; + value_month = 12; + } + }else{ + value_month--; + } + setmonthcal(); +} + +function timeselect_fwd(){ + if(value_month >= 12){ + value_year++; + value_month = 1; + }else{ + value_month++; + } + setmonthcal(); +} + +function timeselect_direct(){ + document.getElementById("timeedit_year").style.display = "inline"; + document.getElementById("timeedit_month").style.display = "inline"; + document.getElementById("timeedit_apply").style.display = "inline"; + document.getElementById("timeedit_cancel").style.display = "inline"; + document.getElementById("timeselect_year").style.display = "none"; + document.getElementById("timeselect_month").style.display = "none"; + document.getElementById("timeselect_prev").style.display = "none"; + document.getElementById("timeselect_fwd").style.display = "none"; + + document.getElementById("timeedit_year").value = value_year; + document.getElementById("timeedit_month").value = value_month; +} + +function timeedit_apply(){ + var newyear = parseInt(document.getElementById("timeedit_year").value); + var newmonth = parseInt(document.getElementById("timeedit_month").value); + if(newyear <= 0 || newmonth < 1 || newmonth > 12){ + alert("請輸入正確的年份和月份!"); + return; + } + value_year = newyear; + value_month = newmonth; + setmonthcal(); + timeedit_cancel(); +} + +function timeedit_cancel(){ + document.getElementById("timeedit_year").style.display = "none"; + document.getElementById("timeedit_month").style.display = "none"; + document.getElementById("timeedit_apply").style.display = "none"; + document.getElementById("timeedit_cancel").style.display = "none"; + document.getElementById("timeselect_year").style.display = "inline"; + document.getElementById("timeselect_month").style.display = "inline"; + document.getElementById("timeselect_prev").style.display = "inline"; + document.getElementById("timeselect_fwd").style.display = "inline"; +} + +function createcaltable(){ + objbd = document.getElementById("calbody"); + +} + +function setmonthcal(){ + objyear.innerHTML = value_year; + objmonth.innerHTML = value_month; + setcookievalue(cookie_year, value_year); + setcookievalue(cookie_month, value_month); +} + diff --git a/js/shortcut.js b/js/shortcut.js new file mode 100644 index 0000000..debaffb --- /dev/null +++ b/js/shortcut.js @@ -0,0 +1,223 @@ +/** + * http://www.openjs.com/scripts/events/keyboard_shortcuts/ + * Version : 2.01.B + * By Binny V A + * License : BSD + */ +shortcut = { + 'all_shortcuts':{},//All the shortcuts are stored in this array + 'add': function(shortcut_combination,callback,opt) { + //Provide a set of default options + var default_options = { + 'type':'keydown', + 'propagate':false, + 'disable_in_input':false, + 'target':document, + 'keycode':false + } + if(!opt) opt = default_options; + else { + for(var dfo in default_options) { + if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo]; + } + } + + var ele = opt.target; + if(typeof opt.target == 'string') ele = document.getElementById(opt.target); + var ths = this; + shortcut_combination = shortcut_combination.toLowerCase(); + + //The function to be called at keypress + var func = function(e) { + e = e || window.event; + + if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields + var element; + if(e.target) element=e.target; + else if(e.srcElement) element=e.srcElement; + if(element.nodeType==3) element=element.parentNode; + + if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return; + } + + //Find Which key is pressed + if (e.keyCode) code = e.keyCode; + else if (e.which) code = e.which; + var character = String.fromCharCode(code).toLowerCase(); + + if(code == 188) character=","; //If the user presses , when the type is onkeydown + if(code == 190) character="."; //If the user presses , when the type is onkeydown + + var keys = shortcut_combination.split("+"); + //Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked + var kp = 0; + + //Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken + var shift_nums = { + "`":"~", + "1":"!", + "2":"@", + "3":"#", + "4":"$", + "5":"%", + "6":"^", + "7":"&", + "8":"*", + "9":"(", + "0":")", + "-":"_", + "=":"+", + ";":":", + "'":"\"", + ",":"<", + ".":">", + "/":"?", + "\\":"|" + } + //Special Keys - and their codes + var special_keys = { + 'esc':27, + 'escape':27, + 'tab':9, + 'space':32, + 'return':13, + 'enter':13, + 'backspace':8, + + 'scrolllock':145, + 'scroll_lock':145, + 'scroll':145, + 'capslock':20, + 'caps_lock':20, + 'caps':20, + 'numlock':144, + 'num_lock':144, + 'num':144, + + 'pause':19, + 'break':19, + + 'insert':45, + 'home':36, + 'delete':46, + 'end':35, + + 'pageup':33, + 'page_up':33, + 'pu':33, + + 'pagedown':34, + 'page_down':34, + 'pd':34, + + 'left':37, + 'up':38, + 'right':39, + 'down':40, + + 'f1':112, + 'f2':113, + 'f3':114, + 'f4':115, + 'f5':116, + 'f6':117, + 'f7':118, + 'f8':119, + 'f9':120, + 'f10':121, + 'f11':122, + 'f12':123 + } + + var modifiers = { + shift: { wanted:false, pressed:false}, + ctrl : { wanted:false, pressed:false}, + alt : { wanted:false, pressed:false}, + meta : { wanted:false, pressed:false} //Meta is Mac specific + }; + + if(e.ctrlKey) modifiers.ctrl.pressed = true; + if(e.shiftKey) modifiers.shift.pressed = true; + if(e.altKey) modifiers.alt.pressed = true; + if(e.metaKey) modifiers.meta.pressed = true; + + for(var i=0; k=keys[i],i<keys.length; i++) { + //Modifiers + if(k == 'ctrl' || k == 'control') { + kp++; + modifiers.ctrl.wanted = true; + + } else if(k == 'shift') { + kp++; + modifiers.shift.wanted = true; + + } else if(k == 'alt') { + kp++; + modifiers.alt.wanted = true; + } else if(k == 'meta') { + kp++; + modifiers.meta.wanted = true; + } else if(k.length > 1) { //If it is a special key + if(special_keys[k] == code) kp++; + + } else if(opt['keycode']) { + if(opt['keycode'] == code) kp++; + + } else { //The special keys did not match + if(character == k) kp++; + else { + if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase + character = shift_nums[character]; + if(character == k) kp++; + } + } + } + } + + if(kp == keys.length && + modifiers.ctrl.pressed == modifiers.ctrl.wanted && + modifiers.shift.pressed == modifiers.shift.wanted && + modifiers.alt.pressed == modifiers.alt.wanted && + modifiers.meta.pressed == modifiers.meta.wanted) { + callback(e); + + if(!opt['propagate']) { //Stop the event + //e.cancelBubble is supported by IE - this will kill the bubbling process. + e.cancelBubble = true; + e.returnValue = false; + + //e.stopPropagation works in Firefox. + if (e.stopPropagation) { + e.stopPropagation(); + e.preventDefault(); + } + return false; + } + } + } + this.all_shortcuts[shortcut_combination] = { + 'callback':func, + 'target':ele, + 'event': opt['type'] + }; + //Attach the function with the event + if(ele.addEventListener) ele.addEventListener(opt['type'], func, false); + else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func); + else ele['on'+opt['type']] = func; + }, + + //Remove the shortcut - just specify the shortcut and I will remove the binding + 'remove':function(shortcut_combination) { + shortcut_combination = shortcut_combination.toLowerCase(); + var binding = this.all_shortcuts[shortcut_combination]; + delete(this.all_shortcuts[shortcut_combination]) + if(!binding) return; + var type = binding['event']; + var ele = binding['target']; + var callback = binding['callback']; + + if(ele.detachEvent) ele.detachEvent('on'+type, callback); + else if(ele.removeEventListener) ele.removeEventListener(type, callback, false); + else ele['on'+type] = false; + } +}
\ No newline at end of file @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +import cgi +import os +import jinja2 +import webapp2 + +from google.appengine.api import users +from google.appengine.ext import db + +class MainPage(webapp2.RedirectHandler): + def get(self): + guserid = users.get_current_user() + productname = cgi.escape(u'#include <行事曆.h>') + if guserid: + logouturl = cgi.escape(users.create_logout_url(self.request.uri)) + jintemvar = { + 'logouturl': logouturl, + 'productname': productname, + 'googleuser': guserid + } + jinhtml = jinenv.get_template('jinhtml/month.html') + + else: + loginurl = cgi.escape(users.create_login_url(self.request.uri)) + jintemvar = { + 'loginurl': loginurl, + 'productname': productname + } + jinhtml = jinenv.get_template('jinhtml/welcome.html') + + self.response.out.write(jinhtml.render(jintemvar)) + + +jinenv = jinja2.Environment( + loader = jinja2.FileSystemLoader(os.path.dirname(__file__))) + +app = webapp2.WSGIApplication([('/', MainPage)])
\ No newline at end of file |