version 0.5 (1)

This commit is contained in:
Stan Ozier 2010-07-17 02:16:29 +02:00
parent b7a883778d
commit 9dc73a3943
89 changed files with 4546 additions and 65 deletions

View File

@ -1,6 +1,6 @@
TaskFreak! Time Tracking
------------------------
version : 0.4
version : 0.5
Requirements

View File

@ -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

View File

@ -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,

View File

@ -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 <small>%H:%M</small>");
// --- 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',

View File

@ -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')));
@ -154,3 +156,11 @@ if (@constant('APP_TRANS_ID')) {
ini_set('session.use_trans_sid', 0);
ini_set('session.use_only_cookies', 1);
}
// ---- 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');

View File

@ -1,7 +1,7 @@
<?php
define('APP_DB_HOST','localhost');
define('APP_DB_USER','root'); // edit here
define('APP_DB_USER','test'); // edit here
define('APP_DB_PASS',''); // edit here
define('APP_DB_BASE','taskfreak_timer'); // edit here
define('APP_DB_PREFIX','');

View File

@ -101,11 +101,9 @@ class Admin extends AppController {
if ($this->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');

450
app/controller/iphone.php Normal file
View File

@ -0,0 +1,450 @@
<?php
/**
* TaskFreak! Time Tracker
*
* @package taskfreak_tt
* @author Stan Ozier <taskfreak@gmail.com>
* @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 '<script>';
echo 'app.editClear();';
echo '</script>';
/*
// 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 '<script type="text/javascript">app.logout();</script>';
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 '<div id="'.$name.'" class="dyn">';
echo '<div class="toolbar">';
echo '<h1>'.$title.'</h1>';
echo '<a href="#" class="back">Back</a>';
echo '<a href="#edit" class="button new flip">New</a>';
echo '</div>';
if ($data) {
echo '<ul class="rounded">';
while ($data->next()) {
$data->chkDeadline();
// $link = $this->fc->getUrl('iphone','detail',array('id'=>$data->getUid()));
echo '<li class="arrow t-'.$data->getUid().'">'
.'<a href="#details" class="details" rel="'.$data->getUid().'">'.$data->html('title').'</a>'
.'<a href="#details" class="details" rel="'.$data->getUid().'"><em>'
.$data->htmlStatus().'</em> '.$data->get('priority').') '.$data->htmlDeadline().'</a>'
.'</li>';
}
echo '</ul>';
} else {
echo '<ul class="edgtoedge"><li>No task</li></ul>';
}
// echo '<script type="text/javascript">$("#'.$name.' .edit").tap(function (e) {return app.edit(this);});';
$this->incView('iphone/inc_foot');
// echo '<script>app.bindList("'.$name.'");</script>';
echo '</div>';
}
}

120
app/lang/de/freak.php Normal file
View File

@ -0,0 +1,120 @@
<?php
/**
* TaskFreak!
*
* @package taskfreak
* @author IST planbar GmbH - www.istplanbar.de (Lars Wohlfahrt, Franziska Hauser)
* @version 0.4
* @copyright GNU General Public License (GPL) version 3
*/
$GLOBALS['lang']['task'] = array(
'priority' => '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;

View File

@ -0,0 +1,19 @@
<p>Geben Sie eine Aufgabe pro Zeile ein.</p>
<h4>Aufgaben-Format</h4>
<p>Aufgaben-Format : [date] [priority] [label :] Aufgaben-Titel<br />
<small>Felder in Klammern sind optional</small></p>
<p><em>Datum</em> kann sein :</p>
<ul>
<li>ein Datum im Format dd/mm[/yy]</li>
<li>ein + gefolgt von einer Anzahl an Einheiten für die Zukunft</li>
<li>ein - bedeutet, dass es keine Deadline gibt</li>
<li>nichts bedeutet, dass die Deadline heute ist</li>
</ul>
<p><em>Priorität</em> ist eine Zahl zwischen 1 und 9, gefolgt von einer )<br />
<small>&laquo; 1) &raquo; für dringende Aufgaben, &laquo; 5) &raquo; für normale Priorität</small></p>
<p><em>Bezeichnung</em> ist optional</p>
<h4>Standards für mehrere Aufgaben</h4>
<p>eine Zeile angefangen mit einem * richtet Standards ein</p>
<p>Format ist : * [date] [label]<br />
<small>&laquo; * +1 Aufgabe &raquo; der &laquo; * 12/04 &raquo;</small></p>
<p>Standards zurücksetzen durch eine Zeile mit &laquo; ** &raquo;</p>

View File

@ -0,0 +1,8 @@
<p>Geben Sie eine der folgenden Möglichkeiten ein:</p>
<ul>
<li>Nur einen Startzeitpunkt (berechnet die Zeit von damals bis heute) </li>
<li>Nur einen Zeitaufwand (überprüft, ob Sie die Aufgabe beendet haben)</li>
<li>Einen Startzeitpunkt und einen Endzeitpunkt</li>
<li>Einen Startzeitpunkt und einen Zeitaufwand</li>
<li>Einen Endzeitpunkt und einen Zeitaufwand</li>
</ul>

123
app/lang/no/freak.php Executable file
View File

@ -0,0 +1,123 @@
<?php
/**
* TaskFreak!
*
* @package taskfreak
* @author Stan Ozier <taskfreak@gmail.com>
* @version 0.4
* @copyright GNU General Public License (GPL) version 3
*
* @languagePack Norwegian | Norsk
* @translator Hans Hovde <hhovde@yahoo.com>
*/
$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;

View File

@ -0,0 +1,19 @@
<p>Skriv en oppgave pr. linje.</p>
<h4>Oppgave format:</h4>
<p>Oppgave format : [dato] [prioritet] [label :] oppgave overskrift<br />
<small>felter innenfor [rammer] er frivillig</small></p>
<p><em>dato</em> kan være :</p>
<ul>
<li>en dato i formatet dd/mm[/åå]</li>
<li>plusstegn (+) etterfulgt av antall dager frem i tid</li>
<li>minustegn (-) dersom du ikke ønsker deadline</li>
<li>tomt felt gir dedline dagens dato</li>
</ul>
<p><em>prioritet</em> er et nummer mellom 1 og 9, etterfulgt av )<br />
<small>&laquo; 1) &raquo; for kritiske gjøremål, &laquo; 5) &raquo; for normal prioritet</small></p>
<p><em>label</em> er valgfri</p>
<h4>Standarder for flere oppgaver</h4>
<p>en linje som starter med * angir standard verdi</p>
<p>Formatet er : * [dato] [label]<br />
<small>&laquo; * +1 taskfreak &raquo; eller &laquo; * 12/04 &raquo;</small></p>
<p>tilbakestill standarder med en linje som starter med &laquo; ** &raquo;</p>

View File

@ -0,0 +1,8 @@
<p>Skriv enten :</p>
<ul>
<li>Kun starttid (kalkulerer tiden fra start frem til )</li>
<li>Tidsforbruk (Tar høyde for at du nettopp har avsluttet oppgaven)</li>
<li>Start tid og stop tid</li>
<li>Start tid og forbrukt tid</li>
<li>Stopp tid og forbrukt tid</li>
</ul>

View File

@ -4,7 +4,7 @@
*
* @package taskfreak_tt
* @author Stan Ozier <taskfreak@gmail.com>
* @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).' &gt; '.$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
*/

View File

@ -4,7 +4,7 @@
*
* @package taskfreak_tt
* @author Stan Ozier <taskfreak@gmail.com>
* @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'";

View File

@ -5,7 +5,7 @@ $this->incView('include/page-top', false);
<div id="dmain" class="full">
<div id="dfilters">
<span>
<a href="<?php echo $this->fc->getUrl('admin/edit');?>" class="ajax box new inv" title="<?php TR::phtml('ui','create_user'); ?>"><?php TR::phtml('ui','create_user'); ?></a>
<a href="<?php echo $this->fc->getUrl('admin','edit');?>" class="ajax box new inv" title="<?php TR::phtml('ui','create_user'); ?>"><?php TR::phtml('ui','create_user'); ?></a>
</span>
<ul class="links horiz">
<?php

View File

@ -3,7 +3,7 @@
<div id="dfoot">
<div id="dcopy">
<a href="http://www.taskfreak.com" target="_blank">TaskFreak</a>
<span>TT v0.3</span>
<span>TT v0.5</span>
</div>
<?php
$err = false;

22
app/view/iphone/edit.php Normal file
View File

@ -0,0 +1,22 @@
<form id="edit" action="<?php echo $this->fc->getUrl('iphone','edit'); ?>" method="post">
<div class="toolbar">
<h1>Edit task</h1>
<a href="#" class="back">Cancel</a>
</div>
<ul class="edit rounded">
<li><input id="i_title" type="text" name="title" placeholder="<?php TR::phtml('form','title'); ?>" value="" /></li>
<li><textarea id="i_note" type="text" name="note" placeholder="<?php TR::phtml('task','note'); ?>"></textarea></li>
</ul>
<ul class="edit rounded">
<li><input id="i_deadline" type="number" name="deadline" placeholder="<?php TR::phtml('form','deadline'); ?>" value="" /></li>
<li><?php echo $this->edit->iSelectTranslate('priority','priority'); ?></li>
<li><?php echo $this->edit->iSelectTranslate('status','task'); ?></li>
</ul>
<p>
<input type="hidden" id="i_id" name="id" value="" />
<a href="#" class="save lightButton"><?php TR::phtml('button','save'); ?></a>
</p>
<?php
$this->incView('iphone/inc_foot');
?>
</form>

View File

@ -0,0 +1,9 @@
<div class="info">
<?php
echo $this->fc->user->html('nickname');
/*
| <a href="#login" class="logout slideup"><?php TR::phtml('security','logout'); ?></a>
*/
?>
<br /><small><?php echo VarDtm::html(APP_SQL_NOW,APP_DATETIME_LNX); ?></small>
</div>

View File

@ -0,0 +1,37 @@
<div id="main" class="dyn">
<div class="toolbar">
<h1>TaskFreak!</h1>
<a href="/index.php?c=iphone&a=logout" class="logout out"><?php TR::phtml('security','logout'); ?></a>
</div>
<?php
if ($this->current) {
$this->incView('iphone/inc_timer');
}
?>
<h2>By Status</h2>
<ul class="rounded">
<li class="arrow"><a href="#list-st0"><?php TR::phtml('pages','todo'); ?></a><small class="counter"><?php echo $this->dataTodo->count(); ?></small></li>
<li class="arrow"><a href="#list-st1"><?php TR::phtml('pages','done'); ?></a><small class="counter"><?php echo $this->dataDone->count(); ?></small></li>
<li class="arrow"><a href="#list-st2"><?php TR::phtml('pages','valid'); ?></a><small class="counter"><?php echo $this->dataValid->count(); ?></small></li>
</ul>
<?php
/*
if (count($this->dataTags)) {
?>
<h2>By Tag</h2>
<ul class="rounded">
<?php
foreach ($this->dataTags as $row) {
$tag = trim($row['tag']);
echo '<li class="arrow"><a href="'
.$this->fc->getUrl('iphone','list',array('tag'=>$tag))
.'">'.VarStr::html($tag).'</a></li>';
}
?>
</ul>
<?php
}
*/
$this->incView('iphone/inc_foot');
?>
</div>

View File

@ -0,0 +1,32 @@
<form id="running" action="<?php echo $this->fc->getUrl('iphone','home'); ?>" method="post" class="highlight">
<input type="hidden" name="id" value="<?php echo $this->current->getUid(); ?>" />
<input type="hidden" id="runaction" name="action" value="" />
<h3><a href="#details" onclick="app.view(<?php echo $this->current->getUid(); ?>)" class="pop"><?php echo $this->current->html('title'); ?></a></h3>
<?php
if ($this->current->isEmpty('stop')) {
// task is running
?>
<p class="triple">
<span><a id="b_pause" href="#pause" class="lightButton action"><?php TR::phtml('button','pause'); ?></a></span>
<span><a id="b_stop" href="#stop" class="darkButton action"><?php TR::phtml('button','stop'); ?></a></span>
<span><a id="b_close" href="<?php echo $this->fc->getUrl('iphone','main',array('id'=>$this->current->getUid(),'action'=>'close')); ?>" class="blackButton action" onclick="return confirm('<?php TR::phtml('ui','done_confirm'); ?>')"><?php TR::phtml('button','done'); ?></a></span>
</p>
<?php
} else {
// task is paused (requested from ajax only)
?>
<p class="dual">
<span><a id="b_resume" href="#resume" class="lightButton action"><?php TR::phtml('button','resume'); ?></a></span>
<span><a id="b_stop" href="#stop" class="darkButton action"><?php TR::phtml('button','stop'); ?></a></span>
</p>
<?php
}
?>
<script type="text/javascript">
jQuery(function () {
$(".action").tap(function (e) {
return app.taskAction(this);
});
});
</script>
</form>

18
app/view/iphone/login.php Normal file
View File

@ -0,0 +1,18 @@
<form id="login" action="<?php echo $this->fc->thisUrl(); ?>" method="post" class="current slideup">
<div class="toolbar">
<h1>TaskFreak!</h1>
</div>
<ul class="form rounded">
<?php
if ($str = $this->fc->user->getAuthError()) {
echo '<li class="error">'.TR::html('error',$str).'</li>';
}
?>
<li><input type="text" name="username" value="<?php echo $this->fc->user->value('username'); ?>" placeholder="<?php TR::phtml('form','username'); ?>" /></li>
<li><input type="text" name="password" value="" placeholder="<?php TR::phtml('form','password'); ?>" /></li>
</ul>
<p><button type="submit" name="login" class="darkButton submit slideup"><?php TR::phtml('button','login'); ?></button></p>
<div class="info">
TaskFreak! Time Tracking v0.5
</div>
</form>

34
app/view/iphone/main.php Normal file
View File

@ -0,0 +1,34 @@
<?php
if ($this->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);
}
?>
<form id="login" action="<?php echo $this->fc->getUrl('iphone','login'); ?>" method="post" class="<?php
if (!$this->fc->user->isLoggedIn()) {
echo 'current';
}
?>">
<div class="toolbar">
<h1>TaskFreak!</h1>
</div>
<ul class="form rounded">
<?php
if ($str = $this->fc->user->getAuthError()) {
echo '<li class="error">'.TR::html('error',$str).'</li>';
}
?>
<li><input type="text" name="username" value="<?php echo $this->fc->user->value('username'); ?>" placeholder="<?php TR::phtml('form','username'); ?>" /></li>
<li><input type="text" name="password" value="" placeholder="<?php TR::phtml('form','password'); ?>" /></li>
</ul>
<p><a href="#" class="login lightButton"><?php TR::phtml('button','login'); ?></a></p>
<div class="info bottom">
TaskFreak! Time Tracking v0.5
</div>
</form>
<?php
$this->incView('iphone/edit');
$this->incView('iphone/view');
?>

46
app/view/iphone/view.php Normal file
View File

@ -0,0 +1,46 @@
<form id="details" action="<?php echo $this->fc->getUrl('iphone','detail'); ?>" method="post">
<div class="toolbar">
<h1>Task details</h1>
<a href="#" class="back">Back</a>
<a href="#edit" class="modify flip">Edit</a>
</div>
<ul class="edgetoedge">
<li id="dv_title">...</li>
<li id="dv_note" class="note">...</li>
</ul>
<ul class="rounded">
<li>
Deadline
<small id="dv_deadline">...</small>
</li>
<li>
Priority
<small id="dv_priority">...</small>
</li>
<li class="arrow">
<small id="dv_spent">...</small>
<a href="#details-spent">Time spent</a>
</li>
</ul>
<p>
<input id="dv_id" type="hidden" name="id" value="" />
<input id="dv_action" type="hidden" name="action" value="" />
<span id="dv_stop" class="hide"><a href="#" class="react darkButton"><?php TR::phtml('button','stop'); ?></a></span>
<span id="dv_start" class="hide"><a href="#" class="react lightButton"><?php TR::phtml('button','start'); ?></a></span>
</p>
<?php
$this->incView('iphone/inc_foot');
?>
</form>
<div id="details-spent">
<div class="toolbar">
<h1>Task timesheet</h1>
<a href="#" class="back">Back</a>
<!-- a href="" class="button slideup">+</a -->
</div>
<ul class="rounded">
</ul>
<?php
$this->incView('iphone/inc_foot');
?>
</div>

View File

@ -0,0 +1,97 @@
<?php
// generate timesheet
$total = 0;
$str ='';
if ($this->data->get('spent')) {
$str = '<ul class="rounded">';
do {
$total += $this->data->get('spent');
$str .= '<li>';
// start and stop times
$str .= $this->data->htmlTimes();
// time spent
$str .= '<small>'.$this->data->getTimeSpent().'</small>';
$str .= '</li>';
} while ($this->data->next());
$str .= '<li>'.TR::html('ui','total').'<small>'.TaskSummary::htmlTime($total).'</small></li>';
$str .= '</ul>';
}
?>
<form id="details-<?php echo $this->data->getUid(); ?>" action="<?php echo $this->fc->getUrl('iphone','detail'); ?>" method="post">
<div class="toolbar">
<h1>Task details</h1>
<a href="#" class="back">Back</a>
<a href="<?php echo $this->fc->getUrl('iphone','edit',array('id'=>$this->data->getUid())); ?>" class="modify flip">Edit</a>
</div>
<ul class="edgetoedge">
<li><?php echo $this->data->html('title'); ?></li>
<?php
if (!$this->data->isEmpty('note')) {
?>
<li class="note"><?php echo $this->data->html('note'); ?></li>
<?php
}
?>
</ul>
<ul class="rounded">
<li>
Deadline
<small><?php echo $this->data->htmlDeadline(); ?></small>
</li>
<li>
Priority
<small><?php echo $this->data->htmlPriority(); ?></small>
</li>
<li class="arrow">
<small><?php echo TaskSummary::htmlTime($total); ?></small>
<a href="#details-<?php echo $this->data->getUid(); ?>-spent">Time spent</a>
</li>
</ul>
<p>
<input type="hidden" name="id" value="<?php echo $this->data->getUid(); ?>" />
<?php
if ($this->current && ($this->current->getUid() == $this->data->getUid())) {
// task is currently running
echo '<input type="hidden" name="action" value="stop" />';
echo '<a href="#" class="react darkButton">'.TR::html('button','stop').'</a>';
} else {
// not running, wanna start ?
echo '<input type="hidden" name="action" value="start" />';
echo '<a href="#" class="react lightButton">'.TR::html('button','start').'</a>';
}
?>
</p>
<script>
jQuery(function () {
$(".react").tap(function (e) {
return app.viewAction(this);
});
console.log('wiired');
$("#details-<?php echo $this->data->getUid(); ?> a.modify").css('color','#f00').click(function(e){
console.log('edit clicked');
return app.editAction(this);
});
console.log('wiiiired');
});
</script>
<?php
$this->incView('iphone/inc_foot');
?>
</form>
<div id="details-<?php echo $this->data->getUid(); ?>-spent">
<div class="toolbar">
<h1>Task timesheet</h1>
<a href="#" class="back">Back</a>
<a href="<?php echo $this->fc->getUrl('iphone','timer',array('id'=>$this->data->getUid())); ?>" class="button slideup">+</a>
</div>
<?php
if ($str) {
echo $str;
} else {
echo '<ul class="rounded"><li>'.TR::html('ui','history_empty').'</li></ul>';
}
$this->incView('iphone/inc_foot');
?>
</div>

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
<?php
/*
<link rel="apple-touch-icon-precomposed" href="<?php echo APP_WWW_URI.'skin/'.$GLOBALS['config']['skin'].'/iphone_icon.png'; ?>"/>
<link rel="apple-touch-startup-image" href="<?php echo APP_WWW_URI.'skin/'.$GLOBALS['config']['skin'].'/iphone_startup.png'; ?>" />
*/
?>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title><?php echo $this->html('title'); ?></title>
<?php
/*
if (!$this->isEmpty('description')) {
?>
<meta name="description" content="<?php echo $this->html('description'); ?>" />
<?php
}
if (!$this->isEmpty('keywords')) {
?>
<meta name="keywords" content="<?php echo $this->html('keywords'); ?>" />
<?php
}
*/
$this->callHelper('html_asset','headerStuff', true);
?>
</head>

View File

@ -17,7 +17,7 @@ if (!$this->isEmpty('keywords')) {
}
if (file_exists(APP_WWW_PATH.'favicon.ico')) {
echo '<link rel="SHORTCUT ICON" href="'.APP_WWW_URI.'favicon.ico" />';
echo '<link rel="SHORTCUT ICON" href="'.APP_WWW_URI.'favicon.ico" />'."\n";
}
$this->callHelper('html_asset','headerStuff');

373
asset/jqtouch/jqtouch.css Normal file
View File

@ -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;
}
}

676
asset/jqtouch/jqtouch.js Normal file
View File

@ -0,0 +1,676 @@
/*
_/ _/_/ _/_/_/_/_/ _/
_/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/
_/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/
_/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/
_/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/
_/
_/
Created by David Kaneda <http://www.davidkaneda.com>
Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/>
Special thanks to Jonathan Stark <http://jonathanstark.com/>
and pinch/zoom <http://www.pinchzoom.com/>
(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 += '<link rel="apple-touch-icon' + precomposed + '" href="' + jQTSettings.icon + '" />';
}
// Set startup screen
if (jQTSettings.startupScreen) {
hairextensions += '<link rel="apple-touch-startup-image" href="' + jQTSettings.startupScreen + '" />';
}
// Set viewport
if (jQTSettings.fixedViewport) {
hairextensions += '<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;"/>';
}
// Set full-screen
if (jQTSettings.fullScreen) {
hairextensions += '<meta name="apple-mobile-web-app-capable" content="yes" />';
if (jQTSettings.statusBar) {
hairextensions += '<meta name="apple-mobile-web-app-status-bar-style" content="' + jQTSettings.statusBar + '" />';
}
}
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);

1
asset/jqtouch/jqtouch.min.css vendored Normal file

File diff suppressed because one or more lines are too long

1
asset/jqtouch/jqtouch.min.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 783 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 521 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 B

View File

@ -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;
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 B

View File

@ -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 */

File diff suppressed because one or more lines are too long

268
asset/js/iphone.js Normal file
View File

@ -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('<li>'+k+'<small>'+v+'</small></li>');
});
// 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');
});

View File

@ -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

View File

@ -4,7 +4,7 @@
*
* @package tzn_core_classes
* @author Stan Ozier <framework@tirzen.com>
* @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:

View File

@ -4,7 +4,7 @@
*
* @package tzn_core_classes
* @author Stan Ozier <framework@tirzen.com>
* @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') {
@ -927,13 +935,6 @@ class VarDtm extends VarAbstract
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);
}
}
/**

View File

@ -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');

View File

@ -4,7 +4,7 @@
*
* @package tzn_helpers
* @author Stan Ozier <framework@tirzen.com>
* @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());
}

View File

@ -4,7 +4,7 @@
*
* @package tzn_helpers
* @author Stan Ozier <framework@tirzen.com>
* @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');
@ -86,6 +88,12 @@ class HtmlAssetHelper extends Collectable {
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)) {
echo '<script type="text/javascript">'."\n";
@ -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) {

View File

@ -347,25 +347,36 @@ class HtmlFormHelper extends Helper {
}
$timezone_identifiers = DateTimeZone::listIdentifiers();
$str = '<select id="id_'.$key.'" name="'.$key.'">';
$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 '</optgroup>';
$str .= '<optgroup label="'.$ex[0].'">';
}
$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 = '<select id="id_'.$key.'" name="'.$key.'">';
foreach( $arrTz as $continent => $arrCt ) {
$str .= '<optgroup label="'.$continent.'">';
foreach($arrCt as $city => $value) {
$str .= '<option value="'.$value.'"';
if ($value == $default) {
$str .= ' selected="selected"';
}
$str .='>'.$city.'</option>';
}
$str .= '</optgroup>';
}
$str .= '</optgroup>';
return $str.'</select>';
}

31
lib/helper/json.php Normal file
View File

@ -0,0 +1,31 @@
<?php
/**
* Tzn Framework
*
* @package tzn_helpers
* @author Stan Ozier <framework@tirzen.com>
* @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);
}
}

View File

@ -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;
}
}

250
lib/lang/de/common.php Normal file
View File

@ -0,0 +1,250 @@
<?php
/**
* Tzn Framework
*
* @package tzn_language
* @author IST planbar GmbH - www.istplanbar.de (Lars Wohlfahrt, Franziska Hauser)
* @version 0.4
* @copyright GNU Lesser General Public License (LGPL) version 3
*/
$GLOBALS['lang']['data'] = array(
'new' => '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'
);

15
lib/lang/de/config.php Normal file
View File

@ -0,0 +1,15 @@
<?php
/**
* Tzn Framework
*
* @package tzn_language
* @author Stan Ozier <framework@tirzen.com>
* @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');

View File

@ -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',

250
lib/lang/no/common.php Executable file
View File

@ -0,0 +1,250 @@
<?php
/**
* Tzn Framework
*
* @package tzn_language
* @author Stan Ozier <framework@tirzen.com>
* @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&oslash;rdag',
'sunday' => 's&oslash;ndag',
'mon' => 'man',
'tue' => 'tirs',
'wed' => 'ons',
'thu' => 'tors',
'fri' => 'fre',
'sat' => 'l&oslash;r',
'sun' => 's&oslash;n'
);

15
lib/lang/no/config.php Executable file
View File

@ -0,0 +1,15 @@
<?php
/**
* Tzn Framework
*
* @package tzn_language
* @author Stan Ozier <framework@tirzen.com>
* @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');

View File

@ -4,7 +4,7 @@
*
* @package tzn_models
* @author Stan Ozier <framework@tirzen.com>
* @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';
}

168
skin/default/css/iphone.css Normal file
View File

@ -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%;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB