diff --git a/DOCS/readme.txt b/DOCS/readme.txt
index 72b76c0..f3778aa 100644
--- a/DOCS/readme.txt
+++ b/DOCS/readme.txt
@@ -1,6 +1,6 @@
TaskFreak! Time Tracking
------------------------
-version : 0.4
+version : 0.5
Requirements
diff --git a/DOCS/release.txt b/DOCS/release.txt
index 35fd667..f4c6878 100644
--- a/DOCS/release.txt
+++ b/DOCS/release.txt
@@ -1,6 +1,18 @@
TaskFreak! Time Tracking
------------------------
+Version 0.5 : 2010-07-16
+------------------------
+Added iphone (beta) version
+Added german translation
+Added norwegian translation
+Added missing time zones
+Fixed time difference bug with time zones not GMT
+Fixed multi task creation bug
+Fixed windows server file path bug
+Fixed bug on user creation
+
+
Version 0.4 : 2010-06-11
------------------------
Added multi language support
diff --git a/DOCS/taskfreak_timer.sql b/DOCS/taskfreak_timer.sql
index 5869fe2..80a9481 100644
--- a/DOCS/taskfreak_timer.sql
+++ b/DOCS/taskfreak_timer.sql
@@ -56,8 +56,8 @@ CREATE TABLE IF NOT EXISTS `task` (
KEY `member_id` (`member_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-INSERT INTO `task` VALUES(1, 'taskfreak : README first about this beta version', 'Please keep in mind that this is a beta version. There are quite a few known bugs, a handful of unknown bugs.\r\n\r\nHere''s what you can do so far :\r\n- create, edit and archive tasks\r\n- start and stop task timers\r\n- report time spent on a task\r\n- edit your own profile\r\n- see other''s tasks (task manager only)\r\n- create and edit users (user admin only)\r\n\r\nMake sure you read the README file under the DOCS/ folder. There''s a few setup tips in there.', 5, '9999-00-00', '2010-06-11', 0, 0, 1);
-INSERT INTO `task` VALUES(2, 'taskfreak : quick notes about TT 0.4', 'Here''s the list of known bugs at release time :\r\n- some errors might occur on dates depending on your time zone\r\n- order by start, stop, or spent doesn''t really make sense\r\n- very buggy under IE8, and simply unusable with older versions of IE\r\n\r\nPlease report found bugs here :\r\nhttp://forum.taskfreak.com/index.php?board=7.0', 4, '9999-00-00', '9999-00-00', 0, 0, 1);
+INSERT INTO `task` VALUES(1, 'taskfreak : README first about this beta version', 'Please keep in mind that this is a beta version. There are quite a few known bugs, a handful of unknown bugs.\r\n\r\nHere''s what you can do so far :\r\n- create, edit and archive tasks\r\n- start and stop task timers\r\n- report time spent on a task\r\n- edit your own profile\r\n- see other''s tasks (task manager only)\r\n- create and edit users (user admin only)\r\n\r\nMake sure you read the README file under the DOCS/ folder. There''s a few setup tips in there.', 5, '9999-00-00', '2010-07-17', 0, 0, 1);
+INSERT INTO `task` VALUES(2, 'taskfreak : quick notes about TT 0.5', 'Here''s the list of known bugs at release time :\r\n- iphone version is slow and not full featured yet\r\n- order by start, stop, or spent doesn''t really make sense\r\n- very buggy under IE8, and simply unusable with older versions of IE\r\n\r\nPlease report found bugs here :\r\nhttp://forum.taskfreak.com/index.php?board=7.0', 4, '9999-00-00', '9999-00-00', 0, 0, 1);
CREATE TABLE IF NOT EXISTS `timer` (
`task_id` int(10) unsigned NOT NULL,
diff --git a/app/config/app.php b/app/config/app.php
index 83e0fff..9580124 100644
--- a/app/config/app.php
+++ b/app/config/app.php
@@ -3,10 +3,10 @@
// ---- LOG and DEBUGGING -----------------------------------------------------
$GLOBALS['config']['log_front'] = 0;
-$GLOBALS['config']['log_debug'] = 0;
+$GLOBALS['config']['log_debug'] = 1;
$GLOBALS['config']['log_message'] = 0;
$GLOBALS['config']['log_warn'] = 0;
-$GLOBALS['config']['log_error'] = 1;
+$GLOBALS['config']['log_error'] = 2;
$GLOBALS['config']['log_core'] = 0;
$GLOBALS['config']['log_signature'] = '[TF]';
@@ -44,10 +44,13 @@ define("APP_DATETIME","%d/%m %H:%M ");
// --- TASKFREAK DEFAULTS ---------------------------------------------------------
$GLOBALS['config']['task'] = array(
- 'date' => APP_SQL_TODAY, // default date is today
+ 'date' => 'now', // default date is today
'validate' => true // add validation button
);
+// note for default date :
+// can be any PHP valid date eg. +1 days, +1 week, or false for no date
+
$GLOBALS['config']['task']['priority'] = array(
'options' => array(
1 => 'urgent',
diff --git a/app/config/core.php b/app/config/core.php
index dbad8da..96ae524 100644
--- a/app/config/core.php
+++ b/app/config/core.php
@@ -125,6 +125,8 @@ define("APP_DATETIME_LNG","%d %B %Y, %H:%M");
define("APP_DATETIME_LNX","%A %d %B %Y, %H:%M");
define("APP_DATETIME_HRS","%H:%M");
+define('APP_DATE_RFC822', '%a, %d %b %Y %H:%M:%S %z');
+
// date_default_timezone_set('Europe/Paris');
define('APP_TIMEZONE_SERVER',date_default_timezone_get());
define('APP_TZSERVER',intval(date('Z')));
@@ -153,4 +155,12 @@ if (@constant('APP_TRANS_ID')) {
} else {
ini_set('session.use_trans_sid', 0);
ini_set('session.use_only_cookies', 1);
-}
\ No newline at end of file
+}
+
+// ---- AGENT DETECTION -------------------------------------------------------
+
+define('APP_ROBOT_AGENT', 'Google|msnbot|Rambler|Yahoo|AbachoBOT|accoona|AcioRobot|ASPSeek|'
+ .'CocoCrawler|Dumbot|FAST\-WebCrawler|GeonaBot|Gigabot|Lycos|MSRBOT|Scooter|'
+ .'AltaVista|IDBot|eStyle|Scrubby');
+
+define('APP_IPHONE_AGENT', 'iPhone|iPod|iPad');
\ No newline at end of file
diff --git a/app/config/db.php b/app/config/db.php
index bc48e8f..6aa7ee3 100644
--- a/app/config/db.php
+++ b/app/config/db.php
@@ -1,7 +1,7 @@
fc->chkReqVar('pass1') && $this->fc->chkReqVar('pass2')) {
if ($this->data->setPassword($this->fc->getReqVar('pass1'), $this->fc->getReqVar('pass2'))) {
// save it all
- error_log('setting new password : '.$this->fc->getReqVar('pass1'));
$this->data->ignore();
} else {
// do not save password
- error_log('can not save password');
$this->data->ignore('password,salt');
}
}
@@ -116,7 +114,6 @@ class Admin extends AppController {
if ($this->data->save(!$myself)) {
if ($myself) {
// editing own profile need to reset session
- error_log('updating session');
$this->data->updateSessionVariables();
}
$this->fc->autoRedirect('saved');
diff --git a/app/controller/iphone.php b/app/controller/iphone.php
new file mode 100644
index 0000000..942d42e
--- /dev/null
+++ b/app/controller/iphone.php
@@ -0,0 +1,450 @@
+
+ * @version 0.5
+ * @copyright GNU General Public License (GPL) version 3
+ */
+
+/**
+ * iphone
+ *
+ * iphone version
+ * @since 0.5
+ */
+class Iphone extends AppController {
+
+ public function __construct() {
+ parent::__construct(false, true);
+ // parent::__construct(false, true);
+
+ $this->fc->loadModel('TaskModel');
+
+ // $this->page->clean('css');
+ // $this->page->clean('js');
+ $GLOBALS['config']['path']['css'][] = 'asset/jqtouch/';
+ $GLOBALS['config']['path']['css'][] = 'asset/jqtouch/themes/jqt/';
+ $GLOBALS['config']['path']['js'][] = 'asset/jqtouch/';
+
+ $this->page->add('css',array('jqtouch.min.css','theme.css','iphone.css'));
+ // $this->page->add('js',array('jquery.form.min.js','jquery.colorbox-min.js'));
+ $this->page->add('js',array('jqtouch.js','iphone.js'));
+ $jsCode = "var APP_LOGOUT='". $this->fc->getUrl('iphone','logout')."';\n";
+ $jsCode .= "var APP_RELOAD='". $this->fc->getUrl('iphone','home')."';\n";
+ $jsCode .= "var APP_VIEW='". $this->fc->getUrl('iphone','detail',array('id'=>''))."';\n";
+ $jsCode .= "var APP_EDIT='". $this->fc->getUrl('iphone','edit',array('id'=>''))."';\n";
+ $jsCode .= "var jQT = new $.jQTouch({
+ icon: '".APP_WWW_URI.'skin/'.$GLOBALS['config']['skin']."/img/iphone_icon.png',
+ addGlossToIcon: false,
+ startupScreen: '".APP_WWW_URI.'skin/'.$GLOBALS['config']['skin']."/img/iphone_startup.png',
+ statusBar: 'black',
+ formSelector: '.form',
+ touchSelector: '.button, .back, .cancel, .add, .touch',
+ preloadImages: [
+ '".APP_WWW_URI."asset/jqtouch/themes/jqt/img/back_button.png',
+ '".APP_WWW_URI."asset/jqtouch/themes/jqt/img/back_button_clicked.png',
+ '".APP_WWW_URI."asset/jqtouch/themes/jqt/img/button_clicked.png',
+ '".APP_WWW_URI."asset/jqtouch/themes/jqt/img/grayButton.png',
+ '".APP_WWW_URI."asset/jqtouch/themes/jqt/img/whiteButton.png',
+ '".APP_WWW_URI."skin/".$GLOBALS['config']['skin']."/img/lightButton.png',
+ '".APP_WWW_URI."skin/".$GLOBALS['config']['skin']."/img/darkButton.png',
+ '".APP_WWW_URI."asset/jqtouch/themes/jqt/img/loading.gif'
+ ]
+ });";
+ $this->page->add('jsCode',$jsCode);
+ }
+
+ /**
+ * main menu (list tasks)
+ */
+ public function mainAction() {
+
+ $this->_loadHomeView();
+
+ $this->page->set('title','TaskFreak! Time Tracking');
+ $this->setView('iphone/main');
+ $this->viewIPhone();
+ }
+
+ /**
+ * main menu (list tasks)
+ */
+ public function homeAction() {
+
+ $this->_loadHomeView();
+
+ $this->incView('iphone/inc_main');
+ $this->incList('list-st0',TR::html('pages','todo'),$this->dataTodo);
+ $this->incList('list-st1',TR::html('pages','done'),$this->dataDone);
+ $this->incList('list-st2',TR::html('pages','valid'),$this->dataValid);
+ }
+
+ /**
+ * reacts to current task actions
+ */
+ public function homeReaction() {
+ // error_log('lets '.$this->fc->getReqVar('action').' on '.$this->fc->getReqVar('id'));
+ return $this->_taskStatus();
+ }
+
+ /**
+ * list tasks for a specific tag
+ */
+ public function listAction() {
+
+ $this->_checkLogin(true);
+
+ if ($tag = $this->fc->getReqVar('tag')) {
+ $data = $this->_loadTaskList("title LIKE '$tag%'");
+ $this->incList('list-'.StringHelper::cleanStrip($tag), $tag, $data);
+ return true;
+ }
+
+ // reaching this point means error has occured
+ header('HTTP/1.0 404 Not Found');
+
+ }
+
+ /**
+ * display task details
+ */
+ public function detailAction() {
+ $this->_checkLogin(true);
+ sleep(1);
+ // load current running task to check if it's actually running
+ $this->current = TaskSummary::loadCurrent();
+ // load task full details and history
+ $this->_loadTaskSummary(true);
+ $data = $this->data->exportData();
+ $data['running'] = ($this->current && ($this->current->getUid() == $this->data->getUid()))?true:false;
+ header('Content-type: application/json');
+ echo json_encode($data);
+ }
+
+ /**
+ * reacts to displayed task actions
+ */
+ public function detailReaction() {
+ return $this->_taskStatus();
+ }
+
+ /**
+ * edit task (sends back data in JSON format)
+ */
+ public function editAction() {
+ $this->_checkLogin(true);
+ sleep(1);
+ $this->_loadTask(false);
+ $this->edit->addHelper('json');
+ header('Content-type: application/json');
+ echo $this->edit->export('value');
+ }
+
+ /**
+ * save task (form reaction)
+ */
+ public function editReaction() {
+ $this->_checkLogin(true);
+ $this->_loadTask(false);
+ $this->edit->ignore('creation_date'); // do not submit or change creation date
+ $this->edit->set($this->fc->request);
+ if ($this->edit->check($this->fc->user->getUid())) {
+ $this->edit->save();
+ }
+ echo '';
+ /*
+ // send back list of tasks for this status
+ $status = $this->edit->get('status');
+ $data = $this->_loadTaskList("status=$status");
+ $arr = array_keys($GLOBALS['lang']['pages']);
+ $this->incList('list-st'.$status, TR::html('pages',$arr[$status]), $data);
+ */
+ }
+
+ /**
+ * display task timer history
+ */
+ public function historyAction() {
+ }
+
+ /**
+ * displays new timer form
+ */
+ public function timerAction() {
+ }
+
+ /**
+ * reacts to timer form
+ */
+ public function timerReaction() {
+ }
+
+ /**
+ * login on iphone
+ */
+ public function loginAction() {
+ $this->fc->user->addHelper('html_form');
+ $this->page->set('title','TaskFreak! '.TR::get('security','login'));
+ $this->setView('iphone/login');
+ $this->viewIPhone();
+ }
+
+ /**
+ * Logs user in
+ * @todo redirect to requested page
+ */
+ public function loginReaction() {
+ $this->fc->user->fields('username,password');
+ $this->fc->user->set($this->fc->request);
+ if ($this->fc->user->login($this->fc->user->get('username'), $this->fc->user->get('password'))) {
+ $this->fc->user->setAutoLogin();
+ header('HTTP/1.0 200 OK');
+ $this->homeAction();
+ } else {
+ header('HTTP/1.0 403 Forbidden');
+ }
+ return false;
+ }
+
+ /**
+ * Logs user out
+ * @todo show logout summary page
+ */
+ public function logoutAction() {
+ $this->fc->user->logout();
+ // NaviHelper::redirect($this->fc->getUrl('iphone','main'));
+ // echo '';
+ return false;
+ }
+
+ /**
+ * check if user is logged in
+ * sends back a 403 if user is not allowed
+ */
+ protected function _checkLogin($exit) {
+ if (!$this->fc->user->isLoggedIn()) {
+ if ($exit) {
+ header('HTTP/1.0 403 Forbidden');
+ exit;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * change task status
+ */
+ protected function _taskStatus() {
+ $this->current = TaskSummary::loadCurrent();
+
+ $arrReload = array();
+
+ if ($id = $this->fc->getReqVar('id')) {
+ if ($this->current && $this->current->getUid() != $id) {
+ // we have a running task, but it's not the requested one
+ // so first, we need to stop it.
+ $cid = $this->current->getUid();
+ TimerModel::stop($cid);
+ // and we'll have to reload the page details later
+ $arrReload[] = $cid;
+ } else {
+ $this->current = new TaskSummary();
+ $this->current->connectDb();
+ $this->current->setUid($id);
+ $this->current->load();
+ }
+
+ if ($this->current->getUid()) {
+ // -TODO- check rights
+ switch($this->fc->getReqVar('action')) {
+ case 'pause':
+ // try to pause
+ if ($this->current && $this->current->getUid() == $id) {
+ // ok, task is actually running
+ TimerModel::stop($id);
+ $this->current->set('stop',APP_SQL_NOW);
+ $this->jsCode .= "";
+ } else {
+ // nope, requested task is not running, show error
+ FC::log_debug('error trying to pause non running task');
+ header('HTTP/1.0 403 Forbidden');
+ exit;
+ }
+ $this->setView('iphone/inc_timer');
+ $this->viewRaw();
+ break;
+ case 'resume':
+ case 'start':
+ TimerModel::start($id);
+ $this->current = TaskSummary::loadCurrent();
+ $this->jsCode = "clockstart();";
+ $this->setView('iphone/inc_timer');
+ $this->viewRaw();
+ break;
+ case 'stop':
+ if (TimerModel::stop($id)) {
+ $this->jsCode = "clockstatus();";
+ } else {
+ $this->jsCode = "alert('".TR::get('error','action_failed')."');";
+ }
+ $this->current = false;
+ break;
+ case 'close':
+ if (TimerModel::stop($id)) {
+ $this->jsCode = "clockstatus();";
+ $this->current->updateStatus(1); // mark as done
+ $this->current = false;
+ }
+ break;
+ }
+ // need to reload newly modified task details
+ $arrReload[] = $id;
+ }
+
+ return false;
+ }
+
+ // reaching this point means an error has occured
+ header('HTTP/1.0 404 Not Found');
+ exit;
+ }
+
+ /**
+ * load home screen
+ */
+ protected function _loadHomeView() {
+
+ $this->edit = new TaskModel();
+ $this->edit->addHelper('html_form');
+
+ if (!$this->_checkLogin(false)) {
+ return false;
+ }
+ $this->current = TaskSummary::loadCurrent();
+
+ $this->dataTodo = $this->_loadTaskList('status=0');
+ $this->dataDone = $this->_loadTaskList('status=1');
+ $this->dataValid = $this->_loadTaskList('status=2');
+
+ /*
+ $db = DbHelper::factory();
+ $db->select("DISTINCT (SUBSTRING_INDEX( title, ':', 1 )) as tag");
+ $db->from('task');
+ $db->where("title LIKE '%:%'");
+ $this->dataTags = $db->loadRaw();
+ */
+
+ return true;
+ }
+
+ /**
+ * load task
+ */
+ protected function _loadTask($exit) {
+
+ if (isset($this->edit) && is_a($this->edit, 'TaskModel')) {
+ // task already loaded
+ return true;
+ }
+
+ $this->edit = new TaskModel();
+ $this->edit->connectDb();
+
+ if ($id = $this->fc->getReqVar('id')) {
+ $this->edit->setUid($id);
+ if ($this->edit->load()) {
+ return true;
+ }
+ }
+
+ // reaching this point means error has occured
+ if ($exit) {
+ header('HTTP/1.0 404 Not Found');
+ exit;
+ }
+ return false;
+ }
+
+ /**
+ * load task with timer info
+ */
+ protected function _loadTaskSummary($exit) {
+
+ if (isset($this->data) && is_a($this->data, 'TaskSummary') && ($this->data->getUid())) {
+ // task already loaded
+ return true;
+ }
+
+ $this->data = new TaskSummary();
+ $this->data->connectDb();
+
+ $ok = false;
+ if ($id = $this->fc->getReqVar('id')) {
+ $this->data->where('id='.$id);
+ $this->data->orderBy('start ASC');
+ if ($this->data->loadExpandList()) {
+ if ($this->data->next()) {
+ $this->data->chkDeadline();
+ return true;
+ }
+ }
+ }
+
+ // reaching this point means error has occured
+ if ($exit) {
+ header('HTTP/1.0 404 Not Found');
+ exit;
+ }
+ return false;
+ }
+
+ /**
+ * load task list
+ */
+ protected function _loadTaskList($filter) {
+ $data = new TaskSummary();
+ $data->connectDb();
+ $data->where($filter);
+ $data->where('archived=0');
+ $data->where('member_id='.$this->fc->user->getUid());
+ $data->orderBy('status ASC, deadline ASC, priority ASC, title ASC, start ASC');
+ $data->loadCompactList();
+ return $data;
+ }
+
+ /**
+ * view list
+ */
+ protected function incList($name, $title, &$data) {
+ echo '
';
+ echo '
';
+ if ($data) {
+ echo '
';
+ } else {
+ echo '
';
+ }
+ // echo '';
+ echo '
';
+ }
+}
\ No newline at end of file
diff --git a/app/controller/task.php b/app/controller/task.php
index ed674b7..9330ad4 100644
--- a/app/controller/task.php
+++ b/app/controller/task.php
@@ -18,7 +18,7 @@ class Task extends AppController {
public function __construct() {
parent::__construct(true);
-
+
$this->fc->setSessionDefault('order','deadline');
$this->fc->setSessionDefault('limit',$GLOBALS['config']['task']['pagination_default']);
if (APP_SETUP_USER_MODEL) {
diff --git a/app/lang/de/freak.php b/app/lang/de/freak.php
new file mode 100644
index 0000000..18c007b
--- /dev/null
+++ b/app/lang/de/freak.php
@@ -0,0 +1,120 @@
+ 'Priorität',
+ 'spent' => 'aufgewendet',
+ 'note' => 'notieren',
+ 'todo' => 'zu erledigen',
+ 'done' => 'erledigt',
+ 'valid' => 'gültig',
+ 'archived' => 'archiviert',
+ 'running' => 'laufend',
+ 'paused' => 'pausiert'
+);
+
+$GLOBALS['lang']['priority'] = array(
+ 'urgent' => 'dringend',
+ 'important' => 'wichtig',
+ 'high' => 'hoch',
+ 'quickly' => 'schnell',
+ 'pretty_soon' => 'sehr bald',
+ 'soon' => 'bald',
+ 'normal' => 'normal',
+ 'after' => 'nach',
+ 'later' => 'später',
+ 'low' => 'niedrig',
+ 'anytime' => 'irgendwann',
+ 'whenever' => 'wann immer'
+);
+
+$GLOBALS['lang']['ui'] = array(
+ 'reload' => 'neu laden',
+ 'reload_list' => 'Liste neu laden',
+ 'task' => 'Aufgabe',
+ 'tasks' => 'Aufgaben',
+ 'create_single' => 'Einzelne Aufgabe erstellen',
+ 'create_multi' => 'Mehrere Aufgaben erstellen',
+ 'edit_task' => 'Aufgabe bearbeiten',
+ 'delete_task' => 'Aufgabe löschen',
+ 'start_task' => 'Aufgabe starten',
+ 'mark_archived' => 'Aufgabe als archiviert markieren',
+ 'done_confirm' => 'verschieben und diese Aufgabe wirklich als beendet markieren ?',
+ 'compact' => 'kompakt',
+ 'expand' => 'Ausklappen',
+ 'select_all' => 'Alle auswählen',
+ 'info' => 'Info',
+ 'history' => 'Verlauf',
+ 'history_empty' => 'Bisher noch keine Zeitberichte',
+ 'report_spent' => 'Bericht über Zeitaufwand',
+ 'total' => 'insgesamt',
+ 'user_menu' => 'Benutzermenü anzeigen',
+ 'admin' => 'Admin',
+ 'settings' => 'Einstellungen',
+ 'all_users' => 'Alle Benutzer',
+ 'switch' => 'Wechseln',
+ 'switch_user' => 'Aufgaben anderer Benutzer anzeigen',
+ 'select_user' => 'Wählen Sie den Benutzer, dessen Aufgaben Sie sehen möchten',
+ 'switched' => 'Zu anderem Benutzer gewechselt',
+ 'task_manager' => 'Aufgaben-Manager',
+ 'task_managers' => 'Aufgaben-Manager',
+ 'user_admin' => 'Benutzeradministrator',
+ 'user_admins' => 'Benutzeradministratoren',
+ 'last_visit' => 'Letzter Besuch',
+ 'preferences' => 'Meine Präferenzen',
+ 'create_user' => 'Benutzer erstellen',
+ 'edit_user' => 'Benutzer bearbeiten',
+ 'delete_user' => 'Benutzer löschen'
+);
+
+$GLOBALS['lang']['pages'] = array(
+ 'todo' => 'Zu erledigen',
+ 'done' => 'Erledigt',
+ 'valid' => 'Gültig',
+ 'archives' => 'Archiv',
+ 'edit_task' => 'Aufgabe bearbeiten',
+ 'create_task' => 'Aufgabe erstellen',
+ 'create_tasks' => 'Mehrere Aufgaben erstellen',
+ 'view_task' => 'Aufgaben-Details'
+);
+
+$arrMess = array(
+ 'task_created' => 'Aufgabe erstellt',
+ 'task_updated' => 'Aufgabe aktualisiert',
+ '%_task_created' => '% Aufgabe(n) erstellt',
+ 'task_deleted' => 'Aufgabe gelöscht',
+ 'time_added' => 'Berichtete Arbeitszeit'
+);
+
+$GLOBALS['lang']['message'] = $GLOBALS['lang']['message']+$arrMess;
+
+$arrButton = array(
+ 'pause' => 'Pause',
+ 'resume' => 'Fortfahren',
+ 'done' => 'Erledigt',
+ 'reopen' => 'Wiedereröffnen',
+ 'postpone_1_day' => 'Um 1 Tag verschieben',
+ 'postpone_2_days' => 'Um 2 Tage verschieben',
+ 'postpone_1_week' => 'Um 1 Woche verschieben',
+ 'postpone_2_weeks' => 'Um 2 Wochen verschieben',
+ 'postpone_1_month' => 'Um 1 Monat verschieben',
+ 'postpone_2_months' => 'Um 2 Monate verschieben',
+ 'postpone_1_year' => 'Um 1 Jahr verschieben',
+ 'postpone_2_years' => 'Um 2 Jahre verschieben',
+ 'mark_done' => 'Als erledigt markieren',
+ 'validate' => 'Überprüfen',
+ 'archive' => 'archivieren',
+ 'unarchive' => 'Archivierung rückgängig machen',
+ 'save_report' => 'Bericht speichern',
+ 'save_task' => 'Aufgabe speichern',
+ 'save_and_start' => 'Speichern und starten'
+);
+
+$GLOBALS['lang']['button'] = $GLOBALS['lang']['button']+$arrButton;
diff --git a/app/lang/de/help_multi_creation.php b/app/lang/de/help_multi_creation.php
new file mode 100644
index 0000000..fc79d0a
--- /dev/null
+++ b/app/lang/de/help_multi_creation.php
@@ -0,0 +1,19 @@
+Geben Sie eine Aufgabe pro Zeile ein.
+Aufgaben-Format
+Aufgaben-Format : [date] [priority] [label :] Aufgaben-Titel
+Felder in Klammern sind optional
+Datum kann sein :
+
+ ein Datum im Format dd/mm[/yy]
+ ein + gefolgt von einer Anzahl an Einheiten für die Zukunft
+ ein - bedeutet, dass es keine Deadline gibt
+ nichts bedeutet, dass die Deadline heute ist
+
+Priorität ist eine Zahl zwischen 1 und 9, gefolgt von einer )
+« 1) » für dringende Aufgaben, « 5) » für normale Priorität
+Bezeichnung ist optional
+Standards für mehrere Aufgaben
+eine Zeile angefangen mit einem * richtet Standards ein
+Format ist : * [date] [label]
+« * +1 Aufgabe » der « * 12/04 »
+Standards zurücksetzen durch eine Zeile mit « ** »
diff --git a/app/lang/de/help_timer_creation.php b/app/lang/de/help_timer_creation.php
new file mode 100644
index 0000000..629a023
--- /dev/null
+++ b/app/lang/de/help_timer_creation.php
@@ -0,0 +1,8 @@
+Geben Sie eine der folgenden Möglichkeiten ein:
+
+ Nur einen Startzeitpunkt (berechnet die Zeit von damals bis heute)
+ Nur einen Zeitaufwand (überprüft, ob Sie die Aufgabe beendet haben)
+ Einen Startzeitpunkt und einen Endzeitpunkt
+ Einen Startzeitpunkt und einen Zeitaufwand
+ Einen Endzeitpunkt und einen Zeitaufwand
+
diff --git a/app/lang/no/freak.php b/app/lang/no/freak.php
new file mode 100755
index 0000000..3ea8c68
--- /dev/null
+++ b/app/lang/no/freak.php
@@ -0,0 +1,123 @@
+
+ * @version 0.4
+ * @copyright GNU General Public License (GPL) version 3
+ *
+ * @languagePack Norwegian | Norsk
+ * @translator Hans Hovde
+ */
+
+$GLOBALS['lang']['task'] = array(
+ 'priority' => 'prioritet',
+ 'spent' => 'brukt',
+ 'note' => 'notat',
+ 'todo' => 'oppgave',
+ 'done' => 'ferdig',
+ 'valid' => 'gyldig',
+ 'archived' => 'oppnådd',
+ 'running' => 'kjører',
+ 'paused' => 'pauset'
+);
+
+$GLOBALS['lang']['priority'] = array(
+ 'urgent' => 'Kritisk',
+ 'important' => 'Høyeste',
+ 'high' => 'Høyere',
+ 'quickly' => 'Høy',
+ 'pretty_soon' => 'Ganske snart',
+ 'soon' => 'Snart',
+ 'normal' => 'Normal',
+ 'after' => 'Lav',
+ 'later' => 'Lavere',
+ 'low' => 'Laverste',
+ 'anytime' => 'NÃ¥r tid',
+ 'whenever' => 'Uviktig'
+);
+
+$GLOBALS['lang']['ui'] = array(
+ 'reload' => 'reload',
+ 'reload_list' => 'reload list',
+ 'task' => 'oppgave',
+ 'tasks' => 'oppgaver',
+ 'create_single' => 'lag en oppgave',
+ 'create_multi' => 'lag flere oppgaver',
+ 'edit_task' => 'endre oppgave',
+ 'delete_task' => 'slett oppgave',
+ 'start_task' => 'start oppgave',
+ 'mark_archived' => 'merk oppgave som arkivert',
+ 'done_confirm' => 'er du sikker på at du vil merke oppgaven som ferdig ?',
+ 'compact' => 'minimer',
+ 'expand' => 'maksimer',
+ 'select_all' => 'velg alle',
+ 'info' => 'info',
+ 'history' => 'historie',
+ 'history_empty' => 'ingen tidsrapporter enda',
+ 'report_spent' => 'rapporter brukt tid',
+ 'total' => 'total',
+ 'user_menu' => 'vis brukermeny',
+ 'admin' => 'admin',
+ 'settings' => 'instillinger',
+ 'all_users' => 'alle brukere',
+ 'switch' => 'bytt',
+ 'switch_user' => 'se andre brukeres oppgaver',
+ 'select_user' => 'velg bruker du vil se oppgaver til',
+ 'switched' => 'bytt til en annen bruker',
+ 'task_manager' => 'oppgave behandling',
+ 'task_managers' => 'oppgave behandlinger',
+ 'user_admin' => 'bruker administrator',
+ 'user_admins' => 'bruker administratorer',
+ 'last_visit' => 'siste besøk',
+ 'preferences' => 'mine instillinger',
+ 'create_user' => 'lag bruker',
+ 'edit_user' => 'endre bruker',
+ 'delete_user' => 'slett bruker'
+);
+
+$GLOBALS['lang']['pages'] = array(
+ 'todo' => 'oppgave',
+ 'done' => 'ferdig',
+ 'valid' => 'gyldig',
+ 'archives' => 'arkiv',
+ 'edit_task' => 'endre oppgave',
+ 'create_task' => 'lag oppgave',
+ 'create_tasks' => 'lag flere oppgaver',
+ 'view_task' => 'oppgave detaljer'
+);
+
+$arrMess = array(
+ 'task_created' => 'oppgave opprettet',
+ 'task_updated' => 'oppgave oppdatert',
+ '%_task_created' => '% oppgave(r) opprettet',
+ 'task_deleted' => 'oppgave slettet',
+ 'time_added' => 'arbeidstid registrert'
+);
+// we're adding these translations to the standard messages translations
+$GLOBALS['lang']['message'] = $GLOBALS['lang']['message']+$arrMess;
+
+$arrButton = array(
+ 'pause' => 'pause',
+ 'resume' => 'fortsett',
+ 'done' => 'ferdig',
+ 'reopen' => 'åpne på nytt',
+ 'postpone_1_day' => 'utsett 1 dag',
+ 'postpone_2_days' => 'utsett 2 dager',
+ 'postpone_1_week' => 'utsett 1 uke',
+ 'postpone_2_weeks' => 'utsett 2 uker',
+ 'postpone_1_month' => 'utsett 1 måned',
+ 'postpone_2_months' => 'utsett 2 måneder',
+ 'postpone_1_year' => 'utsett 1 år',
+ 'postpone_2_years' => 'utsett 2 år',
+ 'mark_done' => 'marker som ferdig',
+ 'validate' => 'valider',
+ 'archive' => 'arkiver',
+ 'unarchive' => 'gjenopprett',
+ 'save_report' => 'lagre rapport',
+ 'save_task' => 'lagre oppgave',
+ 'save_and_start' => 'lagre og start'
+);
+// we're adding these translations to the standard button translations
+$GLOBALS['lang']['button'] = $GLOBALS['lang']['button']+$arrButton;
\ No newline at end of file
diff --git a/app/lang/no/help_multi_creation.php b/app/lang/no/help_multi_creation.php
new file mode 100755
index 0000000..d48ee1c
--- /dev/null
+++ b/app/lang/no/help_multi_creation.php
@@ -0,0 +1,19 @@
+Skriv en oppgave pr. linje.
+Oppgave format:
+Oppgave format : [dato] [prioritet] [label :] oppgave overskrift
+felter innenfor [rammer] er frivillig
+dato kan være :
+
+ en dato i formatet dd/mm[/åå]
+ plusstegn (+) etterfulgt av antall dager frem i tid
+ minustegn (-) dersom du ikke ønsker deadline
+ tomt felt gir dedline på dagens dato
+
+prioritet er et nummer mellom 1 og 9, etterfulgt av )
+« 1) » for kritiske gjøremÃ¥l, « 5) » for normal prioritet
+label er valgfri
+Standarder for flere oppgaver
+en linje som starter med * angir standard verdi
+Formatet er : * [dato] [label]
+« * +1 taskfreak » eller « * 12/04 »
+tilbakestill standarder med en linje som starter med « ** »
\ No newline at end of file
diff --git a/app/lang/no/help_timer_creation.php b/app/lang/no/help_timer_creation.php
new file mode 100755
index 0000000..128db0f
--- /dev/null
+++ b/app/lang/no/help_timer_creation.php
@@ -0,0 +1,8 @@
+Skriv enten :
+
+ Kun starttid (kalkulerer tiden fra start frem til nå)
+ Tidsforbruk (Tar høyde for at du nettopp har avsluttet oppgaven)
+ Start tid og stop tid
+ Start tid og forbrukt tid
+ Stopp tid og forbrukt tid
+
\ No newline at end of file
diff --git a/app/model/task.php b/app/model/task.php
index c4d800f..f45306f 100644
--- a/app/model/task.php
+++ b/app/model/task.php
@@ -4,7 +4,7 @@
*
* @package taskfreak_tt
* @author Stan Ozier
- * @version 0.4
+ * @version 0.5
* @copyright GNU General Public License (GPL) version 3
*/
@@ -57,7 +57,7 @@ class TaskModel extends Model {
}
ArrayHelper::arrayTrim($arr);
$obj = new TaskModel();
- $tst = substr($arr[2],0,1);
+ $tst = (empty($arr[1]))?substr($arr[2],0,1):'*';
switch ($tst) {
case '*': // multiple
if ($arr[1] == '**') {
@@ -97,7 +97,7 @@ class TaskModel extends Model {
$obj->set('deadline',$arr[2].' days');
} else {
// no number, means today
- $obj->set('deadline', APP_SQL_TODAY);
+ $obj->set('deadline', date_format(new DateTime('now', $GLOBALS['config']['datetime']['timezone_user']), 'Y-m-d'));
}
break;
default:
@@ -110,7 +110,7 @@ class TaskModel extends Model {
$obj->set('deadline', $dte);
} else if ($GLOBALS['config']['task']['date']) {
// use default date (config)
- $obj->set('deadline', $GLOBALS['config']['task']['date']);
+ $obj->set('deadline', date_format(new DateTime($GLOBALS['config']['task']['date'], $GLOBALS['config']['datetime']['timezone_user']), 'Y-m-d'));
// $dte = $obj->get('deadline');
} else {
// no date by default (config)
@@ -196,6 +196,10 @@ class TaskSummary extends TaskModel {
return $str;
}
+ public function htmlTimes() {
+ return $this->html('start',APP_DATETIME_SHT).' > '.$this->html('stop','%H:%M');
+ }
+
public function htmlBegin() {
if ($this->isEmpty('start')) {
if ($this->isEmpty('begin')) {
@@ -220,9 +224,9 @@ class TaskSummary extends TaskModel {
}
}
- public function htmlEnd($expanded=false) {
+ public function htmlEnd($expanded=false, $default='-') {
if ($this->isEmpty('stop')) {
- return '-';
+ return $default;
} else {
return $this->html('stop',APP_DATETIME);
}
@@ -270,7 +274,9 @@ class TaskSummary extends TaskModel {
$this->_diff = 9999;
} else {
$dead = strtotime($this->get('deadline'));
- $this->_diff = ($dead - intval(APP_TODAY)) / 3600 / 24;
+ // -TODO- optimize ! maybe using DateTime diff ?
+ $usernow = date_timestamp_get(new DateTime('now', $GLOBALS['config']['datetime']['timezone_user']));
+ $this->_diff = round(($dead - $usernow) / 3600 / 24);
}
}
@@ -320,6 +326,36 @@ class TaskSummary extends TaskModel {
return str_pad($h, 2, '0',STR_PAD_LEFT).':'.str_pad($m, 2, '0',STR_PAD_LEFT);
}
+ /**
+ * export data in array for the mobile version (ajax requests)
+ */
+ public function exportData($method='html') {
+ // prepare general info
+ $arrInfo = array();
+ $arr = $this->getFields();
+ foreach ($arr as $key => $type) {
+ $arrInfo[$key] = $this->$method($key);
+ }
+
+ // prepare timer history and totals
+ $total = 0;
+ $arrSpent = array();
+ if ($this->get('spent')) {
+ do {
+ $total += $this->get('spent');
+ // start and stop times
+ $times = $this->htmlTimes();
+ $spent = $this->getTimeSpent();
+ $arrSpent[$times] = $spent;
+ } while ($this->next());
+ }
+
+ $arrInfo['total'] = $this->htmlTime($total);
+
+ return array('info' => $arrInfo, 'spent' => $arrSpent);
+ // return $arrInfo;
+ }
+
/**
* update current task status
*/
diff --git a/app/model/timer.php b/app/model/timer.php
index c4928f9..7fe8277 100644
--- a/app/model/timer.php
+++ b/app/model/timer.php
@@ -4,7 +4,7 @@
*
* @package taskfreak_tt
* @author Stan Ozier
- * @version 0.1
+ * @version 0.5
* @copyright GNU General Public License (GPL) version 3
*/
@@ -75,7 +75,7 @@ class TimerModel extends Model {
* stops a timer
*/
public static function stop($tid) {
- if (!($tid = VarUid::sanitize($tid, $err))) {
+ if (!($tid = VarUid::sani($tid))) {
return false;
}
$filter = "task_id='$tid' AND stop='0000-00-00 00:00:00'";
diff --git a/app/view/admin/user-list.php b/app/view/admin/user-list.php
index dd7f556..3f86e60 100644
--- a/app/view/admin/user-list.php
+++ b/app/view/admin/user-list.php
@@ -5,7 +5,7 @@ $this->incView('include/page-top', false);
-
+
fc->getUrl('iphone','edit'); ?>" method="post">
+
+
+
+
+
+
+
+ incView('iphone/inc_foot');
+ ?>
+
\ No newline at end of file
diff --git a/app/view/iphone/inc_foot.php b/app/view/iphone/inc_foot.php
new file mode 100644
index 0000000..dd70a5f
--- /dev/null
+++ b/app/view/iphone/inc_foot.php
@@ -0,0 +1,9 @@
+
+ fc->user->html('nickname');
+ /*
+ |
+ */
+ ?>
+
+
\ No newline at end of file
diff --git a/app/view/iphone/inc_main.php b/app/view/iphone/inc_main.php
new file mode 100644
index 0000000..f4f3374
--- /dev/null
+++ b/app/view/iphone/inc_main.php
@@ -0,0 +1,37 @@
+
+
+ current) {
+ $this->incView('iphone/inc_timer');
+ }
+ ?>
+
By Status
+
+ dataTodo->count(); ?>
+ dataDone->count(); ?>
+ dataValid->count(); ?>
+
+ dataTags)) {
+ ?>
+
By Tag
+
+ incView('iphone/inc_foot');
+ ?>
+
\ No newline at end of file
diff --git a/app/view/iphone/inc_timer.php b/app/view/iphone/inc_timer.php
new file mode 100644
index 0000000..8075cd6
--- /dev/null
+++ b/app/view/iphone/inc_timer.php
@@ -0,0 +1,32 @@
+
\ No newline at end of file
diff --git a/app/view/iphone/login.php b/app/view/iphone/login.php
new file mode 100644
index 0000000..57f3fb2
--- /dev/null
+++ b/app/view/iphone/login.php
@@ -0,0 +1,18 @@
+
\ No newline at end of file
diff --git a/app/view/iphone/main.php b/app/view/iphone/main.php
new file mode 100644
index 0000000..fe38d73
--- /dev/null
+++ b/app/view/iphone/main.php
@@ -0,0 +1,34 @@
+fc->user->isLoggedIn()) {
+ $this->incView('iphone/inc_main');
+ $this->incList('list-st0',TR::html('pages','todo'),$this->dataTodo);
+ $this->incList('list-st1',TR::html('pages','done'),$this->dataDone);
+ $this->incList('list-st2',TR::html('pages','valid'),$this->dataValid);
+}
+?>
+
+incView('iphone/edit');
+$this->incView('iphone/view');
+?>
diff --git a/app/view/iphone/view.php b/app/view/iphone/view.php
new file mode 100644
index 0000000..43946d5
--- /dev/null
+++ b/app/view/iphone/view.php
@@ -0,0 +1,46 @@
+
+
+
+
+ incView('iphone/inc_foot');
+ ?>
+
\ No newline at end of file
diff --git a/app/view/iphone/view.server.php b/app/view/iphone/view.server.php
new file mode 100644
index 0000000..d351b46
--- /dev/null
+++ b/app/view/iphone/view.server.php
@@ -0,0 +1,97 @@
+data->get('spent')) {
+ $str = '
';
+ do {
+ $total += $this->data->get('spent');
+ $str .= '';
+ // start and stop times
+ $str .= $this->data->htmlTimes();
+ // time spent
+ $str .= ''.$this->data->getTimeSpent().' ';
+ $str .= ' ';
+ } while ($this->data->next());
+ $str .= ''.TR::html('ui','total').''.TaskSummary::htmlTime($total).' ';
+ $str .= ' ';
+}
+?>
+
+
+
+
+
'.TR::html('ui','history_empty').' ';
+ }
+ $this->incView('iphone/inc_foot');
+?>
+
\ No newline at end of file
diff --git a/asset/html/iphone-header.php b/asset/html/iphone-header.php
new file mode 100644
index 0000000..fdcb7c9
--- /dev/null
+++ b/asset/html/iphone-header.php
@@ -0,0 +1,30 @@
+
+
+
+
+"/>
+
+*/
+?>
+
+
html('title'); ?>
+isEmpty('description')) {
+?>
+
+isEmpty('keywords')) {
+?>
+
+callHelper('html_asset','headerStuff', true);
+?>
+
\ No newline at end of file
diff --git a/asset/html/page-header.php b/asset/html/page-header.php
index 589d7de..d1dde3d 100644
--- a/asset/html/page-header.php
+++ b/asset/html/page-header.php
@@ -17,7 +17,7 @@ if (!$this->isEmpty('keywords')) {
}
if (file_exists(APP_WWW_PATH.'favicon.ico')) {
- echo '
';
+ echo '
'."\n";
}
$this->callHelper('html_asset','headerStuff');
diff --git a/asset/jqtouch/jqtouch.css b/asset/jqtouch/jqtouch.css
new file mode 100644
index 0000000..328afae
--- /dev/null
+++ b/asset/jqtouch/jqtouch.css
@@ -0,0 +1,373 @@
+* {
+ margin: 0;
+ padding: 0;
+}
+a {
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+}
+
+body {
+ overflow-x: hidden;
+ -webkit-user-select: none;
+ -webkit-text-size-adjust: none;
+ font-family: Helvetica;
+ -webkit-perspective: 800;
+ -webkit-transform-style: preserve-3d;
+}
+.selectable, input, textarea {
+ -webkit-user-select: auto;
+}
+body > * {
+ -webkit-backface-visibility: hidden;
+ -webkit-box-sizing: border-box;
+ display: none;
+ position: absolute;
+ left: 0;
+ width: 100%;
+ -webkit-transform: translate3d(0,0,0) rotate(0) scale(1);
+ min-height: 420px !important;
+}
+body.fullscreen > * {
+ min-height: 460px !important;
+}
+body.fullscreen.black-translucent > * {
+ min-height: 480px !important;
+}
+body.landscape > * {
+ min-height: 320px;
+}
+body > .current {
+ display: block !important;
+}
+
+.in, .out {
+ -webkit-animation-timing-function: ease-in-out;
+ -webkit-animation-duration: 350ms;
+}
+
+.slide.in {
+ -webkit-animation-name: slideinfromright;
+}
+
+.slide.out {
+ -webkit-animation-name: slideouttoleft;
+}
+
+.slide.in.reverse {
+ -webkit-animation-name: slideinfromleft;
+}
+
+.slide.out.reverse {
+ -webkit-animation-name: slideouttoright;
+}
+
+@-webkit-keyframes slideinfromright {
+ from { -webkit-transform: translateX(100%); }
+ to { -webkit-transform: translateX(0); }
+}
+
+@-webkit-keyframes slideinfromleft {
+ from { -webkit-transform: translateX(-100%); }
+ to { -webkit-transform: translateX(0); }
+}
+
+@-webkit-keyframes slideouttoleft {
+ from { -webkit-transform: translateX(0); }
+ to { -webkit-transform: translateX(-100%); }
+}
+
+@-webkit-keyframes slideouttoright {
+ from { -webkit-transform: translateX(0); }
+ to { -webkit-transform: translateX(100%); }
+}
+
+@-webkit-keyframes fadein {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}
+
+@-webkit-keyframes fadeout {
+ from { opacity: 1; }
+ to { opacity: 0; }
+}
+
+.fade.in {
+ z-index: 10;
+ -webkit-animation-name: fadein;
+}
+.fade.out {
+ z-index: 0;
+}
+
+.dissolve.in {
+ -webkit-animation-name: fadein;
+}
+
+.dissolve.out {
+ -webkit-animation-name: fadeout;
+}
+
+
+
+.flip {
+ -webkit-animation-duration: .65s;
+}
+
+.flip.in {
+ -webkit-animation-name: flipinfromleft;
+}
+
+.flip.out {
+ -webkit-animation-name: flipouttoleft;
+}
+
+/* Shake it all about */
+
+.flip.in.reverse {
+ -webkit-animation-name: flipinfromright;
+}
+
+.flip.out.reverse {
+ -webkit-animation-name: flipouttoright;
+}
+
+@-webkit-keyframes flipinfromright {
+ from { -webkit-transform: rotateY(-180deg) scale(.8); }
+ to { -webkit-transform: rotateY(0) scale(1); }
+}
+
+@-webkit-keyframes flipinfromleft {
+ from { -webkit-transform: rotateY(180deg) scale(.8); }
+ to { -webkit-transform: rotateY(0) scale(1); }
+}
+
+@-webkit-keyframes flipouttoleft {
+ from { -webkit-transform: rotateY(0) scale(1); }
+ to { -webkit-transform: rotateY(-180deg) scale(.8); }
+}
+
+@-webkit-keyframes flipouttoright {
+ from { -webkit-transform: rotateY(0) scale(1); }
+ to { -webkit-transform: rotateY(180deg) scale(.8); }
+}
+
+.slideup.in {
+ -webkit-animation-name: slideup;
+ z-index: 10;
+}
+
+.slideup.out {
+ -webkit-animation-name: dontmove;
+ z-index: 0;
+}
+
+.slideup.out.reverse {
+ z-index: 10;
+ -webkit-animation-name: slidedown;
+}
+
+.slideup.in.reverse {
+ z-index: 0;
+ -webkit-animation-name: dontmove;
+}
+
+
+@-webkit-keyframes slideup {
+ from { -webkit-transform: translateY(100%); }
+ to { -webkit-transform: translateY(0); }
+}
+
+@-webkit-keyframes slidedown {
+ from { -webkit-transform: translateY(0); }
+ to { -webkit-transform: translateY(100%); }
+}
+
+
+
+/* Hackish, but reliable. */
+
+@-webkit-keyframes dontmove {
+ from { opacity: 1; }
+ to { opacity: 1; }
+}
+
+.swap {
+ -webkit-transform: perspective(800);
+ -webkit-animation-duration: .7s;
+}
+.swap.out {
+ -webkit-animation-name: swapouttoleft;
+}
+.swap.in {
+ -webkit-animation-name: swapinfromright;
+}
+.swap.out.reverse {
+ -webkit-animation-name: swapouttoright;
+}
+.swap.in.reverse {
+ -webkit-animation-name: swapinfromleft;
+}
+
+
+@-webkit-keyframes swapouttoright {
+ 0% {
+ -webkit-transform: translate3d(0px, 0px, 0px) rotateY(0deg);
+ -webkit-animation-timing-function: ease-in-out;
+ }
+ 50% {
+ -webkit-transform: translate3d(-180px, 0px, -400px) rotateY(20deg);
+ -webkit-animation-timing-function: ease-in;
+ }
+ 100% {
+ -webkit-transform: translate3d(0px, 0px, -800px) rotateY(70deg);
+ }
+}
+
+@-webkit-keyframes swapouttoleft {
+ 0% {
+ -webkit-transform: translate3d(0px, 0px, 0px) rotateY(0deg);
+ -webkit-animation-timing-function: ease-in-out;
+ }
+ 50% {
+ -webkit-transform: translate3d(180px, 0px, -400px) rotateY(-20deg);
+ -webkit-animation-timing-function: ease-in;
+ }
+ 100% {
+ -webkit-transform: translate3d(0px, 0px, -800px) rotateY(-70deg);
+ }
+}
+
+@-webkit-keyframes swapinfromright {
+ 0% {
+ -webkit-transform: translate3d(0px, 0px, -800px) rotateY(70deg);
+ -webkit-animation-timing-function: ease-out;
+ }
+ 50% {
+ -webkit-transform: translate3d(-180px, 0px, -400px) rotateY(20deg);
+ -webkit-animation-timing-function: ease-in-out;
+ }
+ 100% {
+ -webkit-transform: translate3d(0px, 0px, 0px) rotateY(0deg);
+ }
+}
+
+@-webkit-keyframes swapinfromleft {
+ 0% {
+ -webkit-transform: translate3d(0px, 0px, -800px) rotateY(-70deg);
+ -webkit-animation-timing-function: ease-out;
+ }
+ 50% {
+ -webkit-transform: translate3d(180px, 0px, -400px) rotateY(-20deg);
+ -webkit-animation-timing-function: ease-in-out;
+ }
+ 100% {
+ -webkit-transform: translate3d(0px, 0px, 0px) rotateY(0deg);
+ }
+}
+
+.cube {
+ -webkit-animation-duration: .55s;
+}
+
+.cube.in {
+ -webkit-animation-name: cubeinfromright;
+ -webkit-transform-origin: 0% 50%;
+}
+.cube.out {
+ -webkit-animation-name: cubeouttoleft;
+ -webkit-transform-origin: 100% 50%;
+}
+.cube.in.reverse {
+ -webkit-animation-name: cubeinfromleft;
+ -webkit-transform-origin: 100% 50%;
+}
+.cube.out.reverse {
+ -webkit-animation-name: cubeouttoright;
+ -webkit-transform-origin: 0% 50%;
+
+}
+
+@-webkit-keyframes cubeinfromleft {
+ from {
+ -webkit-transform: rotateY(-90deg) translateZ(320px);
+ opacity: .5;
+ }
+ to {
+ -webkit-transform: rotateY(0deg) translateZ(0);
+ opacity: 1;
+ }
+}
+@-webkit-keyframes cubeouttoright {
+ from {
+ -webkit-transform: rotateY(0deg) translateX(0);
+ opacity: 1;
+ }
+ to {
+ -webkit-transform: rotateY(90deg) translateZ(320px);
+ opacity: .5;
+ }
+}
+@-webkit-keyframes cubeinfromright {
+ from {
+ -webkit-transform: rotateY(90deg) translateZ(320px);
+ opacity: .5;
+ }
+ to {
+ -webkit-transform: rotateY(0deg) translateZ(0);
+ opacity: 1;
+ }
+}
+@-webkit-keyframes cubeouttoleft {
+ from {
+ -webkit-transform: rotateY(0deg) translateZ(0);
+ opacity: 1;
+ }
+ to {
+ -webkit-transform: rotateY(-90deg) translateZ(320px);
+ opacity: .5;
+ }
+}
+
+
+
+
+.pop {
+ -webkit-transform-origin: 50% 50%;
+}
+
+.pop.in {
+ -webkit-animation-name: popin;
+ z-index: 10;
+}
+
+.pop.out.reverse {
+ -webkit-animation-name: popout;
+ z-index: 10;
+}
+
+.pop.in.reverse {
+ z-index: 0;
+ -webkit-animation-name: dontmove;
+}
+
+@-webkit-keyframes popin {
+ from {
+ -webkit-transform: scale(.2);
+ opacity: 0;
+ }
+ to {
+ -webkit-transform: scale(1);
+ opacity: 1;
+ }
+}
+
+@-webkit-keyframes popout {
+ from {
+ -webkit-transform: scale(1);
+ opacity: 1;
+ }
+ to {
+ -webkit-transform: scale(.2);
+ opacity: 0;
+ }
+}
\ No newline at end of file
diff --git a/asset/jqtouch/jqtouch.js b/asset/jqtouch/jqtouch.js
new file mode 100644
index 0000000..0883580
--- /dev/null
+++ b/asset/jqtouch/jqtouch.js
@@ -0,0 +1,676 @@
+/*
+
+ _/ _/_/ _/_/_/_/_/ _/
+ _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/
+ _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/
+ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/
+ _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/
+ _/
+ _/
+
+ Created by David Kaneda
+ Documentation and issue tracking on Google Code
+
+ Special thanks to Jonathan Stark
+ and pinch/zoom
+
+ (c) 2009 by jQTouch project members.
+ See LICENSE.txt for license.
+
+ $Revision: 109 $
+ $Date: 2009-10-06 12:23:30 -0400 (Tue, 06 Oct 2009) $
+ $LastChangedBy: davidcolbykaneda $
+
+*/
+
+(function($) {
+ $.jQTouch = function(options) {
+
+ // Set support values
+ $.support.WebKitCSSMatrix = (typeof WebKitCSSMatrix == "object");
+ $.support.touch = (typeof Touch == "object");
+ $.support.WebKitAnimationEvent = (typeof WebKitTransitionEvent == "object");
+
+ // Initialize internal variables
+ var $body,
+ $head=$('head'),
+ hist=[],
+ newPageCount=0,
+ jQTSettings={},
+ hashCheck,
+ currentPage,
+ orientation,
+ isMobileWebKit = RegExp(" Mobile/").test(navigator.userAgent),
+ tapReady=true,
+ lastAnimationTime=0,
+ touchSelectors=[],
+ publicObj={},
+ extensions=$.jQTouch.prototype.extensions,
+ defaultAnimations=['slide','flip','slideup','swap','cube','pop','dissolve','fade','back'],
+ animations=[],
+ hairextensions='';
+
+ // Get the party started
+ init(options);
+
+ function init(options) {
+
+ var defaults = {
+ addGlossToIcon: true,
+ backSelector: '.back, .cancel, .goback',
+ cacheGetRequests: true,
+ cubeSelector: '.cube',
+ dissolveSelector: '.dissolve',
+ fadeSelector: '.fade',
+ fixedViewport: true,
+ flipSelector: '.flip',
+ formSelector: 'form',
+ fullScreen: true,
+ fullScreenClass: 'fullscreen',
+ icon: null,
+ touchSelector: 'a, .touch',
+ popSelector: '.pop',
+ preloadImages: false,
+ slideSelector: 'body > * > ul li a',
+ slideupSelector: '.slideup',
+ startupScreen: null,
+ statusBar: 'default', // other options: black-translucent, black
+ submitSelector: '.submit',
+ swapSelector: '.swap',
+ useAnimations: true,
+ useFastTouch: true // Experimental.
+ };
+ jQTSettings = $.extend({}, defaults, options);
+
+ // Preload images
+ if (jQTSettings.preloadImages) {
+ for (var i = jQTSettings.preloadImages.length - 1; i >= 0; i--){
+ (new Image()).src = jQTSettings.preloadImages[i];
+ };
+ }
+ // Set icon
+ if (jQTSettings.icon) {
+ var precomposed = (jQTSettings.addGlossToIcon) ? '' : '-precomposed';
+ hairextensions += ' ';
+ }
+ // Set startup screen
+ if (jQTSettings.startupScreen) {
+ hairextensions += ' ';
+ }
+ // Set viewport
+ if (jQTSettings.fixedViewport) {
+ hairextensions += ' ';
+ }
+ // Set full-screen
+ if (jQTSettings.fullScreen) {
+ hairextensions += ' ';
+ if (jQTSettings.statusBar) {
+ hairextensions += ' ';
+ }
+ }
+ if (hairextensions) $head.append(hairextensions);
+
+ // Initialize on document load:
+ $(document).ready(function(){
+
+ // Add extensions
+ for (var i in extensions)
+ {
+ var fn = extensions[i];
+ if ($.isFunction(fn))
+ {
+ $.extend(publicObj, fn(publicObj));
+ }
+ }
+
+ // Add animations
+ for (var i in defaultAnimations)
+ {
+ var name = defaultAnimations[i];
+ var selector = jQTSettings[name + 'Selector'];
+ if (typeof(selector) == 'string') {
+ addAnimation({name:name, selector:selector});
+ }
+ }
+
+ touchSelectors.push('input');
+ touchSelectors.push(jQTSettings.touchSelector);
+ touchSelectors.push(jQTSettings.backSelector);
+ touchSelectors.push(jQTSettings.submitSelector);
+ $(touchSelectors.join(', ')).css('-webkit-touch-callout', 'none');
+ $(jQTSettings.backSelector).tap(liveTap);
+ $(jQTSettings.submitSelector).tap(submitParentForm);
+
+ $body = $('body');
+
+ if (jQTSettings.fullScreenClass && window.navigator.standalone == true) {
+ $body.addClass(jQTSettings.fullScreenClass + ' ' + jQTSettings.statusBar);
+ }
+
+ // Create custom live events
+ $body
+ .bind('touchstart', handleTouch)
+ .bind('orientationchange', updateOrientation)
+ .trigger('orientationchange')
+ .submit(submitForm);
+
+ if (jQTSettings.useFastTouch && $.support.touch)
+ {
+ $body.click(function(e){
+ var $el = $(e.target);
+ if ($el.attr('target') == '_blank' || $el.attr('rel') == 'external' || $el.is('input[type="checkbox"]'))
+ {
+ return true;
+ } else {
+ return false;
+ }
+ });
+
+ // This additionally gets rid of form focusses
+ $body.mousedown(function(e){
+ var timeDiff = (new Date()).getTime() - lastAnimationTime;
+ if (timeDiff < 200)
+ {
+ return false;
+ }
+ });
+ }
+
+ // Make sure exactly one child of body has "current" class
+ if ($('body > .current').length == 0) {
+ currentPage = $('body > *:first');
+ } else {
+ currentPage = $('body > .current:first');
+ $('body > .current').removeClass('current');
+ }
+
+ // Go to the top of the "current" page
+ $(currentPage).addClass('current');
+ location.hash = $(currentPage).attr('id');
+ addPageToHistory(currentPage);
+ scrollTo(0, 0);
+ dumbLoopStart();
+ });
+ }
+
+ // PUBLIC FUNCTIONS
+ function goBack(to) {
+ showHistoryLog();
+ // Init the param
+ if (hist.length > 1) {
+ var numberOfPages = Math.min(parseInt(to || 1, 10), hist.length-1);
+
+ // Search through the history for an ID
+ if( isNaN(numberOfPages) && typeof(to) === "string" && to != '#' ) {
+ for( var i=1, length=hist.length; i < length; i++ ) {
+ if( '#' + hist[i].id === to ) {
+ numberOfPages = i;
+ break;
+ }
+ }
+ }
+
+ // If still nothing, assume one
+ if( isNaN(numberOfPages) || numberOfPages < 1 ) {
+ numberOfPages = 1;
+ };
+
+ // Grab the current page for the "from" info
+ var animation = hist[0].animation;
+ var fromPage = hist[0].page;
+
+ // Remove all pages in front of the target page
+ hist.splice(0, numberOfPages);
+
+ // Grab the target page
+ var toPage = hist[0].page;
+
+ // Make the animations
+ animatePages(fromPage, toPage, animation, true);
+
+ return publicObj;
+ } else {
+ console.error('No pages in history.');
+ return false;
+ }
+ }
+ function goTo(toPage, animation) {
+ var fromPage = hist[0].page;
+
+ if (typeof(toPage) === 'string') {
+ toPage = $(toPage);
+ }
+ if (typeof(animation) === 'string') {
+ for (var i = animations.length - 1; i >= 0; i--){
+ if (animations[i].name === animation)
+ {
+ animation = animations[i];
+ break;
+ }
+ }
+ }
+ if (animatePages(fromPage, toPage, animation)) {
+ addPageToHistory(toPage, animation);
+ return publicObj;
+ }
+ else
+ {
+ console.error('Could not animate pages.');
+ return false;
+ }
+ }
+ function getOrientation() {
+ return orientation;
+ }
+
+ // PRIVATE FUNCTIONS
+ function liveTap(e){
+
+ // Grab the clicked element
+ var $el = $(e.target);
+
+ if ($el.attr('nodeName')!=='A'){
+ $el = $el.parent('a');
+ }
+
+ var target = $el.attr('target'),
+ hash = $el.attr('hash'),
+ animation=null;
+
+ if (tapReady == false || !$el.length) {
+ console.warn('Not able to tap element.')
+ return false;
+ }
+
+ if ($el.attr('target') == '_blank' || $el.attr('rel') == 'external')
+ {
+ return true;
+ }
+
+ // Figure out the animation to use
+ for (var i = animations.length - 1; i >= 0; i--){
+ if ($el.is(animations[i].selector)) {
+ animation = animations[i];
+ break;
+ }
+ };
+
+ // User clicked an internal link, fullscreen mode
+ if (target == '_webapp') {
+ window.location = $el.attr('href');
+ }
+ // User clicked a back button
+ else if ($el.is(jQTSettings.backSelector)) {
+ goBack(hash);
+ }
+ // Branch on internal or external href
+ else if (hash && hash!='#') {
+ $el.addClass('active');
+ goTo($(hash).data('referrer', $el), animation);
+ } else {
+ $el.addClass('loading active');
+ showPageByHref($el.attr('href'), {
+ animation: animation,
+ callback: function(){
+ $el.removeClass('loading');
+ setTimeout($.fn.unselect, 250, $el);
+ },
+ $referrer: $el
+ });
+ }
+ return false;
+ }
+ function addPageToHistory(page, animation) {
+ // Grab some info
+ var pageId = page.attr('id');
+
+ // Prepend info to page history
+ hist.unshift({
+ page: page,
+ animation: animation,
+ id: pageId
+ });
+ }
+ function showHistoryLog() {
+ if (hist.length > 1) {
+ var str = 'history';
+ // Search through the history for an ID
+ for( var i=0, length=hist.length; i < length; i++ ) {
+ str += ' : '+hist[i].id;
+ }
+ console.log(str);
+ } else {
+ console.log('no history');
+ }
+ }
+ function animatePages(fromPage, toPage, animation, backwards) {
+ // Error check for target page
+ if(toPage.length === 0){
+ $.fn.unselect();
+ console.error('Target element is missing.');
+ return false;
+ }
+
+ // Collapse the keyboard
+ $(':focus').blur();
+
+ // Make sure we are scrolled up to hide location bar
+ scrollTo(0, 0);
+
+ // Define callback to run after animation completes
+ var callback = function(event){
+
+ if (animation)
+ {
+ toPage.removeClass('in reverse ' + animation.name);
+ fromPage.removeClass('current out reverse ' + animation.name);
+ }
+ else
+ {
+ fromPage.removeClass('current');
+ }
+
+ toPage.trigger('pageAnimationEnd', { direction: 'in' });
+ fromPage.trigger('pageAnimationEnd', { direction: 'out' });
+
+ clearInterval(dumbLoop);
+ currentPage = toPage;
+ location.hash = currentPage.attr('id');
+ dumbLoopStart();
+
+ var $originallink = toPage.data('referrer');
+ if ($originallink) {
+ $originallink.unselect();
+ }
+ lastAnimationTime = (new Date()).getTime();
+ tapReady = true;
+ }
+
+ fromPage.trigger('pageAnimationStart', { direction: 'out' });
+ toPage.trigger('pageAnimationStart', { direction: 'in' });
+
+ if ($.support.WebKitAnimationEvent && animation && jQTSettings.useAnimations) {
+ toPage.one('webkitAnimationEnd', callback);
+ tapReady = false;
+ toPage.addClass(animation.name + ' in current ' + (backwards ? ' reverse' : ''));
+ fromPage.addClass(animation.name + ' out' + (backwards ? ' reverse' : ''));
+ console.log('-> anim from '+fromPage.attr('id')+' to '+toPage.attr('id')+' ('+animation.name+')');
+ } else {
+ console.log('-> directly to '+toPage.attr('id'));
+ toPage.addClass('current');
+ callback();
+ }
+ showHistoryLog();
+ return true;
+ }
+ function dumbLoopStart() {
+ dumbLoop = setInterval(function(){
+ var curid = currentPage.attr('id');
+ if (location.hash == '') {
+ location.hash = '#' + curid;
+ } else if (location.hash != '#' + curid) {
+ try {
+ goBack(location.hash)
+ } catch(e) {
+ console.error('Unknown hash change.');
+ }
+ }
+ }, 100);
+ }
+ function insertNode($node) {
+ $ff = $('#'+$node.attr('id'));
+ if ($ff[0]) {
+ // delete previous version of the page
+ $ff.empty();
+ $node.children().appendTo($ff);
+ } else {
+ $node.appendTo($body);
+ }
+ }
+ function insertPages(nodes, animation) {
+ var targetPage = null;
+ $(nodes).each(function(index, node){
+ var $node = $(this);
+ if (!$node.attr('id')) {
+ $node.attr('id', 'page-' + (++newPageCount));
+ }
+ insertNode($node);
+ if ($node.hasClass('current') || !targetPage ) {
+ targetPage = $node;
+ }
+ });
+ if (targetPage !== null && animation != 'ignore') {
+ goTo(targetPage, animation);
+ return targetPage;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ function appendPages(nodes) {
+ var targetPage = null;
+ $(nodes).each(function(index, node){
+ var $node = $(this);
+ if (!$node.attr('id')) {
+ $node.attr('id', 'page-' + (++newPageCount));
+ }
+ if ($node.attr('id') !== undefined && $node.attr('id') != null) {
+ var id = $node.attr('id');
+ $node.addClass('dyn');
+ insertNode($node);
+ }
+ });
+ return false;
+ }
+ function showPageByHref(href, options) {
+ var defaults = {
+ data: null,
+ method: 'GET',
+ animation: null,
+ callback: null,
+ $referrer: null
+ };
+
+ var settings = $.extend({}, defaults, options);
+
+ if (href != '#')
+ {
+ $.ajax({
+ url: href,
+ data: settings.data,
+ type: settings.method,
+ success: function (data, textStatus) {
+ var firstPage = insertPages(data, settings.animation);
+ if (firstPage)
+ {
+ if (settings.method == 'GET' && jQTSettings.cacheGetRequests && settings.$referrer)
+ {
+ settings.$referrer.attr('href', '#' + firstPage.attr('id'));
+ }
+ if (settings.callback) {
+ settings.callback(true);
+ }
+ }
+ },
+ error: function (data) {
+ if (settings.$referrer) settings.$referrer.unselect();
+ if (settings.callback) {
+ settings.callback(false);
+ }
+ }
+ });
+ }
+ else if ($referrer)
+ {
+ $referrer.unselect();
+ }
+ }
+ function submitForm(e, callback){
+ var $form = (typeof(e)==='string') ? $(e) : $(e.target);
+
+ if ($form.length && $form.is(jQTSettings.formSelector) && $form.attr('action')) {
+ showPageByHref($form.attr('action'), {
+ data: $form.serialize(),
+ method: $form.attr('method') || "POST",
+ animation: animations[0] || null,
+ callback: callback
+ });
+ return false;
+ }
+ return true;
+ }
+ function submitParentForm(e){
+ var $form = $(this).closest('form');
+ if ($form.length)
+ {
+ evt = jQuery.Event("submit");
+ evt.preventDefault();
+ $form.trigger(evt);
+ return false;
+ }
+ return true;
+ }
+ function addAnimation(animation) {
+ if (typeof(animation.selector) == 'string' && typeof(animation.name) == 'string') {
+ animations.push(animation);
+ $(animation.selector).tap(liveTap);
+ touchSelectors.push(animation.selector);
+ }
+ }
+ function updateOrientation() {
+ orientation = window.innerWidth < window.innerHeight ? 'profile' : 'landscape';
+ $body.removeClass('profile landscape').addClass(orientation).trigger('turn', {orientation: orientation});
+ // scrollTo(0, 0);
+ }
+ function handleTouch(e) {
+
+ var $el = $(e.target);
+
+ // Only handle touchSelectors
+ if (!$(e.target).is(touchSelectors.join(', ')))
+ {
+ var $link = $(e.target).closest('a');
+
+ if ($link.length){
+ $el = $link;
+ } else {
+ return;
+ }
+ }
+ if (event)
+ {
+ var hoverTimeout = null,
+ startX = event.changedTouches[0].clientX,
+ startY = event.changedTouches[0].clientY,
+ startTime = (new Date).getTime(),
+ deltaX = 0,
+ deltaY = 0,
+ deltaT = 0;
+
+ // Let's bind these after the fact, so we can keep some internal values
+ $el.bind('touchmove', touchmove).bind('touchend', touchend);
+
+ hoverTimeout = setTimeout(function(){
+ $el.makeActive();
+ }, 100);
+
+ }
+
+ // Private touch functions (TODO: insert dirty joke)
+ function touchmove(e) {
+
+ updateChanges();
+ var absX = Math.abs(deltaX);
+ var absY = Math.abs(deltaY);
+
+ // Check for swipe
+ if (absX > absY && (absX > 35) && deltaT < 1000) {
+ $el.trigger('swipe', {direction: (deltaX < 0) ? 'left' : 'right'}).unbind('touchmove touchend');
+ } else if (absY > 1) {
+ $el.removeClass('active');
+ }
+
+ clearTimeout(hoverTimeout);
+ }
+
+ function touchend(){
+ updateChanges();
+
+ if (deltaY === 0 && deltaX === 0) {
+ $el.makeActive();
+ // New approach:
+ // Fake the double click?
+ // TODO: Try with all click events (no tap)
+ // if (deltaT < 40)
+ // {
+ // setTimeout(function(){
+ // $el.trigger('touchstart')
+ // .trigger('touchend');
+ // }, 0);
+ // }
+ $el.trigger('tap');
+ } else {
+ $el.removeClass('active');
+ }
+ $el.unbind('touchmove touchend');
+ clearTimeout(hoverTimeout);
+ }
+
+ function updateChanges(){
+ var first = event.changedTouches[0] || null;
+ deltaX = first.pageX - startX;
+ deltaY = first.pageY - startY;
+ deltaT = (new Date).getTime() - startTime;
+ }
+
+ } // End touch handler
+
+ // Public jQuery Fns
+ $.fn.unselect = function(obj) {
+ if (obj) {
+ obj.removeClass('active');
+ } else {
+ $('.active').removeClass('active');
+ }
+ }
+ $.fn.makeActive = function(){
+ return $(this).addClass('active');
+ }
+ $.fn.swipe = function(fn) {
+ if ($.isFunction(fn))
+ {
+ return this.each(function(i, el){
+ $(el).bind('swipe', fn);
+ });
+ }
+ }
+ $.fn.tap = function(fn){
+ if ($.isFunction(fn))
+ {
+ var tapEvent = (jQTSettings.useFastTouch && $.support.touch) ? 'tap' : 'click';
+ return $(this).live(tapEvent, fn);
+ } else {
+ $(this).trigger('tap');
+ }
+ }
+
+ publicObj = {
+ getOrientation: getOrientation,
+ goBack: goBack,
+ goTo: goTo,
+ addAnimation: addAnimation,
+ submitForm: submitForm,
+ appendPages: appendPages
+ }
+
+ return publicObj;
+ }
+
+ // Extensions directly manipulate the jQTouch object, before it's initialized.
+ $.jQTouch.prototype.extensions = [];
+ $.jQTouch.addExtension = function(extension){
+ $.jQTouch.prototype.extensions.push(extension);
+ }
+
+})(jQuery);
\ No newline at end of file
diff --git a/asset/jqtouch/jqtouch.min.css b/asset/jqtouch/jqtouch.min.css
new file mode 100644
index 0000000..37ef6fe
--- /dev/null
+++ b/asset/jqtouch/jqtouch.min.css
@@ -0,0 +1 @@
+*{margin:0;padding:0;}a{-webkit-tap-highlight-color:rgba(0,0,0,0);}body{overflow-x:hidden;-webkit-user-select:none;-webkit-text-size-adjust:none;font-family:Helvetica;-webkit-perspective:800;-webkit-transform-style:preserve-3d;}.selectable,input,textarea{-webkit-user-select:auto;}body>*{-webkit-backface-visibility:hidden;-webkit-box-sizing:border-box;display:none;position:absolute;left:0;width:100%;-webkit-transform:translate3d(0,0,0) rotate(0) scale(1);min-height:420px!important;}body.fullscreen>*{min-height:460px!important;}body.fullscreen.black-translucent>*{min-height:480px!important;}body.landscape>*{min-height:320px;}body>.current{display:block!important;}.in,.out{-webkit-animation-timing-function:ease-in-out;-webkit-animation-duration:350ms;}.slide.in{-webkit-animation-name:slideinfromright;}.slide.out{-webkit-animation-name:slideouttoleft;}.slide.in.reverse{-webkit-animation-name:slideinfromleft;}.slide.out.reverse{-webkit-animation-name:slideouttoright;}@-webkit-keyframes slideinfromright{from{-webkit-transform:translateX(100%);}to{-webkit-transform:translateX(0);}}@-webkit-keyframes slideinfromleft{from{-webkit-transform:translateX(-100%);}to{-webkit-transform:translateX(0);}}@-webkit-keyframes slideouttoleft{from{-webkit-transform:translateX(0);}to{-webkit-transform:translateX(-100%);}}@-webkit-keyframes slideouttoright{from{-webkit-transform:translateX(0);}to{-webkit-transform:translateX(100%);}}@-webkit-keyframes fadein{from{opacity:0;}to{opacity:1;}}@-webkit-keyframes fadeout{from{opacity:1;}to{opacity:0;}}.fade.in{z-index:10;-webkit-animation-name:fadein;}.fade.out{z-index:0;}.dissolve.in{-webkit-animation-name:fadein;}.dissolve.out{-webkit-animation-name:fadeout;}.flip{-webkit-animation-duration:.65s;}.flip.in{-webkit-animation-name:flipinfromleft;}.flip.out{-webkit-animation-name:flipouttoleft;}.flip.in.reverse{-webkit-animation-name:flipinfromright;}.flip.out.reverse{-webkit-animation-name:flipouttoright;}@-webkit-keyframes flipinfromright{from{-webkit-transform:rotateY(-180deg) scale(.8);}to{-webkit-transform:rotateY(0) scale(1);}}@-webkit-keyframes flipinfromleft{from{-webkit-transform:rotateY(180deg) scale(.8);}to{-webkit-transform:rotateY(0) scale(1);}}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0) scale(1);}to{-webkit-transform:rotateY(-180deg) scale(.8);}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0) scale(1);}to{-webkit-transform:rotateY(180deg) scale(.8);}}.slideup.in{-webkit-animation-name:slideup;z-index:10;}.slideup.out{-webkit-animation-name:dontmove;z-index:0;}.slideup.out.reverse{z-index:10;-webkit-animation-name:slidedown;}.slideup.in.reverse{z-index:0;-webkit-animation-name:dontmove;}@-webkit-keyframes slideup{from{-webkit-transform:translateY(100%);}to{-webkit-transform:translateY(0);}}@-webkit-keyframes slidedown{from{-webkit-transform:translateY(0);}to{-webkit-transform:translateY(100%);}}@-webkit-keyframes dontmove{from{opacity:1;}to{opacity:1;}}.swap{-webkit-transform:perspective(800);-webkit-animation-duration:.7s;}.swap.out{-webkit-animation-name:swapouttoleft;}.swap.in{-webkit-animation-name:swapinfromright;}.swap.out.reverse{-webkit-animation-name:swapouttoright;}.swap.in.reverse{-webkit-animation-name:swapinfromleft;}@-webkit-keyframes swapouttoright{0%{-webkit-transform:translate3d(0px,0px,0px) rotateY(0deg);-webkit-animation-timing-function:ease-in-out;}50%{-webkit-transform:translate3d(-180px,0px,-400px) rotateY(20deg);-webkit-animation-timing-function:ease-in;}100%{-webkit-transform:translate3d(0px,0px,-800px) rotateY(70deg);}}@-webkit-keyframes swapouttoleft{0%{-webkit-transform:translate3d(0px,0px,0px) rotateY(0deg);-webkit-animation-timing-function:ease-in-out;}50%{-webkit-transform:translate3d(180px,0px,-400px) rotateY(-20deg);-webkit-animation-timing-function:ease-in;}100%{-webkit-transform:translate3d(0px,0px,-800px) rotateY(-70deg);}}@-webkit-keyframes swapinfromright{0%{-webkit-transform:translate3d(0px,0px,-800px) rotateY(70deg);-webkit-animation-timing-function:ease-out;}50%{-webkit-transform:translate3d(-180px,0px,-400px) rotateY(20deg);-webkit-animation-timing-function:ease-in-out;}100%{-webkit-transform:translate3d(0px,0px,0px) rotateY(0deg);}}@-webkit-keyframes swapinfromleft{0%{-webkit-transform:translate3d(0px,0px,-800px) rotateY(-70deg);-webkit-animation-timing-function:ease-out;}50%{-webkit-transform:translate3d(180px,0px,-400px) rotateY(-20deg);-webkit-animation-timing-function:ease-in-out;}100%{-webkit-transform:translate3d(0px,0px,0px) rotateY(0deg);}}.cube{-webkit-animation-duration:.55s;}.cube.in{-webkit-animation-name:cubeinfromright;-webkit-transform-origin:0 50%;}.cube.out{-webkit-animation-name:cubeouttoleft;-webkit-transform-origin:100% 50%;}.cube.in.reverse{-webkit-animation-name:cubeinfromleft;-webkit-transform-origin:100% 50%;}.cube.out.reverse{-webkit-animation-name:cubeouttoright;-webkit-transform-origin:0 50%;}@-webkit-keyframes cubeinfromleft{from{-webkit-transform:rotateY(-90deg) translateZ(320px);opacity:.5;}to{-webkit-transform:rotateY(0deg) translateZ(0);opacity:1;}}@-webkit-keyframes cubeouttoright{from{-webkit-transform:rotateY(0deg) translateX(0);opacity:1;}to{-webkit-transform:rotateY(90deg) translateZ(320px);opacity:.5;}}@-webkit-keyframes cubeinfromright{from{-webkit-transform:rotateY(90deg) translateZ(320px);opacity:.5;}to{-webkit-transform:rotateY(0deg) translateZ(0);opacity:1;}}@-webkit-keyframes cubeouttoleft{from{-webkit-transform:rotateY(0deg) translateZ(0);opacity:1;}to{-webkit-transform:rotateY(-90deg) translateZ(320px);opacity:.5;}}.pop{-webkit-transform-origin:50% 50%;}.pop.in{-webkit-animation-name:popin;z-index:10;}.pop.out.reverse{-webkit-animation-name:popout;z-index:10;}.pop.in.reverse{z-index:0;-webkit-animation-name:dontmove;}@-webkit-keyframes popin{from{-webkit-transform:scale(.2);opacity:0;}to{-webkit-transform:scale(1);opacity:1;}}@-webkit-keyframes popout{from{-webkit-transform:scale(1);opacity:1;}to{-webkit-transform:scale(.2);opacity:0;}}
\ No newline at end of file
diff --git a/asset/jqtouch/jqtouch.min.js b/asset/jqtouch/jqtouch.min.js
new file mode 100644
index 0000000..f43917e
--- /dev/null
+++ b/asset/jqtouch/jqtouch.min.js
@@ -0,0 +1 @@
+(function($){$.jQTouch=function(_2){$.support.WebKitCSSMatrix=(typeof WebKitCSSMatrix=="object");$.support.touch=(typeof Touch=="object");$.support.WebKitAnimationEvent=(typeof WebKitTransitionEvent=="object");var _3,$head=$("head"),hist=[],newPageCount=0,jQTSettings={},hashCheck,currentPage,orientation,isMobileWebKit=RegExp(" Mobile/").test(navigator.userAgent),tapReady=true,lastAnimationTime=0,touchSelectors=[],publicObj={},extensions=$.jQTouch.prototype.extensions,defaultAnimations=["slide","flip","slideup","swap","cube","pop","dissolve","fade","back"],animations=[],hairextensions="";init(_2);function init(_4){var _5={addGlossToIcon:true,backSelector:".back, .cancel, .goback",cacheGetRequests:true,cubeSelector:".cube",dissolveSelector:".dissolve",fadeSelector:".fade",fixedViewport:true,flipSelector:".flip",formSelector:"form",fullScreen:true,fullScreenClass:"fullscreen",icon:null,touchSelector:"a, .touch",popSelector:".pop",preloadImages:false,slideSelector:"body > * > ul li a",slideupSelector:".slideup",startupScreen:null,statusBar:"default",submitSelector:".submit",swapSelector:".swap",useAnimations:true,useFastTouch:true};jQTSettings=$.extend({},_5,_4);if(jQTSettings.preloadImages){for(var i=jQTSettings.preloadImages.length-1;i>=0;i--){(new Image()).src=jQTSettings.preloadImages[i];}}if(jQTSettings.icon){var _7=(jQTSettings.addGlossToIcon)?"":"-precomposed";hairextensions+=" ";}if(jQTSettings.startupScreen){hairextensions+=" ";}if(jQTSettings.fixedViewport){hairextensions+=" ";}if(jQTSettings.fullScreen){hairextensions+=" ";if(jQTSettings.statusBar){hairextensions+=" ";}}if(hairextensions){$head.append(hairextensions);}$(document).ready(function(){for(var i in extensions){var fn=extensions[i];if($.isFunction(fn)){$.extend(publicObj,fn(publicObj));}}for(var i in defaultAnimations){var _a=defaultAnimations[i];var _b=jQTSettings[_a+"Selector"];if(typeof (_b)=="string"){addAnimation({name:_a,selector:_b});}}touchSelectors.push("input");touchSelectors.push(jQTSettings.touchSelector);touchSelectors.push(jQTSettings.backSelector);touchSelectors.push(jQTSettings.submitSelector);$(touchSelectors.join(", ")).css("-webkit-touch-callout","none");$(jQTSettings.backSelector).tap(liveTap);$(jQTSettings.submitSelector).tap(submitParentForm);_3=$("body");if(jQTSettings.fullScreenClass&&window.navigator.standalone==true){_3.addClass(jQTSettings.fullScreenClass+" "+jQTSettings.statusBar);}_3.bind("touchstart",handleTouch).bind("orientationchange",updateOrientation).trigger("orientationchange").submit(submitForm);if(jQTSettings.useFastTouch&&$.support.touch){_3.click(function(e){var _d=$(e.target);if(_d.attr("target")=="_blank"||_d.attr("rel")=="external"||_d.is("input[type=\"checkbox\"]")){return true;}else{return false;}});_3.mousedown(function(e){var _f=(new Date()).getTime()-lastAnimationTime;if(_f<200){return false;}});}if($("body > .current").length==0){currentPage=$("body > *:first");}else{currentPage=$("body > .current:first");$("body > .current").removeClass("current");}$(currentPage).addClass("current");location.hash=$(currentPage).attr("id");addPageToHistory(currentPage);scrollTo(0,0);dumbLoopStart();});}function goBack(to){if(hist.length>1){var _11=Math.min(parseInt(to||1,10),hist.length-1);if(isNaN(_11)&&typeof (to)==="string"&&to!="#"){for(var i=1,length=hist.length;i=0;i--){if(animations[i].name===_17){_17=animations[i];break;}}}if(animatePages(_18,_16,_17)){addPageToHistory(_16,_17);return publicObj;}else{console.error("Could not animate pages.");return false;}}function getOrientation(){return orientation;}function liveTap(e){var $el=$(e.target);if($el.attr("nodeName")!=="A"){$el=$el.parent("a");}var _1c=$el.attr("target"),hash=$el.attr("hash"),animation=null;if(tapReady==false||!$el.length){console.warn("Not able to tap element.");return false;}if($el.attr("target")=="_blank"||$el.attr("rel")=="external"){return true;}for(var i=animations.length-1;i>=0;i--){if($el.is(animations[i].selector)){animation=animations[i];break;}}if(_1c=="_webapp"){window.location=$el.attr("href");}else{if($el.is(jQTSettings.backSelector)){goBack(hash);}else{if(hash&&hash!="#"){$el.addClass("active");goTo($(hash).data("referrer",$el),animation);}else{$el.addClass("loading active");showPageByHref($el.attr("href"),{animation:animation,callback:function(){$el.removeClass("loading");setTimeout($.fn.unselect,250,$el);},$referrer:$el});}}}return false;}function addPageToHistory(_1e,_1f){var _20=_1e.attr("id");hist.unshift({page:_1e,animation:_1f,id:_20});}function animatePages(_21,_22,_23,_24){if(_22.length===0){$.fn.unselect();console.error("Target element is missing.");return false;}$(":focus").blur();scrollTo(0,0);var _25=function(_26){if(_23){_22.removeClass("in reverse "+_23.name);_21.removeClass("current out reverse "+_23.name);}else{_21.removeClass("current");}_22.trigger("pageAnimationEnd",{direction:"in"});_21.trigger("pageAnimationEnd",{direction:"out"});clearInterval(dumbLoop);currentPage=_22;location.hash=currentPage.attr("id");dumbLoopStart();var _27=_22.data("referrer");if(_27){_27.unselect();}lastAnimationTime=(new Date()).getTime();tapReady=true;};_21.trigger("pageAnimationStart",{direction:"out"});_22.trigger("pageAnimationStart",{direction:"in"});if($.support.WebKitAnimationEvent&&_23&&jQTSettings.useAnimations){_22.one("webkitAnimationEnd",_25);tapReady=false;_22.addClass(_23.name+" in current "+(_24?" reverse":""));_21.addClass(_23.name+" out"+(_24?" reverse":""));}else{_22.addClass("current");_25();}return true;}function dumbLoopStart(){dumbLoop=setInterval(function(){var _28=currentPage.attr("id");if(location.hash==""){location.hash="#"+_28;}else{if(location.hash!="#"+_28){try{goBack(location.hash);}catch(e){console.error("Unknown hash change.");}}}},100);}function insertPages(_29,_2a){var _2b=null;$(_29).each(function(_2c,_2d){var _2e=$(this);if(!_2e.attr("id")){_2e.attr("id","page-"+(++newPageCount));}_2e.appendTo(_3);if(_2e.hasClass("current")||!_2b){_2b=_2e;}});if(_2b!==null){goTo(_2b,_2a);return _2b;}else{return false;}}function showPageByHref(_2f,_30){var _31={data:null,method:"GET",animation:null,callback:null,$referrer:null};var _32=$.extend({},_31,_30);if(_2f!="#"){$.ajax({url:_2f,data:_32.data,type:_32.method,success:function(_33,_34){var _35=insertPages(_33,_32.animation);if(_35){if(_32.method=="GET"&&jQTSettings.cacheGetRequests&&_32.$referrer){_32.$referrer.attr("href","#"+_35.attr("id"));}if(_32.callback){_32.callback(true);}}},error:function(_36){if(_32.$referrer){_32.$referrer.unselect();}if(_32.callback){_32.callback(false);}}});}else{if($referrer){$referrer.unselect();}}}function submitForm(e,_38){var _39=(typeof (e)==="string")?$(e):$(e.target);if(_39.length&&_39.is(jQTSettings.formSelector)&&_39.attr("action")){showPageByHref(_39.attr("action"),{data:_39.serialize(),method:_39.attr("method")||"POST",animation:animations[0]||null,callback:_38});return false;}return true;}function submitParentForm(e){var _3b=$(this).closest("form");if(_3b.length){evt=jQuery.Event("submit");evt.preventDefault();_3b.trigger(evt);return false;}return true;}function addAnimation(_3c){if(typeof (_3c.selector)=="string"&&typeof (_3c.name)=="string"){animations.push(_3c);$(_3c.selector).tap(liveTap);touchSelectors.push(_3c.selector);}}function updateOrientation(){orientation=window.innerWidth_43&&(_42>35)&&deltaT<1000){$el.trigger("swipe",{direction:(deltaX<0)?"left":"right"}).unbind("touchmove touchend");}else{if(_43>1){$el.removeClass("active");}}clearTimeout(_40);}function touchend(){updateChanges();if(deltaY===0&&deltaX===0){$el.makeActive();$el.trigger("tap");}else{$el.removeClass("active");}$el.unbind("touchmove touchend");clearTimeout(_40);}function updateChanges(){var _44=event.changedTouches[0]||null;deltaX=_44.pageX-startX;deltaY=_44.pageY-startY;deltaT=(new Date).getTime()-startTime;}}$.fn.unselect=function(obj){if(obj){obj.removeClass("active");}else{$(".active").removeClass("active");}};$.fn.makeActive=function(){return $(this).addClass("active");};$.fn.swipe=function(fn){if($.isFunction(fn)){return this.each(function(i,el){$(el).bind("swipe",fn);});}};$.fn.tap=function(fn){if($.isFunction(fn)){var _4a=(jQTSettings.useFastTouch&&$.support.touch)?"tap":"click";return $(this).live(_4a,fn);}else{$(this).trigger("tap");}};publicObj={getOrientation:getOrientation,goBack:goBack,goTo:goTo,addAnimation:addAnimation,submitForm:submitForm};return publicObj;};$.jQTouch.prototype.extensions=[];$.jQTouch.addExtension=function(_4b){$.jQTouch.prototype.extensions.push(_4b);};})(jQuery);
\ No newline at end of file
diff --git a/asset/jqtouch/themes/apple/img/backButton.png b/asset/jqtouch/themes/apple/img/backButton.png
new file mode 100644
index 0000000..935f914
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/backButton.png differ
diff --git a/asset/jqtouch/themes/apple/img/blueButton.png b/asset/jqtouch/themes/apple/img/blueButton.png
new file mode 100644
index 0000000..0f92dfd
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/blueButton.png differ
diff --git a/asset/jqtouch/themes/apple/img/cancel.png b/asset/jqtouch/themes/apple/img/cancel.png
new file mode 100644
index 0000000..5f6dcc8
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/cancel.png differ
diff --git a/asset/jqtouch/themes/apple/img/chevron.png b/asset/jqtouch/themes/apple/img/chevron.png
new file mode 100644
index 0000000..6421a16
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/chevron.png differ
diff --git a/asset/jqtouch/themes/apple/img/grayButton.png b/asset/jqtouch/themes/apple/img/grayButton.png
new file mode 100644
index 0000000..0ce6a30
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/grayButton.png differ
diff --git a/asset/jqtouch/themes/apple/img/listArrowSel.png b/asset/jqtouch/themes/apple/img/listArrowSel.png
new file mode 100644
index 0000000..86832eb
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/listArrowSel.png differ
diff --git a/asset/jqtouch/themes/apple/img/listGroup.png b/asset/jqtouch/themes/apple/img/listGroup.png
new file mode 100644
index 0000000..567d858
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/listGroup.png differ
diff --git a/asset/jqtouch/themes/apple/img/loading.gif b/asset/jqtouch/themes/apple/img/loading.gif
new file mode 100644
index 0000000..8522ddf
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/loading.gif differ
diff --git a/asset/jqtouch/themes/apple/img/on_off.png b/asset/jqtouch/themes/apple/img/on_off.png
new file mode 100644
index 0000000..62325a8
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/on_off.png differ
diff --git a/asset/jqtouch/themes/apple/img/pinstripes.png b/asset/jqtouch/themes/apple/img/pinstripes.png
new file mode 100644
index 0000000..c997775
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/pinstripes.png differ
diff --git a/asset/jqtouch/themes/apple/img/selection.png b/asset/jqtouch/themes/apple/img/selection.png
new file mode 100644
index 0000000..537e3f0
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/selection.png differ
diff --git a/asset/jqtouch/themes/apple/img/thumb.png b/asset/jqtouch/themes/apple/img/thumb.png
new file mode 100644
index 0000000..81495a0
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/thumb.png differ
diff --git a/asset/jqtouch/themes/apple/img/toggle.png b/asset/jqtouch/themes/apple/img/toggle.png
new file mode 100644
index 0000000..3b62ebf
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/toggle.png differ
diff --git a/asset/jqtouch/themes/apple/img/toggleOn.png b/asset/jqtouch/themes/apple/img/toggleOn.png
new file mode 100644
index 0000000..b016814
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/toggleOn.png differ
diff --git a/asset/jqtouch/themes/apple/img/toolButton.png b/asset/jqtouch/themes/apple/img/toolButton.png
new file mode 100644
index 0000000..dfbba4e
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/toolButton.png differ
diff --git a/asset/jqtouch/themes/apple/img/toolbar.png b/asset/jqtouch/themes/apple/img/toolbar.png
new file mode 100644
index 0000000..2159c7d
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/toolbar.png differ
diff --git a/asset/jqtouch/themes/apple/img/whiteButton.png b/asset/jqtouch/themes/apple/img/whiteButton.png
new file mode 100644
index 0000000..5514b27
Binary files /dev/null and b/asset/jqtouch/themes/apple/img/whiteButton.png differ
diff --git a/asset/jqtouch/themes/apple/theme.css b/asset/jqtouch/themes/apple/theme.css
new file mode 100644
index 0000000..07d85eb
--- /dev/null
+++ b/asset/jqtouch/themes/apple/theme.css
@@ -0,0 +1,677 @@
+body {
+ background: rgb(0,0,0);
+}
+
+body > * {
+ background: rgb(197,204,211) url(img/pinstripes.png);
+}
+
+h1, h2 {
+ font: bold 18px Helvetica;
+ text-shadow: rgba(255,255,255,.2) 0 1px 1px;
+ color: rgb(76, 86, 108);
+ margin: 10px 20px 6px;
+}
+
+/* @group Toolbar */
+
+.toolbar {
+ -webkit-box-sizing: border-box;
+ border-bottom: 1px solid #2d3642;
+ padding: 10px;
+ height: 45px;
+ background: url(img/toolbar.png) #6d84a2 repeat-x;
+ position: relative;
+}
+
+.black-translucent .toolbar {
+ margin-top: 20px;
+}
+
+.toolbar > h1 {
+ position: absolute;
+ overflow: hidden;
+ left: 50%;
+ top: 10px;
+ line-height: 1em;
+ margin: 1px 0 0 -75px;
+ height: 40px;
+ font-size: 20px;
+ width: 150px;
+ font-weight: bold;
+ text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
+ text-align: center;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ color: #fff;
+}
+
+body.landscape .toolbar > h1 {
+ margin-left: -125px;
+ width: 250px;
+}
+
+.button, .back, .cancel, .add {
+ position: absolute;
+ overflow: hidden;
+ top: 8px;
+ right: 6px;
+ margin: 0;
+ border-width: 0 5px;
+ padding: 0 3px;
+ width: auto;
+ height: 30px;
+ line-height: 30px;
+ font-family: inherit;
+ font-size: 12px;
+ font-weight: bold;
+ color: #fff;
+ text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0;
+ text-overflow: ellipsis;
+ text-decoration: none;
+ white-space: nowrap;
+ background: none;
+ -webkit-border-image: url(img/toolButton.png) 0 5 0 5;
+}
+
+.button.active, .back.active, .cancel.active, .add.active {
+ -webkit-border-image: url(img/toolButton.png) 0 5 0 5;
+}
+
+.blueButton {
+ -webkit-border-image: url(img/blueButton.png) 0 5 0 5;
+ border-width: 0 5px;
+}
+
+.back {
+ left: 6px;
+ right: auto;
+ padding: 0;
+ max-width: 55px;
+ border-width: 0 8px 0 14px;
+ -webkit-border-image: url(img/backButton.png) 0 8 0 14;
+}
+
+.leftButton, .cancel {
+ left: 6px;
+ right: auto;
+}
+
+.add {
+ font-size: 24px;
+ line-height: 24px;
+ font-weight: bold;
+}
+
+.whiteButton,
+.grayButton {
+ display: block;
+ border-width: 0 12px;
+ padding: 10px;
+ text-align: center;
+ font-size: 20px;
+ font-weight: bold;
+ text-decoration: inherit;
+ color: inherit;
+}
+
+.whiteButton {
+ -webkit-border-image: url(img/whiteButton.png) 0 12 0 12;
+ text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0;
+}
+
+.grayButton {
+ -webkit-border-image: url(img/grayButton.png) 0 12 0 12;
+ color: #FFFFFF;
+}
+
+/* @end */
+
+/* @group Lists */
+
+h1 + ul, h2 + ul, h3 + ul, h4 + ul, h5 + ul, h6 + ul {
+ margin-top: 0;
+}
+
+ul {
+ color: black;
+ background: #fff;
+ border: 1px solid #B4B4B4;
+ font: bold 17px Helvetica;
+ padding: 0;
+ margin: 15px 10px 17px 10px;
+ -webkit-border-radius: 8px;
+}
+
+ul li {
+ color: #666;
+ border-top: 1px solid #B4B4B4;
+ list-style-type: none;
+ padding: 10px 10px 10px 10px;
+}
+
+/* when you have a first LI item on any list */
+
+li:first-child, li:first-child a {
+ border-top: 0;
+ -webkit-border-top-left-radius: 8px;
+ -webkit-border-top-right-radius: 8px;
+}
+
+li:last-child, li:last-child a {
+ -webkit-border-bottom-left-radius: 8px;
+ -webkit-border-bottom-right-radius: 8px;
+}
+
+/* universal arrows */
+
+ul li.arrow {
+ background-image: url(img/chevron.png);
+ background-position: right center;
+ background-repeat: no-repeat;
+}
+
+#plastic ul li.arrow, #metal ul li.arrow {
+ background-image: url(../images/chevron_dg.png);
+ background-position: right center;
+ background-repeat: no-repeat;
+}
+
+/* universal links on list */
+
+ul li a, li.img a + a {
+ color: #000;
+ text-decoration: none;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ display: block;
+ padding: 12px 10px 12px 10px;
+ margin: -10px;
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+}
+
+ul li a.active {
+ background: #194fdb url(img/selection.png) 0 0 repeat-x;
+ color: #fff;
+}
+
+ul li a.button {
+ background-color: #194fdb;
+ color: #fff;
+}
+
+ul li.img a + a {
+ margin: -10px 10px -20px -5px;
+ font-size: 17px;
+ font-weight: bold;
+}
+
+ul li.img a + a + a {
+ font-size: 14px;
+ font-weight: normal;
+ margin-left: -10px;
+ margin-bottom: -10px;
+ margin-top: 0;
+}
+
+ul li.img a + small + a {
+ margin-left: -5px;
+}
+
+ul li.img a + small + a + a {
+ margin-left: -10px;
+ margin-top: -20px;
+ margin-bottom: -10px;
+ font-size: 14px;
+ font-weight: normal;
+}
+
+ul li.img a + small + a + a + a {
+ margin-left: 0px !important;
+ margin-bottom: 0;
+}
+
+ul li a + a {
+ color: #000;
+ font: 14px Helvetica;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ display: block;
+ margin: 0;
+ padding: 0;
+}
+
+ul li a + a + a, ul li.img a + a + a + a, ul li.img a + small + a + a + a {
+ color: #666;
+ font: 13px Helvetica;
+ margin: 0;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ display: block;
+ padding: 0;
+}
+
+/*
+@end */
+
+/* @group Forms */
+
+ul.form li {
+ padding: 7px 10px;
+}
+
+ul.form li.error {
+ border: 2px solid red;
+}
+
+ul.form li.error + li.error {
+ border-top: 0;
+}
+
+ul.form li:hover {
+ background: #fff;
+}
+
+ul li input[type="text"], ul li input[type="password"], ul li textarea, ul li select {
+ color: #777;
+ background: #fff url(../.png);
+ border: 0;
+ font: normal 17px Helvetica;
+ padding: 0;
+ display: inline-block;
+ margin-left: 0px;
+ width: 100%;
+ -webkit-appearance: textarea;
+}
+
+ul li textarea {
+ height: 120px;
+ padding: 0;
+ text-indent: -2px;
+}
+
+ul li select {
+ text-indent: 0px;
+ background: transparent url(../images/chevron.png) no-repeat 103% 3px;
+ -webkit-appearance: textfield;
+ margin-left: -6px;
+ width: 104%;
+}
+
+ul li input[type="checkbox"], ul li input[type="radio"] {
+ margin: 0;
+ color: rgb(50,79,133);
+ padding: 10px 10px;
+}
+
+ul li input[type="checkbox"]:after, ul li input[type="radio"]:after {
+ content: attr(title);
+ font: 17px Helvetica;
+ display: block;
+ width: 246px;
+ margin: -12px 0 0 17px;
+}
+
+/* @end */
+
+/* @group Edge to edge */
+
+.edgetoedge h4 {
+ color: #fff;
+ background: rgb(154,159,170) url(img/listGroup.png) top left repeat-x;
+ border-top: 1px solid rgb(165,177,186);
+ text-shadow: #666 0 1px 0;
+ margin: 0;
+ padding: 2px 10px;
+}
+
+.edgetoedge, .metal {
+ margin: 0;
+ padding: 0;
+ background-color: rgb(255,255,255);
+}
+
+.edgetoedge ul, .metal ul, .plastic ul {
+ -webkit-border-radius: 0;
+ margin: 0;
+ border-left: 0;
+ border-right: 0;
+ border-top: 0;
+}
+
+.metal ul {
+ border-top: 0;
+ border-bottom: 0;
+ background: rgb(180,180,180);
+}
+
+.edgetoedge ul li:first-child, .edgetoedge ul li:first-child a, .edgetoedge ul li:last-child, .edgetoedge ul li:last-child a, .metal ul li:first-child a, .metal ul li:last-child a {
+ -webkit-border-radius: 0;
+}
+
+.edgetoedge ul li small {
+ font-size: 16px;
+ line-height: 28px;
+}
+
+.edgetoedge li, .metal li {
+ -webkit-border-radius: 0;
+}
+
+.edgetoedge li em {
+ font-weight: normal;
+ font-style: normal;
+}
+
+.edgetoedge h4 + ul {
+ border-top: 1px solid rgb(152,158,164);
+ border-bottom: 1px solid rgb(113,125,133);
+}
+
+/* @end */
+
+/* @group Mini Label */
+
+ul li small {
+ color: #369;
+ font: 17px Helvetica;
+ text-align: right;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ display: block;
+ width: 23%;
+ float: right;
+ padding: 3px 0px;
+}
+
+ul li.arrow small {
+ padding: 0 15px;
+}
+
+ul li small.counter {
+ font-size: 17px !important;
+ line-height: 13px !important;
+ font-weight: bold;
+ background: rgb(154,159,170);
+ color: #fff;
+ -webkit-border-radius: 11px;
+ padding: 4px 10px 5px 10px;
+ display: inline !important;
+ width: auto;
+ margin-top: -22px;
+}
+
+ul li.arrow small.counter {
+ margin-right: 15px;
+}
+
+/* @end */
+
+/* @group Plastic */
+
+#plastic ul li.arrow, #metal ul li.arrow {
+ background-image: url(img/listArrow.png);
+ background-position: right center;
+ background-repeat: no-repeat;
+}
+
+.edgetoedge ul, .metal ul, .plastic ul {
+ -webkit-border-radius: 0;
+ margin: 0;
+ border-left: 0;
+ border-right: 0;
+ border-top: 0;
+}
+
+.metal ul li {
+ border-top: 1px solid rgb(238,238,238);
+ border-bottom: 1px solid rgb(156,158,165);
+ background: url(../images/bgMetal.png) top left repeat-x;
+ font-size: 26px;
+ text-shadow: #fff 0 1px 0;
+}
+
+.metal ul li a {
+ line-height: 26px;
+ margin: 0;
+ padding: 13px 0;
+}
+
+.metal ul li a:hover {
+ color: rgb(0,0,0);
+}
+
+.metal ul li:hover small {
+ color: inherit;
+}
+
+.metal ul li a em {
+ display: block;
+ font-size: 14px;
+ font-style: normal;
+ color: #444;
+ width: 50%;
+ line-height: 14px;
+}
+
+.metal ul li small {
+ float: right;
+ position: relative;
+ margin-top: 10px;
+ font-weight: bold;
+}
+
+.metal ul li.arrow a small {
+ padding-right: 0;
+ line-height: 17px;
+}
+
+.metal ul li.arrow {
+ background: url(../images/bgMetal.png) top left repeat-x,
+ url(../images/chevron_dg.png) right center no-repeat;
+}
+
+.plastic {
+ margin: 0;
+ padding: 0;
+ background: rgb(173,173,173);
+}
+
+.plastic ul {
+ -webkit-border-radius: 0;
+ margin: 0;
+ border-left: 0;
+ border-right: 0;
+ border-top: 0;
+ background-color: rgb(173,173,173);
+}
+
+.plastic ul li {
+ -webkit-border-radius: 0;
+ border-top: 1px solid rgb(191,191,191);
+ border-bottom: 1px solid rgb(157,157,157);
+}
+
+.plastic ul li:nth-child(odd) {
+ background-color: rgb(152,152,152);
+ border-top: 1px solid rgb(181,181,181);
+ border-bottom: 1px solid rgb(138,138,138);
+}
+
+.plastic ul + p {
+ font-size: 11px;
+ color: #2f3237;
+ text-shadow: none;
+ padding: 10px 10px;
+}
+
+.plastic ul + p strong {
+ font-size: 14px;
+ line-height: 18px;
+ text-shadow: #fff 0 1px 0;
+}
+
+.plastic ul li a {
+ text-shadow: rgb(211,211,211) 0 1px 0;
+}
+
+.plastic ul li:nth-child(odd) a {
+ text-shadow: rgb(191,191,191) 0 1px 0;
+}
+
+.plastic ul li small {
+ color: #3C3C3C;
+ text-shadow: rgb(211,211,211) 0 1px 0;
+ font-size: 13px;
+ font-weight: bold;
+ text-transform: uppercase;
+ line-height: 24px;
+}
+
+#plastic ul.minibanner, #plastic ul.bigbanner {
+ margin: 10px;
+ border: 0;
+ height: 81px;
+ clear: both;
+}
+
+#plastic ul.bigbanner {
+ height: 140px !important;
+}
+
+#plastic ul.minibanner li {
+ border: 1px solid rgb(138,138,138);
+ background-color: rgb(152,152,152);
+ width: 145px;
+ height: 81px;
+ float: left;
+ -webkit-border-radius: 5px;
+ padding: 0;
+}
+
+#plastic ul.bigbanner li {
+ border: 1px solid rgb(138,138,138);
+ background-color: rgb(152,152,152);
+ width: 296px;
+ height: 140px;
+ float: left;
+ -webkit-border-radius: 5px;
+ padding: 0;
+ margin-bottom: 4px;
+}
+
+#plastic ul.minibanner li:first-child {
+ margin-right: 6px;
+}
+
+#plastic ul.minibanner li a {
+ color: transparent;
+ text-shadow: none;
+ display: block;
+ width: 145px;
+ height: 81px;
+}
+
+#plastic ul.bigbanner li a {
+ color: transparent;
+ text-shadow: none;
+ display: block;
+ width: 296px;
+ height: 145px;
+}
+
+/* @end */
+
+/* @group Individual */
+
+ul.individual {
+ border: 0;
+ background: none;
+ clear: both;
+ overflow: hidden;
+}
+
+ul.individual li {
+ color: rgb(183,190,205);
+ background: white;
+ border: 1px solid rgb(180,180,180);
+ font-size: 14px;
+ text-align: center;
+ -webkit-border-radius: 8px;
+ -webkit-box-sizing: border-box;
+ width: 48%;
+ float: left;
+ display: block;
+ padding: 11px 10px 14px 10px;
+}
+
+ul.individual li + li {
+ float: right;
+}
+
+ul.individual li a {
+ color: rgb(50,79,133);
+ line-height: 16px;
+ margin: -11px -10px -14px -10px;
+ padding: 11px 10px 14px 10px;
+ -webkit-border-radius: 8px;
+}
+
+ul.individual li a:hover {
+ color: #fff;
+ background: #36c;
+}
+
+/* @end */
+
+/* @group Toggle */
+
+
+.toggle {
+ width: 94px;
+ position: relative;
+ height: 27px;
+ display: block;
+ overflow: hidden;
+ float: right;
+}
+
+.toggle input[type="checkbox"]:checked {
+ left: 0px;
+}
+
+.toggle input[type="checkbox"] {
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+ margin: 0;
+ -webkit-border-radius: 5px;
+ background: #fff url(img/on_off.png) 0 0 no-repeat;
+ height: 27px;
+ overflow: hidden;
+ width: 149px;
+ border: 0;
+ -webkit-appearance: textarea;
+ background-color: transparent;
+ -webkit-transition: left .15s;
+ position: absolute;
+ top: 0;
+ left: -55px;
+}
+/* @end */
+
+
+
+.info {
+ background: #dce1eb;
+ font-size: 12px;
+ line-height: 16px;
+ text-align: center;
+ text-shadow: rgba(255,255,255,.8) 0 1px 0;
+ color: rgb(76, 86, 108);
+ padding: 15px;
+ border-top: 1px solid rgba(76, 86, 108, .3);
+ font-weight: bold;
+}
diff --git a/asset/jqtouch/themes/apple/theme.min.css b/asset/jqtouch/themes/apple/theme.min.css
new file mode 100644
index 0000000..decc185
--- /dev/null
+++ b/asset/jqtouch/themes/apple/theme.min.css
@@ -0,0 +1 @@
+body{background:#000;}body>*{background:#c5ccd3 url(img/pinstripes.png);}h1,h2{font:bold 18px Helvetica;text-shadow:rgba(255,255,255,.2) 0 1px 1px;color:#4c566c;margin:10px 20px 6px;}.toolbar{-webkit-box-sizing:border-box;border-bottom:1px solid #2d3642;padding:10px;height:45px;background:url(img/toolbar.png) #6d84a2 repeat-x;position:relative;}.black-translucent .toolbar{margin-top:20px;}.toolbar>h1{position:absolute;overflow:hidden;left:50%;top:10px;line-height:1em;margin:1px 0 0 -75px;height:40px;font-size:20px;width:150px;font-weight:bold;text-shadow:rgba(0,0,0,0.4) 0 -1px 0;text-align:center;text-overflow:ellipsis;white-space:nowrap;color:#fff;}body.landscape .toolbar>h1{margin-left:-125px;width:250px;}.button,.back,.cancel,.add{position:absolute;overflow:hidden;top:8px;right:6px;margin:0;border-width:0 5px;padding:0 3px;width:auto;height:30px;line-height:30px;font-family:inherit;font-size:12px;font-weight:bold;color:#fff;text-shadow:rgba(0,0,0,0.5) 0 -1px 0;text-overflow:ellipsis;text-decoration:none;white-space:nowrap;background:none;-webkit-border-image:url(img/toolButton.png) 0 5 0 5;}.button.active,.back.active,.cancel.active,.add.active{-webkit-border-image:url(img/toolButton.png) 0 5 0 5;}.blueButton{-webkit-border-image:url(img/blueButton.png) 0 5 0 5;border-width:0 5px;}.back{left:6px;right:auto;padding:0;max-width:55px;border-width:0 8px 0 14px;-webkit-border-image:url(img/backButton.png) 0 8 0 14;}.leftButton,.cancel{left:6px;right:auto;}.add{font-size:24px;line-height:24px;font-weight:bold;}.whiteButton,.grayButton{display:block;border-width:0 12px;padding:10px;text-align:center;font-size:20px;font-weight:bold;text-decoration:inherit;color:inherit;}.whiteButton{-webkit-border-image:url(img/whiteButton.png) 0 12 0 12;text-shadow:rgba(255,255,255,0.7) 0 1px 0;}.grayButton{-webkit-border-image:url(img/grayButton.png) 0 12 0 12;color:#FFF;}h1+ul,h2+ul,h3+ul,h4+ul,h5+ul,h6+ul{margin-top:0;}ul{color:black;background:#fff;border:1px solid #B4B4B4;font:bold 17px Helvetica;padding:0;margin:15px 10px 17px 10px;-webkit-border-radius:8px;}ul li{color:#666;border-top:1px solid #B4B4B4;list-style-type:none;padding:10px 10px 10px 10px;}li:first-child,li:first-child a{border-top:0;-webkit-border-top-left-radius:8px;-webkit-border-top-right-radius:8px;}li:last-child,li:last-child a{-webkit-border-bottom-left-radius:8px;-webkit-border-bottom-right-radius:8px;}ul li.arrow{background-image:url(img/chevron.png);background-position:right center;background-repeat:no-repeat;}#plastic ul li.arrow,#metal ul li.arrow{background-image:url(../images/chevron_dg.png);background-position:right center;background-repeat:no-repeat;}ul li a,li.img a+a{color:#000;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;padding:12px 10px 12px 10px;margin:-10px;-webkit-tap-highlight-color:rgba(0,0,0,0);}ul li a.active{background:#194fdb url(img/selection.png) 0 0 repeat-x;color:#fff;}ul li a.button{background-color:#194fdb;color:#fff;}ul li.img a+a{margin:-10px 10px -20px -5px;font-size:17px;font-weight:bold;}ul li.img a+a+a{font-size:14px;font-weight:normal;margin-left:-10px;margin-bottom:-10px;margin-top:0;}ul li.img a+small+a{margin-left:-5px;}ul li.img a+small+a+a{margin-left:-10px;margin-top:-20px;margin-bottom:-10px;font-size:14px;font-weight:normal;}ul li.img a+small+a+a+a{margin-left:0!important;margin-bottom:0;}ul li a+a{color:#000;font:14px Helvetica;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;margin:0;padding:0;}ul li a+a+a,ul li.img a+a+a+a,ul li.img a+small+a+a+a{color:#666;font:13px Helvetica;margin:0;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;padding:0;}ul.form li{padding:7px 10px;}ul.form li.error{border:2px solid red;}ul.form li.error+li.error{border-top:0;}ul.form li:hover{background:#fff;}ul li input[type="text"],ul li input[type="password"],ul li textarea,ul li select{color:#777;background:#fff url(../.png);border:0;font:normal 17px Helvetica;padding:0;display:inline-block;margin-left:0;width:100%;-webkit-appearance:textarea;}ul li textarea{height:120px;padding:0;text-indent:-2px;}ul li select{text-indent:0;background:transparent url(../images/chevron.png) no-repeat 103% 3px;-webkit-appearance:textfield;margin-left:-6px;width:104%;}ul li input[type="checkbox"],ul li input[type="radio"]{margin:0;color:#324f85;padding:10px 10px;}ul li input[type="checkbox"]:after,ul li input[type="radio"]:after{content:attr(title);font:17px Helvetica;display:block;width:246px;margin:-12px 0 0 17px;}.edgetoedge h4{color:#fff;background:#9a9faa url(img/listGroup.png) top left repeat-x;border-top:1px solid #a5b1ba;text-shadow:#666 0 1px 0;margin:0;padding:2px 10px;}.edgetoedge,.metal{margin:0;padding:0;background-color:#fff;}.edgetoedge ul,.metal ul,.plastic ul{-webkit-border-radius:0;margin:0;border-left:0;border-right:0;border-top:0;}.metal ul{border-top:0;border-bottom:0;background:#b4b4b4;}.edgetoedge ul li:first-child,.edgetoedge ul li:first-child a,.edgetoedge ul li:last-child,.edgetoedge ul li:last-child a,.metal ul li:first-child a,.metal ul li:last-child a{-webkit-border-radius:0;}.edgetoedge ul li small{font-size:16px;line-height:28px;}.edgetoedge li,.metal li{-webkit-border-radius:0;}.edgetoedge li em{font-weight:normal;font-style:normal;}.edgetoedge h4+ul{border-top:1px solid #989ea4;border-bottom:1px solid #717d85;}ul li small{color:#369;font:17px Helvetica;text-align:right;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;width:23%;float:right;padding:3px 0;}ul li.arrow small{padding:0 15px;}ul li small.counter{font-size:17px!important;line-height:13px!important;font-weight:bold;background:#9a9faa;color:#fff;-webkit-border-radius:11px;padding:4px 10px 5px 10px;display:inline!important;width:auto;margin-top:-22px;}ul li.arrow small.counter{margin-right:15px;}#plastic ul li.arrow,#metal ul li.arrow{background-image:url(img/listArrow.png);background-position:right center;background-repeat:no-repeat;}.edgetoedge ul,.metal ul,.plastic ul{-webkit-border-radius:0;margin:0;border-left:0;border-right:0;border-top:0;}.metal ul li{border-top:1px solid #eee;border-bottom:1px solid #9c9ea5;background:url(../images/bgMetal.png) top left repeat-x;font-size:26px;text-shadow:#fff 0 1px 0;}.metal ul li a{line-height:26px;margin:0;padding:13px 0;}.metal ul li a:hover{color:#000;}.metal ul li:hover small{color:inherit;}.metal ul li a em{display:block;font-size:14px;font-style:normal;color:#444;width:50%;line-height:14px;}.metal ul li small{float:right;position:relative;margin-top:10px;font-weight:bold;}.metal ul li.arrow a small{padding-right:0;line-height:17px;}.metal ul li.arrow{background:url(../images/bgMetal.png) top left repeat-x,url(../images/chevron_dg.png) right center no-repeat;}.plastic{margin:0;padding:0;background:#adadad;}.plastic ul{-webkit-border-radius:0;margin:0;border-left:0;border-right:0;border-top:0;background-color:#adadad;}.plastic ul li{-webkit-border-radius:0;border-top:1px solid #bfbfbf;border-bottom:1px solid #9d9d9d;}.plastic ul li:nth-child(odd){background-color:#989898;border-top:1px solid #b5b5b5;border-bottom:1px solid #8a8a8a;}.plastic ul+p{font-size:11px;color:#2f3237;text-shadow:none;padding:10px 10px;}.plastic ul+p strong{font-size:14px;line-height:18px;text-shadow:#fff 0 1px 0;}.plastic ul li a{text-shadow:#d3d3d3 0 1px 0;}.plastic ul li:nth-child(odd) a{text-shadow:#bfbfbf 0 1px 0;}.plastic ul li small{color:#3C3C3C;text-shadow:#d3d3d3 0 1px 0;font-size:13px;font-weight:bold;text-transform:uppercase;line-height:24px;}#plastic ul.minibanner,#plastic ul.bigbanner{margin:10px;border:0;height:81px;clear:both;}#plastic ul.bigbanner{height:140px!important;}#plastic ul.minibanner li{border:1px solid #8a8a8a;background-color:#989898;width:145px;height:81px;float:left;-webkit-border-radius:5px;padding:0;}#plastic ul.bigbanner li{border:1px solid #8a8a8a;background-color:#989898;width:296px;height:140px;float:left;-webkit-border-radius:5px;padding:0;margin-bottom:4px;}#plastic ul.minibanner li:first-child{margin-right:6px;}#plastic ul.minibanner li a{color:transparent;text-shadow:none;display:block;width:145px;height:81px;}#plastic ul.bigbanner li a{color:transparent;text-shadow:none;display:block;width:296px;height:145px;}ul.individual{border:0;background:none;clear:both;overflow:hidden;}ul.individual li{color:#b7becd;background:white;border:1px solid #b4b4b4;font-size:14px;text-align:center;-webkit-border-radius:8px;-webkit-box-sizing:border-box;width:48%;float:left;display:block;padding:11px 10px 14px 10px;}ul.individual li+li{float:right;}ul.individual li a{color:#324f85;line-height:16px;margin:-11px -10px -14px -10px;padding:11px 10px 14px 10px;-webkit-border-radius:8px;}ul.individual li a:hover{color:#fff;background:#36c;}.toggle{width:94px;position:relative;height:27px;display:block;overflow:hidden;float:right;}.toggle input[type="checkbox"]:checked{left:0;}.toggle input[type="checkbox"]{-webkit-tap-highlight-color:rgba(0,0,0,0);margin:0;-webkit-border-radius:5px;background:#fff url(img/on_off.png) 0 0 no-repeat;height:27px;overflow:hidden;width:149px;border:0;-webkit-appearance:textarea;background-color:transparent;-webkit-transition:left .15s;position:absolute;top:0;left:-55px;}.info{background:#dce1eb;font-size:12px;line-height:16px;text-align:center;text-shadow:rgba(255,255,255,.8) 0 1px 0;color:#4c566c;padding:15px;border-top:1px solid rgba(76,86,108,.3);font-weight:bold;}
\ No newline at end of file
diff --git a/asset/jqtouch/themes/jqt/img/back_button.png b/asset/jqtouch/themes/jqt/img/back_button.png
new file mode 100644
index 0000000..9873901
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/back_button.png differ
diff --git a/asset/jqtouch/themes/jqt/img/back_button_clicked.png b/asset/jqtouch/themes/jqt/img/back_button_clicked.png
new file mode 100644
index 0000000..5ec4230
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/back_button_clicked.png differ
diff --git a/asset/jqtouch/themes/jqt/img/button.png b/asset/jqtouch/themes/jqt/img/button.png
new file mode 100644
index 0000000..52cc7e2
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/button.png differ
diff --git a/asset/jqtouch/themes/jqt/img/button_clicked.png b/asset/jqtouch/themes/jqt/img/button_clicked.png
new file mode 100644
index 0000000..25d478f
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/button_clicked.png differ
diff --git a/asset/jqtouch/themes/jqt/img/chevron.png b/asset/jqtouch/themes/jqt/img/chevron.png
new file mode 100644
index 0000000..5bdaa46
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/chevron.png differ
diff --git a/asset/jqtouch/themes/jqt/img/chevron_circle.png b/asset/jqtouch/themes/jqt/img/chevron_circle.png
new file mode 100644
index 0000000..b477e7c
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/chevron_circle.png differ
diff --git a/asset/jqtouch/themes/jqt/img/grayButton.png b/asset/jqtouch/themes/jqt/img/grayButton.png
new file mode 100644
index 0000000..0ce6a30
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/grayButton.png differ
diff --git a/asset/jqtouch/themes/jqt/img/loading.gif b/asset/jqtouch/themes/jqt/img/loading.gif
new file mode 100644
index 0000000..2b4205b
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/loading.gif differ
diff --git a/asset/jqtouch/themes/jqt/img/on_off.png b/asset/jqtouch/themes/jqt/img/on_off.png
new file mode 100644
index 0000000..95d6d5c
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/on_off.png differ
diff --git a/asset/jqtouch/themes/jqt/img/rowhead.png b/asset/jqtouch/themes/jqt/img/rowhead.png
new file mode 100644
index 0000000..b2fa8f6
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/rowhead.png differ
diff --git a/asset/jqtouch/themes/jqt/img/toggle.png b/asset/jqtouch/themes/jqt/img/toggle.png
new file mode 100644
index 0000000..3b62ebf
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/toggle.png differ
diff --git a/asset/jqtouch/themes/jqt/img/toggleOn.png b/asset/jqtouch/themes/jqt/img/toggleOn.png
new file mode 100644
index 0000000..b016814
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/toggleOn.png differ
diff --git a/asset/jqtouch/themes/jqt/img/toolbar.png b/asset/jqtouch/themes/jqt/img/toolbar.png
new file mode 100644
index 0000000..c17bcf2
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/toolbar.png differ
diff --git a/asset/jqtouch/themes/jqt/img/whiteButton.png b/asset/jqtouch/themes/jqt/img/whiteButton.png
new file mode 100644
index 0000000..5514b27
Binary files /dev/null and b/asset/jqtouch/themes/jqt/img/whiteButton.png differ
diff --git a/asset/jqtouch/themes/jqt/theme.css b/asset/jqtouch/themes/jqt/theme.css
new file mode 100644
index 0000000..cbfe608
--- /dev/null
+++ b/asset/jqtouch/themes/jqt/theme.css
@@ -0,0 +1,528 @@
+body {
+ background: #000;
+ color: #ddd;
+}
+body > * {
+ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#333), to(#5e5e65));
+}
+h1, h2 {
+ font: bold 18px Helvetica;
+ text-shadow: rgba(255,255,255,.2) 0 1px 1px;
+ color: #000;
+ margin: 10px 20px 5px;
+}
+/* @group Toolbar */
+.toolbar {
+ -webkit-box-sizing: border-box;
+ border-bottom: 1px solid #000;
+ padding: 10px;
+ height: 45px;
+ background: url(img/toolbar.png) #000000 repeat-x;
+ position: relative;
+}
+.black-translucent .toolbar {
+ margin-top: 20px;
+}
+.toolbar > h1 {
+ position: absolute;
+ overflow: hidden;
+ left: 50%;
+ top: 10px;
+ line-height: 1em;
+ margin: 1px 0 0 -75px;
+ height: 40px;
+ font-size: 20px;
+ width: 150px;
+ font-weight: bold;
+ text-shadow: rgba(0,0,0,1) 0 -1px 1px;
+ text-align: center;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ color: #fff;
+}
+body.landscape .toolbar > h1 {
+ margin-left: -125px;
+ width: 250px;
+}
+.button, .back, .cancel, .add {
+ position: absolute;
+ overflow: hidden;
+ top: 8px;
+ right: 10px;
+ margin: 0;
+ border-width: 0 5px;
+ padding: 0 3px;
+ width: auto;
+ height: 30px;
+ line-height: 30px;
+ font-family: inherit;
+ font-size: 12px;
+ font-weight: bold;
+ color: #fff;
+ text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0;
+ text-overflow: ellipsis;
+ text-decoration: none;
+ white-space: nowrap;
+ background: none;
+ -webkit-border-image: url(img/button.png) 0 5 0 5;
+}
+.blueButton {
+ -webkit-border-image: url(img/blueButton.png) 0 5 0 5;
+ border-width: 0 5px;
+}
+.back {
+ left: 6px;
+ right: auto;
+ padding: 0;
+ max-width: 55px;
+ border-width: 0 8px 0 14px;
+ -webkit-border-image: url(img/back_button.png) 0 8 0 14;
+}
+.back.active {
+ -webkit-border-image: url(img/back_button_clicked.png) 0 8 0 14;
+ color: #aaa;
+}
+.leftButton, .cancel {
+ left: 6px;
+ right: auto;
+}
+.add {
+ font-size: 24px;
+ line-height: 24px;
+ font-weight: bold;
+}
+.whiteButton,
+.grayButton {
+ display: block;
+ border-width: 0 12px;
+ padding: 10px;
+ text-align: center;
+ font-size: 20px;
+ font-weight: bold;
+ text-decoration: inherit;
+ color: inherit;
+}
+.whiteButton {
+ -webkit-border-image: url(img/whiteButton.png) 0 12 0 12;
+ text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0;
+}
+.grayButton {
+ -webkit-border-image: url(img/grayButton.png) 0 12 0 12;
+ color: #FFFFFF;
+}
+/* @end */
+/* @group Lists */
+h1 + ul, h2 + ul, h3 + ul, h4 + ul, h5 + ul, h6 + ul {
+ margin-top: 0;
+}
+ul {
+ color: #aaa;
+ border: 1px solid #333333;
+ font: bold 18px Helvetica;
+ padding: 0;
+ margin: 15px 10px 17px 10px;
+}
+ul.rounded {
+ -webkit-border-radius: 8px;
+ -webkit-box-shadow: rgba(0,0,0,.3) 1px 1px 3px;
+}
+ul.rounded li:first-child, ul.rounded li:first-child a {
+ border-top: 0;
+ -webkit-border-top-left-radius: 8px;
+ -webkit-border-top-right-radius: 8px;
+}
+ul.rounded li:last-child, ul.rounded li:last-child a {
+ -webkit-border-bottom-left-radius: 8px;
+ -webkit-border-bottom-right-radius: 8px;
+}
+ul li {
+ color: #666;
+ border-top: 1px solid #333;
+ border-bottom: #555858;
+ list-style-type: none;
+ padding: 10px 10px 10px 10px;
+ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4c4d4e), to(#404142));
+ overflow: hidden;
+}
+ul li.arrow {
+ background-image: url(img/chevron.png), -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4c4d4e), to(#404142));
+ background-position: right center;
+ background-repeat: no-repeat;
+}
+ul li.forward {
+ background-image: url(img/chevron_circle.png), -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4c4d4e), to(#404142));
+ background-position: right center;
+ background-repeat: no-repeat;
+}
+/* universal links on list */
+ul li a, li.img a + a {
+ color: #fff;
+ text-decoration: none;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ display: block;
+ padding: 12px 10px 12px 10px;
+ margin: -10px;
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+ text-shadow: rgba(0,0,0,.2) 0 1px 1px;
+}
+ul li a.active, ul li a.button {
+ background-color: #53b401;
+ color: #fff;
+}
+ul li a.active.loading {
+ background-image: url(img/loading.gif);
+ background-position: 95% center;
+ background-repeat: no-repeat;
+}
+ul li.arrow a.active {
+ background-image: url(img/chevron.png);
+ background-position: right center;
+ background-repeat: no-repeat;
+}
+ul li.forward a.active {
+ background-image: url(img/chevron_circle.png);
+ background-position: right center;
+ background-repeat: no-repeat;
+}
+ul li.img a + a {
+ margin: -10px 10px -20px -5px;
+ font-size: 17px;
+ font-weight: bold;
+}
+ul li.img a + a + a {
+ font-size: 14px;
+ font-weight: normal;
+ margin-left: -10px;
+ margin-bottom: -10px;
+ margin-top: 0;
+}
+ul li.img a + small + a {
+ margin-left: -5px;
+}
+ul li.img a + small + a + a {
+ margin-left: -10px;
+ margin-top: -20px;
+ margin-bottom: -10px;
+ font-size: 14px;
+ font-weight: normal;
+}
+ul li.img a + small + a + a + a {
+ margin-left: 0px !important;
+ margin-bottom: 0;
+}
+ul li a + a {
+ color: #000;
+ font: 14px Helvetica;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ display: block;
+ margin: 0;
+ padding: 0;
+}
+ul li a + a + a, ul li.img a + a + a + a, ul li.img a + small + a + a + a {
+ color: #666;
+ font: 13px Helvetica;
+ margin: 0;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ display: block;
+ padding: 0;
+}
+/*
+@end */
+/* @group Forms */
+ul.form li {
+ padding: 7px 10px;
+}
+ul.form li.error {
+ border: 2px solid red;
+}
+ul.form li.error + li.error {
+ border-top: 0;
+}
+ul li input[type="text"], ul li input[type="password"], ul li textarea, ul li select {
+ color: #777;
+ background: transparent;
+ background-image: none;;
+ border: 0;
+ font: normal 17px Helvetica;
+ padding: 0;
+ display: inline-block;
+ margin-left: 0px;
+ width: 100%;
+ -webkit-appearance: textarea;
+}
+ul li textarea {
+ height: 120px;
+ padding: 0;
+ text-indent: -2px;
+}
+ul li select {
+ text-indent: 0px;
+ background: transparent url(img/chevron.png) no-repeat right center;
+ -webkit-appearance: textfield;
+ margin-left: -6px;
+ width: 104%;
+}
+ul li input[type="checkbox"], ul li input[type="radio"] {
+ margin: 0;
+ padding: 10px 10px;
+}
+ul li input[type="checkbox"]:after, ul li input[type="radio"]:after {
+ content: attr(title);
+ font: 17px Helvetica;
+ display: block;
+ width: 246px;
+ color: #777;
+ margin: -12px 0 0 17px;
+}
+/* @end */
+/* @group Mini Label */
+ul li small {
+ color: #64c114;
+ font: 17px Helvetica;
+ text-align: right;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ display: block;
+ width: 23%;
+ float: right;
+ padding: 0;
+}
+ul li.arrow small {
+ padding: 0 15px;
+}
+ul li small.counter {
+ font-size: 17px;
+ line-height: 13px;
+ font-weight: bold;
+ background: rgba(0,0,0,.15);
+ color: #fff;
+ -webkit-border-radius: 11px;
+ padding: 4px 10px 5px 10px;
+ display: block;
+ width: auto;
+ margin-top: -22px;
+ -webkit-box-shadow: rgba(255,255,255,.1) 0 1px 0;
+}
+ul li.arrow small.counter {
+ margin-right: 15px;
+}
+/* @end */
+/* @group Individual */
+ul.individual {
+ border: 0;
+ background: none;
+ clear: both;
+ overflow: hidden;
+ padding-bottom: 3px;
+ -webkit-box-shadow: none;
+}
+ul.individual li {
+ background: #4c4d4e;
+ border: 1px solid #333;
+ font-size: 14px;
+ text-align: center;
+ -webkit-border-radius: 8px;
+ -webkit-box-sizing: border-box;
+ width: 48%;
+ float: left;
+ display: block;
+ padding: 11px 10px 14px 10px;
+ -webkit-box-shadow: rgba(0,0,0,.2) 1px 1px 3px;
+ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4c4d4e), to(#404142));
+}
+ul.individual li + li {
+ float: right;
+}
+ul.individual li a {
+ color: #fff;
+ line-height: 16px;
+ margin: -11px -10px -14px -10px;
+ padding: 11px 10px 14px 10px;
+ -webkit-border-radius: 8px;
+}
+/* @end */
+/* @group Toggle */
+.toggle {
+ width: 94px;
+ position: relative;
+ height: 27px;
+ display: block;
+ overflow: hidden;
+ float: right;
+}
+.toggle input[type="checkbox"]:checked {
+ left: 0px;
+}
+.toggle input[type="checkbox"] {
+ -webkit-appearance: textarea;
+ -webkit-border-radius: 5px;
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
+ -webkit-transition: left .15s;
+ background-color: transparent;
+ background: #fff url(img/on_off.png) 0 0 no-repeat;
+ border: 0;
+ height: 27px;
+ left: -55px;
+ margin: 0;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ width: 149px;
+}
+/* @end */
+/* @group Info */
+.info {
+ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#ccc), to(#aaa), color-stop(.6,#CCCCCC));
+ font-size: 12px;
+ line-height: 16px;
+ text-align: center;
+ text-shadow: rgba(255,255,255,.8) 0 1px 0;
+ color: #444;
+ padding: 15px;
+ border-top: 1px solid rgba(255,255,255,.2);
+ font-weight: bold;
+}
+/* @end */
+/* @group Edge to edge */
+ul.edgetoedge {
+ border-width: 1px 0;
+ margin: 0;
+ padding: 0;
+}
+ul.edgetoedge li {
+ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#1e1f21), to(#272729));
+ border-bottom: 2px solid #000;
+ border-top: 1px solid #4a4b4d;
+ font-size: 20px;
+ margin-bottom: -1px;
+}
+ul.edgetoedge li.sep {
+ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(0,0,0,0)), to(rgba(0,0,0,.5)));
+ border-bottom: 1px solid #111113;
+ border-top: 1px solid #666;
+ color: #3e9ac3;
+ font-size: 16px;
+ margin: 1px 0 0 0;
+ padding: 2px 10px;
+ text-shadow: #000 0 1px 0;
+}
+ul.edgetoedge li em {
+ font-weight: normal;
+ font-style: normal;
+}
+/* @end */
+/* @group Plastic */
+#plastic {
+ background: #17181a;
+}
+ul.plastic {
+ background: #17181a;
+ color: #aaa;
+ font: bold 18px Helvetica;
+ margin: 0;
+ padding: 0;
+ border-width: 0 0 1px 0;
+}
+ul.plastic li {
+ border-width: 1px 0;
+ border-style: solid;
+ border-top-color: #222;
+ border-bottom-color: #000;
+ color: #666;
+ list-style-type: none;
+ overflow: hidden;
+ padding: 10px 10px 10px 10px;
+}
+ul.plastic li a.active.loading {
+ background-image: url(img/loading.gif);
+ background-position: 95% center;
+ background-repeat: no-repeat;
+}
+ul.plastic li small {
+ color: #888;
+ font-size: 13px;
+ font-weight: bold;
+ line-height: 24px;
+ text-transform: uppercase;
+}
+ul.plastic li:nth-child(odd) {
+ background-color: #1c1c1f;
+}
+ul.plastic li.arrow {
+ background-image: url(img/chevron.png);
+ background-position: right center;
+ background-repeat: no-repeat;
+}
+ul.plastic li.arrow a.active {
+ background-image: url(img/chevron.png);
+ background-position: right center;
+ background-repeat: no-repeat;
+}
+ul.plastic li.forward {
+ background-image: url(img/chevron_circle.png);
+ background-position: right center;
+ background-repeat: no-repeat;
+}
+ul.plastic li.forward a.active {
+ background-image: url(img/chevron_circle.png);
+ background-position: right center;
+ background-repeat: no-repeat;
+}
+/* @group Metal */
+ul.metal {
+ border-bottom: 0;
+ border-left: 0;
+ border-right: 0;
+ border-top: 0;
+ margin: 0;
+}
+ul.metal li {
+ background-image: none;
+ border-top: 1px solid #fff;
+ border-bottom: 1px solid #666;
+ font-size: 26px;
+ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(238,238,238,1)), to(rgba(156,158,160,1)));
+}
+ul.metal li a {
+ line-height: 26px;
+ margin: 0;
+ text-shadow: #fff 0 1px 0;
+ padding: 13px 0;
+}
+ul.metal li a em {
+ display: block;
+ font-size: 14px;
+ font-style: normal;
+ color: #444;
+ width: 50%;
+ line-height: 14px;
+}
+ul.metal li a.active {
+ color: rgb(0,0,0);
+}
+ul.metal li small {
+ float: right;
+ position: relative;
+ margin-top: 10px;
+ font-weight: bold;
+}
+ul.metal li.arrow {
+ background-image: url(img/chevron.png);
+ background-position: right center;
+ background-repeat: no-repeat;
+ background-image: url(img/chevron.png), -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(238,238,238,1)), to(rgba(156,158,160,1)));
+ background-repeat: no-repeat;
+ background-position: right center;
+}
+ul.metal li.arrow a small {
+ padding-right: 15px;
+ line-height: 17px;
+}
+/* @end */
diff --git a/asset/jqtouch/themes/jqt/theme.min.css b/asset/jqtouch/themes/jqt/theme.min.css
new file mode 100644
index 0000000..bbcdf9b
--- /dev/null
+++ b/asset/jqtouch/themes/jqt/theme.min.css
@@ -0,0 +1 @@
+body{background:#000;color:#ddd;}body>*{background:-webkit-gradient(linear,0% 0,0% 100%,from(#333),to(#5e5e65));}h1,h2{font:bold 18px Helvetica;text-shadow:rgba(255,255,255,.2) 0 1px 1px;color:#000;margin:10px 20px 5px;}.toolbar{-webkit-box-sizing:border-box;border-bottom:1px solid #000;padding:10px;height:45px;background:url(img/toolbar.png) #000 repeat-x;position:relative;}.black-translucent .toolbar{margin-top:20px;}.toolbar>h1{position:absolute;overflow:hidden;left:50%;top:10px;line-height:1em;margin:1px 0 0 -75px;height:40px;font-size:20px;width:150px;font-weight:bold;text-shadow:rgba(0,0,0,1) 0 -1px 1px;text-align:center;text-overflow:ellipsis;white-space:nowrap;color:#fff;}body.landscape .toolbar>h1{margin-left:-125px;width:250px;}.button,.back,.cancel,.add{position:absolute;overflow:hidden;top:8px;right:10px;margin:0;border-width:0 5px;padding:0 3px;width:auto;height:30px;line-height:30px;font-family:inherit;font-size:12px;font-weight:bold;color:#fff;text-shadow:rgba(0,0,0,0.5) 0 -1px 0;text-overflow:ellipsis;text-decoration:none;white-space:nowrap;background:none;-webkit-border-image:url(img/button.png) 0 5 0 5;}.blueButton{-webkit-border-image:url(img/blueButton.png) 0 5 0 5;border-width:0 5px;}.back{left:6px;right:auto;padding:0;max-width:55px;border-width:0 8px 0 14px;-webkit-border-image:url(img/back_button.png) 0 8 0 14;}.back.active{-webkit-border-image:url(img/back_button_clicked.png) 0 8 0 14;color:#aaa;}.leftButton,.cancel{left:6px;right:auto;}.add{font-size:24px;line-height:24px;font-weight:bold;}.whiteButton,.lightButton,.grayButton{display:block;border-width:0 12px;padding:10px;text-align:center;font-size:20px;font-weight:bold;text-decoration:inherit;color:inherit;}.whiteButton{-webkit-border-image:url(img/whiteButton.png) 0 12 0 12;text-shadow:rgba(255,255,255,0.7) 0 1px 0;}.lightButton{-webkit-border-image: url(img/lightButton.png) 0 12 0 12;text-shadow: rgba(51, 51, 51, 0.7) 0 1px 0;}.grayButton{-webkit-border-image:url(img/grayButton.png) 0 12 0 12;color:#FFF;}h1+ul,h2+ul,h3+ul,h4+ul,h5+ul,h6+ul{margin-top:0;}ul{color:#aaa;border:1px solid #333;font:bold 18px Helvetica;padding:0;margin:15px 10px 17px 10px;}ul.rounded{-webkit-border-radius:8px;-webkit-box-shadow:rgba(0,0,0,.3) 1px 1px 3px;}ul.rounded li:first-child,ul.rounded li:first-child a{border-top:0;-webkit-border-top-left-radius:8px;-webkit-border-top-right-radius:8px;}ul.rounded li:last-child,ul.rounded li:last-child a{-webkit-border-bottom-left-radius:8px;-webkit-border-bottom-right-radius:8px;}ul li{color:#666;border-top:1px solid #333;border-bottom:#555858;list-style-type:none;padding:10px 10px 10px 10px;background:-webkit-gradient(linear,0% 0,0% 100%,from(#4c4d4e),to(#404142));overflow:hidden;}ul li.arrow{background-image:url(img/chevron.png),-webkit-gradient(linear,0% 0,0% 100%,from(#4c4d4e),to(#404142));background-position:right center;background-repeat:no-repeat;}ul li.forward{background-image:url(img/chevron_circle.png),-webkit-gradient(linear,0% 0,0% 100%,from(#4c4d4e),to(#404142));background-position:right center;background-repeat:no-repeat;}ul li a,li.img a+a{color:#fff;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;padding:12px 10px 12px 10px;margin:-10px;-webkit-tap-highlight-color:rgba(0,0,0,0);text-shadow:rgba(0,0,0,.2) 0 1px 1px;}ul li a.active,ul li a.button{background-color:#53b401;color:#fff;}ul li a.active.loading{background-image:url(img/loading.gif);background-position:95% center;background-repeat:no-repeat;}ul li.arrow a.active{background-image:url(img/chevron.png);background-position:right center;background-repeat:no-repeat;}ul li.forward a.active{background-image:url(img/chevron_circle.png);background-position:right center;background-repeat:no-repeat;}ul li.img a+a{margin:-10px 10px -20px -5px;font-size:17px;font-weight:bold;}ul li.img a+a+a{font-size:14px;font-weight:normal;margin-left:-10px;margin-bottom:-10px;margin-top:0;}ul li.img a+small+a{margin-left:-5px;}ul li.img a+small+a+a{margin-left:-10px;margin-top:-20px;margin-bottom:-10px;font-size:14px;font-weight:normal;}ul li.img a+small+a+a+a{margin-left:0!important;margin-bottom:0;}ul li a+a{color:#000;font:14px Helvetica;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;margin:0;padding:0;}ul li a+a+a,ul li.img a+a+a+a,ul li.img a+small+a+a+a{color:#666;font:13px Helvetica;margin:0;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;padding:0;}ul.form li{padding:7px 10px;}ul.form li.error{border:2px solid red;}ul.form li.error+li.error{border-top:0;}ul li input[type="text"],ul li input[type="number"], ul li input[type="email"], ul li input[type="password"],ul li textarea,ul li select{color:#777;background:transparent url(../.png);border:0;font:normal 17px Helvetica;padding:0;display:inline-block;margin-left:0;width:100%;-webkit-appearance:textarea;}ul li textarea{height:120px;padding:0;text-indent:-2px;}ul li select{text-indent:0;background:transparent url(img/chevron.png) no-repeat right center;-webkit-appearance:textfield;margin-left:-6px;width:104%;}ul li input[type="checkbox"],ul li input[type="radio"]{margin:0;padding:10px 10px;}ul li input[type="checkbox"]:after,ul li input[type="radio"]:after{content:attr(title);font:17px Helvetica;display:block;width:246px;color:#777;margin:-12px 0 0 17px;}ul li small{color:#64c114;font:17px Helvetica;text-align:right;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;display:block;width:23%;float:right;padding:0;}ul li.arrow small{padding:0 15px;}ul li small.counter{font-size:17px;line-height:13px;font-weight:bold;background:rgba(0,0,0,.15);color:#fff;-webkit-border-radius:11px;padding:4px 10px 5px 10px;display:block;width:auto;margin-top:-22px;-webkit-box-shadow:rgba(255,255,255,.1) 0 1px 0;}ul li.arrow small.counter{margin-right:15px;}ul.individual{border:0;background:none;clear:both;overflow:hidden;padding-bottom:3px;-webkit-box-shadow:none;}ul.individual li{background:#4c4d4e;border:1px solid #333;font-size:14px;text-align:center;-webkit-border-radius:8px;-webkit-box-sizing:border-box;width:48%;float:left;display:block;padding:11px 10px 14px 10px;-webkit-box-shadow:rgba(0,0,0,.2) 1px 1px 3px;background:-webkit-gradient(linear,0% 0,0% 100%,from(#4c4d4e),to(#404142));}ul.individual li+li{float:right;}ul.individual li a{color:#fff;line-height:16px;margin:-11px -10px -14px -10px;padding:11px 10px 14px 10px;-webkit-border-radius:8px;}.toggle{width:94px;position:relative;height:27px;display:block;overflow:hidden;float:right;}.toggle input[type="checkbox"]:checked{left:0;}.toggle input[type="checkbox"]{-webkit-appearance:textarea;-webkit-border-radius:5px;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-transition:left .15s;background-color:transparent;background:#fff url(img/on_off.png) 0 0 no-repeat;border:0;height:27px;left:-55px;margin:0;overflow:hidden;position:absolute;top:0;width:149px;}.info{background:-webkit-gradient(linear,0% 0,0% 100%,from(#ccc),to(#aaa),color-stop(.6,#CCC));font-size:12px;line-height:16px;text-align:center;text-shadow:rgba(255,255,255,.8) 0 1px 0;color:#444;padding:15px;border-top:1px solid rgba(255,255,255,.2);font-weight:bold;}ul.edgetoedge{border-width:1px 0;margin:0;padding:0;}ul.edgetoedge li{background:-webkit-gradient(linear,0% 0,0% 100%,from(#1e1f21),to(#272729));border-bottom:2px solid #000;border-top:1px solid #4a4b4d;font-size:20px;margin-bottom:-1px;}ul.edgetoedge li.sep{background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(0,0,0,0)),to(rgba(0,0,0,.5)));border-bottom:1px solid #111113;border-top:1px solid #666;color:#3e9ac3;font-size:16px;margin:1px 0 0 0;padding:2px 10px;text-shadow:#000 0 1px 0;}ul.edgetoedge li em{font-weight:normal;font-style:normal;}#plastic{background:#17181a;}ul.plastic{background:#17181a;color:#aaa;font:bold 18px Helvetica;margin:0;padding:0;border-width:0 0 1px 0;}ul.plastic li{border-width:1px 0;border-style:solid;border-top-color:#222;border-bottom-color:#000;color:#666;list-style-type:none;overflow:hidden;padding:10px 10px 10px 10px;}ul.plastic li a.active.loading{background-image:url(img/loading.gif);background-position:95% center;background-repeat:no-repeat;}ul.plastic li small{color:#888;font-size:13px;font-weight:bold;line-height:24px;text-transform:uppercase;}ul.plastic li:nth-child(odd){background-color:#1c1c1f;}ul.plastic li.arrow{background-image:url(img/chevron.png);background-position:right center;background-repeat:no-repeat;}ul.plastic li.arrow a.active{background-image:url(img/chevron.png);background-position:right center;background-repeat:no-repeat;}ul.plastic li.forward{background-image:url(img/chevron_circle.png);background-position:right center;background-repeat:no-repeat;}ul.plastic li.forward a.active{background-image:url(img/chevron_circle.png);background-position:right center;background-repeat:no-repeat;}ul.metal{border-bottom:0;border-left:0;border-right:0;border-top:0;margin:0;}ul.metal li{background-image:none;border-top:1px solid #fff;border-bottom:1px solid #666;font-size:26px;background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(238,238,238,1)),to(rgba(156,158,160,1)));}ul.metal li a{color:#333;line-height:26px;margin:0;text-shadow:#fff 0 1px 0;padding:13px 0;}ul.metal li a em{display:block;font-size:14px;font-style:normal;color:#444;width:50%;line-height:14px;}ul.metal li a.active{color:#000;}ul.metal li small{float:right;position:relative;margin-top:10px;font-weight:bold;}ul.metal li.arrow{background-image:url(img/chevron.png);background-position:right center;background-repeat:no-repeat;background-image:url(img/chevron.png),-webkit-gradient(linear,0% 0,0% 100%,from(rgba(238,238,238,1)),to(rgba(156,158,160,1)));background-repeat:no-repeat;background-position:right center;}ul.metal li.arrow a small{padding-right:15px;line-height:17px;}
\ No newline at end of file
diff --git a/asset/js/iphone.js b/asset/js/iphone.js
new file mode 100644
index 0000000..2c8fbc9
--- /dev/null
+++ b/asset/js/iphone.js
@@ -0,0 +1,268 @@
+var app = {
+ login:function ($form) {
+ $.ajax({
+ type:$form.attr("method"),
+ url:$form.attr("action"),
+ dataType:"html",
+ data:$form.serialize(),
+ success: function (data){
+ // $('body').append(data);
+ jQT.appendPages(data, 'ignore');
+ },
+ complete:function (req) {
+ if (req.status === 200 || req.status === 304) {
+ app.bindList('list-st0');
+ app.bindList('list-st1');
+ app.bindList('list-st2');
+ jQT.goTo('#main', 'fade');
+ $(".logout").tap(function (e) {
+ return app.logout();
+ });
+ // $('.details').css('color','#f00').tap(app.loadTaskDetails(this));
+ } else {
+ alert("There was an error logging in. Try again.");
+ }
+ }
+ });
+ return false;
+ },
+ logout:function() {
+ $.ajax({
+ type:'get',
+ url:APP_LOGOUT,
+ success:function() {
+ },
+ complete:function() {
+ $('#login').bind('pageAnimationEnd', function(event, info){
+ $('.dyn').remove();
+ $(this).unbind('pageAnimationEnd');
+ })
+ jQT.goTo('#login','fade');
+ }
+ });
+ return false;
+ },
+ bindList: function(id) {
+ console.log('wiring list #'+id);
+ $('#'+id).bind('pageAnimationEnd',function(){
+ app.clearView();
+ });
+ $('#'+id+' a.details').tap(function() {
+ var td = $(this).attr('rel');
+ console.log('load '+td+' details ...');
+ app.view(td);
+ });
+ },
+ /* VIEW TASK */
+ view:function(id) {
+ console.log('lets view dis #'+id+' bitch');
+ $.ajax({
+ type:'get',
+ url:APP_VIEW+id,
+ dataType:'json',
+ success: function(data) {
+ // details
+ $('#dv_id').val(data.info.id);
+ $('#dv_title').html(data.info.title);
+ $('#dv_note').html(data.info.note);
+ $('#dv_deadline').html(data.info.deadline);
+ $('#dv_priority').html(data.info.priority);
+ $('#dv_spent').html(data.info.total);
+ // time stamps
+ var ll = $('#details-spent ul');
+ $.each(data.spent, function(k,v) {
+ ll.append(''+k+''+v+' ');
+ });
+ // action (running or not)
+ if (data.running) {
+ $('#dv_action').val('stop');
+ $('#dv_stop').removeClass('hide');
+ } else {
+ $('#dv_action').val('start');
+ $('#dv_start').removeClass('hide');
+ }
+ },
+ complete: function() {
+ // jQT.goTo('#view','slide');
+ }
+ });
+ return false;
+ },
+ /* REACT TO ACTION FROM VIEW */
+ viewAction:function(lnk) {
+ var $form = $(lnk).closest("form");
+ var $id = $form.attr('id').substr(8);
+ console.log('ID1='+$id);
+ $.ajax({
+ type:'post',
+ url:$form.attr('action'),
+ data:$form.serialize(),
+ dataType:"html",
+ success: function (data) {
+ el = $('#running')[0];
+ if (el) {
+ $('#running').replaceWith(data);
+ } else {
+ $('#main .toolbar').after(data);
+ }
+ },
+ complete:function (req) {
+ if (req.status === 200 || req.status === 304) {
+ jQT.goBack();
+ } else {
+ alert("Error updating task !");
+ }
+ }
+ });
+ return false;
+ },
+ /* CLEAR VIEW (after going back to list) */
+ clearView:function() {
+ $('#dv_id').val(0);
+ $('#dv_action').val('');
+ $('#dv_title').html('...');
+ $('#dv_note').html('...');
+ $('#dv_deadline').html('...');
+ $('#dv_priority').html('...');
+ $('#dv_spent').html('...');
+ $('#details-spent ul').empty();
+ $('#dv_start').addClass('hide');
+ $('#dv_stop').addClass('hide');
+ },
+ /* EDIT TASK */
+ edit:function() {
+ var id = $('#dv_id').val();
+ console.log('lets edit dis #'+id+' bitch');
+ $.ajax({
+ type:'get',
+ url:APP_EDIT+id,
+ dataType:'json',
+ success: function(data) {
+ $('#i_id').val(data.id);
+ $('#i_title').val(data.title);
+ $('#i_note').val(data.note);
+ $('#i_deadline').val(data.deadline);
+ $('#i_priority').val(data.priority);
+ $('#i_status').val(data.status);
+ },
+ complete: function() {
+ // jQT.goTo('#edit','flip');
+ }
+ });
+ return false;
+ },
+ /* SAVE TASK */
+ editAction:function ($form) {
+ var i = $('#i_id').val();
+ var w = $('#i_status').val();
+ $.ajax({
+ type:$form.attr("method"),
+ url:$form.attr("action"),
+ dataType:"html",
+ data:$form.serialize(),
+ success: function (data){
+ jQT.goBack();
+ },
+ complete:function (req) {
+ switch (req.status) {
+ case 200:
+ case 304:
+ if (i) {
+ // task been updated
+ app.view(i);
+ }
+ // jQT.goBack();
+ break;
+ default:
+ alert("There was an error saving the task.");
+ }
+ window.setTimeout(function() {
+ app.reloadMain();
+ app.clearEdit();
+ },500);
+ }
+ });
+ return false;
+ },
+ /* CLEAR EDIT FORM */
+ clearEdit: function() {
+ $("#edit :input").val('');
+ $("#i_priority").val(5);
+ $("#i_status").val(0);
+ return true;
+ },
+ /* ACTION ON CURRENT TASK */
+ taskAction:function(lnk) {
+ var act = lnk.href.substr(lnk.href.lastIndexOf('#')+1);
+ $('#runaction').val(act);
+ var $form = $('#running');
+ $.ajax({
+ type:'post',
+ url:$form.attr('action'),
+ data:$form.serialize(),
+ dataType:"html",
+ success: function (data) {
+ $('#running').replaceWith(data);
+ },
+ complete:function (req) {
+ if (req.status === 200 || req.status === 304) {
+ } else {
+ alert("Error updating task !");
+ }
+ }
+ });
+ return false;
+ },
+ reloadMain:function() {
+ $.ajax({
+ type:'get',
+ url:APP_RELOAD,
+ dataType:'html',
+ success: function(data) {
+ jQT.appendPages(data, 'ignore');
+ // -TODO- bind links ?
+ }
+ });
+ }
+};
+
+
+jQuery(function () {
+ // login form
+ $("#login a.login").tap(function (e) {
+ var $form = $(this).closest("form");
+ return app.login($form);
+ });
+ $("#login").submit(function (e) {
+ var $form = $(this);
+ return app.login($form);
+ });
+ // logout button
+ $(".logout").tap(function (e) {
+ return app.logout();
+ });
+ // view actions
+ $(".react").tap(function (e) {
+ return app.viewAction(this);
+ });
+ // edit button (on view)
+ $("#details a.modify").click(function(e){
+ app.edit();
+ });;
+ // edit form
+ $("#edit a.save").tap(function (e) {
+ var $form = $(this).closest("form");
+ return app.editAction($form);
+ });
+ $("#edit").submit(function (e) {
+ var $form = $(this);
+ return app.editAction($form);
+ });
+ $('#edit a.back').click(function (e) {
+ return app.clearEdit();
+ });
+ // bind list (if logged in)
+ app.bindList('list-st0');
+ app.bindList('list-st1');
+ app.bindList('list-st2');
+});
\ No newline at end of file
diff --git a/lib/class/app.php b/lib/class/app.php
index 28224b6..ed9917d 100644
--- a/lib/class/app.php
+++ b/lib/class/app.php
@@ -26,7 +26,7 @@ abstract class AppController extends Pluginable {
* constructor
* @param mixed $login is user login required
*/
- public function __construct($login=false) {
+ public function __construct($login=false, $iphone=false) {
parent::__construct();
// get front controller instance
@@ -35,10 +35,21 @@ abstract class AppController extends Pluginable {
// instantiate page
$this->page = new PageModel();
+ // detect iphone
+ if (preg_match('/'.APP_IPHONE_AGENT.'/', $_SERVER['HTTP_USER_AGENT']) && !$iphone) {
+ NaviHelper::redirect($this->fc->getUrl('iphone'));
+ }
+
// check login ?
if ($login && APP_SETUP_USER_MODEL) {
if (!$this->fc->user->isLoggedIn()) {
- NaviHelper::redirect($this->fc->getUrl('login'));
+ if (is_string($login)) {
+ if ($this->fc->controller != StringHelper::flatToCamel($login,true) || $this->fc->action != 'login') {
+ NaviHelper::redirect($this->fc->getUrl($login,'login'));
+ }
+ } else {
+ NaviHelper::redirect($this->fc->getUrl('login'));
+ }
}
}
}
@@ -66,6 +77,16 @@ abstract class AppController extends Pluginable {
include APP_VIEW_PATH.$this->view.'.php';
}
+ protected function viewIPhone() {
+ $this->page->iphoneHeader();
+ include APP_VIEW_PATH.$this->view.'.php';
+ $this->page->dispatchFooter();
+ }
+
+ protected function viewRaw() {
+ include APP_VIEW_PATH.$this->view.'.php';
+ }
+
/**
* include another view (called within a view)
* @todo search in other folders, such as plugins
diff --git a/lib/class/db_connector.php b/lib/class/db_connector.php
index d9e4b0a..1c473a0 100644
--- a/lib/class/db_connector.php
+++ b/lib/class/db_connector.php
@@ -4,7 +4,7 @@
*
* @package tzn_core_classes
* @author Stan Ozier
- * @version 0.1
+ * @version 0.5
* @copyright GNU Lesser General Public License (LGPL) version 3
*/
@@ -156,7 +156,7 @@ class DbConnector { // extends HelpableSingleton
// if critical, should at least show an error code in browser
$debug = ($this->critical && $this->debug < 2)?2:$this->debug;
- $html = '';
+ $htm = '';
$str = 'DB Error #'.$this->connector->getErrorNo().' : '.$this->connector->getErrorMsg();
switch ($debug) {
case 2:
diff --git a/lib/class/model.php b/lib/class/model.php
index 6cbb250..9a83923 100644
--- a/lib/class/model.php
+++ b/lib/class/model.php
@@ -4,7 +4,7 @@
*
* @package tzn_core_classes
* @author Stan Ozier
- * @version 0.4
+ * @version 0.5
* @copyright GNU Lesser General Public License (LGPL) version 3
*/
@@ -568,6 +568,11 @@ abstract class VarAbstract
{
abstract public static function sanitize($val, &$info);
+ public static function sani($val) {
+ $tmp = array();
+ return static::sanitize($val, $tmp);
+ }
+
public static function get($val) {
return $val;
}
@@ -673,6 +678,7 @@ class VarDte extends VarAbstract
return '0000-00-00';
}
if (preg_match('/^[0|2|9][0|1|9][0-9]{2}\-[0-1][0-9]\-[0-3][0-9]$/', $val)) {
+ // SQL format, return as it is (no timezone evaluation)
return $val;
}
if (!$GLOBALS['config']['datetime']['us_format']) {
@@ -698,7 +704,7 @@ class VarDte extends VarAbstract
public static function html($val, $format='', $default='') {
if (!$format) {
- $format = $format = $GLOBALS['config']['datetime']['us_format']?APP_DATE_USA:APP_DATE_EUR;;
+ $format = $format = $GLOBALS['config']['datetime']['us_format']?APP_DATE_USA:APP_DATE_EUR;
}
$t = VarDte::strToUnix($val);
if ($t === false) {
@@ -733,8 +739,10 @@ class VarDte extends VarAbstract
if ($t === false) {
return false;
}
+ $t += self::getUserTimeZoneOffset();
return $t;
}
+
}
/**
@@ -812,7 +820,7 @@ class VarTim extends VarDur
return 0;
}
if (preg_match('/^[0-9]+$/', $val)) {
- // number of seconds, must be coming from SQL
+ // must come from SQL (number of seconds) return as it is (ignore timezone)
return intval($val);
}
if (preg_match('/^([0-2]?[0-9])\:([0-5][0-9])(\:([0-5][0-9]))?$/', $val, $arr)) {
@@ -856,7 +864,7 @@ class VarDtm extends VarAbstract
return '0000-00-00 00:00:00';
}
if (preg_match('/^[0|2|9][0|1|9][0-9]{2}\-[0-1][0-9]\-[0-3][0-9]( ([0-2][0-9]\:[0-5][0-9])(\:[0-5][0-9])?)?$/', $val)) {
- // SQL format, return it as it is
+ // SQL format, return as it is (no timezone evaluation)
return $val;
}
if ($val == 'NOW') {
@@ -926,14 +934,7 @@ class VarDtm extends VarAbstract
$t += self::getUserTimeZoneOffset();
return $t;
}
-
- /**
- * work on date format to return human readable value
- */
- public static function workout($val, $seconds=true) {
- $val += self::getUserTimeZoneOffset();
- return parent::workout($val);
- }
+
}
/**
diff --git a/lib/helper/auth.php b/lib/helper/auth.php
index d031433..2f2c7da 100644
--- a/lib/helper/auth.php
+++ b/lib/helper/auth.php
@@ -279,21 +279,21 @@ class AuthHelper extends Helper {
return false;
}
$arrVal = explode(":",$_COOKIE['auto_login']);
- $id = VarUid::sanitize($arrVal[0]);
- $salt = VarStr::sanitize($arrVal[1]);
+ $id = VarUid::sani($arrVal[0]);
+ $salt = VarStr::sani($arrVal[1]);
if (!$id || !$salt) {
return false;
}
- if ($this->obj->load($this->dbUid(true)."='".$id
- ."' AND ".$this->dbField('salt', $salt)." AND "
- .$this->dbField('auto_login',1)." AND ".$this->dbField('enabled',1))
+ if ($this->obj->load($this->obj->dbUid(true)."='".$id
+ ."' AND ".$this->obj->dbField('salt', $salt)." AND "
+ .$this->obj->dbField('auto_login',1)." AND ".$this->obj->dbField('enabled',1))
) {
if (!$forReal) {
return true;
}
setCookie('auto_login',$this->obj->getUid().":".$this->obj->get('salt')
,time()+(3600*24*30));
- $this->activateLogin();
+ $this->_activateLogin();
return true;
} else {
return false;
@@ -304,7 +304,7 @@ class AuthHelper extends Helper {
*/
public function setAutoLogin() {
if (($this->obj->getUid()) && ($this->obj->get('salt'))) {
- setCookie('autoLogin',$this->obj->getUid().":".$this->obj->get('salt')
+ setCookie('auto_login',$this->obj->getUid().":".$this->obj->get('salt')
,time()+(3600*24*30));
$this->obj->set('auto_login','1');
$this->obj->fields('auto_login');
@@ -318,7 +318,7 @@ class AuthHelper extends Helper {
*/
public function resetAutoLogin() {
if (($this->obj->getUid()) && ($this->obj->get('salt'))) {
- setCookie('autoLogin');
+ setCookie('auto_login');
if ($this->obj->get('auto_login')) {
$this->obj->set('auto_login', 0);
$this->obj->fields('auto_login');
diff --git a/lib/helper/db.php b/lib/helper/db.php
index 0bde014..f323891 100644
--- a/lib/helper/db.php
+++ b/lib/helper/db.php
@@ -4,7 +4,7 @@
*
* @package tzn_helpers
* @author Stan Ozier
- * @version 0.2
+ * @version 0.5
* @since 0.1
* @copyright GNU Lesser General Public License (LGPL) version 3
*/
@@ -32,6 +32,10 @@ class DbHelper extends Helper implements Callable {
$this->table = $table;
}
+ public static function factory() {
+ return new DbHelper(null, '');
+ }
+
// ----- INSERTion queries ---------------------------------------------------
public function save() {
@@ -133,6 +137,7 @@ class DbHelper extends Helper implements Callable {
public function load($filter='', $auto=true) {
if ($auto) {
$this->buildSelect();
+ $this->buildFrom();
}
if ($this->buildWhere($filter)) {
$this->qry->where($filter);
@@ -157,8 +162,9 @@ class DbHelper extends Helper implements Callable {
public function loadList($auto=true) {
if ($auto) {
$this->buildSelect();
+ $this->buildFrom();
+ $this->obj->all();
}
- $this->obj->all();
if ($data = $this->db->query($this->qry->build())) {
$this->idx = 0;
$this->total = 0;
@@ -180,6 +186,13 @@ class DbHelper extends Helper implements Callable {
return false;
}
+ /**
+ * query database and return result set directly
+ */
+ public function loadRaw() {
+ return $this->db->query($this->qry->build());
+ }
+
public function count() {
return count($this->rows);
}
@@ -190,7 +203,9 @@ class DbHelper extends Helper implements Callable {
public function next() {
if (array_key_exists($this->idx, $this->rows)) {
- $this->obj->set($this->rows[$this->idx]);
+ if (is_a($this->obj, 'Model')) {
+ $this->obj->set($this->rows[$this->idx]);
+ }
$this->idx++;
return true;
} else {
@@ -287,6 +302,12 @@ class DbHelper extends Helper implements Callable {
$select = $this->buildFields();
// add SELECT clause
$this->qry->select($select);
+ }
+
+ /**
+ * build FROM clause
+ */
+ public function buildFrom() {
// add FROM clause
$this->qry->from($this->dbTable());
}
diff --git a/lib/helper/html_asset.php b/lib/helper/html_asset.php
index d3f2e65..f2c7544 100644
--- a/lib/helper/html_asset.php
+++ b/lib/helper/html_asset.php
@@ -4,7 +4,7 @@
*
* @package tzn_helpers
* @author Stan Ozier
- * @version 0.3
+ * @version 0.5
* @since 0.1
* @copyright GNU Lesser General Public License (LGPL) version 3
*/
@@ -17,9 +17,11 @@
class HtmlAssetHelper extends Collectable {
protected $css, $cssCode, $js, $jsCode, $jsEditor, $jsCalendar, $jsOnLoad, $rss;
+ protected $_jsInHeader;
public function __construct() {
parent::__construct();
+ $this->_jsInHeader = false;
}
protected function _init($key,$reset=false) {
@@ -31,7 +33,7 @@ class HtmlAssetHelper extends Collectable {
}
}
- public function headerStuff() {
+ public function headerStuff($full=false) {
if (count($this->jsCalendar)) {
$this->add('css',APP_WWW_URI.'asset/css/calendar.css');
@@ -85,6 +87,12 @@ class HtmlAssetHelper extends Collectable {
if (count($this->cssCode)) {
echo implode("\n",$this->cssCode)."\n";
}
+
+ // javascript external scripts (if specifically requested)
+ if ($full) {
+ $this->_jsInHeader = true;
+ $this->_javascript();
+ }
// javascrpt direct code
if (count($this->jsCode)) {
@@ -119,6 +127,12 @@ class HtmlAssetHelper extends Collectable {
}
public function footerStuff() {
+ if (!$this->_jsInHeader) {
+ $this->_javascript();
+ }
+ }
+
+ protected function _javascript() {
// javascript (include)
if (count($this->js)) {
foreach($this->js as $it) {
diff --git a/lib/helper/html_form.php b/lib/helper/html_form.php
index 7e1417c..520a4c2 100644
--- a/lib/helper/html_form.php
+++ b/lib/helper/html_form.php
@@ -347,25 +347,36 @@ class HtmlFormHelper extends Helper {
}
$timezone_identifiers = DateTimeZone::listIdentifiers();
- $str = '';
+ $arrTz = $arrCt = array();
$continent = '';
foreach( $timezone_identifiers as $value ) {
- if ( preg_match( '/^(America|Antartica|Arctic|Asia|Atlantic|Europe|Indian|Pacific)\//', $value ) ) {
- $ex=explode("/",$value);//obtain continent,city
- if ($continent!=$ex[0]){
- if ($continent!="") echo '';
- $str .= '';
- }
- $city=$ex[1];
- $continent=$ex[0];
+ if (!preg_match( '/^(Africa|America|Antartica|Arctic|Asia|Atlantic|Australia|Europe|Indian|Pacific)\//', $value )) {
+ continue;
+ }
+ $arrZn = explode('/', $value);
+ if ($continent != $arrZn[0]) {
+ if (count($arrCt)) {
+ ksort($arrCt);
+ $arrTz[$continent] = $arrCt;
+ }
+ $continent = $arrZn[0];
+ $arrCt = array();
+ }
+ $city = str_replace('_',' ',(count($arrZn)>2)?$arrZn[2]:$arrZn[1]);
+ $arrCt[$city] = $value;
+ }
+ $str = '';
+ foreach( $arrTz as $continent => $arrCt ) {
+ $str .= '';
+ foreach($arrCt as $city => $value) {
$str .= '';
}
+ $str .= ' ';
}
- $str .= ' ';
return $str.' ';
}
diff --git a/lib/helper/json.php b/lib/helper/json.php
new file mode 100644
index 0000000..88aced0
--- /dev/null
+++ b/lib/helper/json.php
@@ -0,0 +1,31 @@
+
+ * @version 0.5
+ * @since 0.5
+ * @copyright GNU Lesser General Public License (LGPL) version 3
+ */
+
+/**
+ * JsonHelper
+ *
+ * JSON format helper to export/import data in JSON format
+ */
+class JsonHelper extends Helper {
+
+ public function __construct($obj) {
+ parent::__construct($obj);
+ }
+
+ public function export($method='html') {
+ $arr = $this->obj->getFields();
+ $data = array();
+ foreach ($arr as $key => $type) {
+ $data[$key] = $this->obj->$method($key);
+ }
+ return json_encode($data);
+ }
+}
diff --git a/lib/helper/string.php b/lib/helper/string.php
index b58e5b5..e28d514 100644
--- a/lib/helper/string.php
+++ b/lib/helper/string.php
@@ -75,4 +75,28 @@ class StringHelper {
}
return $strCode;
}
+
+ /**
+ * convert string to XML friendly string (no space, no special caracters)
+ */
+ public static function cleanStrip($str) {
+ $str = trim($str);
+ if ($str) {
+ /*
+ if (constant('APP_CHARSET') == 'UTF-8') {
+ $str = utf8_decode($str);
+ }
+ */
+ $str = utf8_decode($str);
+ $str = preg_replace(
+ array('/[éèêë]/','/[àáâä]/','/[ìíîï]/','/[ùúûü]/','/[öôòø]/','/[ç‡]/','/[ \'\?\/\\&"]/'),
+ array('e','a','i','u','o','c','-'),
+ strtolower($str));
+ $str = preg_replace('/[^a-z0-9\-]/','_',$str);
+ $str = str_replace('---','-',$str);
+ $str = trim($str,'_');
+ $str = trim($str,'-');
+ }
+ return $str;
+ }
}
\ No newline at end of file
diff --git a/lib/lang/de/common.php b/lib/lang/de/common.php
new file mode 100644
index 0000000..7e4b382
--- /dev/null
+++ b/lib/lang/de/common.php
@@ -0,0 +1,250 @@
+ 'Neuer Eintrag',
+ 'read' => 'Diesen Eintrag lesen',
+ 'view' => 'Details anzeigen',
+ 'modify' => 'Eintrag ändern',
+ 'delete' => 'Diesen Eintrag löschen',
+ 'delete_confirm' => 'Diesen Eintrag wirklich löschen?',
+ 'remove' => 'Diesen Eintrag entfernen',
+ 'remove_confirm' => 'Wirklich aus der Liste entfernen?',
+ 'search' => 'Suchen',
+ 'next' => 'Nächste',
+ 'previous' => 'Vorherige',
+ 'next_page' => 'Nächste Seite',
+ 'previous_page' => 'Vorherige Seite',
+ 'all' => 'Alle',
+ 'more' => 'Mehr',
+ 'less' => 'Weniger',
+ 'item_found' => 'Gefundener Eintrag',
+ 'items_found' => 'Gefundene Einträge',
+ 'empty' => 'Keine Daten verfügbar'
+);
+
+$GLOBALS['lang']['message'] = array(
+ 'saved' => 'Daten erfolgreich gespeichert',
+ 'created' => 'Daten erfolgreich erstellt',
+ 'updated' => 'Daten erfolgreich aktualisiert',
+ 'deleted' => 'Daten erfolgreich gelöscht',
+ 'removed' => 'Daten erfolgreich entfernt'
+);
+
+$GLOBALS['lang']['error'] = array(
+ 'db_no_connection' => 'Es konnte keine Verbindung zur Datenbank hergestellt werden',
+ 'db_no_database' => 'Datenbank nicht gefunden',
+ 'db_sql_error' => 'Fehler bei der Datenbank-Anfrage',
+ 'sql_injection' => 'Mögliche SQL-Injection intendiert',
+ 'search_empty' => 'Leider konnte kein Eintrag gefunden werden',
+ 'not_found' => 'Daten nicht gefunden',
+ 'login_failed' => 'Login fehlgeschlagen',
+ 'access_denied' => 'Zugriff verweigert',
+ 'data_denied' => 'Zugriff auf Daten verweigert',
+ 'not_found_denied' => 'Daten nicht gefunden oder Zugriff verweigert',
+ 'action_failed' => 'Die angeforderte Aktion konnte nicht ausgeführt werden',
+ 'form_error' => 'Formular enthält Fehler',
+ 'compulsory_field' => 'Information erforderlich',
+ 'account_disabled' => 'Account ist deaktiviert',
+ 'account_expired' => 'Account ist abgelaufen',
+ 'account_not_found' => 'Account existiert nicht',
+ 'username_required' => 'Bitte geben Sie einen Benutzernamen ein',
+ 'username_not_found' => 'Benutzername existiert nicht',
+ 'username_invalid' => 'Kein gültiger Benutzername (vermeiden Sie Sonder- oder Leerzeichen)',
+ 'username_length' => 'Der Benutzername muss aus mindestens '.APP_USER_NAME_MIN.' und maximal '.APP_USER_NAME_MAX.' Zeichen bestehen',
+ 'email_not_found' => 'E-Mail existiert nicht',
+ 'password_required' => 'Passwort erforderlich',
+ 'password_invalid' => 'Ungültiges Passwort',
+ 'password_length' => 'Passwort muss aus mindestens '.APP_USER_PASS_MIN.' and maximal '.APP_USER_PASS_MAX.' Zeichen betsehen',
+ 'password_mismatch' => 'Passwort und Überprüfung stimmen nicht überein',
+ 'password_recover' => 'Passwort kann nicht wiederhergestellt werden',
+ 'field_length' => 'Zu kurz oder zu lang',
+ 'field_exists' => 'Dieser Eintrag existiert bereits',
+ 'field_invalid' => 'Eintrag ist ungültig',
+ 'field_mismatch' => 'Einträge stimmen nicht überein',
+ 'invalid_date' => 'Ungültiges Datum',
+ 'invalid_time' => 'Ungültige Zeit',
+ 'invalid_email' => 'E-Mail-Adresse ist ungültig',
+ 'invalid_duration' => 'Ungültige Dauer',
+ 'file_wrong_type' => 'Falscher Dateityp',
+ 'file_empty' => 'Bitte wählen Sie eine Datei aus',
+ 'none_checked' => 'Bitte wählen Sie mindestens einen Eintrag'
+);
+
+$GLOBALS['lang']['security'] = array(
+ 'login' => 'Anmeldung',
+ 'logout' => 'Abmeldung',
+ 'sign_in' => 'Kein Mitglied? Melden Sie sich jetzt an!',
+ 'my_account' => 'Mein Account',
+ 'account' => 'Account',
+ 'account_active' => 'Account ist aktiviert',
+ 'account_not_active' => 'Account ist nicht aktiviert',
+ 'account_enabled' => 'Account ist freigegeben',
+ 'visit_count' => 'Besuche',
+ 'visit_fail_count' => 'Fehlgeschlagene Anmeldeversuche',
+ 'access_denied' => 'Zugriff verweigert',
+ 'permission_denied' => 'Erlaubnis verweigert',
+ 'session_expired' => 'Ihre Session ist abgelaufen',
+ 'login_last_date' => 'Leztes Anmeldedatum',
+ 'login_last_address' => 'Letzte Anmeldeadresse'
+);
+
+$GLOBALS['lang']['form'] = array(
+ 'compulsory' => 'obligatorisch',
+ 'username' => 'Benutzername',
+ 'password' => 'Passwort',
+ 'password_confirm' => '(Überprüfung)',
+ 'auto_login' => 'Login-Daten auf diesem Computer speichern',
+ 'password_legend' => 'Geben Sie ein Passwort ein (und bestätigen Sie es) nur dann, wenn Sie es ändern möchten.',
+ 'name' => 'Name',
+ 'category' => 'Kategorie',
+ 'title' => 'Titel',
+ 'last_name' => 'Nachname',
+ 'middle_name' => 'Zweiter Vorname',
+ 'first_name' => 'Vorname',
+ 'nick_name' => 'Spitzname',
+ 'address' => 'Adresse',
+ 'location' => 'Ort',
+ 'city' => 'Stadt',
+ 'state' => 'Bundesland',
+ 'state_us_only' => 'nur für US-Bürger',
+ 'country' => 'Land',
+ 'time_zone' => 'Zeitzone',
+ 'user_rights' => 'Berechtigungen',
+ 'email' => 'E-Mail',
+ 'subject' => 'Betreff',
+ 'body' => 'Textkörper',
+ 'comment' => 'Kommentar',
+ 'in' => 'In',
+ 'out' => 'Aus',
+ 'from' => 'Von',
+ 'to' => 'An',
+ 'cc' => 'CC',
+ 'url' => 'URL',
+ 'website' => 'Webseite',
+ 'description' => 'Beschreibung',
+ 'user' => 'Benutzer',
+ 'member' => 'Mitglied',
+ 'author' => 'Autor',
+ 'status' => 'Status',
+ 'file' => 'Datei',
+ 'image' => 'Bild',
+ 'thumbnail' => 'Vorschau',
+ 'document' => 'Dokument',
+ 'file_legend' => 'Bitte wählen Sie eine Datei durch Klicken des \'Browse..\'-Buttons',
+ 'file_name' => 'Dateiname',
+ 'file_size' => 'Dateigröße',
+ 'file_type' => 'Dateityp',
+ 'date' => 'Datum',
+ 'deadline' => 'Deadline',
+ 'start' => 'Start',
+ 'stop' => 'Stop',
+ 'publish_date' => 'Veröffentlichen',
+ 'post_date' => 'Absenden',
+ 'creation_date' => 'Erstellungsdatum',
+ 'last_change_date' => 'Letzte Aktualisierung',
+ 'last_visit_date' => 'Letzter Besuch',
+ 'last_visit_addr' => 'Von',
+ 'posted_on' => 'Abgesendet am',
+ 'published on' => 'Veröffentlicht am',
+ 'by' => 'von',
+ 'action' => 'Aktion'
+);
+
+// buttons
+$GLOBALS['lang']['button'] = array(
+ 'add' => 'Hinzufügen',
+ 'create' => 'Erstellen',
+ 'edit' => 'Bearbeiten',
+ 'submit' => 'Abschicken',
+ 'login' => 'Anmelden',
+ 'save' => 'Speichern',
+ 'save_changes' => 'Änderungen speichern',
+ 'save_and_add' => 'Speichern und weitere hinzufügen',
+ 'save_and_close' => 'Speichern und schließen',
+ 'update' => 'Aktualisieren',
+ 'cancel' => 'Änderungen aufheben',
+ 'close' => 'Schließen',
+ 'reset' => 'Formular zurücksetzen',
+ 'delete' => 'Löschen',
+ 'remove' => 'Entfernen',
+ 'start' => 'Start',
+ 'stop' => 'Stopp',
+ 'enable' => 'Freigeben',
+ 'disable' => 'Sperren',
+ 'activate' => 'Aktivieren',
+ 'deactivate' => 'Deaktivieren',
+ 'next_step' => 'Nächster Schritt',
+ 'previous_step' => 'Vorheriger Schritt',
+ 'back' => 'Zurückgehen',
+ 'back_to_list' => 'Zurück zur Liste'
+);
+
+$GLOBALS['lang']['date'] = array(
+ 'future_pre' => 'in', // eg. "in" 2 days
+ 'future_app' => '', // ie. when keyword needs to be appended to the date
+ 'past_pre' => 'vor', // eg. "il y a" 2 jours (french)
+ 'past_app' => '', // eg. 2 days "ago"
+ 'yesterday' => 'Gestern',
+ 'today' => 'Heute',
+ 'tomorrow' => 'Morgen',
+ 'days' => 'Tage',
+ 'day' => 'Tag',
+ 'weeks' => 'Wochen',
+ 'week' => 'Woche',
+ 'months' => 'Monate',
+ 'month' => 'Monat',
+ 'years' => 'Jahre',
+ 'year' => 'Jahr',
+ 'hour' => 'Stunde',
+ 'hours' => 'Stunden',
+ 'minute' => 'Minute',
+ 'minutes' => 'Minuten',
+ 'second' => 'Sekunde',
+ 'seconds' => 'Sekunden',
+ 'january' => 'Januar',
+ 'february' => 'Februar',
+ 'march' => 'März',
+ 'april' => 'April',
+ 'may' => 'Mai',
+ 'june' => 'Juni',
+ 'july' => 'Juli',
+ 'august' => 'August',
+ 'september' => 'September',
+ 'october' => 'Oktober',
+ 'november' => 'November',
+ 'december' => 'Dezember',
+ 'jan' => 'Jan',
+ 'feb' => 'Feb',
+ 'mar' => 'Mär',
+ 'apr' => 'Apr',
+ 'may' => 'Mai',
+ 'jun' => 'Jun',
+ 'jul' => 'Jul',
+ 'aug' => 'Aug',
+ 'sep' => 'Sep',
+ 'oct' => 'Okt',
+ 'nov' => 'Nov',
+ 'dec' => 'Dez',
+ 'monday' => 'Montag',
+ 'tuesday' => 'Dienstag',
+ 'wednesday' => 'Mittwoch',
+ 'thursday' => 'Donnerstag',
+ 'friday' => 'Freitag',
+ 'saturday' => 'Samstag',
+ 'sunday' => 'Sonntag',
+ 'mon' => 'Mo',
+ 'tue' => 'Di',
+ 'wed' => 'Mi',
+ 'thu' => 'Do',
+ 'fri' => 'Fr',
+ 'sat' => 'Sa',
+ 'sun' => 'So'
+);
diff --git a/lib/lang/de/config.php b/lib/lang/de/config.php
new file mode 100644
index 0000000..9ab229d
--- /dev/null
+++ b/lib/lang/de/config.php
@@ -0,0 +1,15 @@
+
+ * @version 0.4
+ * @copyright GNU Lesser General Public License (LGPL) version 3
+ */
+
+
+$GLOBALS['config']['lang']['specialchars'] = 3;
+$GLOBALS['config']['lang']['ucfirst'] = false;
+
+setLocale(LC_ALL, 'de_DE.UTF-8', 'de_DE', 'de');
\ No newline at end of file
diff --git a/lib/lang/en/common.php b/lib/lang/en/common.php
index cc34949..d04d3fa 100644
--- a/lib/lang/en/common.php
+++ b/lib/lang/en/common.php
@@ -170,7 +170,7 @@ $GLOBALS['lang']['button'] = array(
'save_and_add' => 'save and add more',
'save_and_close' => 'save and close',
'update' => 'update',
- 'cancel' => 'cancel changes',
+ 'cancel' => 'cancel',
'close' => 'close',
'reset' => 'reset form',
'delete' => 'delete',
diff --git a/lib/lang/no/common.php b/lib/lang/no/common.php
new file mode 100755
index 0000000..14b111e
--- /dev/null
+++ b/lib/lang/no/common.php
@@ -0,0 +1,250 @@
+
+ * @version 0.4
+ * @copyright GNU Lesser General Public License (LGPL) version 3
+ */
+
+$GLOBALS['lang']['data'] = array(
+ 'new' => 'ny forekomst',
+ 'read' => 'se på forekomsten',
+ 'view' => 'vis detaljer',
+ 'modify' => 'endre forekomsten',
+ 'delete' => 'slett forekomsten',
+ 'delete_confirm' => 'er du sikker på at du vil slette denne ?',
+ 'remove' => 'fjærn forekomst',
+ 'remove_confirm' => 'er du sikker på at du vil slette denne ?',
+ 'search' => 'søk',
+ 'next' => 'neste',
+ 'previous' => 'forrige',
+ 'next_page' => 'neste side',
+ 'previous_page' => 'forrige side',
+ 'all' => 'alle',
+ 'more' => 'mer',
+ 'less' => 'mindre',
+ 'item_found' => 'forekomst funnet',
+ 'items_found' => 'forekomster funnet',
+ 'empty' => 'ingen data tilgjengelig'
+);
+
+$GLOBALS['lang']['message'] = array(
+ 'saved' => 'data ble lagret',
+ 'created' => 'data ble laget',
+ 'updated' => 'data ble oppdatert',
+ 'deleted' => 'data ble slettet',
+ 'removed' => 'data ble fjernet'
+);
+
+$GLOBALS['lang']['error'] = array(
+ 'db_no_connection' => 'kan ikke koble til databasen',
+ 'db_no_database' => 'databasen ble ikke funnet',
+ 'db_sql_error' => 'feil i database spørring',
+ 'sql_injection' => 'mulig SQL injection angrep',
+ 'search_empty' => 'beklager, fant ingen forekomster',
+ 'not_found' => 'ingen data funnet',
+ 'login_failed' => 'kunne ikke logge inn',
+ 'access_denied' => 'ingen tilgang',
+ 'data_denied' => 'du har ikke tilgang til valgte data',
+ 'not_found_denied' => 'data ikke funnet, eller ingen tilgang',
+ 'action_failed' => 'forespurte oppgave kunne ikke utføres',
+ 'form_error' => 'skjemaet inneholder feil',
+ 'compulsory_field' => 'informasjon påkrevet',
+ 'account_disabled' => 'konto er deaktivert',
+ 'account_expired' => 'konto har foreldet',
+ 'account_not_found' => 'konto eksisterrer ikke',
+ 'username_required' => 'skriv inn brukernavn',
+ 'username_not_found'=> 'brukernavn eksisterer ikke',
+ 'username_invalid' => 'ikke gyldig brukernavn (unngå spesialtegn og/eller mellomrom)',
+ 'username_length' => 'brukernavn må ha mellom '.APP_USER_NAME_MIN.' og '.APP_USER_NAME_MAX.' bokstaver',
+ 'email_not_found' => 'epost eksisterer ikke',
+ 'password_required' => 'passord påkrevet',
+ 'password_invalid' => 'galt passord',
+ 'password_length' => 'passordet må ha mellom '.APP_USER_PASS_MIN.' og '.APP_USER_PASS_MAX.' tegn',
+ 'password_mismatch' => 'passpordene stemmer ikke med hverandre (verifisering)',
+ 'password_recover' => 'passordet kan ikke gjenfinnes',
+ 'field_length' => 'for kort eller lang',
+ 'field_exists' => 'denne forekomsten finnes allerede',
+ 'field_invalid' => 'oppføringen er ikke gyldig',
+ 'field_mismatch' => 'oppføringene stemmer ikke med hverandre',
+ 'invalid_date' => 'ikke gyldig dato',
+ 'invalid_time' => 'ikke gyldig tid',
+ 'invalid_email' => 'ugyldig e-post adresse',
+ 'invalid_duration' => 'ikke gyldig varihet',
+ 'file_wrong_type' => 'gal filtype',
+ 'file_empty' => 'vennligst velg en fil',
+ 'none_checked' => 'vennligst velg minst en enhet'
+);
+
+$GLOBALS['lang']['security'] = array(
+ 'login' => 'logg inn',
+ 'logout' => 'logg ut',
+ 'sign_in' => 'ikke medlem? registrer deg nå!',
+ 'my_account' => 'min konto',
+ 'account' => 'konto',
+ 'account_active' => 'konto er aktivert',
+ 'account_not_active'=> 'konto er ikke aktivert',
+ 'account_enabled' => 'konto er opprettet',
+ 'visit_count' => 'besøk',
+ 'visit_fail_count' => 'feilede innloggingsforsøk',
+ 'access_denied' => 'ingen tilgang',
+ 'permission_denied' => 'ingen rettigheter',
+ 'session_expired' => 'økten er utgått',
+ 'login_last_date' => 'Sist innlogget dato',
+ 'login_last_address'=> 'Sist innlogget fra'
+);
+
+$GLOBALS['lang']['form'] = array(
+ 'compulsory' => 'compulsory',
+ 'username' => 'brukernavn',
+ 'password' => 'passord',
+ 'password_confirm' => '(verifisering)',
+ 'auto_login' => 'husk meg på denne datamaskinen',
+ 'password_legend' => 'skriv et passord (og bekreft) bare dersom du ønsker å ENDRE passord.',
+ 'name' => 'Navn',
+ 'category' => 'Kategori',
+ 'title' => 'tittel',
+ 'last_name' => 'etternavn',
+ 'middle_name' => 'mellomnavn',
+ 'first_name' => 'fornavn',
+ 'nick_name' => 'kallenavn',
+ 'address' => 'adresse',
+ 'location' => 'sted',
+ 'city' => 'by',
+ 'state' => 'fylke',
+ 'state_us_only' => 'Kun for USA',
+ 'country' => 'land',
+ 'time_zone' => 'tidssone',
+ 'user_rights' => 'rettigheter',
+ 'email' => 'epost',
+ 'subject' => 'tittel',
+ 'body' => 'innhold',
+ 'comment' => 'kommentar',
+ 'in' => 'inn',
+ 'out' => 'ut',
+ 'from' => 'fra',
+ 'to' => 'til',
+ 'cc' => 'kopi',
+ 'url' => 'URL',
+ 'website' => 'webside',
+ 'description' => 'beskrivelse',
+ 'user' => 'bruker',
+ 'member' => 'medlem',
+ 'author' => 'forfatter',
+ 'status' => 'status',
+ 'file' => 'fil',
+ 'image' => 'bilde',
+ 'thumbnail' => 'miniatyrbilde',
+ 'document' => 'dokument',
+ 'file_legend' => 'vennligst velg en fil ved å trykke \'Browse..\' knappen',
+ 'file_name' => 'filnavn',
+ 'file_size' => 'fil størrelse',
+ 'file_type' => 'fil type',
+ 'date' => 'dato',
+ 'deadline' => 'deadline',
+ 'start' => 'start',
+ 'stop' => 'stop',
+ 'publish_date' => 'publiser',
+ 'post_date' => 'post',
+ 'creation_date' => 'opprettet dato',
+ 'last_change_date' => 'sist oppdatert',
+ 'last_visit_date' => 'sist besøkt',
+ 'last_visit_addr' => 'fra',
+ 'posted_on' => 'postet på',
+ 'published on' => 'publisert på',
+ 'by' => 'av',
+ 'action' => 'handling'
+);
+
+// buttons
+$GLOBALS['lang']['button'] = array(
+ 'add' => 'legg til',
+ 'create' => 'lag',
+ 'edit' => 'endre',
+ 'submit' => 'send',
+ 'login' => 'logg inn',
+ 'save' => 'lagre',
+ 'save_changes' => 'lagre endringer',
+ 'save_and_add' => 'lagre og legg til mer',
+ 'save_and_close' => 'slagre og lukk',
+ 'update' => 'oppdater',
+ 'cancel' => 'avbryt endringer',
+ 'close' => 'lukk',
+ 'reset' => 'tilbakestill skjema',
+ 'delete' => 'slett',
+ 'remove' => 'fjern',
+ 'start' => 'start',
+ 'stop' => 'stop',
+ 'enable' => 'aktiver',
+ 'disable' => 'deaktiver',
+ 'activate' => 'aktiver',
+ 'deactivate' => 'deaktiver',
+ 'next_step' => 'neste steg',
+ 'previous_step' => 'forrige steg',
+ 'back' => 'tilbake',
+ 'back_to_list' => 'tilbake til listen'
+);
+
+$GLOBALS['lang']['date'] = array(
+ 'future_pre' => 'om', // eg. "in" 2 days
+ 'future_app' => '', // ie. when keyword needs to be appended to the date
+ 'past_pre' => '', // eg. "il y a" 2 jours (french)
+ 'past_app' => 'siden', // eg. 2 days "ago"
+ 'yesterday' => 'i går',
+ 'today' => 'i dag',
+ 'tomorrow' => 'i morgen',
+ 'days' => 'dager',
+ 'day' => 'dag',
+ 'weeks' => 'uker',
+ 'week' => 'uke',
+ 'months' => 'måneder',
+ 'month' => 'måned',
+ 'years' => 'Ã¥r',
+ 'year' => 'Ã¥r',
+ 'hour' => 'time',
+ 'hours' => 'timer',
+ 'minute' => 'minutt',
+ 'minutes' => 'minutter',
+ 'second' => 'sekund',
+ 'seconds' => 'sekunder',
+ 'january' => 'januar',
+ 'february' => 'februar',
+ 'march' => 'mars',
+ 'april' => 'april',
+ 'may' => 'mai',
+ 'june' => 'juni',
+ 'july' => 'juli',
+ 'august' => 'august',
+ 'september' => 'september',
+ 'october' => 'oktober',
+ 'november' => 'november',
+ 'december' => 'desember',
+ 'jan' => 'jan',
+ 'feb' => 'feb',
+ 'mar' => 'mar',
+ 'apr' => 'apr',
+ 'may' => 'mai',
+ 'jun' => 'jun',
+ 'jul' => 'jul',
+ 'aug' => 'aug',
+ 'sep' => 'sep',
+ 'oct' => 'okt',
+ 'nov' => 'nov',
+ 'dec' => 'des',
+ 'monday' => 'mandag',
+ 'tuesday' => 'tirsdag',
+ 'wednesday' => 'onsdag',
+ 'thursday' => 'torsdag',
+ 'friday' => 'fredag',
+ 'saturday' => 'lørdag',
+ 'sunday' => 'søndag',
+ 'mon' => 'man',
+ 'tue' => 'tirs',
+ 'wed' => 'ons',
+ 'thu' => 'tors',
+ 'fri' => 'fre',
+ 'sat' => 'lør',
+ 'sun' => 'søn'
+);
\ No newline at end of file
diff --git a/lib/lang/no/config.php b/lib/lang/no/config.php
new file mode 100755
index 0000000..fb7a554
--- /dev/null
+++ b/lib/lang/no/config.php
@@ -0,0 +1,15 @@
+
+ * @version 0.4
+ * @copyright GNU Lesser General Public License (LGPL) version 3
+ */
+
+
+$GLOBALS['config']['lang']['specialchars'] = 3;
+$GLOBALS['config']['lang']['ucfirst'] = false;
+
+setLocale(LC_ALL, 'en_NO.UTF-8', 'no_NO.utf8', 'no_NO', 'no_BM.utf8', 'no_BM', 'no');
diff --git a/lib/model/page.php b/lib/model/page.php
index 08c8b2c..3195161 100644
--- a/lib/model/page.php
+++ b/lib/model/page.php
@@ -4,7 +4,7 @@
*
* @package tzn_models
* @author Stan Ozier
- * @version 0.2
+ * @version 0.5
* @since 0.1
* @copyright GNU Lesser General Public License (LGPL) version 3
*/
@@ -39,6 +39,10 @@ class PageModel extends Model {
include APP_ASSET_PATH.'html/page-header.php';
}
+ public function iphoneHeader() {
+ include APP_ASSET_PATH.'html/iphone-header.php';
+ }
+
public function dispatchFooter() {
include APP_ASSET_PATH.'html/page-footer.php';
}
diff --git a/skin/default/css/iphone.css b/skin/default/css/iphone.css
new file mode 100644
index 0000000..030eeae
--- /dev/null
+++ b/skin/default/css/iphone.css
@@ -0,0 +1,168 @@
+/* login */
+form p {
+ padding: 5px 10px 50px;
+}
+ul.form li {
+ padding: 7px 10px;
+}
+ul.form li.error {
+ color: #c33;
+ font-weight: normal;
+ font-size: .80em;
+ text-align: center;
+ border: 0 none;
+}
+/* current task */
+form.highlight {
+ border-bottom: 0;
+ border-left: 0;
+ border-right: 0;
+ border-top: 0;
+ margin: 0;
+ padding: 0 10px 5px;
+ background-image: none;
+ border-top: 1px solid #fff;
+ border-bottom: 1px solid #666;
+ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(238,238,238,1)), to(rgba(156,158,160,1)));
+}
+form.highlight h3 {
+ font-size: 18px;
+ line-height: 22px;
+ margin: 0;
+ text-shadow: #fff 0 1px 0;
+ padding: 10px 0;
+}
+form.highlight h3 a {
+ display: block;
+ color: #333;
+ text-decoration: none;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ text-align: center;
+}
+form p.dual, form p.triple {
+ clear: both;
+ overflow: hidden;
+ padding-bottom: 3px;
+}
+form p.dual span, form p.triple span {
+ float: left;
+ text-align: center;
+ -webkit-box-sizing: border-box;
+ width: 48%;
+ display: block;
+ padding: 11px 10px 14px 10px;
+}
+form p.dual span + span {
+ float: right;
+}
+form p.triple span {
+ width: 31%;
+}
+form p.triple span + span {
+ margin-left: 3%;
+}
+form p.triple span + span + span {
+ float: right;
+}
+form p.dual span a, form p.triple span a {
+ color: #fff;
+ font-size: 14px;
+ line-height: 16px;
+ margin: -11px -10px -14px -10px;
+ padding: 11px 10px 14px 10px;
+}
+/* more fields */
+ul li {
+ color: #999;
+}
+ul li.note {
+ font-size: 14px;
+ text-align: justify;
+}
+ul li input[type="text"], ul li input[type="password"], ul li textarea, ul li select,
+ul li input[type="number"], ul li input[type="email"] {
+ color: #777;
+ background-color: transparent;
+ background-image: none;
+ border: 0 none;
+ font: normal 17px Helvetica;
+ padding: 3px 1px;
+ display: inline-block;
+ margin-left: 0px;
+ width: 100%;
+ -webkit-appearance: textarea;
+}
+/* buttons */
+button {
+ background-color: transparent;
+}
+.whiteButton,
+.lightButton,
+.darkButton,
+.blackButton {
+ display: block;
+ border-width: 0 12px;
+ padding: 10px;
+ text-align: center;
+ font-size: 20px;
+ font-weight: bold;
+ text-decoration: inherit;
+ color: #fff;
+}
+.whiteButton {
+ text-shadow: rgba(51, 51, 51, 0.7) 0 1px 0;
+}
+.lightButton {
+ -webkit-border-image: url(../img/lightButton.png) 0 12 0 12;
+ text-shadow: rgba(51, 51, 51, 0.7) 0 1px 0;
+}
+.darkButton {
+ -webkit-border-image: url(../img/darkButton.png) 0 12 0 12;
+ text-shadow: rgba(0, 0, 0, 0.7) 0 1px 0;
+}
+.blackButton {
+ -webkit-border-image: url(../../../asset/jqtouch/themes/jqt/img/grayButton.png) 0 12 0 12;
+ color: #FFFFFF;
+}
+.logout, .modify {
+ position: absolute;
+ overflow: hidden;
+ top: 8px;
+ right: 10px;
+ margin: 0;
+ border-width: 0 5px;
+ padding: 0 3px;
+ width: auto;
+ height: 30px;
+ line-height: 30px;
+ font-family: inherit;
+ font-size: 12px;
+ font-weight: bold;
+ color: #fff;
+ text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0;
+ text-overflow: ellipsis;
+ text-decoration: none;
+ white-space: nowrap;
+ background: none;
+ -webkit-border-image: url(../../../asset/jqtouch/themes/jqt/img/button.png) 0 5 0 5;
+}
+.logout {
+ left: 6px;
+ right: auto;
+ padding: 0;
+ max-width: 55px;
+}
+.hide {
+ display: none;
+}
+/* bottom info bar */
+.info a {
+ color: #633;
+}
+.bottom {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+}
\ No newline at end of file
diff --git a/skin/default/img/darkButton.png b/skin/default/img/darkButton.png
new file mode 100644
index 0000000..1853bed
Binary files /dev/null and b/skin/default/img/darkButton.png differ
diff --git a/skin/default/img/iphone_icon.png b/skin/default/img/iphone_icon.png
new file mode 100644
index 0000000..82abb2d
Binary files /dev/null and b/skin/default/img/iphone_icon.png differ
diff --git a/skin/default/img/iphone_startup.png b/skin/default/img/iphone_startup.png
new file mode 100644
index 0000000..7193923
Binary files /dev/null and b/skin/default/img/iphone_startup.png differ
diff --git a/skin/default/img/lightButton.png b/skin/default/img/lightButton.png
new file mode 100644
index 0000000..287166a
Binary files /dev/null and b/skin/default/img/lightButton.png differ