├── cache └── .gitignore ├── test ├── Tpl │ └── Tests │ │ ├── _files │ │ └── template.html │ │ ├── Tpl │ │ ├── PluginTest.php │ │ └── PluginContainerTest.php │ │ └── TplTest.php └── bootstrap.php ├── .gitignore ├── templates ├── multiple-template-directories │ ├── base │ │ └── subfolder │ │ │ ├── head.html │ │ │ └── index.html │ └── newimplement │ │ └── subfolder │ │ ├── gnb.html │ │ └── index.html ├── raintpl3 │ ├── img │ │ ├── bg │ │ ├── bg.gif │ │ ├── list │ │ ├── easy.jpg │ │ ├── fast.jpg │ │ ├── list.jpg │ │ ├── logo.gif │ │ ├── logo.jpg │ │ ├── top.gif │ │ ├── bottom.gif │ │ ├── pencil.png │ │ ├── search.gif │ │ ├── useful.jpg │ │ ├── wysiwyg.jpg │ │ ├── easy_text.jpg │ │ ├── fast_text.jpg │ │ ├── googlegroup.jpg │ │ ├── home_title.jpg │ │ ├── useful_text.jpg │ │ ├── wysiwyg_text.jpg │ │ ├── groups_logo_sm.gif │ │ ├── groups_logo_sm.jpg │ │ └── groups_logo_sm.png │ ├── subfolder │ │ └── footer.html │ ├── css │ │ └── style.css │ └── page.html ├── raintpl2 │ ├── img │ │ ├── logo.gif │ │ ├── top.gif │ │ └── bottom.gif │ ├── style.css │ └── page.html ├── image_resize │ ├── img │ │ ├── logo.jpeg │ │ └── wysiwyg.jpg │ ├── page.html │ └── style.css ├── compress │ ├── test.js │ ├── style.css │ └── test_compress.html ├── simple │ ├── simple_template.html │ └── style.css ├── bootstrap │ ├── lib │ │ ├── bootstrap.less │ │ ├── variables.less │ │ ├── scaffolding.less │ │ ├── type.less │ │ ├── reset.less │ │ ├── tables.less │ │ ├── mixins.less │ │ └── forms.less │ ├── js │ │ ├── bootstrap-dropdown.js │ │ ├── bootstrap-buttons.js │ │ ├── bootstrap-tabs.js │ │ ├── bootstrap-popover.js │ │ ├── bootstrap-scrollspy.js │ │ ├── bootstrap-alerts.js │ │ ├── bootstrap-modal.js │ │ └── bootstrap-twipsy.js │ └── hero.html ├── nested_loop │ ├── test.html │ └── style.css └── test │ ├── style.css │ └── test.html ├── .travis.yml ├── composer.json ├── example-multiple-template-directories.php ├── phpunit.xml.dist ├── example-simple.php ├── library └── Rain │ ├── Tpl │ ├── NotFoundException.php │ ├── Exception.php │ ├── IPlugin.php │ ├── SyntaxException.php │ ├── Plugin.php │ ├── PluginContainer.php │ └── Plugin │ │ ├── PathReplace.php │ │ ├── ImageResize.php │ │ └── Compress.php │ ├── autoload.php │ └── Tpl.php ├── example-extend-class.php ├── example-webpage.php ├── example-webpage-new.php ├── example-plugin-compress.php ├── example-bootstrap.php ├── example-nested-loop.php ├── example-plugin-img-resize.php ├── README.md ├── example-all.php └── example-draw-string.php /cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /test/Tpl/Tests/_files/template.html: -------------------------------------------------------------------------------- 1 | template -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | nbproject 3 | vendor/* 4 | test/cache/* 5 | -------------------------------------------------------------------------------- /templates/multiple-template-directories/base/subfolder/head.html: -------------------------------------------------------------------------------- 1 | Old Header -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | - 5.6 8 | -------------------------------------------------------------------------------- /templates/multiple-template-directories/base/subfolder/index.html: -------------------------------------------------------------------------------- 1 | {include="head"} 2 | Old Index -------------------------------------------------------------------------------- /templates/multiple-template-directories/newimplement/subfolder/gnb.html: -------------------------------------------------------------------------------- 1 | {include="head"} 2 | New GNB -------------------------------------------------------------------------------- /templates/raintpl3/img/bg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/bg -------------------------------------------------------------------------------- /templates/raintpl3/img/bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/bg.gif -------------------------------------------------------------------------------- /templates/raintpl3/img/list: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/list -------------------------------------------------------------------------------- /templates/raintpl2/img/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl2/img/logo.gif -------------------------------------------------------------------------------- /templates/raintpl2/img/top.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl2/img/top.gif -------------------------------------------------------------------------------- /templates/raintpl3/img/easy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/easy.jpg -------------------------------------------------------------------------------- /templates/raintpl3/img/fast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/fast.jpg -------------------------------------------------------------------------------- /templates/raintpl3/img/list.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/list.jpg -------------------------------------------------------------------------------- /templates/raintpl3/img/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/logo.gif -------------------------------------------------------------------------------- /templates/raintpl3/img/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/logo.jpg -------------------------------------------------------------------------------- /templates/raintpl3/img/top.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/top.gif -------------------------------------------------------------------------------- /templates/raintpl2/img/bottom.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl2/img/bottom.gif -------------------------------------------------------------------------------- /templates/raintpl3/img/bottom.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/bottom.gif -------------------------------------------------------------------------------- /templates/raintpl3/img/pencil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/pencil.png -------------------------------------------------------------------------------- /templates/raintpl3/img/search.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/search.gif -------------------------------------------------------------------------------- /templates/raintpl3/img/useful.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/useful.jpg -------------------------------------------------------------------------------- /templates/raintpl3/img/wysiwyg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/wysiwyg.jpg -------------------------------------------------------------------------------- /templates/image_resize/img/logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/image_resize/img/logo.jpeg -------------------------------------------------------------------------------- /templates/raintpl3/img/easy_text.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/easy_text.jpg -------------------------------------------------------------------------------- /templates/raintpl3/img/fast_text.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/fast_text.jpg -------------------------------------------------------------------------------- /templates/image_resize/img/wysiwyg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/image_resize/img/wysiwyg.jpg -------------------------------------------------------------------------------- /templates/multiple-template-directories/newimplement/subfolder/index.html: -------------------------------------------------------------------------------- 1 | {include="gnb"} 2 | This is new implement Index Source -------------------------------------------------------------------------------- /templates/raintpl3/img/googlegroup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/googlegroup.jpg -------------------------------------------------------------------------------- /templates/raintpl3/img/home_title.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/home_title.jpg -------------------------------------------------------------------------------- /templates/raintpl3/img/useful_text.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/useful_text.jpg -------------------------------------------------------------------------------- /templates/raintpl3/img/wysiwyg_text.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/wysiwyg_text.jpg -------------------------------------------------------------------------------- /templates/raintpl3/img/groups_logo_sm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/groups_logo_sm.gif -------------------------------------------------------------------------------- /templates/raintpl3/img/groups_logo_sm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/groups_logo_sm.jpg -------------------------------------------------------------------------------- /templates/raintpl3/img/groups_logo_sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feulf/raintpl3/HEAD/templates/raintpl3/img/groups_logo_sm.png -------------------------------------------------------------------------------- /templates/compress/test.js: -------------------------------------------------------------------------------- 1 | var testClass = { 2 | testFunction: function(){ 3 | alert('this is a test, Javascript can break easily so test your JS before use the CompressPlugin in production'); 4 | } 5 | }; 6 | testClass.testFunction(); -------------------------------------------------------------------------------- /templates/raintpl3/subfolder/footer.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/simple/simple_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Simple template 5 | 6 | 7 | 8 | 9 | 10 |

Variable

11 | Hi {$name}, this is a beautiful day for a Jedi! 12 | 13 |
14 |
15 | 16 |

Week

17 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rain/raintpl", 3 | "type": "library", 4 | "description": "easy and fast template engine", 5 | "homepage":"http://raintpl.com", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Federico Ulfo", 10 | "email": "rainelemental@gmail.com" 11 | }, 12 | { 13 | "name": "Rain Community" 14 | } 15 | ], 16 | "require": { 17 | "php": ">=5.3" 18 | }, 19 | "require-dev": { 20 | "phpunit/phpunit": "4.4.*" 21 | }, 22 | "minimum-stability": "dev", 23 | "autoload": { 24 | "psr-0": { 25 | "Rain": "library/" 26 | } 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /templates/bootstrap/lib/bootstrap.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap @VERSION 3 | * 4 | * Copyright 2011 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | * Date: @DATE 10 | */ 11 | 12 | // CSS Reset 13 | @import "reset.less"; 14 | 15 | // Core variables and mixins 16 | @import "variables.less"; // Modify this for custom colors, font-sizes, etc 17 | @import "mixins.less"; 18 | 19 | // Grid system and page structure 20 | @import "scaffolding.less"; 21 | 22 | // Styled patterns and elements 23 | @import "type.less"; 24 | @import "forms.less"; 25 | @import "tables.less"; 26 | @import "patterns.less"; -------------------------------------------------------------------------------- /example-multiple-template-directories.php: -------------------------------------------------------------------------------- 1 | array( 12 | "templates/multiple-template-directories/newimplement/", 13 | "templates/multiple-template-directories/base/" 14 | ), 15 | "cache_dir" => "cache/", 16 | "debug" => true, // set to false to improve the speed 17 | ); 18 | 19 | Tpl::configure($config); 20 | 21 | 22 | // Add PathReplace plugin (necessary to load the CSS with path replace) 23 | Tpl::registerPlugin(new Tpl\Plugin\PathReplace()); 24 | 25 | 26 | // create the Tpl object 27 | $tpl = new Tpl; 28 | $tpl->draw("subfolder/index"); 29 | 30 | ?> -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 15 | 16 | ./test/Tpl/ 17 | 18 | 19 | 20 | 21 | 22 | ./library/Rain/ 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /templates/raintpl2/style.css: -------------------------------------------------------------------------------- 1 | /* CSS Document */ 2 | 3 | body{ margin:0px; color:#333; font: 13px Helvetica; background:#eee;} 4 | a{ color: #333; } 5 | a:hover{ color: #999; } 6 | img{border:0px;} 7 | 8 | #logo{width:100%;height:80px;background:url('img/top.gif') repeat-x #666;} 9 | #content{ height: 100%;padding:20px; } 10 | #footer{background: url('img/bottom.gif') repeat-x;color:#ccff00; padding:15px; text-align:center;} 11 | #footer a{color:#ccff00;} 12 | 13 | .layout{background:#fff;border: 1px solid #ccc; padding:20px;margin-bottom:30px;} 14 | code{ display:block;font:12px monospace; background: #e9ffe9;padding: 15px; border: solid 1px #ccddcc; margin-bottom:10px;} 15 | tt{ display:block; font:12px monospace; background: #f6fdfd; padding: 15px; border: solid 1px #ccdddd; margin-bottom:0 0 10px 0; } 16 | 17 | .color1{background:#eeeeff;} 18 | .color2{background:#ddddee;} -------------------------------------------------------------------------------- /example-simple.php: -------------------------------------------------------------------------------- 1 | "templates/simple/", 12 | "cache_dir" => "cache/", 13 | "debug" => true, // set to false to improve the speed 14 | ); 15 | 16 | Tpl::configure( $config ); 17 | 18 | 19 | // Add PathReplace plugin (necessary to load the CSS with path replace) 20 | Tpl::registerPlugin( new Tpl\Plugin\PathReplace() ); 21 | 22 | 23 | // create the Tpl object 24 | $tpl = new Tpl; 25 | 26 | // assign a variable 27 | $tpl->assign( "name", "Obi Wan Kenoby" ); 28 | 29 | // assign an array 30 | $tpl->assign( "week", array( "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ) ); 31 | 32 | // draw the template 33 | $tpl->draw( "simple_template" ); 34 | 35 | 36 | ?> -------------------------------------------------------------------------------- /templates/nested_loop/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test 5 | 6 | 7 | 8 | 9 |

Loop NEST example with associative array

10 | 11 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /templates/image_resize/page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {$title} 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Image resize plugin

13 | 14 | Original image


15 | 16 | Resized and cropped image


17 | 18 | Image resized but not cropped


19 | 20 | This image is not resized by PHP, only by the browser:


21 | 22 |
23 | 24 | Original image


25 | 26 | Resized


27 | 28 | Resized and Cropped


29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /templates/test/style.css: -------------------------------------------------------------------------------- 1 | body{font-family:Helvetica;font-size:14px;color:#333;} 2 | a{color:#333;text-decoration:none} 3 | a:hover{color:#393;text-decoration:underline} 4 | h1{color:#393;font-size:24px;font-weight:normal;} 5 | h2{color:#369;font-size:20px;font-weight:normal;} 6 | h3{color:#333;font-size:17px;font-weight:normal;} 7 | 8 | #msg{color:#666;background:#efc;border-top:5px solid #ac0;padding:10px;} 9 | #msg span{color:#ac0} 10 | #msg a:hover{color:#ac0} 11 | 12 | section, header, nav, footer {width:900px;margin:0 auto;} 13 | header {height:100px;margin-top:50px} 14 | nav a{margin-right:30px} 15 | section{margin-top:50px;} 16 | 17 | footer{font-size:11px;clear:both;} 18 | footer a{margin-right:10px} 19 | 20 | #slogan{background:red;float:left;clear:both;height:300px;width:900px;background:red;list-style:none;padding:0px;margin:0px;overflow:auto;} 21 | #slogan li{float:left;clear:both;padding:0px;margin:0px;background:red;float:left;clear:both;height:300px;width:900px;background:red;list-style:none;overflow:auto;} 22 | .block_separator{float:left;margin:30px;} 23 | .block{float:left;width:170px;margin:80px 0 30px} 24 | .block div{font-size:14px;color:#777;margin:0 0 10px 10px} 25 | 26 | .left{float:left;} 27 | .right{float:right;} 28 | -------------------------------------------------------------------------------- /templates/compress/style.css: -------------------------------------------------------------------------------- 1 | body{font-family:Helvetica;font-size:14px;color:#333;} 2 | a{color:#333;text-decoration:none} 3 | a:hover{color:#393;text-decoration:underline} 4 | h1{color:#393;font-size:24px;font-weight:normal;} 5 | h2{color:#369;font-size:20px;font-weight:normal;} 6 | h3{color:#333;font-size:17px;font-weight:normal;} 7 | 8 | #msg{color:#666;background:#efc;border-top:5px solid #ac0;padding:10px;} 9 | #msg span{color:#ac0} 10 | #msg a:hover{color:#ac0} 11 | 12 | section, header, nav, footer {width:900px;margin:0 auto;} 13 | header {height:100px;margin-top:50px} 14 | nav a{margin-right:30px} 15 | section{margin-top:50px;} 16 | 17 | footer{font-size:11px;clear:both;} 18 | footer a{margin-right:10px} 19 | 20 | #slogan{background:red;float:left;clear:both;height:300px;width:900px;background:red;list-style:none;padding:0px;margin:0px;overflow:auto;} 21 | #slogan li{float:left;clear:both;padding:0px;margin:0px;background:red;float:left;clear:both;height:300px;width:900px;background:red;list-style:none;overflow:auto;} 22 | .block_separator{float:left;margin:30px;} 23 | .block{float:left;width:170px;margin:80px 0 30px} 24 | .block div{font-size:14px;color:#777;margin:0 0 10px 10px} 25 | 26 | .left{float:left;} 27 | .right{float:right;} 28 | -------------------------------------------------------------------------------- /templates/simple/style.css: -------------------------------------------------------------------------------- 1 | body{font-family:Helvetica;font-size:14px;color:#333;} 2 | a{color:#333;text-decoration:none} 3 | a:hover{color:#393;text-decoration:underline} 4 | h1{color:#393;font-size:24px;font-weight:normal;} 5 | h2{color:#369;font-size:20px;font-weight:normal;} 6 | h3{color:#333;font-size:17px;font-weight:normal;} 7 | 8 | #msg{color:#666;background:#efc;border-top:5px solid #ac0;padding:10px;} 9 | #msg span{color:#ac0} 10 | #msg a:hover{color:#ac0} 11 | 12 | section, header, nav, footer {width:900px;margin:0 auto;} 13 | header {height:100px;margin-top:50px} 14 | nav a{margin-right:30px} 15 | section{margin-top:50px;} 16 | 17 | footer{font-size:11px;clear:both;} 18 | footer a{margin-right:10px} 19 | 20 | #slogan{background:red;float:left;clear:both;height:300px;width:900px;background:red;list-style:none;padding:0px;margin:0px;overflow:auto;} 21 | #slogan li{float:left;clear:both;padding:0px;margin:0px;background:red;float:left;clear:both;height:300px;width:900px;background:red;list-style:none;overflow:auto;} 22 | .block_separator{float:left;margin:30px;} 23 | .block{float:left;width:170px;margin:80px 0 30px} 24 | .block div{font-size:14px;color:#777;margin:0 0 10px 10px} 25 | 26 | .left{float:left;} 27 | .right{float:right;} 28 | -------------------------------------------------------------------------------- /templates/nested_loop/style.css: -------------------------------------------------------------------------------- 1 | body{font-family:Helvetica;font-size:14px;color:#333;} 2 | a{color:#333;text-decoration:none} 3 | a:hover{color:#393;text-decoration:underline} 4 | h1{color:#393;font-size:24px;font-weight:normal;} 5 | h2{color:#369;font-size:20px;font-weight:normal;} 6 | h3{color:#333;font-size:17px;font-weight:normal;} 7 | 8 | #msg{color:#666;background:#efc;border-top:5px solid #ac0;padding:10px;} 9 | #msg span{color:#ac0} 10 | #msg a:hover{color:#ac0} 11 | 12 | section, header, nav, footer {width:900px;margin:0 auto;} 13 | header {height:100px;margin-top:50px} 14 | nav a{margin-right:30px} 15 | section{margin-top:50px;} 16 | 17 | footer{font-size:11px;clear:both;} 18 | footer a{margin-right:10px} 19 | 20 | #slogan{background:red;float:left;clear:both;height:300px;width:900px;background:red;list-style:none;padding:0px;margin:0px;overflow:auto;} 21 | #slogan li{float:left;clear:both;padding:0px;margin:0px;background:red;float:left;clear:both;height:300px;width:900px;background:red;list-style:none;overflow:auto;} 22 | .block_separator{float:left;margin:30px;} 23 | .block{float:left;width:170px;margin:80px 0 30px} 24 | .block div{font-size:14px;color:#777;margin:0 0 10px 10px} 25 | 26 | .left{float:left;} 27 | .right{float:right;} 28 | -------------------------------------------------------------------------------- /templates/image_resize/style.css: -------------------------------------------------------------------------------- 1 | *{margin:0;padding:0} 2 | body{font-family:Helvetica;font-size:14px;color:#333;} 3 | a{color:#333;text-decoration:none} 4 | a:hover{color:#393;text-decoration:underline} 5 | h1{color:#393;font-size:24px;font-weight:normal;} 6 | h2{color:#369;font-size:20px;font-weight:normal;} 7 | h3{color:#333;font-size:17px;font-weight:normal;} 8 | 9 | #msg{color:#666;background:#efc;border-top:5px solid #ac0;padding:10px;} 10 | #msg span{color:#ac0} 11 | #msg a:hover{color:#ac0} 12 | 13 | section, header, nav, footer {width:900px;margin:0 auto;} 14 | header {height:100px;margin-top:50px} 15 | nav a{margin-right:30px} 16 | section{margin-top:50px;} 17 | 18 | footer{font-size:11px;clear:both;} 19 | footer a{margin-right:10px} 20 | 21 | #slogan{background:red;float:left;clear:both;height:300px;width:900px;background:red;list-style:none;padding:0px;margin:0px;overflow:auto;} 22 | #slogan li{float:left;clear:both;padding:0px;margin:0px;background:red;float:left;clear:both;height:300px;width:900px;background:red;list-style:none;overflow:auto;} 23 | .block_separator{float:left;margin:30px;} 24 | .block{float:left;width:170px;margin:80px 0 30px} 25 | .block div{font-size:14px;color:#777;margin:0 0 10px 10px} 26 | 27 | .left{float:left;} 28 | .right{float:right;} 29 | -------------------------------------------------------------------------------- /templates/raintpl3/css/style.css: -------------------------------------------------------------------------------- 1 | *{margin:0;padding:0} 2 | body{font-family:Helvetica;font-size:14px;color:#333;} 3 | a{color:#333;text-decoration:none} 4 | a:hover{color:#393;text-decoration:underline} 5 | h1{color:#393;font-size:24px;font-weight:normal;} 6 | h2{color:#369;font-size:20px;font-weight:normal;} 7 | h3{color:#333;font-size:17px;font-weight:normal;} 8 | 9 | #msg{color:#666;background:#efc;border-top:5px solid #ac0;padding:10px;} 10 | #msg span{color:#ac0} 11 | #msg a:hover{color:#ac0} 12 | 13 | section, header, nav, footer {width:900px;margin:0 auto;clear:both;} 14 | header {height:100px;margin-top:50px} 15 | nav a{margin-right:30px} 16 | section{margin-top:50px;} 17 | 18 | footer {margin-bottom:50px;font-size:11px;} 19 | footer a{margin-right:10px;} 20 | 21 | #slogan{background:red;float:left;clear:both;height:300px;width:900px;background:red;list-style:none;padding:0px;margin:0px;overflow:auto;} 22 | #slogan li{float:left;clear:both;padding:0px;margin:0px;background:red;float:left;clear:both;height:300px;width:900px;background:red;list-style:none;overflow:auto;} 23 | .block_separator{float:left;margin:30px;} 24 | .block{float:left;width:170px;margin:80px 0 30px} 25 | .block div{font-size:14px;color:#777;margin:0 0 10px 10px} 26 | 27 | .left{float:left;} 28 | .right{float:right;} 29 | -------------------------------------------------------------------------------- /library/Rain/Tpl/NotFoundException.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test 5 | 6 | 7 | 8 | 9 | 10 | {* This is a comment *} 11 | 12 |

Test Rain Tpl {$version}

13 |
14 | 15 |

Variables

16 | Variable: {$variable}

17 | Init Variable {$v = 10}

18 | Show Variable {$v}

19 | Modifier {$variable|strlen}

20 | Cascade Modifier {$variable|substr:2,5|strlen}

21 | Scoping (array) {$week.0}

22 | Var test {$variable}

23 | 24 | 25 |

Loop

26 | Simple Loop 27 |

34 | 35 | Modifier on Loop 36 |

41 | 42 | Simple Nested Loop 43 |

52 | 53 | Loop on created array 54 |

59 | 60 |

If

61 | True condition: {if="true"}This is true{/if}

62 | Modifier inside if: {if="$variable|is_string"}True{/if}

63 | 64 | 65 | -------------------------------------------------------------------------------- /test/bootstrap.php: -------------------------------------------------------------------------------- 1 | var[$key] : $this->var; 16 | } 17 | 18 | // set function 19 | function __set( $key, $value ){ 20 | $this->var[$key] = $value; 21 | } 22 | 23 | } 24 | 25 | 26 | // conf 27 | $config = array( 28 | "base_url" => null, 29 | "tpl_dir" => "templates/raintpl3/", 30 | "cache_dir" => "cache/", 31 | "debug" => true, // set to false to improve the speed 32 | "charset" => "iso-8859-1", 33 | ); 34 | 35 | //use Rain; 36 | MyRainTPL::configure( $config ); 37 | 38 | 39 | // Add PathReplace plugin 40 | MyRainTPL::registerPlugin( new Tpl\Plugin\PathReplace() ); 41 | 42 | 43 | global $global_variable; 44 | $global_variable = "I'm Global"; 45 | 46 | 47 | // draw 48 | $tpl = new MyRainTPL; 49 | $tpl->variable = "Hello World"; 50 | $tpl->version = "3.0 Alpha"; 51 | $tpl->menu = array( 52 | array("name" => "Home", "link" => "index.php", "selected" => true ), 53 | array("name" => "FAQ", "link" => "index.php/FAQ/", "selected" => null ), 54 | array("name" => "Documentation", "link" => "index.php/doc/", "selected" => null ) 55 | ); 56 | $tpl->title = "Rain TPL 3 - Easy and Fast template engine"; 57 | $tpl->copyright = "Copyright 2006 - 2012 Rain TPL
Project By Rain Team"; 58 | 59 | $tpl->draw( 'page' ); 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /example-webpage.php: -------------------------------------------------------------------------------- 1 | null, 12 | "tpl_dir" => "templates/raintpl2/", 13 | "cache_dir" => "cache/", 14 | "debug" => true // set to false to improve the speed 15 | ); 16 | Tpl::configure( $config ); 17 | 18 | // Add PathReplace plugin 19 | Tpl::registerPlugin( new Tpl\Plugin\PathReplace() ); 20 | 21 | 22 | global $global_variable; 23 | $global_variable = "I'm Global"; 24 | 25 | // set variables 26 | $var = array( 27 | "variable" => "Hello", 28 | "version" => "3.0 Alpha", 29 | "menu" => array( 30 | array("name" => "Home", "link" => "index.php", "selected" => true ), 31 | array("name" => "FAQ", "link" => "index.php/FAQ/", "selected" => null ), 32 | array("name" => "Documentation", "link" => "index.php/doc/", "selected" => null ) 33 | ), 34 | "week" => array( "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ), 35 | "title" => "Rain TPL 3 - Easy and Fast template engine", 36 | "user" => array( 37 | array("name" => "Fede", "color" => "blue" ), 38 | array("name" => "Sheska", "color" => "red" ), 39 | array("name" => "Who", "color" => "yellow" ), 40 | ), 41 | "empty_array" => array(), 42 | "copyright" => "Copyright 2006 - 2012 Rain TPL
Project By Rain Team", 43 | 44 | ); 45 | 46 | function test( $params ){ 47 | $value = $params[0]; 48 | return "Translate: $value"; 49 | }; 50 | // add a function 51 | Tpl::registerTag( "({@.*?@})", "{@(.*?)@}", "test" ); 52 | 53 | 54 | 55 | // draw 56 | $tpl = new Tpl; 57 | $tpl->assign( $var ); 58 | echo $tpl->draw( "page" ); -------------------------------------------------------------------------------- /example-webpage-new.php: -------------------------------------------------------------------------------- 1 | null, 12 | "tpl_dir" => "templates/raintpl3/", 13 | "cache_dir" => "cache/", 14 | "debug" => true // set to false to improve the speed 15 | ); 16 | 17 | //use Rain; 18 | Tpl::configure( $config ); 19 | 20 | 21 | // Add PathReplace plugin 22 | Tpl::registerPlugin( new Rain\Tpl\Plugin\PathReplace() ); 23 | 24 | 25 | global $global_variable; 26 | $global_variable = "I'm Global"; 27 | 28 | // set variables 29 | $var = array( 30 | "variable" => "Hello", 31 | "version" => "3.0 Alpha", 32 | "menu" => array( 33 | array("name" => "Home", "link" => "index.php", "selected" => true ), 34 | array("name" => "FAQ", "link" => "index.php/FAQ/", "selected" => null ), 35 | array("name" => "Documentation", "link" => "index.php/doc/", "selected" => null ) 36 | ), 37 | "week" => array( "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ), 38 | "title" => "Rain TPL 3 - Easy and Fast template engine", 39 | "user" => array( 40 | array("name" => "Fede", "color" => "blue" ), 41 | array("name" => "Sheska", "color" => "red" ), 42 | array("name" => "Who", "color" => "yellow" ), 43 | ), 44 | "empty_array" => array(), 45 | "copyright" => "Copyright 2006 - 2012 Rain TPL
Project By Rain Team", 46 | 47 | ); 48 | 49 | $test = function( $params ){ 50 | $value = $params[0]; 51 | return "Translate: $value"; 52 | }; 53 | // add a function 54 | Tpl::registerTag( "({@.*?@})", "{@(.*?)@}", $test ); 55 | 56 | 57 | 58 | // draw 59 | $tpl = new Tpl; 60 | $tpl->assign( $var ); 61 | echo $tpl->draw( "page" ); 62 | 63 | 64 | // end -------------------------------------------------------------------------------- /example-plugin-compress.php: -------------------------------------------------------------------------------- 1 | null, 14 | "tpl_dir" => "templates/compress/", 15 | "cache_dir" => "cache/", 16 | "debug" => true // set to false to improve the speed 17 | ); 18 | 19 | Tpl::configure( $config ); 20 | Tpl::registerPlugin( new Tpl\Plugin\PathReplace ); 21 | 22 | $compress = new Tpl\Plugin\Compress; 23 | $compress->configure('css', array('status'=>true)); 24 | $compress->configure('html', array('status'=>true)); 25 | $compress->configure('javascript', array('status'=>true, 'position' => 'bottom')); 26 | Tpl::registerPlugin($compress); 27 | 28 | 29 | global $global_variable; 30 | $global_variable = "I'm Global"; 31 | 32 | // set variables 33 | $var = array( 34 | "variable" => "Hello", 35 | "version" => "3.0 Alpha", 36 | "menu" => array( 37 | array("name" => "Home", "link" => "index.php", "selected" => true ), 38 | array("name" => "FAQ", "link" => "index.php/FAQ/", "selected" => null ), 39 | array("name" => "Documentation", "link" => "index.php/doc/", "selected" => null ) 40 | ), 41 | "week" => array( "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ), 42 | "title" => "Rain TPL 3 - Easy and Fast template engine", 43 | "user" => array( 44 | array("name" => "Fede", "color" => "blue" ), 45 | array("name" => "Laura", "color" => "red" ), 46 | array("name" => "Who", "color" => "yellow" ), 47 | ), 48 | "empty_array" => array(), 49 | "copyright" => "Copyright 2006 - 2012 Rain TPL
Project By Rain Team", 50 | 51 | ); 52 | 53 | // draw 54 | $tpl = new Tpl; 55 | $tpl->assign( $var ); 56 | $tpl->draw( "test_compress" ); 57 | -------------------------------------------------------------------------------- /example-bootstrap.php: -------------------------------------------------------------------------------- 1 | null, 13 | "tpl_dir" => "templates/", 14 | "cache_dir" => "cache/", 15 | "debug" => true // set to false to improve the speed 16 | ); 17 | Tpl::configure( $config ); 18 | 19 | 20 | // Add PathReplace plugin 21 | Tpl::registerPlugin( new Tpl\Plugin\PathReplace() ); 22 | 23 | 24 | 25 | // set variables 26 | $var = array( 27 | "variable" => "Hello World!", 28 | "version" => "3.0 Alpha", 29 | "menu" => array( 30 | array("name" => "Home", "link" => "index.php", "selected" => true ), 31 | array("name" => "FAQ", "link" => "index.php/FAQ/", "selected" => null ), 32 | array("name" => "Documentation", "link" => "index.php/doc/", "selected" => null ) 33 | ), 34 | "week" => array( "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ), 35 | "user" => (object) array("name"=>"Rain", "citizen" => "Earth", "race" => "Human" ), 36 | "numbers" => array( 3, 2, 1 ), 37 | "bad_text" => 'Hey this is a malicious XSS ', 38 | "table" => array( array( "Apple", "1996" ), array( "PC", "1997" ) ), 39 | "title" => "Rain TPL 3 - Easy and Fast template engine", 40 | "copyright" => "Copyright 2006 - 2012 Rain TPL
Project By Rain Team", 41 | 42 | ); 43 | 44 | // add a function 45 | Tpl::registerTag( "({@.*?@})", // preg split 46 | "{@(.*?)@}", // preg match 47 | function( $params ){ // function called by the tag 48 | $value = $params[0]; 49 | return "Translate: $value"; 50 | } 51 | ); 52 | 53 | // draw 54 | $tpl = new Tpl; 55 | $tpl->assign( $var ); 56 | echo $tpl->draw( "bootstrap/hero" ); 57 | 58 | 59 | // end -------------------------------------------------------------------------------- /templates/bootstrap/js/bootstrap-dropdown.js: -------------------------------------------------------------------------------- 1 | /* ============================================================ 2 | * bootstrap-dropdown.js v1.4.0 3 | * http://twitter.github.com/bootstrap/javascript.html#dropdown 4 | * ============================================================ 5 | * Copyright 2011 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================ */ 19 | 20 | 21 | !function( $ ){ 22 | 23 | "use strict" 24 | 25 | /* DROPDOWN PLUGIN DEFINITION 26 | * ========================== */ 27 | 28 | $.fn.dropdown = function ( selector ) { 29 | return this.each(function () { 30 | $(this).delegate(selector || d, 'click', function (e) { 31 | var li = $(this).parent('li') 32 | , isActive = li.hasClass('open') 33 | 34 | clearMenus() 35 | !isActive && li.toggleClass('open') 36 | return false 37 | }) 38 | }) 39 | } 40 | 41 | /* APPLY TO STANDARD DROPDOWN ELEMENTS 42 | * =================================== */ 43 | 44 | var d = 'a.menu, .dropdown-toggle' 45 | 46 | function clearMenus() { 47 | $(d).parent('li').removeClass('open') 48 | } 49 | 50 | $(function () { 51 | $('html').bind("click", clearMenus) 52 | $('body').dropdown( '[data-dropdown] a.menu, [data-dropdown] .dropdown-toggle' ) 53 | }) 54 | 55 | }( window.jQuery || window.ender ); 56 | -------------------------------------------------------------------------------- /library/Rain/Tpl/Exception.php: -------------------------------------------------------------------------------- 1 | templateFile; 47 | 48 | $this->templateFile = (string) $templateFile; 49 | return $this; 50 | } 51 | } 52 | 53 | // -- end 54 | -------------------------------------------------------------------------------- /example-nested-loop.php: -------------------------------------------------------------------------------- 1 | null, 12 | "tpl_dir" => "templates/nested_loop/", 13 | "cache_dir" => "cache/", 14 | "debug" => true // set to false to improve the speed 15 | ); 16 | 17 | Tpl::configure( $config ); 18 | 19 | 20 | // Add PathReplace plugin 21 | Tpl::registerPlugin( new Tpl\Plugin\PathReplace() ); 22 | 23 | 24 | 25 | $user = array( 26 | array( 27 | 'name' => 'Jupiter', 28 | 'color' => 'yellow', 29 | 'orders' => array( 30 | array('order_id' => '123', 'order_name' => 'o1d'), 31 | array('order_id' => '1sn24', 'order_name' => 'o2d') 32 | ) 33 | ), 34 | array( 35 | 'name' => 'Mars', 36 | 'color' => 'red', 37 | 'orders' => array( 38 | array('order_id' => '3rf22', 'order_name' => '¶©µ¥Aj') 39 | ) 40 | ), 41 | array( 42 | 'name' => 'Empty', 43 | 'color' => 'blue', 44 | 'orders' => array( 45 | ) 46 | ), 47 | array( 48 | 'name' => 'Earth', 49 | 'color' => 'blue', 50 | 'orders' => array( 51 | array('order_id' => '2315', 'order_name' => '¶©µ¥15'), 52 | array('order_id' => 'rf2123', 'order_name' => '¶©µ¥215'), 53 | array('order_id' => '0231', 'order_name' => '¶©µ¥315'), 54 | array('order_id' => 'sn09-0fsd', 'order_name' => '¶©µ¥45415') 55 | ) 56 | ) 57 | ); 58 | 59 | 60 | // draw 61 | $tpl = new Tpl; 62 | $tpl->assign( "user", $user ); 63 | echo $tpl->draw( "test" ); 64 | 65 | 66 | 67 | class Test{ 68 | static public function method( $variable ){ 69 | echo "Hi I am a static method, and this is the parameter passed to me: $variable!"; 70 | } 71 | } 72 | 73 | // end -------------------------------------------------------------------------------- /example-plugin-img-resize.php: -------------------------------------------------------------------------------- 1 | null, 12 | "tpl_dir" => "templates/image_resize/", 13 | "cache_dir" => "cache/", 14 | "debug" => true // set to false to improve the speed 15 | ); 16 | Tpl::configure( $config ); 17 | 18 | 19 | // Add PathReplace plugin (necessary to load the CSS with path replace) 20 | Tpl::registerPlugin( new Tpl\Plugin\PathReplace() ); 21 | 22 | $plugin_options = array( 'quality' => 100, 'crop' => true ); 23 | Tpl::registerPlugin( new Tpl\Plugin\ImageResize( $plugin_options ) ); 24 | 25 | global $global_variable; 26 | $global_variable = "I'm Global"; 27 | 28 | // set variables 29 | $var = array( 30 | "variable" => "Hello", 31 | "version" => "3.0 Alpha", 32 | "menu" => array( 33 | array("name" => "Home", "link" => "index.php", "selected" => true ), 34 | array("name" => "FAQ", "link" => "index.php/FAQ/", "selected" => null ), 35 | array("name" => "Documentation", "link" => "index.php/doc/", "selected" => null ) 36 | ), 37 | "week" => array( "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ), 38 | "title" => "Rain TPL 3 - Easy and Fast template engine", 39 | "user" => array( 40 | array("name" => "Fede", "color" => "blue" ), 41 | array("name" => "Sheska", "color" => "red" ), 42 | array("name" => "Who", "color" => "yellow" ), 43 | ), 44 | "empty_array" => array(), 45 | "copyright" => "Copyright 2006 - 2012 Rain TPL
Project By Rain Team", 46 | 47 | ); 48 | 49 | $test = function( $params ){ 50 | $value = $params[0]; 51 | return "Translate: $value"; 52 | }; 53 | // add a function 54 | Tpl::registerTag( "({@.*?@})", "{@(.*?)@}", $test ); 55 | 56 | 57 | 58 | // draw 59 | $tpl = new Tpl; 60 | $tpl->assign( $var ); 61 | $tpl->draw( "page" ); 62 | 63 | // end -------------------------------------------------------------------------------- /templates/bootstrap/js/bootstrap-buttons.js: -------------------------------------------------------------------------------- 1 | /* ============================================================ 2 | * bootstrap-buttons.js v1.4.0 3 | * http://twitter.github.com/bootstrap/javascript.html#buttons 4 | * ============================================================ 5 | * Copyright 2011 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================ */ 19 | 20 | !function( $ ){ 21 | 22 | "use strict" 23 | 24 | function setState(el, state) { 25 | var d = 'disabled' 26 | , $el = $(el) 27 | , data = $el.data() 28 | 29 | state = state + 'Text' 30 | data.resetText || $el.data('resetText', $el.html()) 31 | 32 | $el.html( data[state] || $.fn.button.defaults[state] ) 33 | 34 | setTimeout(function () { 35 | state == 'loadingText' ? 36 | $el.addClass(d).attr(d, d) : 37 | $el.removeClass(d).removeAttr(d) 38 | }, 0) 39 | } 40 | 41 | function toggle(el) { 42 | $(el).toggleClass('active') 43 | } 44 | 45 | $.fn.button = function(options) { 46 | return this.each(function () { 47 | if (options == 'toggle') { 48 | return toggle(this) 49 | } 50 | options && setState(this, options) 51 | }) 52 | } 53 | 54 | $.fn.button.defaults = { 55 | loadingText: 'loading...' 56 | } 57 | 58 | $(function () { 59 | $('body').delegate('.btn[data-toggle]', 'click', function () { 60 | $(this).button('toggle') 61 | }) 62 | }) 63 | 64 | }( window.jQuery || window.ender ); -------------------------------------------------------------------------------- /library/Rain/autoload.php: -------------------------------------------------------------------------------- 1 | "; 47 | echo $path; 48 | echo "
"; 49 | echo $abs_path; 50 | echo "

"; 51 | } 52 | 53 | // require the file 54 | require_once $abs_path; 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /templates/bootstrap/lib/variables.less: -------------------------------------------------------------------------------- 1 | /* Variables.less 2 | * Variables to customize the look and feel of Bootstrap 3 | * ----------------------------------------------------- */ 4 | 5 | 6 | // Links 7 | @linkColor: #0069d6; 8 | @linkColorHover: darken(@linkColor, 15); 9 | 10 | // Grays 11 | @black: #000; 12 | @grayDark: lighten(@black, 25%); 13 | @gray: lighten(@black, 50%); 14 | @grayLight: lighten(@black, 75%); 15 | @grayLighter: lighten(@black, 90%); 16 | @white: #fff; 17 | 18 | // Accent Colors 19 | @blue: #049CDB; 20 | @blueDark: #0064CD; 21 | @green: #46a546; 22 | @red: #9d261d; 23 | @yellow: #ffc40d; 24 | @orange: #f89406; 25 | @pink: #c3325f; 26 | @purple: #7a43b6; 27 | 28 | // Baseline grid 29 | @basefont: 13px; 30 | @baseline: 18px; 31 | 32 | // Griditude 33 | // Modify the grid styles in mixins.less 34 | @gridColumns: 16; 35 | @gridColumnWidth: 40px; 36 | @gridGutterWidth: 20px; 37 | @extraSpace: (@gridGutterWidth * 2); // For our grid calculations 38 | @siteWidth: (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1)); 39 | 40 | // Color Scheme 41 | // Use this to roll your own color schemes if you like (unused by Bootstrap by default) 42 | @baseColor: @blue; // Set a base color 43 | @complement: spin(@baseColor, 180); // Determine a complementary color 44 | @split1: spin(@baseColor, 158); // Split complements 45 | @split2: spin(@baseColor, -158); 46 | @triad1: spin(@baseColor, 135); // Triads colors 47 | @triad2: spin(@baseColor, -135); 48 | @tetra1: spin(@baseColor, 90); // Tetra colors 49 | @tetra2: spin(@baseColor, -90); 50 | @analog1: spin(@baseColor, 22); // Analogs colors 51 | @analog2: spin(@baseColor, -22); 52 | 53 | 54 | 55 | // More variables coming soon: 56 | // - @basefont to @baseFontSize 57 | // - @baseline to @baseLineHeight 58 | // - @baseFontFamily 59 | // - @primaryButtonColor 60 | // - anything else? File an issue on GitHub -------------------------------------------------------------------------------- /templates/test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {$title} 5 | 6 | 7 | 8 | 9 | 10 | 11 | {* This is a comment *} 12 | 13 |

Test Rain Tpl {$version}

14 |
15 | 16 |

Variables

17 | Variable: {$variable}

18 | Init Variable {$v = 10}

19 | Show Variable {$v}

20 | Modifier {$variable|strlen}

21 | Cascade Modifier {$variable|substr:2,5|strlen}

22 | Scoping (object) {$user->name}

23 | Scoping (array) {$week.0}

24 | Variable as key {$week[$numbers.0]}

25 | Var test {$variable}

26 | 27 |

Ternary Operator

28 | The title is: {isset($title)?"$title":'default title'} 29 | 30 | 31 |

Loop

32 | Simple Loop 33 |

40 | 41 | Modifier on Loop 42 |

47 | 48 | Simple Nested Loop 49 |

58 | 59 | Loop on created array 60 |

65 | 66 |

If

67 | True condition: {if="true"}This is true{/if}

68 | Modifier inside if: {if="$variable|is_string"}True{/if}

69 | 70 | 71 |

Function test

72 | Simple function: {function="time"}

73 | Function with parameters: {function="date('d-m-Y')"}

74 | Static method: {function="Test::method('123test')"}

75 | 76 |

Escape Text

77 | Malicious content: {$bad_text}

78 | 79 |

Custom tag

80 | {@message to translate@}

81 | 82 |

Custom tag 2

83 | {%message to translate|english%}

84 | 85 |

Escape variable

86 | {$bad_variable} 87 | {autoescape="off"}{$safe_variable}{/autoescape} 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RainTPL 3 2 | ========= 3 | 4 | By Federico Ulfo and a lot [awesome contributors](https://github.com/rainphp/raintpl3/network)! 5 | 6 | [RainTPL](http://raintpl.com) is an easy template engine for PHP that enables designers and developers to work better together, it loads HTML template to separate the presentation from the logic. 7 | 8 | Features 9 | -------- 10 | * Easy for designers, only 10 tags, *{$variable}*, *{#constant#}*, *{include}*, *{loop}*, *{if}*, *{* comment *}*, *{noparse}*, *{function}* 11 | * Easy for developers, 5 methods to load and draw templates. 12 | * Powerful, modifier and operation with variables 13 | * Extensible, load plugins and register new tags 14 | * Secure, sandbox with blacklist. 15 | 16 | 17 | Installation / Usage 18 | -------------------- 19 | 20 | 1. Install composer https://github.com/composer/composer 21 | 2. Create a composer.json inside your application folder: 22 | 23 | ``` json 24 | { 25 | "require": { 26 | "rain/raintpl": ">=3.0.0" 27 | } 28 | } 29 | ``` 30 | 3. Run the following code 31 | 32 | ``` sh 33 | $ php composer.phar install 34 | ``` 35 | 36 | 4. Run one example of RainTPL with your browser: ```http://localhost/raintpl3/example.php``` 37 | 38 | Documentation 39 | ------------- 40 | The [documentation](https://github.com/rainphp/raintpl3/wiki/Documentation) of RainTPL is divided in [documentation for web designers](https://github.com/rainphp/raintpl3/wiki/Documentation-for-web-designers) and [documentation for PHP developers](https://github.com/rainphp/raintpl3/wiki/Documentation-for-PHP-developers). 41 | 42 | 43 | Licence 44 | ------- 45 | 46 | RainTPL 3, like its antecessor Rain.TPL version 2, is, as of 2018-06-07, published under the MIT Licence. 47 | 48 | The above applies to RainTPL 3 itself, not the entire content of this repository. Some of the `example-*.php` files and the content below `templates/` in this repository are copies of external code under various licences, such as: 49 | 50 | * Twitter Bootstrap, under the Apache v2 licence 51 | * LESS - Leaner CSS, under the Apache v2 licence 52 | 53 | Note that not all external content comes with full source code, it’s usually just a copy of (possibly minified or otherwise modified) parts of their distribution. The example files may be used as starting points without limitation except the licences on the external content. 54 | -------------------------------------------------------------------------------- /library/Rain/Tpl/IPlugin.php: -------------------------------------------------------------------------------- 1 | 34 | * public function declare_hooks() { 35 | * return array('before_parse', 'after_parse' => 'custom_method'); 36 | * } 37 | * 38 | * 39 | * Template will then call the registered method with a context object as parameter. 40 | * Context object implements \ArrayAccess. 41 | * It's properties depends on hook api. 42 | * 43 | * Method can modify some properties. No return value is expected. 44 | */ 45 | interface IPlugin 46 | { 47 | /** 48 | * Returns a list of hooks that are implemented by the plugin. 49 | * This should be an array containing: 50 | * - a key/value pair where key is hook name and value is implementing method, 51 | * - a value only when hook has same name as method. 52 | */ 53 | public function declareHooks(); 54 | 55 | /** 56 | * Sets plugin options. 57 | * 58 | * @var array 59 | */ 60 | public function setOptions($options); 61 | } 62 | -------------------------------------------------------------------------------- /test/Tpl/Tests/Tpl/PluginTest.php: -------------------------------------------------------------------------------- 1 | set_hooks(array('before_parse')); 34 | $this->assertEquals(array('before_parse'), $plugin->declareHooks()); 35 | } 36 | 37 | public function testSetOption() 38 | { 39 | $plugin = $this->getMock('Rain\Tpl\Plugin', array('setParam')); 40 | $plugin->expects($this->once()) 41 | ->method('setParam') 42 | ->with($this->equalTo('value')); 43 | $plugin->setOption('param', 'value'); 44 | $this->setExpectedException('InvalidArgumentException'); 45 | $plugin->setOption('unknown_param', 'value'); 46 | } 47 | 48 | public function testSetOptions() 49 | { 50 | $plugin = $this->getMock('Rain\Tpl\Plugin', array('setParam')); 51 | $plugin->expects($this->once()) 52 | ->method('setParam') 53 | ->with($this->equalTo('value')); 54 | $plugin->setOptions(array('param' => 'value')); 55 | } 56 | } 57 | 58 | class PluginTestPlugin extends Rain\Tpl\Plugin 59 | { 60 | public $param = null; 61 | public function set_hooks($hooks) {$this->hooks = $hooks;} 62 | public function set_param($param) {$this->param = $param;} 63 | } 64 | -------------------------------------------------------------------------------- /templates/bootstrap/js/bootstrap-tabs.js: -------------------------------------------------------------------------------- 1 | /* ======================================================== 2 | * bootstrap-tabs.js v1.4.0 3 | * http://twitter.github.com/bootstrap/javascript.html#tabs 4 | * ======================================================== 5 | * Copyright 2011 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ======================================================== */ 19 | 20 | 21 | !function( $ ){ 22 | 23 | "use strict" 24 | 25 | function activate ( element, container ) { 26 | container 27 | .find('> .active') 28 | .removeClass('active') 29 | .find('> .dropdown-menu > .active') 30 | .removeClass('active') 31 | 32 | element.addClass('active') 33 | 34 | if ( element.parent('.dropdown-menu') ) { 35 | element.closest('li.dropdown').addClass('active') 36 | } 37 | } 38 | 39 | function tab( e ) { 40 | var $this = $(this) 41 | , $ul = $this.closest('ul:not(.dropdown-menu)') 42 | , href = $this.attr('href') 43 | , previous 44 | , $href 45 | 46 | if ( /^#\w+/.test(href) ) { 47 | e.preventDefault() 48 | 49 | if ( $this.parent('li').hasClass('active') ) { 50 | return 51 | } 52 | 53 | previous = $ul.find('.active a').last()[0] 54 | $href = $(href) 55 | 56 | activate($this.parent('li'), $ul) 57 | activate($href, $href.parent()) 58 | 59 | $this.trigger({ 60 | type: 'change' 61 | , relatedTarget: previous 62 | }) 63 | } 64 | } 65 | 66 | 67 | /* TABS/PILLS PLUGIN DEFINITION 68 | * ============================ */ 69 | 70 | $.fn.tabs = $.fn.pills = function ( selector ) { 71 | return this.each(function () { 72 | $(this).delegate(selector || '.tabs li > a, .pills > li > a', 'click', tab) 73 | }) 74 | } 75 | 76 | $(document).ready(function () { 77 | $('body').tabs('ul[data-tabs] li > a, ul[data-pills] > li > a') 78 | }) 79 | 80 | }( window.jQuery || window.ender ); 81 | -------------------------------------------------------------------------------- /library/Rain/Tpl/SyntaxException.php: -------------------------------------------------------------------------------- 1 | templateLine; 58 | 59 | $this->templateLine = (int) $line; 60 | return $this; 61 | } 62 | 63 | /** 64 | * Handles the tag which caused an error. 65 | * 66 | * @param string | null $tag 67 | * 68 | * @return \Rain\Tpl_SyntaxException | string | null 69 | */ 70 | public function tag($tag=null){ 71 | if(is_null($tag)) 72 | return $this->tag; 73 | 74 | $this->tag = (string) $tag; 75 | return $this; 76 | } 77 | } 78 | 79 | // -- end 80 | -------------------------------------------------------------------------------- /example-all.php: -------------------------------------------------------------------------------- 1 | null, 13 | "tpl_dir" => "templates/test/", 14 | "cache_dir" => "cache/", 15 | "remove_comments" => true, 16 | "debug" => true, // set to false to improve the speed 17 | ); 18 | 19 | Tpl::configure( $config ); 20 | 21 | 22 | // Add PathReplace plugin (necessary to load the CSS with path replace) 23 | Tpl::registerPlugin( new Tpl\Plugin\PathReplace() ); 24 | 25 | 26 | // set variables 27 | $var = array( 28 | "variable" => "Hello World!", 29 | "bad_variable" => "", 30 | "safe_variable" => "", 31 | "version" => "3.0 Alpha", 32 | "menu" => array( 33 | array("name" => "Home", "link" => "index.php", "selected" => true ), 34 | array("name" => "FAQ", "link" => "index.php/FAQ/", "selected" => null ), 35 | array("name" => "Documentation", "link" => "index.php/doc/", "selected" => null ) 36 | ), 37 | "week" => array( "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ), 38 | "user" => (object) array("name"=>"Rain", "citizen" => "Earth", "race" => "Human" ), 39 | "numbers" => array( 3, 2, 1 ), 40 | "bad_text" => 'Hey this is a malicious XSS ', 41 | "table" => array( array( "Apple", "1996" ), array( "PC", "1997" ) ), 42 | "title" => "Rain TPL 3 - Easy and Fast template engine", 43 | "copyright" => "Copyright 2006 - 2012 Rain TPL
Project By Rain Team", 44 | 45 | ); 46 | 47 | // add a tag 48 | Tpl::registerTag( "({@.*?@})", // preg split 49 | "{@(.*?)@}", // preg match 50 | function( $params ){ // function called by the tag 51 | $value = $params[1][0]; 52 | return "Translate: $value"; 53 | } 54 | ); 55 | 56 | 57 | // add a tag 58 | Tpl::registerTag( "({%.*?%})", // preg split 59 | "{%(.*?)(?:\|(.*?))%}", // preg match 60 | function( $params ){ // function called by the tag 61 | $value = $params[1][0]; 62 | $value2 = $params[2][0]; 63 | 64 | return "Translate: $value in $value2"; 65 | } 66 | ); 67 | 68 | // draw 69 | $tpl = new Tpl; 70 | $tpl->assign( $var ); 71 | echo $tpl->draw( "test" ); 72 | 73 | 74 | 75 | class Test{ 76 | static public function method( $variable ){ 77 | echo "Hi I am a static method, and this is the parameter passed to me: $variable!"; 78 | } 79 | } 80 | 81 | // end -------------------------------------------------------------------------------- /templates/raintpl3/page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {$title} 5 | 6 | 7 | 8 | 9 |
The easy and fast template engine for PHP.   Rain\Tpl makes application easier to create & enables designers/developers to work better together.
10 | 11 |
12 | 13 |
14 | 15 | 20 | 21 |
22 | 23 | 24 | 25 |

Rain \ TPL version {$version}

26 |

Features

27 | 28 |
29 | 30 | 31 | 32 | 33 |
34 | 8 Tags
35 | 4 Methods 36 |
37 |
38 |
 
39 |
40 | 41 | 42 | 43 | 44 |
45 | compiles HTML to PHP 46 |
47 |
48 |
 
49 |
50 | 51 | 52 | 53 | 54 |
55 | Compatible with Smarty and Twig 56 |
57 |
58 |
 
59 |
60 | 61 | 62 | 63 | 64 |
65 | designs HTML templates 66 |
67 |
68 |
69 | 70 | {include="subfolder/footer"} 71 | 72 | 73 | -------------------------------------------------------------------------------- /test/Tpl/Tests/TplTest.php: -------------------------------------------------------------------------------- 1 | configure(); 36 | $this->engine = new \Rain\Tpl(); 37 | } 38 | 39 | private function configure() 40 | { 41 | Rain\Tpl::configure(array( 42 | 'debug' => true, 43 | 'tpl_dir' => __DIR__ . '/_files/', 44 | 'cache_dir' => __DIR__ . '/../../cache/', 45 | )); 46 | } 47 | 48 | public function testCallHooks() 49 | { 50 | // Make a mock that registers to all hooks and check required context keys. 51 | $hooks = array( 52 | 'beforeParse' => array('code', 'template_basedir', 'template_filepath', 'conf'), 53 | 'afterParse' => array('code', 'template_basedir', 'template_filepath', 'conf'), 54 | ); 55 | 56 | // init mock plugin 57 | $methods = array_keys($hooks); 58 | $plugin = $this->getMock( 59 | 'Rain\Tpl\IPlugin', 60 | array_merge(array('declareHooks', 'setOptions'), $methods) 61 | ); 62 | $plugin->expects($this->once()) 63 | ->method('declareHooks') 64 | ->will($this->returnValue($methods)); 65 | foreach ($hooks as $method => $required) { 66 | $contstrains = array(); 67 | foreach ($required as $key) { 68 | $contstrains[] = $this->arrayHasKey($key); 69 | } 70 | $plugin->expects($this->once()) 71 | ->method($method) 72 | ->with(call_user_func_array(array($this, 'logicalAnd'), $contstrains)); 73 | } 74 | 75 | // register plugin and draw template 76 | Rain\Tpl::registerPlugin($plugin); 77 | $this->engine->draw('template', true); 78 | } 79 | } -------------------------------------------------------------------------------- /templates/bootstrap/js/bootstrap-popover.js: -------------------------------------------------------------------------------- 1 | /* =========================================================== 2 | * bootstrap-popover.js v1.4.0 3 | * http://twitter.github.com/bootstrap/javascript.html#popover 4 | * =========================================================== 5 | * Copyright 2011 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * =========================================================== */ 19 | 20 | 21 | !function( $ ) { 22 | 23 | "use strict" 24 | 25 | var Popover = function ( element, options ) { 26 | this.$element = $(element) 27 | this.options = options 28 | this.enabled = true 29 | this.fixTitle() 30 | } 31 | 32 | /* NOTE: POPOVER EXTENDS BOOTSTRAP-TWIPSY.js 33 | ========================================= */ 34 | 35 | Popover.prototype = $.extend({}, $.fn.twipsy.Twipsy.prototype, { 36 | 37 | setContent: function () { 38 | var $tip = this.tip() 39 | $tip.find('.title')[this.options.html ? 'html' : 'text'](this.getTitle()) 40 | $tip.find('.content > *')[this.options.html ? 'html' : 'text'](this.getContent()) 41 | $tip[0].className = 'popover' 42 | } 43 | 44 | , hasContent: function () { 45 | return this.getTitle() || this.getContent() 46 | } 47 | 48 | , getContent: function () { 49 | var content 50 | , $e = this.$element 51 | , o = this.options 52 | 53 | if (typeof this.options.content == 'string') { 54 | content = $e.attr(this.options.content) 55 | } else if (typeof this.options.content == 'function') { 56 | content = this.options.content.call(this.$element[0]) 57 | } 58 | 59 | return content 60 | } 61 | 62 | , tip: function() { 63 | if (!this.$tip) { 64 | this.$tip = $('
') 65 | .html(this.options.template) 66 | } 67 | return this.$tip 68 | } 69 | 70 | }) 71 | 72 | 73 | /* POPOVER PLUGIN DEFINITION 74 | * ======================= */ 75 | 76 | $.fn.popover = function (options) { 77 | if (typeof options == 'object') options = $.extend({}, $.fn.popover.defaults, options) 78 | $.fn.twipsy.initWith.call(this, options, Popover, 'popover') 79 | return this 80 | } 81 | 82 | $.fn.popover.defaults = $.extend({} , $.fn.twipsy.defaults, { 83 | placement: 'right' 84 | , content: 'data-content' 85 | , template: '

' 86 | }) 87 | 88 | $.fn.twipsy.rejectAttrOptions.push( 'content' ) 89 | 90 | }( window.jQuery || window.ender ); 91 | -------------------------------------------------------------------------------- /library/Rain/Tpl/Plugin.php: -------------------------------------------------------------------------------- 1 | setOptions($options); 51 | } 52 | /** 53 | * Returns a list of hooks that are implemented by the plugin. 54 | * This should be an array containing: 55 | * - a key/value pair where key is hook name and value is implementing method, 56 | * - a value only when hook has same name as method. 57 | */ 58 | public function declareHooks() { 59 | return $this->hooks; 60 | } 61 | 62 | /** 63 | * Sets plugin options. 64 | * 65 | * @var array 66 | */ 67 | public function setOptions($options) { 68 | foreach ((array) $options as $key => $val) { 69 | $this->setOption($key, $val); 70 | } 71 | return $this; 72 | } 73 | 74 | /** 75 | * Sets plugin option. 76 | * 77 | * @param string $name 78 | * @param mixed $value 79 | * @throws \InvalidArgumentException Wrong option name or value 80 | * @return Plugin 81 | */ 82 | public function setOption($name, $value) { 83 | $method = 'set' . ucfirst($name); 84 | 85 | if (!\method_exists($this, $method)) { 86 | throw new \InvalidArgumentException('Key "' . $name . '" is not a valid settings option' ); 87 | } 88 | $this->{$method}($value); 89 | return $this; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /templates/bootstrap/js/bootstrap-scrollspy.js: -------------------------------------------------------------------------------- 1 | /* ============================================================= 2 | * bootstrap-scrollspy.js v1.4.0 3 | * http://twitter.github.com/bootstrap/javascript.html#scrollspy 4 | * ============================================================= 5 | * Copyright 2011 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================== */ 19 | 20 | 21 | !function ( $ ) { 22 | 23 | "use strict" 24 | 25 | var $window = $(window) 26 | 27 | function ScrollSpy( topbar, selector ) { 28 | var processScroll = $.proxy(this.processScroll, this) 29 | this.$topbar = $(topbar) 30 | this.selector = selector || 'li > a' 31 | this.refresh() 32 | this.$topbar.delegate(this.selector, 'click', processScroll) 33 | $window.scroll(processScroll) 34 | this.processScroll() 35 | } 36 | 37 | ScrollSpy.prototype = { 38 | 39 | refresh: function () { 40 | this.targets = this.$topbar.find(this.selector).map(function () { 41 | var href = $(this).attr('href') 42 | return /^#\w/.test(href) && $(href).length ? href : null 43 | }) 44 | 45 | this.offsets = $.map(this.targets, function (id) { 46 | return $(id).offset().top 47 | }) 48 | } 49 | 50 | , processScroll: function () { 51 | var scrollTop = $window.scrollTop() + 10 52 | , offsets = this.offsets 53 | , targets = this.targets 54 | , activeTarget = this.activeTarget 55 | , i 56 | 57 | for (i = offsets.length; i--;) { 58 | activeTarget != targets[i] 59 | && scrollTop >= offsets[i] 60 | && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) 61 | && this.activateButton( targets[i] ) 62 | } 63 | } 64 | 65 | , activateButton: function (target) { 66 | this.activeTarget = target 67 | 68 | this.$topbar 69 | .find(this.selector).parent('.active') 70 | .removeClass('active') 71 | 72 | this.$topbar 73 | .find(this.selector + '[href="' + target + '"]') 74 | .parent('li') 75 | .addClass('active') 76 | } 77 | 78 | } 79 | 80 | /* SCROLLSPY PLUGIN DEFINITION 81 | * =========================== */ 82 | 83 | $.fn.scrollSpy = function( options ) { 84 | var scrollspy = this.data('scrollspy') 85 | 86 | if (!scrollspy) { 87 | return this.each(function () { 88 | $(this).data('scrollspy', new ScrollSpy( this, options )) 89 | }) 90 | } 91 | 92 | if ( options === true ) { 93 | return scrollspy 94 | } 95 | 96 | if ( typeof options == 'string' ) { 97 | scrollspy[options]() 98 | } 99 | 100 | return this 101 | } 102 | 103 | $(document).ready(function () { 104 | $('body').scrollSpy('[data-scrollspy] li > a') 105 | }) 106 | 107 | }( window.jQuery || window.ender ); -------------------------------------------------------------------------------- /templates/bootstrap/hero.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {$title} 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 | Rain TPL 3 36 | 41 |
42 |
43 |
44 | 45 |
46 | 47 | 48 |
49 |

Hello, world!

50 |

Vestibulum id ligula porta felis euismod semper. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.

51 |

Learn more »

52 |
53 | 54 | 55 |
56 |
57 |

Heading

58 |

Etiam porta sem malesuada magna mollis euismod. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.

59 |

View details »

60 |
61 |
62 |

Heading

63 |

Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui.

64 |

View details »

65 |
66 |
67 |

Heading

68 |

Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

69 |

View details »

70 |
71 |
72 | 73 |
74 |

© Company 2011

75 |
76 | 77 |
78 | 79 | 80 | -------------------------------------------------------------------------------- /templates/bootstrap/lib/scaffolding.less: -------------------------------------------------------------------------------- 1 | /* 2 | * Scaffolding 3 | * Basic and global styles for generating a grid system, structural layout, and page templates 4 | * ------------------------------------------------------------------------------------------- */ 5 | 6 | 7 | // STRUCTURAL LAYOUT 8 | // ----------------- 9 | 10 | body { 11 | background-color: @white; 12 | margin: 0; 13 | #font > .sans-serif(normal,@basefont,@baseline); 14 | color: @grayDark; 15 | } 16 | 17 | // Container (centered, fixed-width layouts) 18 | .container { 19 | .fixed-container(); 20 | } 21 | 22 | // Fluid layouts (left aligned, with sidebar, min- & max-width content) 23 | .container-fluid { 24 | position: relative; 25 | min-width: 940px; 26 | padding-left: 20px; 27 | padding-right: 20px; 28 | .clearfix(); 29 | > .sidebar { 30 | position: absolute; 31 | top: 0; 32 | left: 20px; 33 | width: 220px; 34 | } 35 | // TODO in v2: rename this and .popover .content to be more specific 36 | > .content { 37 | margin-left: 240px; 38 | } 39 | } 40 | 41 | 42 | // BASE STYLES 43 | // ----------- 44 | 45 | // Links 46 | a { 47 | color: @linkColor; 48 | text-decoration: none; 49 | line-height: inherit; 50 | font-weight: inherit; 51 | &:hover { 52 | color: @linkColorHover; 53 | text-decoration: underline; 54 | } 55 | } 56 | 57 | // Quick floats 58 | .pull-right { 59 | float: right; 60 | } 61 | .pull-left { 62 | float: left; 63 | } 64 | 65 | // Toggling content 66 | .hide { 67 | display: none; 68 | } 69 | .show { 70 | display: block; 71 | } 72 | 73 | 74 | // GRID SYSTEM 75 | // ----------- 76 | // To customize the grid system, bring up the variables.less file and change the column count, size, and gutter there 77 | 78 | .row { 79 | .clearfix(); 80 | margin-left: -@gridGutterWidth; 81 | } 82 | 83 | // Find all .span# classes within .row and give them the necessary properties for grid columns (supported by all browsers back to IE7) 84 | // Credit to @dhg for the idea 85 | .row > [class*="span"] { 86 | .gridColumn(); 87 | } 88 | 89 | // Default columns 90 | .span1 { .columns(1); } 91 | .span2 { .columns(2); } 92 | .span3 { .columns(3); } 93 | .span4 { .columns(4); } 94 | .span5 { .columns(5); } 95 | .span6 { .columns(6); } 96 | .span7 { .columns(7); } 97 | .span8 { .columns(8); } 98 | .span9 { .columns(9); } 99 | .span10 { .columns(10); } 100 | .span11 { .columns(11); } 101 | .span12 { .columns(12); } 102 | .span13 { .columns(13); } 103 | .span14 { .columns(14); } 104 | .span15 { .columns(15); } 105 | .span16 { .columns(16); } 106 | 107 | // For optional 24-column grid 108 | .span17 { .columns(17); } 109 | .span18 { .columns(18); } 110 | .span19 { .columns(19); } 111 | .span20 { .columns(20); } 112 | .span21 { .columns(21); } 113 | .span22 { .columns(22); } 114 | .span23 { .columns(23); } 115 | .span24 { .columns(24); } 116 | 117 | // Offset column options 118 | .row { 119 | > .offset1 { .offset(1); } 120 | > .offset2 { .offset(2); } 121 | > .offset3 { .offset(3); } 122 | > .offset4 { .offset(4); } 123 | > .offset5 { .offset(5); } 124 | > .offset6 { .offset(6); } 125 | > .offset7 { .offset(7); } 126 | > .offset8 { .offset(8); } 127 | > .offset9 { .offset(9); } 128 | > .offset10 { .offset(10); } 129 | > .offset11 { .offset(11); } 130 | > .offset12 { .offset(12); } 131 | } 132 | 133 | // Unique column sizes for 16-column grid 134 | .span-one-third { width: 300px; } 135 | .span-two-thirds { width: 620px; } 136 | .row { 137 | > .offset-one-third { margin-left: 340px; } 138 | > .offset-two-thirds { margin-left: 660px; } 139 | } -------------------------------------------------------------------------------- /templates/bootstrap/lib/type.less: -------------------------------------------------------------------------------- 1 | /* Typography.less 2 | * Headings, body text, lists, code, and more for a versatile and durable typography system 3 | * ---------------------------------------------------------------------------------------- */ 4 | 5 | 6 | // BODY TEXT 7 | // --------- 8 | 9 | p { 10 | #font > .shorthand(normal,@basefont,@baseline); 11 | margin-bottom: @baseline / 2; 12 | small { 13 | font-size: @basefont - 2; 14 | color: @grayLight; 15 | } 16 | } 17 | 18 | 19 | // HEADINGS 20 | // -------- 21 | 22 | h1, h2, h3, h4, h5, h6 { 23 | font-weight: bold; 24 | color: @grayDark; 25 | small { 26 | color: @grayLight; 27 | } 28 | } 29 | h1 { 30 | margin-bottom: @baseline; 31 | font-size: 30px; 32 | line-height: @baseline * 2; 33 | small { 34 | font-size: 18px; 35 | } 36 | } 37 | h2 { 38 | font-size: 24px; 39 | line-height: @baseline * 2; 40 | small { 41 | font-size: 14px; 42 | } 43 | } 44 | h3, h4, h5, h6 { 45 | line-height: @baseline * 2; 46 | } 47 | h3 { 48 | font-size: 18px; 49 | small { 50 | font-size: 14px; 51 | } 52 | } 53 | h4 { 54 | font-size: 16px; 55 | small { 56 | font-size: 12px; 57 | } 58 | } 59 | h5 { 60 | font-size: 14px; 61 | } 62 | h6 { 63 | font-size: 13px; 64 | color: @grayLight; 65 | text-transform: uppercase; 66 | } 67 | 68 | 69 | // COLORS 70 | // ------ 71 | 72 | // Unordered and Ordered lists 73 | ul, ol { 74 | margin: 0 0 @baseline 25px; 75 | } 76 | ul ul, 77 | ul ol, 78 | ol ol, 79 | ol ul { 80 | margin-bottom: 0; 81 | } 82 | ul { 83 | list-style: disc; 84 | } 85 | ol { 86 | list-style: decimal; 87 | } 88 | li { 89 | line-height: @baseline; 90 | color: @gray; 91 | } 92 | ul.unstyled { 93 | list-style: none; 94 | margin-left: 0; 95 | } 96 | 97 | // Description Lists 98 | dl { 99 | margin-bottom: @baseline; 100 | dt, dd { 101 | line-height: @baseline; 102 | } 103 | dt { 104 | font-weight: bold; 105 | } 106 | dd { 107 | margin-left: @baseline / 2; 108 | } 109 | } 110 | 111 | // MISC 112 | // ---- 113 | 114 | // Horizontal rules 115 | hr { 116 | margin: 20px 0 19px; 117 | border: 0; 118 | border-bottom: 1px solid #eee; 119 | } 120 | 121 | // Emphasis 122 | strong { 123 | font-style: inherit; 124 | font-weight: bold; 125 | } 126 | em { 127 | font-style: italic; 128 | font-weight: inherit; 129 | line-height: inherit; 130 | } 131 | .muted { 132 | color: @grayLight; 133 | } 134 | 135 | // Blockquotes 136 | blockquote { 137 | margin-bottom: @baseline; 138 | border-left: 5px solid #eee; 139 | padding-left: 15px; 140 | p { 141 | #font > .shorthand(300,14px,@baseline); 142 | margin-bottom: 0; 143 | } 144 | small { 145 | display: block; 146 | #font > .shorthand(300,12px,@baseline); 147 | color: @grayLight; 148 | &:before { 149 | content: '\2014 \00A0'; 150 | } 151 | } 152 | } 153 | 154 | // Addresses 155 | address { 156 | display: block; 157 | line-height: @baseline; 158 | margin-bottom: @baseline; 159 | } 160 | 161 | // Inline and block code styles 162 | code, pre { 163 | padding: 0 3px 2px; 164 | font-family: Monaco, Andale Mono, Courier New, monospace; 165 | font-size: 12px; 166 | .border-radius(3px); 167 | } 168 | code { 169 | background-color: lighten(@orange, 40%); 170 | color: rgba(0,0,0,.75); 171 | padding: 1px 3px; 172 | } 173 | pre { 174 | background-color: #f5f5f5; 175 | display: block; 176 | padding: (@baseline - 1) / 2; 177 | margin: 0 0 @baseline; 178 | line-height: @baseline; 179 | font-size: 12px; 180 | border: 1px solid #ccc; 181 | border: 1px solid rgba(0,0,0,.15); 182 | .border-radius(3px); 183 | white-space: pre; 184 | white-space: pre-wrap; 185 | word-wrap: break-word; 186 | 187 | } -------------------------------------------------------------------------------- /templates/bootstrap/js/bootstrap-alerts.js: -------------------------------------------------------------------------------- 1 | /* ========================================================== 2 | * bootstrap-alerts.js v1.4.0 3 | * http://twitter.github.com/bootstrap/javascript.html#alerts 4 | * ========================================================== 5 | * Copyright 2011 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================== */ 19 | 20 | 21 | !function( $ ){ 22 | 23 | "use strict" 24 | 25 | /* CSS TRANSITION SUPPORT (https://gist.github.com/373874) 26 | * ======================================================= */ 27 | 28 | var transitionEnd 29 | 30 | $(document).ready(function () { 31 | 32 | $.support.transition = (function () { 33 | var thisBody = document.body || document.documentElement 34 | , thisStyle = thisBody.style 35 | , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined 36 | return support 37 | })() 38 | 39 | // set CSS transition event type 40 | if ( $.support.transition ) { 41 | transitionEnd = "TransitionEnd" 42 | if ( $.browser.webkit ) { 43 | transitionEnd = "webkitTransitionEnd" 44 | } else if ( $.browser.mozilla ) { 45 | transitionEnd = "transitionend" 46 | } else if ( $.browser.opera ) { 47 | transitionEnd = "oTransitionEnd" 48 | } 49 | } 50 | 51 | }) 52 | 53 | /* ALERT CLASS DEFINITION 54 | * ====================== */ 55 | 56 | var Alert = function ( content, options ) { 57 | if (options == 'close') return this.close.call(content) 58 | this.settings = $.extend({}, $.fn.alert.defaults, options) 59 | this.$element = $(content) 60 | .delegate(this.settings.selector, 'click', this.close) 61 | } 62 | 63 | Alert.prototype = { 64 | 65 | close: function (e) { 66 | var $element = $(this) 67 | , className = 'alert-message' 68 | 69 | $element = $element.hasClass(className) ? $element : $element.parent() 70 | 71 | e && e.preventDefault() 72 | $element.removeClass('in') 73 | 74 | function removeElement () { 75 | $element.remove() 76 | } 77 | 78 | $.support.transition && $element.hasClass('fade') ? 79 | $element.bind(transitionEnd, removeElement) : 80 | removeElement() 81 | } 82 | 83 | } 84 | 85 | 86 | /* ALERT PLUGIN DEFINITION 87 | * ======================= */ 88 | 89 | $.fn.alert = function ( options ) { 90 | 91 | if ( options === true ) { 92 | return this.data('alert') 93 | } 94 | 95 | return this.each(function () { 96 | var $this = $(this) 97 | , data 98 | 99 | if ( typeof options == 'string' ) { 100 | 101 | data = $this.data('alert') 102 | 103 | if (typeof data == 'object') { 104 | return data[options].call( $this ) 105 | } 106 | 107 | } 108 | 109 | $(this).data('alert', new Alert( this, options )) 110 | 111 | }) 112 | } 113 | 114 | $.fn.alert.defaults = { 115 | selector: '.close' 116 | } 117 | 118 | $(document).ready(function () { 119 | new Alert($('body'), { 120 | selector: '.alert-message[data-alert] .close' 121 | }) 122 | }) 123 | 124 | }( window.jQuery || window.ender ); -------------------------------------------------------------------------------- /templates/raintpl2/page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {$title} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 |

Variable example

19 |
20 | 21 |

Variable example

22 | 23 | variable {$variable} 24 | 25 |

26 |

Variable assignment

27 | assignment {$number=10} and print {$number} 28 | 29 |

30 |

Variable Modifiers

31 | 32 | {$variable|strlen}
33 | {$variable|substr:0,7}
34 |
35 | 36 |

37 |

Global variables

38 | The variable is declared as global into the PHP {$GLOBALS.global_variable} 39 |

40 | 41 |

Show all declared variables

42 | To show all declared variable use.

43 | 44 | {$this->var|print_r} 45 | 46 |

47 | 48 |
49 | 50 |

Constants

51 |
52 |

Constant

53 | Constant: {#true#} 54 | 55 |

56 |

Modier on constant as follow

57 | {#PHP_VERSION|strlen|round|count} 58 |
59 | 60 |

Loop example

61 |
62 |

Simple loop example

63 | 64 |
    65 | {loop="$week"} 66 |
  • {$key} = {$value}
  • 67 | {/loop} 68 |
69 |
70 | 71 |

72 | 73 |

Loop example with associative array

74 | 75 |
    76 |
  • ID _ Name _ Color
  • 77 | {loop="$user"} 78 |
  • {$key}) - {$value.name|strtoupper} - {$value.color}
  • 79 | {/loop} 80 |
81 |
82 | 83 |

84 | 85 |

Loop an empty array

86 | 87 |
    88 | {loop="$empty_array"} 89 |
  • {$key}) - {$value.name} - {$value.color}
  • 90 | {else} 91 | The array is empty 92 | {/loop} 93 |
94 |
95 | 96 |
97 | 98 |

If Example

99 |
100 | 101 |

simple if example

102 | 103 | {if="$number==10"}OK! 104 | {else}NO!{/if} 105 | 106 | 107 |

108 | 109 |

example of if, elseif, else example

110 | 111 | {if="substr($variable,0,1)=='A'"}First character is A 112 | {elseif="substr($variable,0,1)=='B'"}First character is B 113 | {else}First character of variable is not A neither B 114 | {/if} 115 | 116 | 117 |
118 | 119 |

Custom function

120 |
121 | {@message@} 122 |
123 | 124 | 125 |

Path Replace (WYSIWYG)

126 |
127 | 128 |

WYSIWYG

129 | 130 | RainTPL replaces relative paths of images, css and links automatically with the correct server paths. 131 |

132 | 133 |

Path replace on relative path of image

134 | into the template the image is wrote as: 135 | <img src="img/logo.gif" alt="logo"/> 136 | in the compiled template the path is replaced with the correct path tpl/img/logo.gif:
137 | logo 138 |


139 | Absolute paths and path ending with # are not replaced 140 |

For more info read the documentation: 141 | http://www.raintpl.com/Documentation/Documentation-for-web-designers/WYSIWYG/ 142 | 143 | 144 |
145 | 146 |
147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /templates/bootstrap/lib/reset.less: -------------------------------------------------------------------------------- 1 | /* Reset.less 2 | * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc). 3 | * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ 4 | 5 | 6 | // ERIC MEYER RESET 7 | // -------------------------------------------------- 8 | 9 | html, body { margin: 0; padding: 0; } 10 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, cite, code, del, dfn, em, img, q, s, samp, small, strike, strong, sub, sup, tt, var, dd, dl, dt, li, ol, ul, fieldset, form, label, legend, button, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; font-weight: normal; font-style: normal; font-size: 100%; line-height: 1; font-family: inherit; } 11 | table { border-collapse: collapse; border-spacing: 0; } 12 | ol, ul { list-style: none; } 13 | q:before, q:after, blockquote:before, blockquote:after { content: ""; } 14 | 15 | 16 | // Normalize.css 17 | // Pulling in select resets form the normalize.css project 18 | // -------------------------------------------------- 19 | 20 | // Display in IE6-9 and FF3 21 | // ------------------------- 22 | // Source: http://github.com/necolas/normalize.css 23 | html { 24 | overflow-y: scroll; 25 | font-size: 100%; 26 | -webkit-text-size-adjust: 100%; 27 | -ms-text-size-adjust: 100%; 28 | } 29 | // Focus states 30 | a:focus { 31 | outline: thin dotted; 32 | } 33 | // Hover & Active 34 | a:hover, 35 | a:active { 36 | outline: 0; 37 | } 38 | 39 | // Display in IE6-9 and FF3 40 | // ------------------------- 41 | // Source: http://github.com/necolas/normalize.css 42 | article, 43 | aside, 44 | details, 45 | figcaption, 46 | figure, 47 | footer, 48 | header, 49 | hgroup, 50 | nav, 51 | section { 52 | display: block; 53 | } 54 | 55 | // Display block in IE6-9 and FF3 56 | // ------------------------- 57 | // Source: http://github.com/necolas/normalize.css 58 | audio, 59 | canvas, 60 | video { 61 | display: inline-block; 62 | *display: inline; 63 | *zoom: 1; 64 | } 65 | 66 | // Prevents modern browsers from displaying 'audio' without controls 67 | // ------------------------- 68 | // Source: http://github.com/necolas/normalize.css 69 | audio:not([controls]) { 70 | display: none; 71 | } 72 | 73 | // Prevents sub and sup affecting line-height in all browsers 74 | // ------------------------- 75 | // Source: http://github.com/necolas/normalize.css 76 | sub, 77 | sup { 78 | font-size: 75%; 79 | line-height: 0; 80 | position: relative; 81 | vertical-align: baseline; 82 | } 83 | sup { 84 | top: -0.5em; 85 | } 86 | sub { 87 | bottom: -0.25em; 88 | } 89 | 90 | // Img border in a's and image quality 91 | // ------------------------- 92 | // Source: http://github.com/necolas/normalize.css 93 | img { 94 | border: 0; 95 | -ms-interpolation-mode: bicubic; 96 | } 97 | 98 | // Forms 99 | // ------------------------- 100 | // Source: http://github.com/necolas/normalize.css 101 | 102 | // Font size in all browsers, margin changes, misc consistency 103 | button, 104 | input, 105 | select, 106 | textarea { 107 | font-size: 100%; 108 | margin: 0; 109 | vertical-align: baseline; 110 | *vertical-align: middle; 111 | } 112 | button, 113 | input { 114 | line-height: normal; // FF3/4 have !important on line-height in UA stylesheet 115 | *overflow: visible; // Inner spacing ie IE6/7 116 | } 117 | button::-moz-focus-inner, 118 | input::-moz-focus-inner { // Inner padding and border oddities in FF3/4 119 | border: 0; 120 | padding: 0; 121 | } 122 | button, 123 | input[type="button"], 124 | input[type="reset"], 125 | input[type="submit"] { 126 | cursor: pointer; // Cursors on all buttons applied consistently 127 | -webkit-appearance: button; // Style clicable inputs in iOS 128 | } 129 | input[type="search"] { // Appearance in Safari/Chrome 130 | -webkit-appearance: textfield; 131 | -webkit-box-sizing: content-box; 132 | -moz-box-sizing: content-box; 133 | box-sizing: content-box; 134 | } 135 | input[type="search"]::-webkit-search-decoration { 136 | -webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5 137 | } 138 | textarea { 139 | overflow: auto; // Remove vertical scrollbar in IE6-9 140 | vertical-align: top; // Readability and alignment cross-browser 141 | } -------------------------------------------------------------------------------- /test/Tpl/Tests/Tpl/PluginContainerTest.php: -------------------------------------------------------------------------------- 1 | container = new Rain\Tpl\PluginContainer(); 35 | } 36 | 37 | public function testSetAndRun() 38 | { 39 | $context = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS); 40 | // mock plugin with default and custom hook methods 41 | $first = $this->getMock('Rain\Tpl\IPlugin', array('declareHooks', 'before', 'custom', 'setOptions')); 42 | $first->expects($this->once()) 43 | ->method('declareHooks') 44 | ->will($this->returnValue(array('before', 'after' => 'custom'))); 45 | $first->expects($this->once()) 46 | ->method('before'); 47 | $first->expects($this->once()) 48 | ->method('custom'); 49 | // second mock to test that all plugins are executed 50 | $second = $this->getMock('Rain\Tpl\IPlugin', array('declareHooks', 'before', 'custom', 'setOptions')); 51 | $second->expects($this->once()) 52 | ->method('declareHooks') 53 | ->will($this->returnValue(array('before' =>'before'))); 54 | $second->expects($this->once()) 55 | ->method('before'); 56 | // set plugins and run them 57 | $this->container->setPlugin('first', $first) 58 | ->setPlugin('second', $second) 59 | ->run('before', $context); 60 | $this->assertEquals('before', $context->_hook_name); 61 | $this->container->run('after', $context); 62 | $this->assertEquals('after', $context->_hook_name); 63 | } 64 | 65 | public function testRejectBadPlugin() 66 | { 67 | $plugin = $this->getMock('Rain\Tpl\IPlugin', array('declareHooks', 'setOptions')); 68 | $plugin->expects($this->once()) 69 | ->method('declareHooks') 70 | ->will($this->returnValue(array('before' => 'no_method'))); 71 | $this->setExpectedException('InvalidArgumentException'); 72 | $this->container->setPlugin('third', $plugin); 73 | } 74 | 75 | public function testRemovePlugin() 76 | { 77 | // mock 2 plugins, one will stay and another will be removed 78 | // Kept will be executed once, removed should be never executed. 79 | $kept = $this->getMock('Rain\Tpl\IPlugin', array('declareHooks', 'remove', 'setOptions')); 80 | $kept->expects($this->once())->method('declareHooks') 81 | ->will($this->returnValue(array('remove'))); 82 | $kept->expects($this->once())->method('remove'); 83 | 84 | $removed = $this->getMock('Rain\Tpl\IPlugin', array('declareHooks', 'remove', 'setOptions')); 85 | $removed->expects($this->once())->method('declareHooks') 86 | ->will($this->returnValue(array('remove'))); 87 | $removed->expects($this->never())->method('remove'); 88 | 89 | $this->container->setPlugin('kept', $kept); 90 | $this->container->setPlugin('removed', $removed); 91 | 92 | // remove one plugin and trigger hook. 93 | $this->container->removePlugin('removed'); 94 | $this->container->run('remove', new ArrayObject()); 95 | } 96 | 97 | public function testAddPlugin() 98 | { 99 | $plugin = $this->getMock('Rain\Tpl\IPlugin', array('declareHooks', 'setOptions')); 100 | $plugin->expects($this->once())->method('declareHooks') 101 | ->will($this->returnValue(array())); 102 | 103 | $this->container->addPlugin('added', $plugin); 104 | $this->setExpectedException('InvalidArgumentException'); 105 | $this->container->addPlugin('added', $plugin); 106 | } 107 | 108 | public function testCreateContext() 109 | { 110 | $context = $this->container->createContext(array('param' => 'value')); 111 | $this->assertEquals('value', $context->param); 112 | $this->assertEquals('value', $context['param']); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /library/Rain/Tpl/PluginContainer.php: -------------------------------------------------------------------------------- 1 | plugins[(string) $name])) { 58 | throw new \InvalidArgumentException('Plugin named "' . $name . '" already exists in container'); 59 | } 60 | return $this->setPlugin($name, $plugin); 61 | } 62 | 63 | /** 64 | * Sets plugin by name. Plugin of same name is replaced when exists. 65 | * 66 | * @param string $name 67 | * @param IPlugin $plugin 68 | * @return PluginContainer 69 | */ 70 | public function setPlugin($name, IPlugin $plugin) { 71 | $this->removePlugin($name); 72 | $this->plugins[(string) $name] = $plugin; 73 | 74 | foreach ((array) $plugin->declareHooks() as $hook => $method) { 75 | if (is_int($hook)) { 76 | // numerical key, method has same name as hook 77 | $hook = $method; 78 | } 79 | $callable = array($plugin, $method); 80 | if (!is_callable($callable)) { 81 | throw new \InvalidArgumentException(sprintf( 82 | 'Wrong callcable suplied by %s for "%s" hook ', 83 | get_class($plugin), $hook 84 | )); 85 | } 86 | $this->hooks[$hook][] = $callable; 87 | } 88 | return $this; 89 | } 90 | 91 | public function removePlugin($name) { 92 | $name = (string) $name; 93 | if (!isset($this->plugins[$name])) { 94 | return; 95 | } 96 | $plugin = $this->plugins[$name]; 97 | unset($this->plugins[$name]); 98 | // remove all registered callables 99 | foreach ($this->hooks as $hook => &$callables) { 100 | foreach ($callables as $i => $callable) { 101 | if ($callable[0] === $plugin) { 102 | unset($callables[$i]); 103 | } 104 | } 105 | } 106 | return $this; 107 | } 108 | 109 | /** 110 | * Passes the context object to registered plugins. 111 | * 112 | * @param string $hook_name 113 | * @param \ArrayAccess $context 114 | * @return PluginContainer 115 | */ 116 | public function run($hook_name, \ArrayAccess $context ){ 117 | if (!isset($this->hooks[$hook_name])) { 118 | return $this; 119 | } 120 | $context['_hook_name'] = $hook_name; 121 | foreach( $this->hooks[$hook_name] as $callable ){ 122 | call_user_func($callable, $context); 123 | } 124 | return $this; 125 | } 126 | 127 | /** 128 | * Retuns context object that will be passed to plugins. 129 | * 130 | * @param array $params 131 | * @return \ArrayObject 132 | */ 133 | public function createContext($params = array()) 134 | { 135 | return new \ArrayObject((array) $params, \ArrayObject::ARRAY_AS_PROPS); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /example-draw-string.php: -------------------------------------------------------------------------------- 1 | null, 19 | "tpl_dir" => "templates/test/", 20 | "cache_dir" => "cache/", 21 | "debug" => true // set to false to improve the speed 22 | ); 23 | 24 | Tpl::configure( $config ); 25 | 26 | // Add PathReplace plugin 27 | Tpl::registerPlugin( new Tpl\Plugin\PathReplace() ); 28 | 29 | 30 | // set variables 31 | $var = array( 32 | "variable" => "Hello World!", 33 | "version" => "3.0 Alpha", 34 | "menu" => array( 35 | array("name" => "Home", "link" => "index.php", "selected" => true ), 36 | array("name" => "FAQ", "link" => "index.php/FAQ/", "selected" => null ), 37 | array("name" => "Documentation", "link" => "index.php/doc/", "selected" => null ) 38 | ), 39 | "week" => array( "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ), 40 | "user" => (object) array("name"=>"Rain", "citizen" => "Earth", "race" => "Human" ), 41 | "numbers" => array( 3, 2, 1 ), 42 | "bad_text" => "Hey this is a malicious XSS ", 43 | "table" => array( array( "Apple", "1996" ), array( "PC", "1997" ) ), 44 | "title" => "Rain TPL 3 - Easy and Fast template engine", 45 | "copyright" => "Copyright 2006 - 2012 Rain TPL
Project By Rain Team", 46 | 47 | ); 48 | 49 | // add a tag 50 | Tpl::registerTag( "({@.*?@})", // preg split 51 | "{@(.*?)@}", // preg match 52 | function( $params ){ // function called by the tag 53 | $value = $params[1][0]; 54 | return "Translate: $value"; 55 | } 56 | ); 57 | 58 | 59 | // add a tag 60 | Tpl::registerTag( "({%.*?%})", // preg split 61 | "{%(.*?)(?:\|(.*?))%}", // preg match 62 | function( $params ){ // function called by the tag 63 | $value = $params[1][0]; 64 | $value2 = $params[2][0]; 65 | 66 | return "Translate: $value in $value2"; 67 | } 68 | ); 69 | 70 | 71 | 72 | $string = file_get_contents( "templates/test/test.html"); 73 | 74 | 75 | class Test{ 76 | static public function method( $variable ){ 77 | echo "Hi I am a static method, and this is the parameter passed to me: $variable!"; 78 | } 79 | } 80 | 81 | 82 | // draw 83 | $tpl = new Tpl; 84 | $tpl->assign( $var ); 85 | echo $tpl->drawString( $string ); 86 | 87 | // -- end 88 | 89 | 90 | 91 | 92 | 93 | //------------------------------------------------------------- 94 | // 95 | // BENCHMARK/DEBUG FUNCTIONS 96 | // 97 | //------------------------------------------------------------- 98 | 99 | echo "
---------
"; 100 | echo memoryUsage(); 101 | echo "
"; 102 | echo timer(); 103 | 104 | /** 105 | * Useful for debug, print the variable $mixed and die 106 | */ 107 | function dump( $mixed, $exit = 1 ){ 108 | echo "
dump \n---------------------- \n\n" . print_r( $mixed, true ) . "\n----------------------
";
109 |     if( $exit ) exit;
110 | }
111 | 
112 | 
113 | 
114 | /**
115 |  * Save the memory used at this point
116 |  */
117 | function memoryUsageStart( $memName = "execution_time" ){
118 |     return $GLOBALS['memoryCounter'][$memName] = memory_get_usage();
119 | }
120 | 
121 | 
122 | 
123 | /**
124 |  * Get the memory used
125 |  */
126 | function memoryUsage( $memName = "execution_time", $byteFormat = true ){
127 |     $totMem = memory_get_usage() - $GLOBALS['memoryCounter'][ $memName ];
128 |     return $byteFormat ? byteFormat($totMem) : $totMem;
129 | }
130 | 
131 | 
132 | //-------------------------------------------------------------
133 | //
134 | //					 TIME FUNCTIONS
135 | //
136 | //-------------------------------------------------------------
137 | 
138 | /**
139 |  * Start the timer
140 |  */
141 | function timerStart( $timeName = "execution_time" ){
142 |     $stimer = explode( ' ', microtime( ) );
143 |     $GLOBALS['timeCounter'][$timeName] = $stimer[ 1 ] + $stimer[ 0 ];
144 | }
145 | 
146 | /**
147 |  * Get the time passed
148 |  */
149 | function timer( $timeName = "execution_time", $precision = 10 ){
150 |     $etimer = explode( ' ', microtime( ) );
151 |     $timeElapsed = $etimer[ 1 ] + $etimer[ 0 ] - $GLOBALS['timeCounter'][ $timeName ];
152 |     return substr( $timeElapsed, 0, $precision );
153 | }
154 | 
155 | 
156 | /**
157 |  * Convert byte to more readable format, like "1 KB" instead of "1024".
158 |  * cut_zero, remove the 0 after comma ex:  10,00 => 10	  14,30 => 14,3
159 |  */
160 | function byteFormat( $size ){
161 |     if( $size > 0 ){
162 |         $unim = array("B","KB","MB","GB","TB","PB");
163 |         for( $i=0; $size >= 1024; $i++ )
164 |             $size = $size / 1024;
165 |         return number_format($size,$i?2:0, ',', '.' )." ".$unim[$i];
166 |     }
167 | }
168 | 
169 | // end


--------------------------------------------------------------------------------
/templates/bootstrap/lib/tables.less:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Tables.less
  3 |  * Tables for, you guessed it, tabular data
  4 |  * ---------------------------------------- */
  5 | 
  6 | 
  7 | // BASELINE STYLES
  8 | // ---------------
  9 | 
 10 | table {
 11 |   width: 100%;
 12 |   margin-bottom: @baseline;
 13 |   padding: 0;
 14 |   font-size: @basefont;
 15 |   border-collapse: collapse;
 16 |   th,
 17 |   td {
 18 |     padding: 10px 10px 9px;
 19 |     line-height: @baseline;
 20 |     text-align: left;
 21 |   }
 22 |   th {
 23 |     padding-top: 9px;
 24 |     font-weight: bold;
 25 |     vertical-align: middle;
 26 |   }
 27 |   td {
 28 |     vertical-align: top;
 29 |     border-top: 1px solid #ddd;
 30 |   }
 31 |   // When scoped to row, fix th in tbody
 32 |   tbody th {
 33 |     border-top: 1px solid #ddd;
 34 |     vertical-align: top;
 35 |   }
 36 | }
 37 | 
 38 | 
 39 | // CONDENSED VERSION
 40 | // -----------------
 41 | .condensed-table {
 42 |   th,
 43 |   td {
 44 |     padding: 5px 5px 4px;
 45 |   }
 46 | }
 47 | 
 48 | 
 49 | // BORDERED VERSION
 50 | // ----------------
 51 | 
 52 | .bordered-table {
 53 |   border: 1px solid #ddd;
 54 |   border-collapse: separate; // Done so we can round those corners!
 55 |   *border-collapse: collapse; /* IE7, collapse table to remove spacing */
 56 |   .border-radius(4px);
 57 |   th + th,
 58 |   td + td,
 59 |   th + td {
 60 |     border-left: 1px solid #ddd;
 61 |   }
 62 |   thead tr:first-child th:first-child,
 63 |   tbody tr:first-child td:first-child {
 64 |     .border-radius(4px 0 0 0);
 65 |   }
 66 |   thead tr:first-child th:last-child,
 67 |   tbody tr:first-child td:last-child {
 68 |     .border-radius(0 4px 0 0);
 69 |   }
 70 |   tbody tr:last-child td:first-child {
 71 |     .border-radius(0 0 0 4px);
 72 |   }
 73 |   tbody tr:last-child td:last-child {
 74 |     .border-radius(0 0 4px 0);
 75 |   }
 76 | }
 77 | 
 78 | 
 79 | // TABLE CELL SIZES
 80 | // ----------------
 81 | 
 82 | // This is a duplication of the main grid .columns() mixin, but subtracts 20px to account for input padding and border
 83 | .tableColumns(@columnSpan: 1) {
 84 |   width: ((@gridColumnWidth - 20) * @columnSpan) + ((@gridColumnWidth - 20) * (@columnSpan - 1));
 85 | }
 86 | table {
 87 |   // Default columns
 88 |   .span1     { .tableColumns(1); }
 89 |   .span2     { .tableColumns(2); }
 90 |   .span3     { .tableColumns(3); }
 91 |   .span4     { .tableColumns(4); }
 92 |   .span5     { .tableColumns(5); }
 93 |   .span6     { .tableColumns(6); }
 94 |   .span7     { .tableColumns(7); }
 95 |   .span8     { .tableColumns(8); }
 96 |   .span9     { .tableColumns(9); }
 97 |   .span10    { .tableColumns(10); }
 98 |   .span11    { .tableColumns(11); }
 99 |   .span12    { .tableColumns(12); }
100 |   .span13    { .tableColumns(13); }
101 |   .span14    { .tableColumns(14); }
102 |   .span15    { .tableColumns(15); }
103 |   .span16    { .tableColumns(16); }
104 | }
105 | 
106 | 
107 | // ZEBRA-STRIPING
108 | // --------------
109 | 
110 | // Default zebra-stripe styles (alternating gray and transparent backgrounds)
111 | .zebra-striped {
112 |   tbody {
113 |     tr:nth-child(odd) td,
114 |     tr:nth-child(odd) th {
115 |       background-color: #f9f9f9;
116 |     }
117 |     tr:hover td,
118 |     tr:hover th {
119 |       background-color: #f5f5f5;
120 |     }
121 |   }
122 | }
123 | 
124 | table {
125 |   // Tablesorting styles w/ jQuery plugin
126 |   .header {
127 |     cursor: pointer;
128 |     &:after {
129 |       content: "";
130 |       float: right;
131 |       margin-top: 7px;
132 |       border-width: 0 4px 4px;
133 |       border-style: solid;
134 |       border-color: #000 transparent;
135 |       visibility: hidden;
136 |     }
137 |   }
138 |   // Style the sorted column headers (THs)
139 |   .headerSortUp,
140 |   .headerSortDown {
141 |     background-color: rgba(141,192,219,.25);
142 |     text-shadow: 0 1px 1px rgba(255,255,255,.75);
143 |   }
144 |   // Style the ascending (reverse alphabetical) column header
145 |   .header:hover {
146 |     &:after {
147 |       visibility:visible;
148 |     }
149 |   }
150 |   // Style the descending (alphabetical) column header
151 |   .headerSortDown,
152 |   .headerSortDown:hover {
153 |     &:after {
154 |       visibility:visible;
155 |       .opacity(60);
156 |     }
157 |   }
158 |   // Style the ascending (reverse alphabetical) column header
159 |   .headerSortUp {
160 |     &:after {
161 |       border-bottom: none;
162 |       border-left: 4px solid transparent;
163 |       border-right: 4px solid transparent;
164 |       border-top: 4px solid #000;
165 |       visibility:visible;
166 |       .box-shadow(none); //can't add boxshadow to downward facing arrow :(
167 |       .opacity(60);
168 |     }
169 |   }
170 |   // Blue Table Headings
171 |   .blue {
172 |     color: @blue;
173 |     border-bottom-color: @blue;
174 |   }
175 |   .headerSortUp.blue,
176 |   .headerSortDown.blue {
177 |     background-color: lighten(@blue, 40%);
178 |   }
179 |   // Green Table Headings
180 |   .green {
181 |     color: @green;
182 |     border-bottom-color: @green;
183 |   }
184 |   .headerSortUp.green,
185 |   .headerSortDown.green {
186 |     background-color: lighten(@green, 40%);
187 |   }
188 |   // Red Table Headings
189 |   .red {
190 |     color: @red;
191 |     border-bottom-color: @red;
192 |   }
193 |   .headerSortUp.red,
194 |   .headerSortDown.red {
195 |     background-color: lighten(@red, 50%);
196 |   }
197 |   // Yellow Table Headings
198 |   .yellow {
199 |     color: @yellow;
200 |     border-bottom-color: @yellow;
201 |   }
202 |   .headerSortUp.yellow,
203 |   .headerSortDown.yellow {
204 |     background-color: lighten(@yellow, 40%);
205 |   }
206 |   // Orange Table Headings
207 |   .orange {
208 |     color: @orange;
209 |     border-bottom-color: @orange;
210 |   }
211 |   .headerSortUp.orange,
212 |   .headerSortDown.orange {
213 |     background-color: lighten(@orange, 40%);
214 |   }
215 |   // Purple Table Headings
216 |   .purple {
217 |     color: @purple;
218 |     border-bottom-color: @purple;
219 |   }
220 |   .headerSortUp.purple,
221 |   .headerSortDown.purple {
222 |     background-color: lighten(@purple, 40%);
223 |   }
224 | }


--------------------------------------------------------------------------------
/library/Rain/Tpl/Plugin/PathReplace.php:
--------------------------------------------------------------------------------
  1 |  template_dir/url
 37 |      * url# => url
 38 |      * http://url => http://url
 39 |      *
 40 |      * @param \ArrayAccess $context
 41 |      */
 42 |     public function afterParse(\ArrayAccess $context){
 43 | 
 44 |         // set variables
 45 |         $html = $context->code;
 46 |         $template_basedir = $context->template_basedir;
 47 |         $tags = $this->tags;
 48 |         $basecode = "";
 49 | 
 50 | 
 51 |         // get the template base directory
 52 |         $template_directory = $basecode . $context->conf['tpl_dir'] . $context->template_basedir;
 53 | 
 54 |         // reduce the path
 55 |         $path = str_replace( "://", "@not_replace@", $template_directory );
 56 |         $path = preg_replace( "#(/+)#", "/", $path );
 57 |         $path = preg_replace( "#(/\./+)#", "/", $path );
 58 |         $path = str_replace( "@not_replace@", "://", $path );
 59 | 
 60 |         while( preg_match( '#\.\./#', $path ) ){
 61 |             $path = preg_replace('#\w+/\.\./#', '', $path );
 62 |         }
 63 | 
 64 | 
 65 | 
 66 |         $exp = $sub = array();
 67 | 
 68 |         if( in_array( "img", $tags ) ){
 69 |             $exp = array( '/code = preg_replace( $exp, $sub, $html );
109 |     }
110 | 
111 | 
112 | 
113 |     public function setTags($tags) {
114 |         $this->tags = (array) $tags;
115 |         return $this;
116 |     }
117 | 
118 | }
119 | 


--------------------------------------------------------------------------------
/library/Rain/Tpl/Plugin/ImageResize.php:
--------------------------------------------------------------------------------
  1 | code;
 38 |         $template_basedir = $context->template_basedir;
 39 |         $quality = $this->quality;
 40 |         $auto_crop = $this->crop;
 41 |         $conf = $context->conf;
 42 | 
 43 |         $img_cache_dir = $template_basedir = $conf['cache_dir'];
 44 | 
 45 | 
 46 |         // get the template base directory
 47 |         $template_directory = $conf['base_url'] . $conf['tpl_dir'] . $template_basedir;
 48 | 
 49 |         // reduce the path
 50 |         $path = preg_replace('/\w+\/\.\.\//', '', $template_directory );
 51 | 
 52 |         $exp = $sub = array();
 53 | 
 54 |         $image_resized = false;
 55 | 
 56 |         // match the images
 57 |         if( preg_match_all( '/.*?)"))|(\s*(width="(?.*?)"))|(\s*height="(?.*?)")|(\s*resize="(?.*?)")|(\s*crop="(?.*?)"))*.*?>/', $html, $matches ) ){
 58 | 
 59 |             for( $i=0,$n=count($matches[0]); $i<$n; $i++ ){
 60 |                 $tag = $matches[0][$i];
 61 |                 $src = $matches['src'][$i];
 62 |                 $w = $matches['width'][$i];
 63 |                 $h = $matches['height'][$i];
 64 |                 $resize = $matches['resize'][$i];
 65 |                 if( $auto_crop )
 66 |                     $crop = $matches['crop'][$i] == 'false' ? false : true;
 67 |                 else
 68 |                     $crop = $matches['crop'][$i] == 'true' ? true : false;
 69 | 
 70 |                 if( $w > 0 && $h > 0 && $resize != 'false' ){
 71 |                     echo $src;exit;
 72 |                     $new_tag = preg_replace( '/(.*?)src="(.*?)"(.*?)/', '$1src=""$3', $tag );
 73 |                     $html = str_replace( $tag, $new_tag, $html );
 74 |                     $image_resized = true;
 75 |                 }
 76 | 
 77 |             }
 78 | 
 79 |             if( $image_resized )
 80 |                 $html = '' . $html;
 81 | 
 82 |         }
 83 | 
 84 |         $context->code = $html;
 85 |     }
 86 | 
 87 |     public function setQuality($quality) {
 88 |         $this->quality = (int) $quality;
 89 |         return $this;
 90 |     }
 91 | 
 92 |     public function setCrop($crop) {
 93 |         $this->crop = (string) $crop;
 94 |         return $this;
 95 |     }
 96 | 
 97 |     public static function imgResize( $src, $dest, $w, $h, $quality, $crop ){
 98 | 
 99 |         $ext = substr(strrchr($src, '.'),1);
100 |         $dest = $dest . 'img.'. md5( $src . $crop . $quality ) . $w . 'x' . $h . '.' . $ext;
101 | 
102 | 
103 |         if( !file_exists( $dest ) )
104 |             static::rainImgResize( $src, $dest, $w, $h, $quality, $crop );
105 |         return $dest;
106 | 
107 |     }
108 | 
109 |     public static function rainImgResize($src, $dst, $width, $height, $quality, $crop=0){
110 | 
111 |         if(!list($w, $h) = getimagesize($src)) return "Unsupported picture type!";
112 | 
113 |         $type = strtolower(substr(strrchr($src,"."),1));
114 |         if($type == 'jpeg') $type = 'jpg';
115 |         switch($type){
116 |             case 'bmp': $img = imagecreatefromwbmp($src); break;
117 |             case 'gif': $img = imagecreatefromgif($src); break;
118 |             case 'jpg': $img = imagecreatefromjpeg($src); break;
119 |             case 'png': $img = imagecreatefrompng($src); break;
120 |             default : return "Unsupported picture type!";
121 |         }
122 | 
123 |         // resize
124 |         if($crop){
125 |             if($w < $width or $h < $height) return "Picture is too small!";
126 |             $ratio = max($width/$w, $height/$h);
127 |             $h = $height / $ratio;
128 |             $x = ($w - $width / $ratio) / 2;
129 |             $w = $width / $ratio;
130 |         }
131 |         else{
132 |             if($w < $width and $h < $height) return "Picture is too small!";
133 |             $ratio = min($width/$w, $height/$h);
134 |             $width = $w * $ratio;
135 |             $height = $h * $ratio;
136 |             $x = 0;
137 |         }
138 | 
139 |         $new = imagecreatetruecolor($width, $height);
140 | 
141 |         // preserve transparency
142 |         if($type == "gif" or $type == "png"){
143 |             imagecolortransparent($new, imagecolorallocatealpha($new, 0, 0, 0, 127));
144 |             imagealphablending($new, false);
145 |             imagesavealpha($new, true);
146 |         }
147 | 
148 |         imagecopyresampled($new, $img, 0, 0, $x, 0, $width, $height, $w, $h);
149 | 
150 |         switch($type){
151 |             case 'bmp': imagewbmp($new, $dst, $quality); break;
152 |             case 'gif': imagegif($new, $dst, $quality); break;
153 |             case 'jpg': imagejpeg($new, $dst, $quality); break;
154 |             case 'png': imagepng($new, $dst, $quality); break;
155 |         }
156 |         return true;
157 |     }
158 | 
159 | }


--------------------------------------------------------------------------------
/templates/bootstrap/js/bootstrap-modal.js:
--------------------------------------------------------------------------------
  1 | /* =========================================================
  2 |  * bootstrap-modal.js v1.4.0
  3 |  * http://twitter.github.com/bootstrap/javascript.html#modal
  4 |  * =========================================================
  5 |  * Copyright 2011 Twitter, Inc.
  6 |  *
  7 |  * Licensed under the Apache License, Version 2.0 (the "License");
  8 |  * you may not use this file except in compliance with the License.
  9 |  * You may obtain a copy of the License at
 10 |  *
 11 |  * http://www.apache.org/licenses/LICENSE-2.0
 12 |  *
 13 |  * Unless required by applicable law or agreed to in writing, software
 14 |  * distributed under the License is distributed on an "AS IS" BASIS,
 15 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 16 |  * See the License for the specific language governing permissions and
 17 |  * limitations under the License.
 18 |  * ========================================================= */
 19 | 
 20 | 
 21 | !function( $ ){
 22 | 
 23 |   "use strict"
 24 | 
 25 |  /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)
 26 |   * ======================================================= */
 27 | 
 28 |   var transitionEnd
 29 | 
 30 |   $(document).ready(function () {
 31 | 
 32 |     $.support.transition = (function () {
 33 |       var thisBody = document.body || document.documentElement
 34 |         , thisStyle = thisBody.style
 35 |         , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined
 36 |       return support
 37 |     })()
 38 | 
 39 |     // set CSS transition event type
 40 |     if ( $.support.transition ) {
 41 |       transitionEnd = "TransitionEnd"
 42 |       if ( $.browser.webkit ) {
 43 |       	transitionEnd = "webkitTransitionEnd"
 44 |       } else if ( $.browser.mozilla ) {
 45 |       	transitionEnd = "transitionend"
 46 |       } else if ( $.browser.opera ) {
 47 |       	transitionEnd = "oTransitionEnd"
 48 |       }
 49 |     }
 50 | 
 51 |   })
 52 | 
 53 | 
 54 |  /* MODAL PUBLIC CLASS DEFINITION
 55 |   * ============================= */
 56 | 
 57 |   var Modal = function ( content, options ) {
 58 |     this.settings = $.extend({}, $.fn.modal.defaults, options)
 59 |     this.$element = $(content)
 60 |       .delegate('.close', 'click.modal', $.proxy(this.hide, this))
 61 | 
 62 |     if ( this.settings.show ) {
 63 |       this.show()
 64 |     }
 65 | 
 66 |     return this
 67 |   }
 68 | 
 69 |   Modal.prototype = {
 70 | 
 71 |       toggle: function () {
 72 |         return this[!this.isShown ? 'show' : 'hide']()
 73 |       }
 74 | 
 75 |     , show: function () {
 76 |         var that = this
 77 |         this.isShown = true
 78 |         this.$element.trigger('show')
 79 | 
 80 |         escape.call(this)
 81 |         backdrop.call(this, function () {
 82 |           var transition = $.support.transition && that.$element.hasClass('fade')
 83 | 
 84 |           that.$element
 85 |             .appendTo(document.body)
 86 |             .show()
 87 | 
 88 |           if (transition) {
 89 |             that.$element[0].offsetWidth // force reflow
 90 |           }
 91 | 
 92 |           that.$element.addClass('in')
 93 | 
 94 |           transition ?
 95 |             that.$element.one(transitionEnd, function () { that.$element.trigger('shown') }) :
 96 |             that.$element.trigger('shown')
 97 | 
 98 |         })
 99 | 
100 |         return this
101 |       }
102 | 
103 |     , hide: function (e) {
104 |         e && e.preventDefault()
105 | 
106 |         if ( !this.isShown ) {
107 |           return this
108 |         }
109 | 
110 |         var that = this
111 |         this.isShown = false
112 | 
113 |         escape.call(this)
114 | 
115 |         this.$element
116 |           .trigger('hide')
117 |           .removeClass('in')
118 | 
119 |         $.support.transition && this.$element.hasClass('fade') ?
120 |           hideWithTransition.call(this) :
121 |           hideModal.call(this)
122 | 
123 |         return this
124 |       }
125 | 
126 |   }
127 | 
128 | 
129 |  /* MODAL PRIVATE METHODS
130 |   * ===================== */
131 | 
132 |   function hideWithTransition() {
133 |     // firefox drops transitionEnd events :{o
134 |     var that = this
135 |       , timeout = setTimeout(function () {
136 |           that.$element.unbind(transitionEnd)
137 |           hideModal.call(that)
138 |         }, 500)
139 | 
140 |     this.$element.one(transitionEnd, function () {
141 |       clearTimeout(timeout)
142 |       hideModal.call(that)
143 |     })
144 |   }
145 | 
146 |   function hideModal (that) {
147 |     this.$element
148 |       .hide()
149 |       .trigger('hidden')
150 | 
151 |     backdrop.call(this)
152 |   }
153 | 
154 |   function backdrop ( callback ) {
155 |     var that = this
156 |       , animate = this.$element.hasClass('fade') ? 'fade' : ''
157 |     if ( this.isShown && this.settings.backdrop ) {
158 |       var doAnimate = $.support.transition && animate
159 | 
160 |       this.$backdrop = $('