├── app ├── views │ ├── item │ │ ├── blank.htm │ │ ├── tmenu.htm │ │ ├── create.htm │ │ ├── update.htm │ │ └── list.htm │ ├── breadcrumbs.htm │ ├── tags │ │ ├── list.htm │ │ ├── update.htm │ │ └── items.htm │ ├── cats │ │ ├── cats.htm │ │ ├── update.htm │ │ └── list.htm │ ├── b3.htm │ └── pagination.htm ├── models │ ├── CatGroup.php │ ├── TagGroup.php │ ├── TagList.php │ ├── ItemsTag.php │ ├── Cat.php │ ├── Tag2Item.php │ ├── Tag.php │ └── Item.php └── controllers │ ├── Controller.php │ ├── CategoryController.php │ └── TagController.php ├── ui ├── img │ ├── favicon.png │ ├── ajax-loader.gif │ ├── glyphicons-halflings.png │ └── glyphicons-halflings-white.png ├── fonts │ ├── ubuntu.woff │ ├── FontAwesome.otf │ ├── ubuntu_light.woff │ ├── ubuntu_italic.woff │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.ttf │ └── fontawesome-webfont.woff ├── css │ ├── prettify.css │ ├── main.css │ └── bootstrap-modal.css └── js │ ├── main.js │ ├── track.js │ ├── application.js │ └── bootstrap-modal.js ├── index.php ├── .htaccess ├── lib ├── f3.php ├── code.css ├── log.php ├── test.php ├── db │ ├── mongo.php │ ├── jig.php │ ├── jig │ │ └── session.php │ ├── mongo │ │ ├── session.php │ │ └── mapper.php │ ├── sql │ │ └── session.php │ ├── cursor.php │ └── sql.php ├── bcrypt.php ├── matrix.php ├── web │ ├── geo.php │ ├── pingback.php │ └── openid.php ├── session.php ├── magic.php ├── basket.php ├── audit.php ├── utf.php ├── auth.php ├── smtp.php └── changelog.txt ├── config ├── config.ini └── routes.ini ├── inc └── func.php ├── db └── db.sql └── README.md /app/views/item/blank.htm: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ui/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mwozniak/bookmark-manager/HEAD/ui/img/favicon.png -------------------------------------------------------------------------------- /ui/fonts/ubuntu.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mwozniak/bookmark-manager/HEAD/ui/fonts/ubuntu.woff -------------------------------------------------------------------------------- /ui/img/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mwozniak/bookmark-manager/HEAD/ui/img/ajax-loader.gif -------------------------------------------------------------------------------- /ui/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mwozniak/bookmark-manager/HEAD/ui/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /ui/fonts/ubuntu_light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mwozniak/bookmark-manager/HEAD/ui/fonts/ubuntu_light.woff -------------------------------------------------------------------------------- /ui/fonts/ubuntu_italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mwozniak/bookmark-manager/HEAD/ui/fonts/ubuntu_italic.woff -------------------------------------------------------------------------------- /ui/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mwozniak/bookmark-manager/HEAD/ui/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /ui/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mwozniak/bookmark-manager/HEAD/ui/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /ui/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mwozniak/bookmark-manager/HEAD/ui/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /ui/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mwozniak/bookmark-manager/HEAD/ui/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /ui/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mwozniak/bookmark-manager/HEAD/ui/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | config('config/config.ini'); 8 | $f3->config('config/routes.ini'); 9 | $f3->run(); 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | DirectoryIndex index.php 2 | 3 | RewriteEngine On 4 | RewriteBase / 5 | RewriteCond %{REQUEST_FILENAME} !-l 6 | RewriteCond %{REQUEST_FILENAME} !-f 7 | RewriteCond %{REQUEST_FILENAME} !-d 8 | RewriteRule .* /index.php [L,QSA] 9 | RewriteRule ^config/? index.php [L] 10 | -------------------------------------------------------------------------------- /app/models/CatGroup.php: -------------------------------------------------------------------------------- 1 | load(); 11 | return $this->query; 12 | } 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/views/breadcrumbs.htm: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /app/views/tags/list.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 |
8 | {{ trim(@tg.tag) }} {{ trim(@tg.tagcount) }} 9 | 10 | 11 | 12 |
13 | 14 | 15 |
16 | 17 | 18 |

no tags

19 |
20 | 21 |
22 | 23 | -------------------------------------------------------------------------------- /app/models/TagGroup.php: -------------------------------------------------------------------------------- 1 | load(); 11 | return $this->query; 12 | } 13 | 14 | 15 | public function loadpages($pageoffset,$pagelimit) { 16 | if($pageoffset<0 || $pageoffset>999999999) $pageoffset=0; 17 | $this->load(NULL,array('order'=>'tagcount DESC','offset'=>$pageoffset,'limit'=>$pagelimit)); 18 | return $this->query; 19 | } 20 | 21 | public function tagcount() { 22 | return $this->count(); 23 | 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /app/models/TagList.php: -------------------------------------------------------------------------------- 1 | load(); 11 | $this->copyTo('TAGS'); 12 | return $this->query; 13 | } 14 | 15 | public function getItemTags($tok) { 16 | $this->load(array('itok=?',$tok)); 17 | $this->copyTo('TAGS'); 18 | return $this->query; 19 | } 20 | 21 | public function getCatTags($tok) { 22 | $this->load(array('ctok=?',$tok)); 23 | $this->copyTo('TAGS'); 24 | return $this->query; 25 | } 26 | 27 | } 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/views/cats/cats.htm: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 6 | All bookmarks 7 | {{ @cgall }} 8 | 9 | 10 | 11 | 12 | 13 | 14 | {{ trim(@c.cat) }} 15 | {{ trim(@c.itemcount) }} 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /app/models/ItemsTag.php: -------------------------------------------------------------------------------- 1 | load(array('tagtok=?',$tok)); 11 | $this->copyTo('POST'); 12 | return $this->query; 13 | } 14 | public function loadtagpages($paramstok,$pageoffset,$pagelimit) { 15 | if($pageoffset<0 || $pageoffset>999999999) $pageoffset=0; 16 | $this->load(array('tagtok=?',$paramstok),array('offset'=>$pageoffset,'limit'=>$pagelimit)); 17 | return $this->query; 18 | } 19 | public function tagcount($tok) { 20 | return $this->count(array('tagtok=?',$tok)); 21 | 22 | } 23 | } 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ui/css/prettify.css: -------------------------------------------------------------------------------- 1 | .com { color: #93a1a1; } 2 | .lit { color: #195f91; } 3 | .pun, .opn, .clo { color: #93a1a1; } 4 | .fun { color: #dc322f; } 5 | .str, .atv { color: #D14; } 6 | .kwd, .prettyprint .tag { color: #1e347b; } 7 | .typ, .atn, .dec, .var { color: teal; } 8 | .pln { color: #48484c; } 9 | 10 | .prettyprint { 11 | padding: 8px; 12 | background-color: #f7f7f9; 13 | border: 1px solid #e1e1e8; 14 | } 15 | .prettyprint.linenums { 16 | -webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 17 | -moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 18 | box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0; 19 | } 20 | 21 | /* Specify class=linenums on a pre to get line numbering */ 22 | ol.linenums { 23 | margin: 0 0 0 33px; /* IE indents via margin-left */ 24 | } 25 | ol.linenums li { 26 | padding-left: 12px; 27 | color: #bebec5; 28 | line-height: 20px; 29 | text-shadow: 0 1px 0 #fff; 30 | } -------------------------------------------------------------------------------- /app/controllers/Controller.php: -------------------------------------------------------------------------------- 1 | db); 13 | $this->f3->set('cs',$cats->all()); 14 | 15 | //item count (menu) 16 | $items = new Item($this->db); 17 | $nb = $items->itemcount(); 18 | $this->f3->set('cgall',$nb); 19 | 20 | //category menu 21 | $cgs = new CatGroup($this->db); 22 | $this->f3->set('cgs',$cgs->all()); 23 | 24 | } 25 | 26 | function afterroute() { 27 | echo Template::instance()->render($this->f3->get('tpl')); 28 | } 29 | 30 | function __construct() { 31 | 32 | $f3=Base::instance(); 33 | 34 | $db=new DB\SQL( 35 | $f3->get('db_dns') . $f3->get('db_name'), 36 | $f3->get('db_user'), 37 | $f3->get('db_pass') 38 | ); 39 | 40 | $this->f3=$f3; 41 | $this->db=$db; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/f3.php: -------------------------------------------------------------------------------- 1 | page 4 | GET /c=CategoryController->index 5 | GET /t=TagController->page 6 | GET /c/@tok/@name=CategoryController->catpage 7 | GET /t/@tok/@name=TagController->tagpage 8 | GET /i/@tok/@name=ItemController->item 9 | 10 | GET /i/page/@number=ItemController->page 11 | GET /t/page/@number=TagController->page 12 | GET /t/@tok/page/@number=TagController->tagpage 13 | GET /c/@tok/page/@number=CategoryController->catpage 14 | 15 | GET|POST /i/create=ItemController->create 16 | GET /i/update/@tok=ItemController->update 17 | POST /i/update=ItemController->update 18 | GET /i/delete/@tok=ItemController->delete 19 | 20 | GET|POST /c/create=CategoryController->create 21 | GET /c/update/@tok=CategoryController->update 22 | POST /c/update=CategoryController->update 23 | GET /c/delete/@tok=CategoryController->delete 24 | 25 | GET|POST /t/create=TagController->create 26 | GET /t/update/@tok=TagController->update 27 | POST /t/update=TagController->update 28 | GET /t/delete/@tok=TagController->delete 29 | 30 | POST /search=ItemController->search 31 | GET /q/@query=ItemController->query 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/models/Cat.php: -------------------------------------------------------------------------------- 1 | load(); 11 | return $this->query; 12 | } 13 | 14 | public function add() { 15 | $this->copyFrom('POST'); 16 | $this->save(); 17 | } 18 | 19 | public function getById($id) { 20 | $this->load(array('tok=?',$id)); 21 | $this->copyTo('POST'); 22 | } 23 | 24 | public function catcountByUrl($url) { 25 | return $this->count(array('url=?',$url)); 26 | } 27 | 28 | public function getIdByTok($tok) { 29 | $this->load(array('tok=?',$tok)); 30 | $this->copyTo('ID'); 31 | } 32 | 33 | public function edit($id) { 34 | $this->load(array('tok=?',$id)); 35 | $this->copyFrom('POST'); 36 | $this->update(); 37 | } 38 | public function catcountByTok($tok) { 39 | return $this->count(array('tok=?',$tok)); 40 | 41 | } 42 | public function delete($id) { 43 | $this->load(array('tok=?',$id)); 44 | $this->erase(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/views/tags/update.htm: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 | Update tag 7 | 8 | 9 |
10 | 11 |
12 | 13 | 14 |
15 | 16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
32 | 33 | 34 | 35 |
36 |
37 | 38 |
39 |
40 | -------------------------------------------------------------------------------- /app/models/Tag2Item.php: -------------------------------------------------------------------------------- 1 | load(); 11 | return $this->query; 12 | } 13 | 14 | public function add() { 15 | $this->save(); 16 | } 17 | 18 | public function getById($id) { 19 | $this->load(array('tok=?',$id)); 20 | $this->copyTo('POST'); 21 | } 22 | 23 | public function getByItemId($id) { 24 | $this->load(array('iid=?',$id)); 25 | return $this->query; 26 | } 27 | public function getByTagId($id) { 28 | $this->load(array('tid=?',$id)); 29 | return $this->query; 30 | } 31 | 32 | public function getByName($name) { 33 | $this->load(array('title=?',$name)); 34 | $this->copyTo('TAGS'); 35 | } 36 | 37 | public function edit($id) { 38 | $this->load(array('tok=?',$id)); 39 | $this->copyFrom('POST'); 40 | $this->update(); 41 | } 42 | 43 | public function delete($id) { 44 | $this->load(array('id=?',$id)); 45 | $this->erase(); 46 | } 47 | 48 | 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /app/views/item/tmenu.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /{{ @BASE }}">Bookmark Manager 7 | 26 | -------------------------------------------------------------------------------- /lib/code.css: -------------------------------------------------------------------------------- 1 | code{word-wrap:break-word;color:black}.comment,.doc_comment,.ml_comment{color:dimgray;font-style:italic}.variable{color:blueviolet}.const,.constant_encapsed_string,.class_c,.dir,.file,.func_c,.halt_compiler,.line,.method_c,.lnumber,.dnumber{color:crimson}.string,.and_equal,.boolean_and,.boolean_or,.concat_equal,.dec,.div_equal,.inc,.is_equal,.is_greater_or_equal,.is_identical,.is_not_equal,.is_not_identical,.is_smaller_or_equal,.logical_and,.logical_or,.logical_xor,.minus_equal,.mod_equal,.mul_equal,.ns_c,.ns_separator,.or_equal,.plus_equal,.sl,.sl_equal,.sr,.sr_equal,.xor_equal,.start_heredoc,.end_heredoc,.object_operator,.paamayim_nekudotayim{color:black}.abstract,.array,.array_cast,.as,.break,.case,.catch,.class,.clone,.continue,.declare,.default,.do,.echo,.else,.elseif,.empty.enddeclare,.endfor,.endforach,.endif,.endswitch,.endwhile,.eval,.exit,.extends,.final,.for,.foreach,.function,.global,.goto,.if,.implements,.include,.include_once,.instanceof,.interface,.isset,.list,.namespace,.new,.print,.private,.public,.protected,.require,.require_once,.return,.static,.switch,.throw,.try,.unset,.use,.var,.while{color:royalblue}.open_tag,.open_tag_with_echo,.close_tag{color:orange}.ini_section{color:black}.ini_key{color:royalblue}.ini_value{color:crimson}.xml_tag{color:dodgerblue}.xml_attr{color:blueviolet}.xml_data{color:red}.section{color:black}.directive{color:blue}.data{color:dimgray} 2 | -------------------------------------------------------------------------------- /lib/log.php: -------------------------------------------------------------------------------- 1 | write( 32 | $this->file, 33 | date($format). 34 | (isset($_SERVER['REMOTE_ADDR'])? 35 | (' ['.$_SERVER['REMOTE_ADDR'].']'):'').' '. 36 | trim($text).PHP_EOL, 37 | TRUE 38 | ); 39 | } 40 | 41 | /** 42 | * Erase log 43 | * @return NULL 44 | **/ 45 | function erase() { 46 | @unlink($this->file); 47 | } 48 | 49 | /** 50 | * Instantiate class 51 | * @param $file string 52 | **/ 53 | function __construct($file) { 54 | $fw=Base::instance(); 55 | if (!is_dir($dir=$fw->get('LOGS'))) 56 | mkdir($dir,Base::MODE,TRUE); 57 | $this->file=$dir.$file; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /app/models/Tag.php: -------------------------------------------------------------------------------- 1 | load(); 11 | return $this->query; 12 | } 13 | 14 | 15 | public function add() { 16 | //$this->copyFrom('TAGS'); 17 | $this->save(); 18 | } 19 | 20 | #tags for item 21 | public function itemtags($tok) { 22 | 23 | $this->exec('SELECT label, url, tok FROM tags e JOIN tag2item ON e.id=tag2item.tid WHERE tag2item.iid=?',$tok); 24 | return $this->query; 25 | } 26 | 27 | public function tagcountByTok($tok) { 28 | return $this->count(array('tok=?',$tok)); 29 | 30 | } 31 | 32 | public function getIdByTok($tok) { 33 | $this->load(array('tok=?',$tok)); 34 | $this->copyTo('ID'); 35 | } 36 | 37 | public function getById($id) { 38 | $this->load(array('tok=?',$id)); 39 | $this->copyTo('POST'); 40 | } 41 | 42 | public function getByName($name) { 43 | $this->load(array('title=?',$name)); 44 | $this->copyTo('TAGS'); 45 | } 46 | 47 | public function edit($id) { 48 | $this->load(array('tok=?',$id)); 49 | $this->copyFrom('POST'); 50 | $this->update(); 51 | } 52 | 53 | public function delete($id) { 54 | $this->load(array('tok=?',$id)); 55 | $this->erase(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/views/cats/update.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 | 6 | 7 | Update category 8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 |
25 | 35 |
36 |
37 | 38 |
39 |
40 | 41 | 42 |
43 | 44 |
45 | 46 | 47 | 48 |
49 |
50 | 51 |
52 |
53 | -------------------------------------------------------------------------------- /inc/func.php: -------------------------------------------------------------------------------- 1 | 'S', 'š'=>'s', 'Ð'=>'Dj','Ž'=>'Z', 'ž'=>'z', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 10 | 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E', 'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 11 | 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U', 'Ú'=>'U', 12 | 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss','à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 13 | 'å'=>'a', 'æ'=>'a', 'ç'=>'c', 'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 14 | 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o', 'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 15 | 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b', 'ÿ'=>'y', 'ƒ'=>'f', 'Ą'=>'A', 'Ć'=>'C', 'Ę'=>'E', 16 | 'Ł'=>'L', 'Ń'=>'N', 'Ó'=>'O', 'Ś'=>'S', 'Ż'=>'Z', 'Ź'=>'Z', 'ą'=>'a', 'ć'=>'c', 'ę'=>'e', 'ł'=>'l', 17 | 'ń'=>'n', 'ó'=>'o', 'ś'=>'s', 'ż'=>'z', 'ź'=>'z', '/'=>'-' 18 | ); 19 | 20 | // small fonts 21 | $sText = strtolower(strtr($string,$normalizeChars)); 22 | // change spaces to - 23 | $sText = str_replace(' ', '-', $sText); 24 | // delete all other characters to - 25 | $sText = preg_replace('|[^0-9a-z\-\/+]|', '', $sText); 26 | // delete too much - if near 27 | $sText = preg_replace('/[\-]+/', '-', $sText); 28 | // trim - 29 | $sText = trim($sText, '-'); 30 | 31 | //limit 150 chars 32 | if(strlen($sText)>150) $turl = substr($sText, 0, 150); 33 | 34 | return $sText; 35 | } 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /lib/test.php: -------------------------------------------------------------------------------- 1 | data; 36 | } 37 | 38 | /** 39 | * Evaluate condition and save test result 40 | * @return NULL 41 | * @param $cond bool 42 | * @param $text string 43 | **/ 44 | function expect($cond,$text=NULL) { 45 | $out=(bool)$cond; 46 | if ($this->level==self::FLAG_True && $out || 47 | $this->level==self::FLAG_False && !$out || 48 | $this->level==self::FLAG_Both) { 49 | $data=array('status'=>$out,'text'=>$text,'source'=>NULL); 50 | foreach (debug_backtrace() as $frame) 51 | if (isset($frame['file'])) { 52 | $data['source']=Base::instance()-> 53 | fixslashes($frame['file']).':'.$frame['line']; 54 | break; 55 | } 56 | $this->data[]=$data; 57 | } 58 | } 59 | 60 | /** 61 | * Append message to test results 62 | * @return NULL 63 | * @param $text string 64 | **/ 65 | function message($text) { 66 | $this->expect(TRUE,$text); 67 | } 68 | 69 | /** 70 | * Class constructor 71 | * @return NULL 72 | * @param $level int 73 | **/ 74 | function __construct($level=self::FLAG_Both) { 75 | $this->level=$level; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /lib/db/mongo.php: -------------------------------------------------------------------------------- 1 | selectcollection('system.profile')->find(); 36 | foreach (iterator_to_array($cursor) as $frame) 37 | if (!preg_match('/\.system\..+$/',$frame['ns'])) 38 | $this->log.=date('r',$frame['ts']->sec).' ('. 39 | sprintf('%.1f',$frame['millis']).'ms) '. 40 | $frame['ns'].' ['.$frame['op'].'] '. 41 | (empty($frame['query'])? 42 | '':json_encode($frame['query'])). 43 | (empty($frame['command'])? 44 | '':json_encode($frame['command'])). 45 | PHP_EOL; 46 | return $this->log; 47 | } 48 | 49 | /** 50 | * Intercept native call to re-enable profiler 51 | * @return int 52 | **/ 53 | function drop() { 54 | $out=parent::drop(); 55 | $this->setprofilinglevel(2); 56 | return $out; 57 | } 58 | 59 | /** 60 | * Instantiate class 61 | * @param $dsn string 62 | * @param $dbname string 63 | * @param $options array 64 | **/ 65 | function __construct($dsn,$dbname,array $options=NULL) { 66 | $class=class_exists('\MongoClient')?'\MongoClient':'\Mongo'; 67 | parent::__construct(new $class($dsn,$options?:array()),$dbname); 68 | $this->setprofilinglevel(2); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /app/views/item/create.htm: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 | Create new bookmark 7 | 8 | 9 |
10 | 11 |
12 | 13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 |
24 |
25 | 26 | 27 |
28 | 29 |
30 | 31 |
32 |
33 | 34 | 35 | 36 | 37 | 38 |
39 | 40 |
41 | 48 |
49 |
50 | 51 |
52 | 53 | 54 |
55 | 56 |
57 | 58 | 59 |
60 |
61 | 62 | 63 | 64 |
65 | 66 |
67 | 68 |
69 |
70 | 71 |
72 |
73 | -------------------------------------------------------------------------------- /lib/bcrypt.php: -------------------------------------------------------------------------------- 1 | 31) 34 | trigger_error(self::E_Cost); 35 | $len=22; 36 | if ($salt) { 37 | if (!preg_match('/^[[:alnum:]\.\/]{'.$len.',}$/',$salt)) 38 | trigger_error(self::E_Salt); 39 | } 40 | else { 41 | $raw=16; 42 | $iv=''; 43 | if (extension_loaded('mcrypt')) 44 | $iv=mcrypt_create_iv($raw,MCRYPT_DEV_URANDOM); 45 | if (!$iv && extension_loaded('openssl')) 46 | $iv=openssl_random_pseudo_bytes($raw); 47 | if (!$iv) 48 | for ($i=0;$i<$raw;$i++) 49 | $iv.=chr(mt_rand(0,255)); 50 | $salt=str_replace('+','.',base64_encode($iv)); 51 | } 52 | $salt=substr($salt,0,$len); 53 | $hash=crypt($pw,sprintf('$2y$%02d$',$cost).$salt); 54 | return strlen($hash)>13?$hash:FALSE; 55 | } 56 | 57 | /** 58 | * Verify password against hash using timing attack resistant approach 59 | * @return bool 60 | * @param $pw string 61 | * @param $hash string 62 | **/ 63 | function verify($pw,$hash) { 64 | $val=crypt($pw,$hash); 65 | $len=strlen($val); 66 | if ($len!=strlen($hash) || $len<14) 67 | return FALSE; 68 | $out=0; 69 | for ($i=0;$i<$len;$i++) 70 | $out|=(ord($val[$i])^ord($hash[$i])); 71 | return $out===0; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /app/views/cats/list.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
CategoryNodeOptions
{{ trim(@cat.name) }}{{ trim(@cat.node) }}edit delete
no categories
27 | 28 | 29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 |
37 |
38 | 39 | 40 | Create new category 41 | 42 | 43 |
44 | 45 |
46 | 47 | 48 |
49 | 50 | 51 | 52 | 53 | 54 |
55 | 56 |
57 | 64 |
65 |
66 | 67 |
68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 |
78 | 79 |
80 | 81 |
82 |
83 | 84 |
85 |
86 | -------------------------------------------------------------------------------- /app/models/Item.php: -------------------------------------------------------------------------------- 1 | load(); 11 | return $this->query; 12 | } 13 | 14 | public function loadpages($pageoffset,$pagelimit) { 15 | if($pageoffset<0 || $pageoffset>999999999) $pageoffset=0; 16 | $this->load(array('active>?',0),array('order'=>'datetime DESC','offset'=>$pageoffset,'limit'=>$pagelimit)); 17 | return $this->query; 18 | } 19 | 20 | public function loadpagesByTok($pageoffset,$pagelimit,$ctok) { 21 | if($pageoffset<0 || $pageoffset>999999999) $pageoffset=0; 22 | $this->load(array('cid=?',$ctok),array('order'=>'datetime DESC','offset'=>$pageoffset,'limit'=>$pagelimit)); 23 | return $this->query; 24 | } 25 | 26 | 27 | public function itemcount() { 28 | return $this->count(); 29 | 30 | } 31 | 32 | public function itemcountByTok($tok) { 33 | return $this->count(array('tok=?',$tok)); 34 | 35 | } 36 | 37 | public function catcountByTok($tok) { 38 | return $this->count(array('cid=?',$tok)); 39 | 40 | } 41 | 42 | public function cat($id) { 43 | $this->load(array('cid=?',$id)); 44 | return $this->query; 45 | } 46 | 47 | 48 | public function add() { 49 | $this->copyFrom('POST'); 50 | $this->save(); 51 | 52 | } 53 | 54 | public function getById($id) { 55 | $this->load(array('tok=?',$id)); 56 | $this->copyTo('POST'); 57 | } 58 | 59 | public function getIdByTok($tok) { 60 | $this->load(array('tok=?',$tok)); 61 | $this->copyTo('ID'); 62 | } 63 | 64 | public function edit($id) { 65 | $this->load(array('tok=?',$id)); 66 | $this->copyFrom('POST'); 67 | $this->update(); 68 | } 69 | 70 | public function search($query,$searchlimit) { 71 | $this->load(array('title LIKE ? OR note LIKE ?',"%$query%","%$query%"),array('order'=>'datetime DESC','limit'=>$searchlimit)); 72 | return $this->query; 73 | } 74 | 75 | public function deleteCat($cid) { 76 | $this->load(array('cid=?',$cid)); 77 | $this->copyFrom('POST'); 78 | $this->update(); 79 | } 80 | 81 | public function delete($id) { 82 | $this->load(array('tok=?',$id)); 83 | $this->erase(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/views/item/update.htm: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 | Update 6 | 7 | 8 |
9 | 10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 | 19 |
20 | 21 | 22 |
23 |
24 | 25 | 26 |
27 | 28 |
29 | 30 |
31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | 40 |
41 | 48 |
49 |
50 | 51 |
52 | 53 | 54 | 55 |
56 | 57 |
58 | {{ @t.label }},"> 59 | 60 |
61 |
62 | 63 | 64 | 65 | 66 |
67 | 68 |
69 | 70 | 71 | 72 |
73 |
74 | 75 |
76 |
77 | -------------------------------------------------------------------------------- /app/views/b3.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ @title }} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 | 22 | 23 | 24 | 25 | 26 | 31 | 32 |
33 | 34 | 35 |
36 |
37 |
38 | 39 | 40 |
41 | 42 |
43 | 44 | {{ @message }} 45 |
46 |
47 |
48 | 49 | 50 | 51 | 52 | 53 | 54 |
55 | 56 | 57 | 58 |
59 | 60 | 61 |
62 | 63 | 64 | 65 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 77 | 78 | 79 | 81 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /app/views/pagination.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
    7 |
  • «
  • 8 | 9 | class="active">1 10 | 11 | 12 | class="active">{{ @i+1 }} 13 | 14 | 15 |
  • »
  • 16 |
17 | 18 |
19 | 20 | 21 | 22 | 23 |
    24 |
  • «
  • 25 | 26 | class="active">1 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | class="active">{{ @i+1 }} 37 | 38 | 39 | 40 |
  • ...
  • 41 |
    42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | class="active">2 50 |
  • ...
  • 51 | 52 | 53 | class="active">{{ @i+1 }} 54 | 55 | 56 |
  • ...
  • 57 | class="active">{{ @pagecount-1 }} 58 | 59 |
    60 | 61 | 62 | 63 | class="active">{{ @pagecount }} 64 | 65 |
  • »
  • 66 |
67 | 68 |
69 |
70 |
-------------------------------------------------------------------------------- /lib/db/jig.php: -------------------------------------------------------------------------------- 1 | dir.$file)) 43 | return array(); 44 | $raw=$fw->read($dst); 45 | switch ($this->format) { 46 | case self::FORMAT_JSON: 47 | $data=json_decode($raw,TRUE); 48 | break; 49 | case self::FORMAT_Serialized: 50 | $data=$fw->unserialize($raw); 51 | break; 52 | } 53 | return $data; 54 | } 55 | 56 | /** 57 | * Write data to file 58 | * @return int 59 | * @param $file string 60 | * @param $data array 61 | **/ 62 | function write($file,array $data=NULL) { 63 | $fw=\Base::instance(); 64 | switch ($this->format) { 65 | case self::FORMAT_JSON: 66 | $out=json_encode($data,@constant('JSON_PRETTY_PRINT')); 67 | break; 68 | case self::FORMAT_Serialized: 69 | $out=$fw->serialize($data); 70 | break; 71 | } 72 | $out=$fw->write($this->dir.$file,$out); 73 | return $out; 74 | } 75 | 76 | /** 77 | * Return SQL profiler results 78 | * @return string 79 | **/ 80 | function log() { 81 | return $this->log; 82 | } 83 | 84 | /** 85 | * Jot down log entry 86 | * @return NULL 87 | * @param $frame string 88 | **/ 89 | function jot($frame) { 90 | if ($frame) 91 | $this->log.=date('r').' '.$frame.PHP_EOL; 92 | } 93 | 94 | /** 95 | * Clean storage 96 | * @return NULL 97 | **/ 98 | function drop() { 99 | if ($glob=@glob($this->dir.'/*',GLOB_NOSORT)) 100 | foreach ($glob as $file) 101 | @unlink($file); 102 | } 103 | 104 | /** 105 | * Instantiate class 106 | * @param $dir string 107 | * @param $format int 108 | **/ 109 | function __construct($dir,$format=self::FORMAT_JSON) { 110 | if (!is_dir($dir)) 111 | mkdir($dir,\Base::MODE,TRUE); 112 | $this->dir=$dir; 113 | $this->format=$format; 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /lib/matrix.php: -------------------------------------------------------------------------------- 1 | $cols) 43 | foreach ($cols as $keyy=>$valy) 44 | $out[$keyy][$keyx]=$valy; 45 | $var=$out; 46 | } 47 | 48 | /** 49 | * Sort a multi-dimensional array variable on a specified column 50 | * @return bool 51 | * @param $var array 52 | * @param $col mixed 53 | * @param $order int 54 | **/ 55 | function sort(array &$var,$col,$order=SORT_ASC) { 56 | uasort( 57 | $var, 58 | function($val1,$val2) use($col,$order) { 59 | list($v1,$v2)=array($val1[$col],$val2[$col]); 60 | $out=is_numeric($v1) && is_numeric($v2)? 61 | Base::instance()->sign($v1-$v2):strcmp($v1,$v2); 62 | if ($order==SORT_DESC) 63 | $out=-$out; 64 | return $out; 65 | } 66 | ); 67 | $var=array_values($var); 68 | } 69 | 70 | /** 71 | * Change the key of a two-dimensional array element 72 | * @return NULL 73 | * @param $var array 74 | * @param $old string 75 | * @param $new string 76 | **/ 77 | function changekey(array &$var,$old,$new) { 78 | $keys=array_keys($var); 79 | $vals=array_values($var); 80 | $keys[array_search($old,$keys)]=$new; 81 | $var=array_combine($keys,$vals); 82 | } 83 | 84 | /** 85 | * Return month calendar of specified date, with optional setting for 86 | * first day of week (0 for Sunday) 87 | * @return array 88 | * @param $date string 89 | * @param $first int 90 | **/ 91 | function calendar($date='now',$first=0) { 92 | $parts=getdate(strtotime($date)); 93 | $days=cal_days_in_month(CAL_GREGORIAN,$parts['mon'],$parts['year']); 94 | $ref=date('w',strtotime(date('Y-m',$parts[0]).'-01'))+(7-$first)%7; 95 | $out=array(); 96 | for ($i=0;$i<$days;$i++) 97 | $out[floor(($ref+$i)/7)][($ref+$i)%7]=$i+1; 98 | return $out; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /db/db.sql: -------------------------------------------------------------------------------- 1 | 2 | 3 | CREATE TABLE IF NOT EXISTS `cats` ( 4 | `id` int(11) NOT NULL AUTO_INCREMENT, 5 | `tok` int(11) NOT NULL, 6 | `url` varchar(255) NOT NULL DEFAULT '', 7 | `name` varchar(255) NOT NULL DEFAULT '', 8 | `node` int(11) DEFAULT NULL, 9 | `dsc` text, 10 | `badge` int(5) DEFAULT NULL, 11 | `badgecolor` int(5) DEFAULT NULL, 12 | `active` tinyint(1) NOT NULL DEFAULT '1', 13 | PRIMARY KEY (`id`) 14 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 15 | 16 | 17 | CREATE TABLE IF NOT EXISTS `items` ( 18 | `id` int(11) NOT NULL AUTO_INCREMENT, 19 | `tok` int(11) NOT NULL, 20 | `url` varchar(255) NOT NULL DEFAULT '', 21 | `title` varchar(255) NOT NULL DEFAULT '', 22 | `user` int(8) DEFAULT NULL, 23 | `note` text, 24 | `type` int(5) DEFAULT NULL, 25 | `cid` int(11) NOT NULL, 26 | `sticked` tinyint(1) DEFAULT NULL, 27 | `badge` varchar(255) NOT NULL DEFAULT '', 28 | `badgecolor` varchar(6) NOT NULL DEFAULT '', 29 | `screen` tinyint(1) DEFAULT NULL, 30 | `datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 31 | `active` tinyint(1) NOT NULL DEFAULT '1', 32 | PRIMARY KEY (`id`) 33 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 34 | 35 | 36 | 37 | CREATE TABLE IF NOT EXISTS `tag2item` ( 38 | `id` int(11) NOT NULL AUTO_INCREMENT, 39 | `iid` int(11) NOT NULL, 40 | `tid` int(11) NOT NULL, 41 | PRIMARY KEY (`id`) 42 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 43 | 44 | 45 | CREATE TABLE IF NOT EXISTS `tags` ( 46 | `id` int(11) NOT NULL AUTO_INCREMENT, 47 | `tok` int(11) NOT NULL, 48 | `url` varchar(255) NOT NULL DEFAULT '', 49 | `title` varchar(255) NOT NULL DEFAULT '', 50 | `label` varchar(255) NOT NULL DEFAULT '', 51 | `dsc` text, 52 | `node` int(11) DEFAULT NULL, 53 | `active` tinyint(1) NOT NULL DEFAULT '1', 54 | PRIMARY KEY (`id`) 55 | ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 56 | 57 | 58 | 59 | CREATE VIEW catgroup AS 60 | SELECT 61 | cats.name AS cat, 62 | cats.tok AS tok, 63 | cats.url AS url, 64 | count(*) AS itemcount 65 | FROM cats 66 | JOIN items ON 67 | items.cid=cats.tok 68 | GROUP BY 69 | cats.name 70 | ORDER BY itemcount DESC; 71 | 72 | 73 | CREATE VIEW taggroup AS 74 | SELECT 75 | tags.label AS tag, 76 | tags.tok AS tok, 77 | tags.url AS url, 78 | count(*) AS tagcount 79 | FROM tags 80 | JOIN tag2item ON 81 | tag2item.tid = tags.id 82 | GROUP BY 83 | tags.label 84 | ORDER BY tagcount DESC; 85 | 86 | 87 | CREATE VIEW itemstag AS 88 | SELECT 89 | items.title AS title, 90 | items.note AS note, 91 | items.tok AS tok, 92 | items.url AS url, 93 | tag2item.tid AS tagid, 94 | tags.tok AS tagtok, 95 | tags.label AS label 96 | FROM items 97 | JOIN tag2item ON 98 | items.id=tag2item.iid 99 | JOIN tags ON 100 | tags.id=tag2item.tid; 101 | 102 | 103 | CREATE VIEW taglist AS 104 | SELECT 105 | tags.label, 106 | tags.tok, 107 | tags.url, 108 | items.tok as itok, 109 | items.cid as ctok 110 | FROM tags 111 | JOIN tag2item ON 112 | tag2item.tid = tags.id 113 | JOIN items ON 114 | tag2item.iid = items.id 115 | ORDER BY items.tok; 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /lib/web/geo.php: -------------------------------------------------------------------------------- 1 | getLocation(); 29 | $trn=$ref->getTransitions($now=time(),$now); 30 | $out=array( 31 | 'offset'=>$ref-> 32 | getOffset(new \DateTime('now',new \DateTimeZone('GMT')))/3600, 33 | 'country'=>$loc['country_code'], 34 | 'latitude'=>$loc['latitude'], 35 | 'longitude'=>$loc['longitude'], 36 | 'dst'=>$trn[0]['isdst'] 37 | ); 38 | unset($ref); 39 | return $out; 40 | } 41 | 42 | /** 43 | * Return geolocation data based on specified/auto-detected IP address 44 | * @return array|FALSE 45 | * @param $ip string 46 | **/ 47 | function location($ip=NULL) { 48 | $fw=\Base::instance(); 49 | $web=\Web::instance(); 50 | if (!$ip) 51 | $ip=$fw->get('IP'); 52 | $public=filter_var($ip,FILTER_VALIDATE_IP, 53 | FILTER_FLAG_IPV4|FILTER_FLAG_IPV6| 54 | FILTER_FLAG_NO_RES_RANGE|FILTER_FLAG_NO_PRIV_RANGE); 55 | if (function_exists('geoip_db_avail') && 56 | geoip_db_avail(GEOIP_CITY_EDITION_REV1) && 57 | $out=@geoip_record_by_name($ip)) { 58 | $out['request']=$ip; 59 | $out['region_code']=$out['region']; 60 | $out['region_name']=geoip_region_name_by_code( 61 | $out['country_code'],$out['region']); 62 | unset($out['country_code3'],$out['region'],$out['postal_code']); 63 | return $out; 64 | } 65 | if (($req=$web->request('http://www.geoplugin.net/json.gp'. 66 | ($public?('?ip='.$ip):''))) && 67 | $data=json_decode($req['body'],TRUE)) { 68 | $out=array(); 69 | foreach ($data as $key=>$val) 70 | if (!strpos($key,'currency') && $key!=='geoplugin_status' 71 | && $key!=='geoplugin_region') 72 | $out[$fw->snakecase(substr($key, 10))]=$val; 73 | return $out; 74 | } 75 | return FALSE; 76 | } 77 | 78 | /** 79 | * Return weather data based on specified latitude/longitude 80 | * @return array|FALSE 81 | * @param $latitude float 82 | * @param $longitude float 83 | **/ 84 | function weather($latitude,$longitude) { 85 | $fw=\Base::instance(); 86 | $web=\Web::instance(); 87 | $query=array( 88 | 'lat'=>$latitude, 89 | 'lng'=>$longitude, 90 | 'username'=>$fw->hash($fw->get('IP')) 91 | ); 92 | return ($req=$web->request( 93 | 'http://ws.geonames.org/findNearByWeatherJSON?'. 94 | http_build_query($query))) && 95 | ($data=json_decode($req['body'],TRUE)) && 96 | isset($data['weatherObservation'])? 97 | $data['weatherObservation']: 98 | FALSE; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /ui/js/main.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /* Delete Item */ 5 | $('.deleteitem').click(function(){ 6 | 7 | var e = $(this).attr("id").split('itemtok_') 8 | var tok = e[1] 9 | 10 | var retval = confirm("Do you want to delete this item?"); 11 | if( retval == true ){ 12 | window.location = base+'/i/delete/'+tok 13 | return true; 14 | }else return false; 15 | 16 | 17 | }); 18 | 19 | 20 | /* Delete Tag */ 21 | $('.deletetag').click(function(){ 22 | 23 | var e = $(this).attr("id").split('tagtok_') 24 | var tok = e[1] 25 | 26 | var retval = confirm("Do you want to delete this tag?"); 27 | if( retval == true ){ 28 | window.location = base+'/t/delete/'+tok 29 | return true; 30 | }else return false; 31 | 32 | 33 | }); 34 | 35 | 36 | 37 | /* Delete Category */ 38 | $('.deletecat').click(function(){ 39 | 40 | var e = $(this).attr("id").split('cattok_') 41 | var tok = e[1] 42 | 43 | var retval = confirm("Do you want to delete this category?"); 44 | if( retval == true ){ 45 | window.location = base+'/c/delete/'+tok 46 | return true; 47 | }else return false; 48 | 49 | 50 | }); 51 | 52 | 53 | 54 | /* Hide messages after X s. */ 55 | $(".hide5s").fadeOut(5000); 56 | $(".hide10s").fadeOut(10000); 57 | 58 | 59 | 60 | 61 | 62 | 63 | /* Validate Category */ 64 | $('.validcat').submit(function(){ 65 | 66 | $( "#message" ).html(''); 67 | 68 | if( $('#name').val()=='' ){ 69 | $( "#message" ).append( '
'+ 70 | ''+ 71 | 'The filed name cannot be empty!'+ 72 | '
' ); 73 | 74 | $('#name').focus(); 75 | $(".hide5s").fadeOut(10000); 76 | return false; 77 | } 78 | 79 | return true; 80 | alert(1) 81 | }); 82 | 83 | 84 | 85 | 86 | /* Validate Item */ 87 | $('.validitem').submit(function(){ 88 | 89 | $( "#message" ).html(''); 90 | 91 | if( $('#title').val()=='' ){ 92 | $( "#message" ).html( '
'+ 93 | ''+ 94 | 'The filed title cannot be empty!'+ 95 | '
' ); 96 | $('#title').focus(); 97 | $(".hide5s").fadeOut(10000); 98 | return false; 99 | } 100 | 101 | return true; 102 | 103 | }); 104 | 105 | 106 | 107 | 108 | /* Validate Tag */ 109 | $('.validtag').submit(function(){ 110 | 111 | $( "#message" ).html(''); 112 | 113 | if( $('#title').val()=='' ){ 114 | $( "#message" ).html( '
'+ 115 | ''+ 116 | 'The filed title cannot be empty!'+ 117 | '
' ); 118 | $('#title').focus(); 119 | $(".hide5s").fadeOut(10000); 120 | return false; 121 | } 122 | if( $('#label').val()=='' ){ 123 | $( "#message" ).html( '
'+ 124 | ''+ 125 | 'The filed label cannot be empty!'+ 126 | '
' ); 127 | $('#label').focus(); 128 | $(".hide5s").fadeOut(10000); 129 | return false; 130 | } 131 | 132 | return true; 133 | 134 | }); 135 | 136 | -------------------------------------------------------------------------------- /app/views/tags/items.htm: -------------------------------------------------------------------------------- 1 | 2 |

{{ @label}}

3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | {{ trim(@item.title) }} 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
{{ trim(@item.note) }}
36 |
37 | 38 | 39 |
40 | 41 | {{ @t.label }} 42 | 43 |
44 |
45 | 46 |
47 | 48 | 49 | 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 |
59 | 60 |
61 | 62 | 63 |
64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
75 | 76 | 77 | 78 | {{ trim(@item.title) }} 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 |
{{ trim(@item.note) }}
87 |
88 | 89 | 90 |
91 | 92 | {{ @t.label }} 93 | 94 |
95 |
96 | 97 |
98 | 99 |
100 |
101 | 102 | 103 | 104 | 105 |
106 | 107 |
108 | 109 | 110 |
111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /lib/session.php: -------------------------------------------------------------------------------- 1 | exists($id.'.@',$data)?$data['data']:FALSE; 44 | } 45 | 46 | /** 47 | * Write session data 48 | * @return TRUE 49 | * @param $id string 50 | * @param $data string 51 | **/ 52 | function write($id,$data) { 53 | $fw=Base::instance(); 54 | $headers=$fw->get('HEADERS'); 55 | $jar=session_get_cookie_params(); 56 | Cache::instance()->set($id.'.@', 57 | array( 58 | 'data'=>$data, 59 | 'ip'=>$fw->get('IP'), 60 | 'agent'=>isset($headers['User-Agent'])? 61 | $headers['User-Agent']:'', 62 | 'stamp'=>time() 63 | ), 64 | $jar['lifetime'] 65 | ); 66 | return TRUE; 67 | } 68 | 69 | /** 70 | * Destroy session 71 | * @return TRUE 72 | * @param $id string 73 | **/ 74 | function destroy($id) { 75 | Cache::instance()->clear($id.'.@'); 76 | return TRUE; 77 | } 78 | 79 | /** 80 | * Garbage collector 81 | * @return TRUE 82 | * @param $max int 83 | **/ 84 | function cleanup($max) { 85 | Cache::instance()->reset('.@',$max); 86 | return TRUE; 87 | } 88 | 89 | /** 90 | * Return IP address associated with specified session ID 91 | * @return string|FALSE 92 | * @param $id string 93 | **/ 94 | function ip($id=NULL) { 95 | return Cache::instance()->exists(($id?:session_id()).'.@',$data)? 96 | $data['ip']:FALSE; 97 | } 98 | 99 | /** 100 | * Return Unix timestamp associated with specified session ID 101 | * @return string|FALSE 102 | * @param $id string 103 | **/ 104 | function stamp($id=NULL) { 105 | return Cache::instance()->exists(($id?:session_id()).'.@',$data)? 106 | $data['stamp']:FALSE; 107 | } 108 | 109 | /** 110 | * Return HTTP user agent associated with specified session ID 111 | * @return string|FALSE 112 | * @param $id string 113 | **/ 114 | function agent($id=NULL) { 115 | return Cache::instance()->exists(($id?:session_id()).'.@',$data)? 116 | $data['agent']:FALSE; 117 | } 118 | 119 | /** 120 | * Instantiate class 121 | * @return object 122 | **/ 123 | function __construct() { 124 | session_set_save_handler( 125 | array($this,'open'), 126 | array($this,'close'), 127 | array($this,'read'), 128 | array($this,'write'), 129 | array($this,'destroy'), 130 | array($this,'cleanup') 131 | ); 132 | register_shutdown_function('session_commit'); 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /app/views/item/list.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 |

{{ @label}}

4 | 5 | 6 | 7 |
8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | {{ trim(@item.title) }} 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
{{ trim(@item.note) }}
36 |
37 | 38 | 39 |
40 | 41 | {{ @t.label }} 42 | 43 |
44 |
45 | 46 |
47 | 48 |
49 |
50 | 51 | 52 | 53 |
54 | 55 |
56 | 57 | 58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
73 | 74 | 75 | 76 | {{ trim(@item.title) }} 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 |
{{ trim(@item.note) }}
85 |
86 | 87 |
88 | 89 | {{ @t.label }} 90 | 91 |
92 |
93 | 94 |
95 | 96 |
97 |
98 | 99 | 100 | 101 | 102 |
103 | 104 | 105 |

no items

106 |
107 | 108 |
109 | 110 | 111 |
112 | 113 | 114 | -------------------------------------------------------------------------------- /lib/magic.php: -------------------------------------------------------------------------------- 1 | ispublic(); 57 | unset($ref); 58 | return $out; 59 | } 60 | return FALSE; 61 | } 62 | 63 | /** 64 | * Convenience method for checking property value 65 | * @return mixed 66 | * @param $key string 67 | **/ 68 | function offsetexists($key) { 69 | return $this->visible($key)?isset($this->$key):$this->exists($key); 70 | } 71 | 72 | /** 73 | * Alias for offsetexists() 74 | * @return mixed 75 | * @param $key string 76 | **/ 77 | function __isset($key) { 78 | return $this->offsetexists($key); 79 | } 80 | 81 | /** 82 | * Convenience method for assigning property value 83 | * @return mixed 84 | * @param $key string 85 | * @param $val scalar 86 | **/ 87 | function offsetset($key,$val) { 88 | return $this->visible($key)?($this->key=$val):$this->set($key,$val); 89 | } 90 | 91 | /** 92 | * Alias for offsetset() 93 | * @return mixed 94 | * @param $key string 95 | * @param $val scalar 96 | **/ 97 | function __set($key,$val) { 98 | return $this->offsetset($key,$val); 99 | } 100 | 101 | /** 102 | * Convenience method for retrieving property value 103 | * @return mixed 104 | * @param $key string 105 | **/ 106 | function offsetget($key) { 107 | return $this->visible($key)?$this->$key:$this->get($key); 108 | } 109 | 110 | /** 111 | * Alias for offsetget() 112 | * @return mixed 113 | * @param $key string 114 | **/ 115 | function __get($key) { 116 | return $this->offsetget($key); 117 | } 118 | 119 | /** 120 | * Convenience method for checking property value 121 | * @return NULL 122 | * @param $key string 123 | **/ 124 | function offsetunset($key) { 125 | if ($this->visible($key)) 126 | unset($this->$key); 127 | else 128 | $this->clear($key); 129 | } 130 | 131 | /** 132 | * Alias for offsetunset() 133 | * @return NULL 134 | * @param $key string 135 | **/ 136 | function __unset($key) { 137 | $this->offsetunset($key); 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /ui/js/track.js: -------------------------------------------------------------------------------- 1 | var _gauges=_gauges||[];(function(){var h=(_gauges['slice'])?_gauges.slice(0):[];_gauges={track_referrer:true,image:new Image(),track:function(){this.setCookie('_gauges_cookie',1,1);var a=this.url();if(a){this.image.src=a;var b=60*60,d=b*24,f=d*31,c=d*365,i=c*10;if(!this.getCookie('_gauges_unique_hour')){this.setCookie('_gauges_unique_hour',1,b)}if(!this.getCookie('_gauges_unique_day')){this.setCookie('_gauges_unique_day',1,d)}if(!this.getCookie('_gauges_unique_month')){this.setCookie('_gauges_unique_month',1,f)}if(!this.getCookie('_gauges_unique_year')){this.setCookie('_gauges_unique_year',1,c)}if(!this.getCookie('_gauges_unique')){this.setCookie('_gauges_unique',1,i)}}},push:function(a){var b=a.shift();if(b=='track'){_gauges.track()}},url:function(){var a,b,d=this.$('gauges-tracker');if(d){b=d.getAttribute('data-site-id');a=d.src.replace('/track.js','/track.gif');a+="?h[site_id]="+b;a+="&h[resource]="+this.resource();a+="&h[referrer]="+this.referrer();a+="&h[title]="+this.title();a+="&h[user_agent]="+this.agent();a+="&h[unique]="+this.unique();a+="&h[unique_hour]="+this.uniqueHour();a+="&h[unique_day]="+this.uniqueDay();a+="&h[unique_month]="+this.uniqueMonth();a+="&h[unique_year]="+this.uniqueYear();a+="&h[screenx]="+this.screenWidth();a+="&h[browserx]="+this.browserWidth();a+="&h[browsery]="+this.browserHeight();a+="×tamp="+this.timestamp()}return a},domain:function(){return window.location.hostname},referrer:function(){var a='';if(!this.track_referrer){return a}this.track_referrer=false;try{a=top.document.referrer}catch(e1){try{a=parent.document.referrer}catch(e2){a=''}}if(a==''){a=document.referrer}return this.escape(a)},agent:function(){return this.escape(navigator.userAgent)},escape:function(a){return(typeof(encodeURIComponent)=='function')?encodeURIComponent(a):escape(a)},resource:function(){return this.escape(document.location.href)},timestamp:function(){return new Date().getTime()},title:function(){return(document.title&&document.title!="")?this.escape(document.title):''},uniqueHour:function(){if(!this.getCookie('_gauges_cookie')){return 0}return this.getCookie('_gauges_unique_hour')?0:1},uniqueDay:function(){if(!this.getCookie('_gauges_cookie')){return 0}return this.getCookie('_gauges_unique_day')?0:1},uniqueMonth:function(){if(!this.getCookie('_gauges_cookie')){return 0}return this.getCookie('_gauges_unique_month')?0:1},uniqueYear:function(){if(!this.getCookie('_gauges_cookie')){return 0}return this.getCookie('_gauges_unique_year')?0:1},unique:function(){if(!this.getCookie('_gauges_cookie')){return 0}return this.getCookie('_gauges_unique')?0:1},screenWidth:function(){try{return screen.width}catch(e){return 0}},browserDimensions:function(){var a=0,b=0;try{if(typeof(window.innerWidth)=='number'){a=window.innerWidth;b=window.innerHeight}else if(document.documentElement&&document.documentElement.clientWidth){a=document.documentElement.clientWidth;b=document.documentElement.clientHeight}else if(document.body&&document.body.clientWidth){a=document.body.clientWidth;b=document.body.clientHeight}}catch(e){}return{width:a,height:b}},browserWidth:function(){return this.browserDimensions().width},browserHeight:function(){return this.browserDimensions().height},$:function(a){if(document.getElementById){return document.getElementById(a)}return null},setCookie:function(a,b,d){var f,c;b=escape(b);if(d){f=new Date();f.setTime(f.getTime()+(d*1000));c='; expires='+f.toGMTString()}else{c=''}document.cookie=a+"="+b+c+"; path=/"},getCookie:function(a){var b=a+"=",d=document.cookie.split(';');for(var f=0;fload(array('@session_id==?',$id)); 46 | return $this->dry()?FALSE:$this->get('data'); 47 | } 48 | 49 | /** 50 | * Write session data 51 | * @return TRUE 52 | * @param $id string 53 | * @param $data string 54 | **/ 55 | function write($id,$data) { 56 | $fw=\Base::instance(); 57 | $headers=$fw->get('HEADERS'); 58 | $this->load(array('@session_id==?',$id)); 59 | $this->set('session_id',$id); 60 | $this->set('data',$data); 61 | $this->set('ip',$fw->get('IP')); 62 | $this->set('agent', 63 | isset($headers['User-Agent'])?$headers['User-Agent']:''); 64 | $this->set('stamp',time()); 65 | $this->save(); 66 | return TRUE; 67 | } 68 | 69 | /** 70 | * Destroy session 71 | * @return TRUE 72 | * @param $id string 73 | **/ 74 | function destroy($id) { 75 | $this->erase(array('@session_id==?',$id)); 76 | return TRUE; 77 | } 78 | 79 | /** 80 | * Garbage collector 81 | * @return TRUE 82 | * @param $max int 83 | **/ 84 | function cleanup($max) { 85 | $this->erase(array('@stamp+?load(array('@session_id==?',$id?:session_id())); 96 | return $this->dry()?FALSE:$this->get('ip'); 97 | } 98 | 99 | /** 100 | * Return Unix timestamp associated with specified session ID 101 | * @return string|FALSE 102 | * @param $id string 103 | **/ 104 | function stamp($id=NULL) { 105 | $this->load(array('@session_id==?',$id?:session_id())); 106 | return $this->dry()?FALSE:$this->get('stamp'); 107 | } 108 | 109 | /** 110 | * Return HTTP user agent associated with specified session ID 111 | * @return string|FALSE 112 | * @param $id string 113 | **/ 114 | function agent($id=NULL) { 115 | $this->load(array('@session_id==?',$id?:session_id())); 116 | return $this->dry()?FALSE:$this->get('agent'); 117 | } 118 | 119 | /** 120 | * Instantiate class 121 | * @param $db object 122 | * @param $table string 123 | **/ 124 | function __construct(\DB\Jig $db,$table='sessions') { 125 | parent::__construct($db,'sessions'); 126 | session_set_save_handler( 127 | array($this,'open'), 128 | array($this,'close'), 129 | array($this,'read'), 130 | array($this,'write'), 131 | array($this,'destroy'), 132 | array($this,'cleanup') 133 | ); 134 | register_shutdown_function('session_commit'); 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /lib/db/mongo/session.php: -------------------------------------------------------------------------------- 1 | load(array('session_id'=>$id)); 46 | return $this->dry()?FALSE:$this->get('data'); 47 | } 48 | 49 | /** 50 | * Write session data 51 | * @return TRUE 52 | * @param $id string 53 | * @param $data string 54 | **/ 55 | function write($id,$data) { 56 | $fw=\Base::instance(); 57 | $headers=$fw->get('HEADERS'); 58 | $this->load(array('session_id'=>$id)); 59 | $this->set('session_id',$id); 60 | $this->set('data',$data); 61 | $this->set('ip',$fw->get('IP')); 62 | $this->set('agent', 63 | isset($headers['User-Agent'])?$headers['User-Agent']:''); 64 | $this->set('stamp',time()); 65 | $this->save(); 66 | return TRUE; 67 | } 68 | 69 | /** 70 | * Destroy session 71 | * @return TRUE 72 | * @param $id string 73 | **/ 74 | function destroy($id) { 75 | $this->erase(array('session_id'=>$id)); 76 | return TRUE; 77 | } 78 | 79 | /** 80 | * Garbage collector 81 | * @return TRUE 82 | * @param $max int 83 | **/ 84 | function cleanup($max) { 85 | $this->erase(array('$where'=>'this.stamp+'.$max.'<'.time())); 86 | return TRUE; 87 | } 88 | 89 | /** 90 | * Return IP address associated with specified session ID 91 | * @return string|FALSE 92 | * @param $id string 93 | **/ 94 | function ip($id=NULL) { 95 | $this->load(array('session_id'=>$id?:session_id())); 96 | return $this->dry()?FALSE:$this->get('ip'); 97 | } 98 | 99 | /** 100 | * Return Unix timestamp associated with specified session ID 101 | * @return string|FALSE 102 | * @param $id string 103 | **/ 104 | function stamp($id=NULL) { 105 | $this->load(array('session_id'=>$id?:session_id())); 106 | return $this->dry()?FALSE:$this->get('stamp'); 107 | } 108 | 109 | /** 110 | * Return HTTP user agent associated with specified session ID 111 | * @return string|FALSE 112 | * @param $id string 113 | **/ 114 | function agent($id=NULL) { 115 | $this->load(array('session_id'=>$id?:session_id())); 116 | return $this->dry()?FALSE:$this->get('agent'); 117 | } 118 | 119 | /** 120 | * Instantiate class 121 | * @param $db object 122 | * @param $table string 123 | **/ 124 | function __construct(\DB\Mongo $db,$table='sessions') { 125 | parent::__construct($db,$table); 126 | session_set_save_handler( 127 | array($this,'open'), 128 | array($this,'close'), 129 | array($this,'read'), 130 | array($this,'write'), 131 | array($this,'destroy'), 132 | array($this,'cleanup') 133 | ); 134 | register_shutdown_function('session_commit'); 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /lib/db/sql/session.php: -------------------------------------------------------------------------------- 1 | load(array('session_id=?',$id)); 46 | return $this->dry()?FALSE:$this->get('data'); 47 | } 48 | 49 | /** 50 | * Write session data 51 | * @return TRUE 52 | * @param $id string 53 | * @param $data string 54 | **/ 55 | function write($id,$data) { 56 | $fw=\Base::instance(); 57 | $headers=$fw->get('HEADERS'); 58 | $this->load(array('session_id=?',$id)); 59 | $this->set('session_id',$id); 60 | $this->set('data',$data); 61 | $this->set('ip',$fw->get('IP')); 62 | $this->set('agent', 63 | isset($headers['User-Agent'])?$headers['User-Agent']:''); 64 | $this->set('stamp',time()); 65 | $this->save(); 66 | return TRUE; 67 | } 68 | 69 | /** 70 | * Destroy session 71 | * @return TRUE 72 | * @param $id string 73 | **/ 74 | function destroy($id) { 75 | $this->erase(array('session_id=?',$id)); 76 | return TRUE; 77 | } 78 | 79 | /** 80 | * Garbage collector 81 | * @return TRUE 82 | * @param $max int 83 | **/ 84 | function cleanup($max) { 85 | $this->erase(array('stamp+?load(array('session_id=?',$id?:session_id())); 96 | return $this->dry()?FALSE:$this->get('ip'); 97 | } 98 | 99 | /** 100 | * Return Unix timestamp associated with specified session ID 101 | * @return string|FALSE 102 | * @param $id string 103 | **/ 104 | function stamp($id=NULL) { 105 | $this->load(array('session_id=?',$id?:session_id())); 106 | return $this->dry()?FALSE:$this->get('stamp'); 107 | } 108 | 109 | /** 110 | * Return HTTP user agent associated with specified session ID 111 | * @return string|FALSE 112 | * @param $id string 113 | **/ 114 | function agent($id=NULL) { 115 | $this->load(array('session_id=?',$id?:session_id())); 116 | return $this->dry()?FALSE:$this->get('agent'); 117 | } 118 | 119 | /** 120 | * Instantiate class 121 | * @param $db object 122 | * @param $table string 123 | **/ 124 | function __construct(\DB\SQL $db,$table='sessions') { 125 | $db->exec( 126 | 'CREATE TABLE IF NOT EXISTS '. 127 | (($name=$db->name())?($name.'.'):'').$table.' ('. 128 | 'session_id VARCHAR(40),'. 129 | 'data TEXT,'. 130 | 'ip VARCHAR(40),'. 131 | 'agent VARCHAR(255),'. 132 | 'stamp INTEGER,'. 133 | 'PRIMARY KEY(session_id)'. 134 | ');' 135 | ); 136 | parent::__construct($db,$table); 137 | session_set_save_handler( 138 | array($this,'open'), 139 | array($this,'close'), 140 | array($this,'read'), 141 | array($this,'write'), 142 | array($this,'destroy'), 143 | array($this,'cleanup') 144 | ); 145 | register_shutdown_function('session_commit'); 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /lib/db/cursor.php: -------------------------------------------------------------------------------- 1 | query[$this->ptr]); 58 | } 59 | 60 | /** 61 | * Return first record (mapper object) that matches criteria 62 | * @return object|FALSE 63 | * @param $filter string|array 64 | * @param $options array 65 | * @param $ttl int 66 | **/ 67 | function findone($filter=NULL,array $options=NULL,$ttl=0) { 68 | return ($data=$this->find($filter,$options,$ttl))?$data[0]:FALSE; 69 | } 70 | 71 | /** 72 | * Return array containing subset of records matching criteria, 73 | * total number of records in superset, number of subsets available, 74 | * and actual subset position 75 | * @return array 76 | * @param $pos int 77 | * @param $size int 78 | * @param $filter string|array 79 | * @param $options array 80 | **/ 81 | function paginate($pos=0,$size=10,$filter=NULL,array $options=NULL) { 82 | $total=$this->count($filter,$options); 83 | $count=ceil($total/$size); 84 | $pos=max(0,min($pos,$count-1)); 85 | return array( 86 | 'subset'=>$this->find($filter, 87 | array_merge( 88 | $options?:array(), 89 | array('limit'=>$size,'offset'=>$pos*$size) 90 | ) 91 | ), 92 | 'total'=>$total, 93 | 'count'=>$count, 94 | 'pos'=>$pos<$count?$pos:0 95 | ); 96 | } 97 | 98 | /** 99 | * Map to first record that matches criteria 100 | * @return array|FALSE 101 | * @param $filter string|array 102 | * @param $options array 103 | **/ 104 | function load($filter=NULL,array $options=NULL) { 105 | return ($this->query=$this->find($filter,$options)) && 106 | $this->skip(0)?$this->query[$this->ptr=0]:FALSE; 107 | } 108 | 109 | /** 110 | * Move pointer to first record in cursor 111 | * @return mixed 112 | **/ 113 | function first() { 114 | return $this->query[$this->ptr=0]; 115 | } 116 | 117 | /** 118 | * Move pointer to last record in cursor 119 | * @return mixed 120 | **/ 121 | function last() { 122 | return $this->query[$this->ptr=($ctr=count($this->query))?$ctr-1:0]; 123 | } 124 | 125 | /** 126 | * Map to nth record relative to current cursor position 127 | * @return mixed 128 | * @param $ofs int 129 | **/ 130 | function skip($ofs=1) { 131 | $this->ptr+=$ofs; 132 | return $this->ptr>-1 && $this->ptrquery)? 133 | $this->query[$this->ptr]:FALSE; 134 | } 135 | 136 | /** 137 | * Map next record 138 | * @return mixed 139 | **/ 140 | function next() { 141 | return $this->skip(); 142 | } 143 | 144 | /** 145 | * Map previous record 146 | * @return mixed 147 | **/ 148 | function prev() { 149 | return $this->skip(-1); 150 | } 151 | 152 | /** 153 | * Save mapped record 154 | * @return mixed 155 | **/ 156 | function save() { 157 | return $this->query?$this->update():$this->insert(); 158 | } 159 | 160 | /** 161 | * Delete current record 162 | * @return int|bool 163 | **/ 164 | function erase() { 165 | $this->query=array_slice($this->query,0,$this->ptr,TRUE)+ 166 | array_slice($this->query,$this->ptr,NULL,TRUE); 167 | $this->ptr=0; 168 | } 169 | 170 | /** 171 | * Reset cursor 172 | * @return NULL 173 | **/ 174 | function reset() { 175 | $this->query=array(); 176 | $this->ptr=0; 177 | } 178 | 179 | } 180 | -------------------------------------------------------------------------------- /ui/js/application.js: -------------------------------------------------------------------------------- 1 | // NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT 2 | // IT'S ALL JUST JUNK FOR OUR DOCS! 3 | // ++++++++++++++++++++++++++++++++++++++++++ 4 | 5 | !function ($) { 6 | 7 | $(function(){ 8 | 9 | var $window = $(window) 10 | 11 | // Disable certain links in docs 12 | $('section [href^=#]').click(function (e) { 13 | e.preventDefault() 14 | }) 15 | 16 | // back to top 17 | setTimeout(function () { 18 | $('.bs-sidebar').affix({ 19 | offset: { 20 | top: function () { return $window.width() <= 980 ? 290 : 210 } 21 | , bottom: 270 22 | } 23 | }) 24 | }, 100) 25 | 26 | setTimeout(function () { 27 | $('.bs-top').affix() 28 | }, 100) 29 | 30 | // add-ons 31 | $('.add-on :checkbox').on('click', function () { 32 | var $this = $(this) 33 | , method = $this.attr('checked') ? 'addClass' : 'removeClass' 34 | $(this).parents('.add-on')[method]('active') 35 | }) 36 | 37 | // add tipsies to grid for scaffolding 38 | if ($('#grid-system').length) { 39 | $('#grid-system').tooltip({ 40 | selector: '.show-grid > [class*="span"]' 41 | , title: function () { return $(this).width() + 'px' } 42 | }) 43 | } 44 | 45 | // tooltip demo 46 | $('.tooltip-demo').tooltip({ 47 | selector: "a[data-toggle=tooltip]" 48 | }) 49 | 50 | $('.tooltip-test').tooltip() 51 | $('.popover-test').popover() 52 | 53 | $('.bs-docs-navbar').tooltip({ 54 | selector: "a[data-toggle=tooltip]", 55 | container: ".bs-docs-navbar .nav" 56 | }) 57 | 58 | // popover demo 59 | $("a[data-toggle=popover]") 60 | .popover() 61 | .click(function(e) { 62 | e.preventDefault() 63 | }) 64 | 65 | // button state demo 66 | $('#fat-btn') 67 | .click(function () { 68 | var btn = $(this) 69 | btn.button('loading') 70 | setTimeout(function () { 71 | btn.button('reset') 72 | }, 3000) 73 | }) 74 | 75 | // carousel demo 76 | $('.bs-docs-carousel-example').carousel() 77 | 78 | // javascript build logic 79 | var inputsComponent = $("#components.download input") 80 | , inputsPlugin = $("#plugins.download input") 81 | , inputsVariables = $("#variables.download input") 82 | 83 | // toggle all plugin checkboxes 84 | $('#components.download .toggle-all').on('click', function (e) { 85 | e.preventDefault() 86 | inputsComponent.attr('checked', !inputsComponent.is(':checked')) 87 | }) 88 | 89 | $('#plugins.download .toggle-all').on('click', function (e) { 90 | e.preventDefault() 91 | inputsPlugin.attr('checked', !inputsPlugin.is(':checked')) 92 | }) 93 | 94 | $('#variables.download .toggle-all').on('click', function (e) { 95 | e.preventDefault() 96 | inputsVariables.val('') 97 | }) 98 | 99 | // request built javascript 100 | $('.download-btn .btn').on('click', function () { 101 | 102 | var css = $("#components.download input:checked") 103 | .map(function () { return this.value }) 104 | .toArray() 105 | , js = $("#plugins.download input:checked") 106 | .map(function () { return this.value }) 107 | .toArray() 108 | , vars = {} 109 | , img = ['glyphicons-halflings.png', 'glyphicons-halflings-white.png'] 110 | 111 | $("#variables.download input") 112 | .each(function () { 113 | $(this).val() && (vars[ $(this).prev().text() ] = $(this).val()) 114 | }) 115 | 116 | $.ajax({ 117 | type: 'POST' 118 | , url: /\?dev/.test(window.location) ? 'http://localhost:3000' : 'http://bootstrap.herokuapp.com' 119 | , dataType: 'jsonpi' 120 | , params: { 121 | js: js 122 | , css: css 123 | , vars: vars 124 | , img: img 125 | } 126 | }) 127 | }) 128 | }) 129 | 130 | // Modified from the original jsonpi https://github.com/benvinegar/jquery-jsonpi 131 | $.ajaxTransport('jsonpi', function(opts, originalOptions, jqXHR) { 132 | var url = opts.url; 133 | 134 | return { 135 | send: function(_, completeCallback) { 136 | var name = 'jQuery_iframe_' + jQuery.now() 137 | , iframe, form 138 | 139 | iframe = $('