├── api ├── .htaccess ├── Slim │ ├── Environment.php │ ├── Exception │ │ ├── Pass.php │ │ ├── RequestSlash.php │ │ └── Stop.php │ ├── Http │ │ ├── Headers.php │ │ ├── Request.php │ │ ├── Response.php │ │ └── Util.php │ ├── Log.php │ ├── LogFileWriter.php │ ├── Middleware.php │ ├── Middleware │ │ ├── ContentTypes.php │ │ ├── Flash.php │ │ ├── MethodOverride.php │ │ ├── PrettyExceptions.php │ │ └── SessionCookie.php │ ├── Route.php │ ├── Router.php │ ├── Slim.php │ └── View.php └── index.php ├── directory.sql ├── iphone ├── css │ ├── images │ │ ├── activity-indicator.png │ │ ├── back-button-active.png │ │ ├── back-button.png │ │ ├── button-active.png │ │ ├── button.png │ │ ├── call.png │ │ ├── comment-arrow.png │ │ ├── detail-disclosure-button.png │ │ ├── disclosure-indicator.png │ │ ├── mail.png │ │ ├── manager.png │ │ ├── message.png │ │ ├── navbar-bg.png │ │ ├── navbar-landscape-bg.png │ │ ├── refresh-icon.png │ │ ├── reports.png │ │ └── search-icon.png │ └── styles.css ├── index.html ├── js │ └── app.js ├── libs │ ├── backbone-min.js │ ├── jquery-1.7.2.min.js │ └── underscore-min.js ├── pics │ ├── Andy_Bernard.jpg │ ├── Angela_Martin.jpg │ ├── Creed_Bratton.jpg │ ├── Dwight_Schrute.jpg │ ├── Jim_Halpert.jpg │ ├── Kelly_Kapoor.jpg │ ├── Kevin_Malone.jpg │ ├── Meredith_Palmer.jpg │ ├── Michael_Scott.jpg │ ├── Oscar_Martinez.jpg │ ├── Pamela_Beesly.jpg │ ├── Phyllis_Lapin.jpg │ ├── Ryan_Howard.jpg │ ├── Stanley_Hudson.jpg │ └── Toby_Flenderson.jpg └── tpl │ ├── employee-list-item.html │ ├── employee-page.html │ ├── report-page.html │ └── search-page.html ├── jquerymobile ├── css │ ├── images │ │ ├── ajax-loader.png │ │ ├── icons-18-black.png │ │ ├── icons-18-white.png │ │ ├── icons-36-black.png │ │ └── icons-36-white.png │ ├── jquery.mobile-1.0.1.min.css │ └── styles.css ├── img │ └── logo.png ├── index.html ├── js │ ├── jqm-config.js │ ├── main.js │ ├── models │ │ └── employeemodel.js │ ├── utils.js │ └── views │ │ ├── employeedetails.js │ │ └── employeelist.js ├── lib │ ├── backbone-min.js │ ├── iscroll.js │ ├── jquery-1.7.1.min.js │ ├── jquery.mobile-1.0.1.min.js │ └── underscore-min.js ├── pics │ ├── Amy_Jones.jpg │ ├── Amy_Jones100.jpg │ ├── Amy_Jones50.jpg │ ├── Eugene_Lee.jpg │ ├── Eugene_Lee100.jpg │ ├── Eugene_Lee50.jpg │ ├── Gary_Donovan.jpg │ ├── Gary_Donovan100.jpg │ ├── Gary_Donovan50.jpg │ ├── James_King.jpg │ ├── James_King100.jpg │ ├── James_King50.jpg │ ├── John_Williams.jpg │ ├── John_Williams100.jpg │ ├── John_Williams50.jpg │ ├── Julie_Taylor.jpg │ ├── Julie_Taylor100.jpg │ ├── Julie_Taylor50.jpg │ ├── Kathleen_Byrne.jpg │ ├── Kathleen_Byrne100.jpg │ ├── Kathleen_Byrne50.jpg │ ├── Lisa_Wong.jpg │ ├── Lisa_Wong100.jpg │ ├── Lisa_Wong50.jpg │ ├── Paul_Jones.jpg │ ├── Paul_Jones100.jpg │ ├── Paul_Jones50.jpg │ ├── Paula_Gates.jpg │ ├── Paula_Gates100.jpg │ ├── Paula_Gates50.jpg │ ├── Ray_Moore.jpg │ ├── Ray_Moore100.jpg │ ├── Ray_Moore50.jpg │ ├── Steven_Wells.jpg │ ├── Steven_Wells100.jpg │ └── Steven_Wells50.jpg └── tpl │ ├── employee-details.html │ ├── employee-list-item.html │ ├── report-list.html │ └── search-page.html ├── localdb ├── css │ ├── images │ │ ├── activity-indicator.png │ │ ├── back-button-active.png │ │ ├── back-button.png │ │ ├── button-active.png │ │ ├── button.png │ │ ├── call.png │ │ ├── comment-arrow.png │ │ ├── detail-disclosure-button.png │ │ ├── disclosure-indicator.png │ │ ├── mail.png │ │ ├── manager.png │ │ ├── message.png │ │ ├── navbar-bg.png │ │ ├── navbar-landscape-bg.png │ │ ├── refresh-icon.png │ │ ├── reports.png │ │ └── search-icon.png │ └── styles.css ├── index.html ├── js │ └── app.js ├── libs │ ├── backbone-min.js │ ├── jquery-1.7.2.min.js │ └── underscore-min.js ├── pics │ ├── Andy_Bernard.jpg │ ├── Angela_Martin.jpg │ ├── Creed_Bratton.jpg │ ├── Dwight_Schrute.jpg │ ├── Jim_Halpert.jpg │ ├── Kelly_Kapoor.jpg │ ├── Kevin_Malone.jpg │ ├── Meredith_Palmer.jpg │ ├── Michael_Scott.jpg │ ├── Oscar_Martinez.jpg │ ├── Pamela_Beesly.jpg │ ├── Phyllis_Lapin.jpg │ ├── Ryan_Howard.jpg │ ├── Stanley_Hudson.jpg │ └── Toby_Flenderson.jpg └── tpl │ ├── employee-list-item.html │ ├── employee-page.html │ ├── report-page.html │ └── search-page.html ├── readme.md └── web ├── css ├── bootstrap.css └── styles.css ├── img ├── glyphicons-halflings-white.png ├── glyphicons-halflings.png └── logo.png ├── index.html ├── js ├── main.js ├── models │ └── employeemodel.js ├── utils.js └── views │ ├── contact.js │ ├── employeedetails.js │ ├── employeelist.js │ ├── header.js │ └── home.js ├── lib ├── backbone-min.js ├── jquery-1.7.2.min.js └── underscore-min.js ├── pics ├── Amy_Jones.jpg ├── Amy_Jones50.jpg ├── Eugene_Lee.jpg ├── Eugene_Lee50.jpg ├── Gary_Donovan.jpg ├── Gary_Donovan50.jpg ├── James_King.jpg ├── James_King50.jpg ├── John_Williams.jpg ├── John_Williams50.jpg ├── Julie_Taylor.jpg ├── Julie_Taylor50.jpg ├── Kathleen_Byrne.jpg ├── Kathleen_Byrne50.jpg ├── Lisa_Wong.jpg ├── Lisa_Wong50.jpg ├── Paul_Jones.jpg ├── Paul_Jones50.jpg ├── Paula_Gates.jpg ├── Paula_Gates50.jpg ├── Ray_Moore.jpg ├── Ray_Moore50.jpg ├── Steven_Wells.jpg └── Steven_Wells50.jpg └── tpl ├── ContactView.html ├── EmployeeListItemView.html ├── EmployeeSummaryView.html ├── EmployeeView.html ├── HeaderView.html └── HomeView.html /api/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | 3 | # Some hosts may require you to use the `RewriteBase` directive. 4 | # If you need to use the `RewriteBase` directive, it should be the 5 | # absolute physical path to the directory that contains this htaccess file. 6 | # 7 | # RewriteBase / 8 | 9 | RewriteCond %{REQUEST_FILENAME} !-f 10 | RewriteRule ^(.*)$ index.php [QSA,L] -------------------------------------------------------------------------------- /api/Slim/Environment.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Environment 36 | * 37 | * This class creates and returns a key/value array of common 38 | * environment variables for the current HTTP request. 39 | * 40 | * This is a singleton class; derived environment variables will 41 | * be common across multiple Slim applications. 42 | * 43 | * This class matches the Rack (Ruby) specification as closely 44 | * as possible. More information available below. 45 | * 46 | * @package Slim 47 | * @author Josh Lockhart 48 | * @since 1.6.0 49 | */ 50 | class Slim_Environment implements ArrayAccess, IteratorAggregate { 51 | /** 52 | * @var array 53 | */ 54 | protected $properties; 55 | 56 | /** 57 | * @var Slim_Environment 58 | */ 59 | protected static $environment; 60 | 61 | /** 62 | * Get environment instance (singleton) 63 | * 64 | * This creates and/or returns an Environment instance (singleton) 65 | * derived from $_SERVER variables. You may override the global server 66 | * variables by using `Environment::mock()` instead. 67 | * 68 | * @param bool $refresh Refresh properties using global server variables? 69 | * @return Slim_Environment 70 | */ 71 | public static function getInstance( $refresh = false ) { 72 | if ( is_null(self::$environment) || $refresh ) { 73 | self::$environment = new self(); 74 | } 75 | return self::$environment; 76 | } 77 | 78 | /** 79 | * Get mock environment instance 80 | * 81 | * @param array $userSettings 82 | * @return Environment 83 | */ 84 | public static function mock( $userSettings = array() ) { 85 | self::$environment = new self(array_merge(array( 86 | 'REQUEST_METHOD' => 'GET', 87 | 'SCRIPT_NAME' => '', 88 | 'PATH_INFO' => '', 89 | 'QUERY_STRING' => '', 90 | 'SERVER_NAME' => 'localhost', 91 | 'SERVER_PORT' => 80, 92 | 'ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 93 | 'ACCEPT_LANGUAGE' => 'en-US,en;q=0.8', 94 | 'ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', 95 | 'USER_AGENT' => 'Slim Framework', 96 | 'REMOTE_ADDR' => '127.0.0.1', 97 | 'slim.url_scheme' => 'http', 98 | 'slim.input' => '', 99 | 'slim.errors' => @fopen('php://stderr', 'w') 100 | ), $userSettings)); 101 | return self::$environment; 102 | } 103 | 104 | /** 105 | * Constructor (private access) 106 | * 107 | * @param array|null $settings If present, these are used instead of global server variables 108 | * @return void 109 | */ 110 | private function __construct( $settings = null ) { 111 | if ( $settings ) { 112 | $this->properties = $settings; 113 | } else { 114 | $env = array(); 115 | 116 | //The HTTP request method 117 | $env['REQUEST_METHOD'] = $_SERVER['REQUEST_METHOD']; 118 | 119 | //The IP 120 | $env['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR']; 121 | 122 | /** 123 | * Application paths 124 | * 125 | * This derives two paths: SCRIPT_NAME and PATH_INFO. The SCRIPT_NAME 126 | * is the real, physical path to the application, be it in the root 127 | * directory or a subdirectory of the public document root. The PATH_INFO is the 128 | * virtual path to the requested resource within the application context. 129 | * 130 | * With htaccess, the SCRIPT_NAME will be an absolute path (without file name); 131 | * if not using htaccess, it will also include the file name. If it is "/", 132 | * it is set to an empty string (since it cannot have a trailing slash). 133 | * 134 | * The PATH_INFO will be an absolute path with a leading slash; this will be 135 | * used for application routing. 136 | */ 137 | if ( strpos($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']) === 0 ) { 138 | $env['SCRIPT_NAME'] = $_SERVER['SCRIPT_NAME']; //Without URL rewrite 139 | } else { 140 | $env['SCRIPT_NAME'] = str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME']) ); //With URL rewrite 141 | } 142 | $env['PATH_INFO'] = substr_replace($_SERVER['REQUEST_URI'], '', 0, strlen($env['SCRIPT_NAME'])); 143 | if ( strpos($env['PATH_INFO'], '?') !== false ) { 144 | $env['PATH_INFO'] = substr_replace($env['PATH_INFO'], '', strpos($env['PATH_INFO'], '?')); //query string is not removed automatically 145 | } 146 | $env['SCRIPT_NAME'] = rtrim($env['SCRIPT_NAME'], '/'); 147 | $env['PATH_INFO'] = '/' . ltrim($env['PATH_INFO'], '/'); 148 | 149 | //The portion of the request URI following the '?' 150 | $env['QUERY_STRING'] = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : ''; 151 | 152 | //Name of server host that is running the script 153 | $env['SERVER_NAME'] = $_SERVER['SERVER_NAME']; 154 | 155 | //Number of server port that is running the script 156 | $env['SERVER_PORT'] = $_SERVER['SERVER_PORT']; 157 | 158 | //HTTP request headers 159 | $specialHeaders = array('CONTENT_TYPE', 'CONTENT_LENGTH', 'PHP_AUTH_USER', 'PHP_AUTH_PW', 'PHP_AUTH_DIGEST', 'AUTH_TYPE'); 160 | foreach ( $_SERVER as $key => $value ) { 161 | $value = is_string($value) ? trim($value) : $value; 162 | if ( strpos($key, 'HTTP_') === 0 ) { 163 | $env[substr($key, 5)] = $value; 164 | } else if ( strpos($key, 'X_') === 0 || in_array($key, $specialHeaders) ) { 165 | $env[$key] = $value; 166 | } 167 | } 168 | 169 | //Is the application running under HTTPS or HTTP protocol? 170 | $env['slim.url_scheme'] = empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off' ? 'http' : 'https'; 171 | 172 | //Input stream (readable one time only; not available for mutipart/form-data requests) 173 | $rawInput = @file_get_contents('php://input'); 174 | if ( !$rawInput ) { 175 | $rawInput = ''; 176 | } 177 | $env['slim.input'] = $rawInput; 178 | 179 | //Error stream 180 | $env['slim.errors'] = fopen('php://stderr', 'w'); 181 | 182 | $this->properties = $env; 183 | } 184 | } 185 | 186 | /** 187 | * Array Access: Offset Exists 188 | */ 189 | public function offsetExists( $offset ) { 190 | return isset($this->properties[$offset]); 191 | } 192 | 193 | /** 194 | * Array Access: Offset Get 195 | */ 196 | public function offsetGet( $offset ) { 197 | if ( isset($this->properties[$offset]) ) { 198 | return $this->properties[$offset]; 199 | } else { 200 | return null; 201 | } 202 | } 203 | 204 | /** 205 | * Array Access: Offset Set 206 | */ 207 | public function offsetSet( $offset, $value ) { 208 | $this->properties[$offset] = $value; 209 | } 210 | 211 | /** 212 | * Array Access: Offset Unset 213 | */ 214 | public function offsetUnset( $offset ) { 215 | unset($this->properties[$offset]); 216 | } 217 | 218 | /** 219 | * IteratorAggregate 220 | * 221 | * @return ArrayIterator 222 | */ 223 | public function getIterator() { 224 | return new ArrayIterator($this->properties); 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /api/Slim/Exception/Pass.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Pass Exception 36 | * 37 | * This Exception will cause the Router::dispatch method 38 | * to skip the current matching route and continue to the next 39 | * matching route. If no subsequent routes are found, a 40 | * HTTP 404 Not Found response will be sent to the client. 41 | * 42 | * @package Slim 43 | * @author Josh Lockhart 44 | * @since 1.0.0 45 | */ 46 | class Slim_Exception_Pass extends Exception {} -------------------------------------------------------------------------------- /api/Slim/Exception/RequestSlash.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Request Slash Exception 36 | * 37 | * This Exception is thrown when Slim detects a matching route 38 | * (defined with a trailing slash) and the HTTP request 39 | * matches the route but does not have a trailing slash. This 40 | * exception will be caught in `Slim::run` and trigger a 301 redirect 41 | * to the same resource URI with a trailing slash. 42 | * 43 | * @package Slim 44 | * @author Josh Lockhart 45 | * @since 1.0.0 46 | */ 47 | class Slim_Exception_RequestSlash extends Exception {} -------------------------------------------------------------------------------- /api/Slim/Exception/Stop.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Stop Exception 36 | * 37 | * This Exception is thrown when the Slim application needs to abort 38 | * processing and return control flow to the outer PHP script. 39 | * 40 | * @package Slim 41 | * @author Josh Lockhart 42 | * @since 1.0.0 43 | */ 44 | class Slim_Exception_Stop extends Exception {} -------------------------------------------------------------------------------- /api/Slim/Http/Headers.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * HTTP Headers 36 | * 37 | * This class is an abstraction of the HTTP response headers and 38 | * provides array access to the header list while automatically 39 | * stores and retrieves headers with lowercase canonical keys regardless 40 | * of the input format. 41 | * 42 | * This class also implements the `Iterator` and `Countable` 43 | * interfaces for even more convenient usage. 44 | * 45 | * @package Slim 46 | * @author Josh Lockhart 47 | * @since 1.6.0 48 | */ 49 | class Slim_Http_Headers implements ArrayAccess, Iterator, Countable { 50 | /** 51 | * @var array HTTP headers 52 | */ 53 | protected $headers; 54 | 55 | /** 56 | * @var array Map canonical header name to original header name 57 | */ 58 | protected $map; 59 | 60 | /** 61 | * Constructor 62 | * @param array $headers 63 | * @return void 64 | */ 65 | public function __construct( $headers = array() ) { 66 | $this->merge($headers); 67 | } 68 | 69 | /** 70 | * Merge Headers 71 | * @param array $headers 72 | * @return void 73 | */ 74 | public function merge( $headers ) { 75 | foreach ( $headers as $name => $value ) { 76 | $this[$name] = $value; 77 | } 78 | } 79 | 80 | /** 81 | * Transform header name into canonical form 82 | * @param string $name 83 | * @return string 84 | */ 85 | protected function canonical( $name ) { 86 | return strtolower(trim($name)); 87 | } 88 | 89 | /** 90 | * Array Access: Offset Exists 91 | */ 92 | public function offsetExists( $offset ) { 93 | return isset($this->headers[$this->canonical($offset)]); 94 | } 95 | 96 | /** 97 | * Array Access: Offset Get 98 | */ 99 | public function offsetGet( $offset ) { 100 | $canonical = $this->canonical($offset); 101 | if ( isset($this->headers[$canonical]) ) { 102 | return $this->headers[$canonical]; 103 | } else { 104 | return null; 105 | } 106 | } 107 | 108 | /** 109 | * Array Access: Offset Set 110 | */ 111 | public function offsetSet( $offset, $value ) { 112 | $canonical = $this->canonical($offset); 113 | $this->headers[$canonical] = $value; 114 | $this->map[$canonical] = $offset; 115 | } 116 | 117 | /** 118 | * Array Access: Offset Unset 119 | */ 120 | public function offsetUnset( $offset ) { 121 | $canonical = $this->canonical($offset); 122 | unset($this->headers[$canonical], $this->map[$canonical]); 123 | } 124 | 125 | /** 126 | * Countable: Count 127 | */ 128 | public function count() { 129 | return count($this->headers); 130 | } 131 | 132 | /** 133 | * Iterator: Rewind 134 | */ 135 | public function rewind() { 136 | reset($this->headers); 137 | } 138 | 139 | /** 140 | * Iterator: Current 141 | */ 142 | public function current() { 143 | return current($this->headers); 144 | } 145 | 146 | /** 147 | * Iterator: Key 148 | */ 149 | public function key() { 150 | $key = key($this->headers); 151 | return $this->map[$key]; 152 | } 153 | 154 | /** 155 | * Iterator: Next 156 | */ 157 | public function next() { 158 | return next($this->headers); 159 | } 160 | 161 | /** 162 | * Iterator: Valid 163 | */ 164 | public function valid() { 165 | return current($this->headers) !== false; 166 | } 167 | } -------------------------------------------------------------------------------- /api/Slim/Log.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Log 36 | * 37 | * This is the primary logger for a Slim application. You may provide 38 | * a Log Writer in conjunction with this Log to write to various output 39 | * destinations (e.g. a file). This class provides this interface: 40 | * 41 | * debug( mixed $object ) 42 | * info( mixed $object ) 43 | * warn( mixed $object ) 44 | * error( mixed $object ) 45 | * fatal( mixed $object ) 46 | * 47 | * This class assumes only that your Log Writer has a public `write()` method 48 | * that accepts any object as its one and only argument. The Log Writer 49 | * class may write or send its argument anywhere: a file, STDERR, 50 | * a remote web API, etc. The possibilities are endless. 51 | * 52 | * @package Slim 53 | * @author Josh Lockhart 54 | * @since 1.0.0 55 | */ 56 | class Slim_Log { 57 | /** 58 | * @var array 59 | */ 60 | static protected $levels = array( 61 | 0 => 'FATAL', 62 | 1 => 'ERROR', 63 | 2 => 'WARN', 64 | 3 => 'INFO', 65 | 4 => 'DEBUG' 66 | ); 67 | 68 | /** 69 | * @var mixed 70 | */ 71 | protected $writer; 72 | 73 | /** 74 | * @var bool 75 | */ 76 | protected $enabled; 77 | 78 | /** 79 | * @var int 80 | */ 81 | protected $level; 82 | 83 | /** 84 | * Constructor 85 | * @param mixed $writer 86 | * @return void 87 | */ 88 | public function __construct( $writer ) { 89 | $this->writer = $writer; 90 | $this->enabled = true; 91 | $this->level = 4; 92 | } 93 | 94 | /** 95 | * Is logging enabled? 96 | * @return bool 97 | */ 98 | public function getEnabled() { 99 | return $this->enabled; 100 | } 101 | 102 | /** 103 | * Enable or disable logging 104 | * @param bool $enabled 105 | * @return void 106 | */ 107 | public function setEnabled( $enabled ) { 108 | if ( $enabled ) { 109 | $this->enabled = true; 110 | } else { 111 | $this->enabled = false; 112 | } 113 | } 114 | 115 | /** 116 | * Set level 117 | * @param int $level 118 | * @return void 119 | * @throws InvalidArgumentException 120 | */ 121 | public function setLevel( $level ) { 122 | if ( !isset(self::$levels[$level]) ) { 123 | throw new InvalidArgumentException('Invalid log level'); 124 | } 125 | $this->level = $level; 126 | } 127 | 128 | /** 129 | * Get level 130 | * @return int 131 | */ 132 | public function getLevel() { 133 | return $this->level; 134 | } 135 | 136 | /** 137 | * Set writer 138 | * @param mixed $writer 139 | * @return void 140 | */ 141 | public function setWriter( $writer ) { 142 | $this->writer = $writer; 143 | } 144 | 145 | /** 146 | * Get writer 147 | * @return mixed 148 | */ 149 | public function getWriter() { 150 | return $this->writer; 151 | } 152 | 153 | /** 154 | * Is logging enabled? 155 | * @return bool 156 | */ 157 | public function isEnabled() { 158 | return $this->enabled; 159 | } 160 | 161 | /** 162 | * Log debug message 163 | * @param mixed $object 164 | * @return mixed|false What the Logger returns, or false if Logger not set or not enabled 165 | */ 166 | public function debug( $object ) { 167 | return $this->log($object, 4); 168 | } 169 | 170 | /** 171 | * Log info message 172 | * @param mixed $object 173 | * @return mixed|false What the Logger returns, or false if Logger not set or not enabled 174 | */ 175 | public function info( $object ) { 176 | return $this->log($object, 3); 177 | } 178 | 179 | /** 180 | * Log warn message 181 | * @param mixed $object 182 | * @return mixed|false What the Logger returns, or false if Logger not set or not enabled 183 | */ 184 | public function warn( $object ) { 185 | return $this->log($object, 2); 186 | } 187 | 188 | /** 189 | * Log error message 190 | * @param mixed $object 191 | * @return mixed|false What the Logger returns, or false if Logger not set or not enabled 192 | */ 193 | public function error( $object ) { 194 | return $this->log($object, 1); 195 | } 196 | 197 | /** 198 | * Log fatal message 199 | * @param mixed $object 200 | * @return mixed|false What the Logger returns, or false if Logger not set or not enabled 201 | */ 202 | public function fatal( $object ) { 203 | return $this->log($object, 0); 204 | } 205 | 206 | /** 207 | * Log message 208 | * @param mixed The object to log 209 | * @param int The message level 210 | * @return int|false 211 | */ 212 | protected function log( $object, $level ) { 213 | if ( $this->enabled && $this->writer && $level <= $this->level ) { 214 | return $this->writer->write($object, $level); 215 | } else { 216 | return false; 217 | } 218 | } 219 | } -------------------------------------------------------------------------------- /api/Slim/LogFileWriter.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Log File Writer 36 | * 37 | * This class is used by Slim_Log to write log messages to a valid, writable 38 | * resource handle (e.g. a file or STDERR). 39 | * 40 | * @package Slim 41 | * @author Josh Lockhart 42 | * @since 1.5.2 43 | */ 44 | class Slim_LogFileWriter { 45 | /** 46 | * @var resource 47 | */ 48 | protected $resource; 49 | 50 | /** 51 | * Constructor 52 | * @param resource $resource 53 | * @return void 54 | * @throws InvalidArgumentException 55 | */ 56 | public function __construct( $resource ) { 57 | if ( !is_resource($resource) ) { 58 | throw new InvalidArgumentException('Cannot create LogFileWriter. Invalid resource handle.'); 59 | } 60 | $this->resource = $resource; 61 | } 62 | 63 | /** 64 | * Write message 65 | * @param mixed $message 66 | * @param int $level 67 | * @return int|false 68 | */ 69 | public function write( $message, $level = null ) { 70 | return fwrite($this->resource, (string)$message . PHP_EOL); 71 | } 72 | } -------------------------------------------------------------------------------- /api/Slim/Middleware.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Middleware 36 | * 37 | * @package Slim 38 | * @author Josh Lockhart 39 | * @since 1.6.0 40 | */ 41 | abstract class Slim_Middleware { 42 | /** 43 | * @var Slim Reference to the primary Slim application instance 44 | */ 45 | protected $app; 46 | 47 | /** 48 | * @var mixed Reference to the next downstream middleware 49 | */ 50 | protected $next; 51 | 52 | /** 53 | * Set application 54 | * 55 | * This method injects the primary Slim application instance into 56 | * this middleware. 57 | * 58 | * @param Slim $application 59 | * @return void 60 | */ 61 | final public function setApplication( $application ) { 62 | $this->app = $application; 63 | } 64 | 65 | /** 66 | * Get application 67 | * 68 | * This method retrieves the application previously injected 69 | * into this middleware. 70 | * 71 | * @return Slim 72 | */ 73 | final public function getApplication() { 74 | return $this->app; 75 | } 76 | 77 | /** 78 | * Set next middleware 79 | * 80 | * This method injects the next downstream middleware into 81 | * this middleware so that it may optionally be called 82 | * when appropriate. 83 | * 84 | * @param Slim|Slim_Middleware 85 | * @return void 86 | */ 87 | final public function setNextMiddleware( $nextMiddleware ) { 88 | $this->next = $nextMiddleware; 89 | } 90 | 91 | /** 92 | * Get next middleware 93 | * 94 | * This method retrieves the next downstream middleware 95 | * previously injected into this middleware. 96 | * 97 | * @return Slim|Slim_Middleware 98 | */ 99 | final public function getNextMiddleware() { 100 | return $this->next; 101 | } 102 | 103 | /** 104 | * Call 105 | * 106 | * Perform actions specific to this middleware and optionally 107 | * call the next downstream middleware. 108 | * 109 | * @return void 110 | */ 111 | abstract public function call(); 112 | } -------------------------------------------------------------------------------- /api/Slim/Middleware/ContentTypes.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Content Types 36 | * 37 | * This is middleware for a Slim application that intercepts 38 | * the HTTP request body and parses it into the appropriate 39 | * PHP data structure if possible; else it returns the HTTP 40 | * request body unchanged. This is particularly useful 41 | * for preparing the HTTP request body for an XML or JSON API. 42 | * 43 | * @package Slim 44 | * @author Josh Lockhart 45 | * @since 1.5.2 46 | */ 47 | class Slim_Middleware_ContentTypes extends Slim_Middleware { 48 | /** 49 | * @var array 50 | */ 51 | protected $contentTypes; 52 | 53 | /** 54 | * Constructor 55 | * @param array $settings 56 | */ 57 | public function __construct( $settings = array() ) { 58 | $this->contentTypes = array_merge(array( 59 | 'application/json' => array($this, 'parseJson'), 60 | 'application/xml' => array($this, 'parseXml'), 61 | 'text/xml' => array($this, 'parseXml'), 62 | 'text/csv' => array($this, 'parseCsv') 63 | ), $settings); 64 | } 65 | 66 | /** 67 | * Call 68 | * @return void 69 | */ 70 | public function call() { 71 | $mediaType = $this->app->request()->getMediaType(); 72 | if ( $mediaType ) { 73 | $env = $this->app->environment(); 74 | $env['slim.input_original'] = $env['slim.input']; 75 | $env['slim.input'] = $this->parse($env['slim.input'], $mediaType); 76 | } 77 | $this->next->call(); 78 | } 79 | 80 | /** 81 | * Parse input 82 | * 83 | * This method will attempt to parse the request body 84 | * based on its content type if available. 85 | * 86 | * @param string $input 87 | * @param string $contentType 88 | * @return mixed 89 | */ 90 | protected function parse ( $input, $contentType ) { 91 | if ( isset($this->contentTypes[$contentType]) && is_callable($this->contentTypes[$contentType]) ) { 92 | $result = call_user_func($this->contentTypes[$contentType], $input); 93 | if ( $result ) { 94 | return $result; 95 | } 96 | } 97 | return $input; 98 | } 99 | 100 | /** 101 | * Parse JSON 102 | * 103 | * This method converts the raw JSON input 104 | * into an associative array. 105 | * 106 | * @param string $input 107 | * @return array|string 108 | */ 109 | protected function parseJson( $input ) { 110 | if ( function_exists('json_decode') ) { 111 | $result = json_decode($input, true); 112 | if ( $result ) { 113 | return $result; 114 | } 115 | } 116 | } 117 | 118 | /** 119 | * Parse XML 120 | * 121 | * This method creates a SimpleXMLElement 122 | * based upon the XML input. If the SimpleXML 123 | * extension is not available, the raw input 124 | * will be returned unchanged. 125 | * 126 | * @param string $input 127 | * @return SimpleXMLElement|string 128 | */ 129 | protected function parseXml( $input ) { 130 | if ( class_exists('SimpleXMLElement') ) { 131 | try { 132 | return new SimpleXMLElement($input); 133 | } catch ( Exception $e ) {} 134 | } 135 | return $input; 136 | } 137 | 138 | /** 139 | * Parse CSV 140 | * 141 | * This method parses CSV content into a numeric array 142 | * containing an array of data for each CSV line. 143 | * 144 | * @param string $input 145 | * @return array 146 | */ 147 | protected function parseCsv( $input ) { 148 | $temp = fopen('php://memory', 'rw'); 149 | fwrite($temp, $input); 150 | fseek($temp, 0); 151 | $res = array(); 152 | while ( ($data = fgetcsv($temp)) !== false ) { 153 | $res[] = $data; 154 | } 155 | fclose($temp); 156 | return $res; 157 | } 158 | } -------------------------------------------------------------------------------- /api/Slim/Middleware/Flash.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Flash 36 | * 37 | * This is middleware for a Slim application that enables 38 | * Flash messaging between HTTP requests. This allows you 39 | * set Flash messages for the current request, for the next request, 40 | * or to retain messages from the previous request through to 41 | * the next request. 42 | * 43 | * @package Slim 44 | * @author Josh Lockhart 45 | * @since 1.5.2 46 | */ 47 | class Slim_Middleware_Flash extends Slim_Middleware implements ArrayAccess { 48 | /** 49 | * @var array 50 | */ 51 | protected $settings; 52 | 53 | /** 54 | * @var array 55 | */ 56 | protected $messages; 57 | 58 | /** 59 | * Constructor 60 | * @param Slim $app 61 | * @param array $settings 62 | * @return void 63 | */ 64 | public function __construct( $settings = array() ) { 65 | $this->settings = array_merge(array('key' => 'slim.flash'), $settings); 66 | $this->messages = array( 67 | 'prev' => array(), //flash messages from prev request (loaded when middleware called) 68 | 'next' => array(), //flash messages for next request 69 | 'now' => array() //flash messages for current request 70 | ); 71 | } 72 | 73 | /** 74 | * Call 75 | * @return void 76 | */ 77 | public function call() { 78 | //Read flash messaging from previous request if available 79 | $this->loadMessages(); 80 | 81 | //Prepare flash messaging for current request 82 | $env = $this->app->environment(); 83 | $env['slim.flash'] = $this; 84 | $this->next->call(); 85 | $this->save(); 86 | } 87 | 88 | /** 89 | * Now 90 | * 91 | * Specify a flash message for a given key to be shown for the current request 92 | * 93 | * @param string $key 94 | * @param string $value 95 | * @return void 96 | */ 97 | public function now( $key, $value ) { 98 | $this->messages['now'][(string)$key] = $value; 99 | } 100 | 101 | /** 102 | * Set 103 | * 104 | * Specify a flash message for a given key to be shown for the next request 105 | * 106 | * @param string $key 107 | * @param string $value 108 | * @return void 109 | */ 110 | public function set( $key, $value ) { 111 | $this->messages['next'][(string)$key] = $value; 112 | } 113 | 114 | /** 115 | * Keep 116 | * 117 | * Retain flash messages from the previous request for the next request 118 | * 119 | * @return void 120 | */ 121 | public function keep() { 122 | foreach ( $this->messages['prev'] as $key => $val ) { 123 | $this->messages['next'][$key] = $val; 124 | } 125 | } 126 | 127 | /** 128 | * Save 129 | */ 130 | public function save() { 131 | $_SESSION[$this->settings['key']] = $this->messages['next']; 132 | } 133 | 134 | /** 135 | * Load messages 136 | * 137 | * Load messages from previous request if available 138 | */ 139 | public function loadMessages() { 140 | if ( isset($_SESSION[$this->settings['key']]) ) { 141 | $this->messages['prev'] = $_SESSION[$this->settings['key']]; 142 | } 143 | } 144 | 145 | /** 146 | * Get messages 147 | * 148 | * Return array of flash messages to be shown for the current request 149 | * 150 | * @return array 151 | */ 152 | public function getMessages() { 153 | return array_merge($this->messages['prev'], $this->messages['now']); 154 | } 155 | 156 | /** 157 | * Array Access: Offset Exists 158 | */ 159 | public function offsetExists( $offset ) { 160 | $messages = $this->getMessages(); 161 | return isset($messages[$offset]); 162 | } 163 | 164 | /** 165 | * Array Access: Offset Get 166 | */ 167 | public function offsetGet( $offset ) { 168 | $messages = $this->getMessages(); 169 | return isset($messages[$offset]) ? $messages[$offset] : null; 170 | } 171 | 172 | /** 173 | * Array Access: Offset Set 174 | */ 175 | public function offsetSet( $offset, $value ) { 176 | $this->now($offset, $value); 177 | } 178 | 179 | /** 180 | * Array Access: Offset Unset 181 | */ 182 | public function offsetUnset( $offset ) { 183 | unset($this->messages['prev'][$offset], $this->messages['now'][$offset]); 184 | } 185 | } -------------------------------------------------------------------------------- /api/Slim/Middleware/MethodOverride.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * HTTP Method Override 36 | * 37 | * This is middleware for a Slim application that allows traditional 38 | * desktop browsers to submit psuedo PUT and DELETE requests by relying 39 | * on a pre-determined request parameter. Without this middleware, 40 | * desktop browsers are only able to submit GET and POST requests. 41 | * 42 | * This middleware is included automatically! 43 | * 44 | * @package Slim 45 | * @author Josh Lockhart 46 | * @since 1.5.2 47 | */ 48 | class Slim_Middleware_MethodOverride extends Slim_Middleware { 49 | /** 50 | * @var array 51 | */ 52 | protected $settings; 53 | 54 | /** 55 | * Constructor 56 | * @param Slim $app 57 | * @param array $settings 58 | * @return void 59 | */ 60 | public function __construct( $settings = array() ) { 61 | $this->settings = array_merge(array('key' => '_METHOD'), $settings); 62 | } 63 | 64 | /** 65 | * Call 66 | * 67 | * Implements Slim middleware interface. This method is invoked and passed 68 | * an array of environemnt variables. This middleware inspects the environment 69 | * variables for the HTTP method override parameter; if found, this middleware 70 | * modifies the environment settings so downstream middleware and/or the Slim 71 | * application will treat the request with the desired HTTP method. 72 | * 73 | * @param array $env 74 | * @return array[status, header, body] 75 | */ 76 | public function call() { 77 | $env = $this->app->environment(); 78 | if ( isset($env['X_HTTP_METHOD_OVERRIDE']) ) { 79 | // Header commonly used by Backbone.js and others 80 | $env['slim.method_override.original_method'] = $env['REQUEST_METHOD']; 81 | $env['REQUEST_METHOD'] = strtoupper($env['X_HTTP_METHOD_OVERRIDE']); 82 | } else if ( isset($env['REQUEST_METHOD']) && $env['REQUEST_METHOD'] === 'POST' ) { 83 | // HTML Form Override 84 | $req = new Slim_Http_Request($env); 85 | $method = $req->post($this->settings['key']); 86 | if ( $method ) { 87 | $env['slim.method_override.original_method'] = $env['REQUEST_METHOD']; 88 | $env['REQUEST_METHOD'] = strtoupper($method); 89 | } 90 | } 91 | $this->next->call(); 92 | } 93 | } -------------------------------------------------------------------------------- /api/Slim/Middleware/PrettyExceptions.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Pretty Exceptions 36 | * 37 | * This middleware catches any Exception thrown by the surrounded 38 | * application and displays a developer-friendly diagnostic screen. 39 | * 40 | * @package Slim 41 | * @author Josh Lockhart 42 | * @since 1.0.0 43 | */ 44 | class Slim_Middleware_PrettyExceptions extends Slim_Middleware { 45 | /** 46 | * @var array 47 | */ 48 | protected $settings; 49 | 50 | /** 51 | * Constructor 52 | * @param Slim|middleware $app 53 | * @param array $settings 54 | */ 55 | public function __construct( $settings = array() ) { 56 | $this->settings = $settings; 57 | } 58 | 59 | /** 60 | * Call 61 | * @return void 62 | */ 63 | public function call() { 64 | try { 65 | $this->next->call(); 66 | } catch ( Exception $e ) { 67 | $env = $this->app->environment(); 68 | $env['slim.log']->error($e); 69 | $this->app->response()->status(500); 70 | $this->app->response()->body($this->renderBody($env, $e)); 71 | } 72 | } 73 | 74 | /** 75 | * Render response body 76 | * @param array $env 77 | * @param Exception $exception 78 | * @return string 79 | */ 80 | protected function renderBody( &$env, $exception ) { 81 | $title = 'Slim Application Error'; 82 | $code = $exception->getCode(); 83 | $message = $exception->getMessage(); 84 | $file = $exception->getFile(); 85 | $line = $exception->getLine(); 86 | $trace = $exception->getTraceAsString(); 87 | $html = sprintf('

%s

', $title); 88 | $html .= '

The application could not run because of the following error:

'; 89 | $html .= '

Details

'; 90 | if ( $code ) { 91 | $html .= sprintf('
Code: %s
', $code); 92 | } 93 | if ( $message ) { 94 | $html .= sprintf('
Message: %s
', $message); 95 | } 96 | if ( $file ) { 97 | $html .= sprintf('
File: %s
', $file); 98 | } 99 | if ( $line ) { 100 | $html .= sprintf('
Line: %s
', $line); 101 | } 102 | if ( $trace ) { 103 | $html .= '

Trace

'; 104 | $html .= sprintf('
%s
', $trace); 105 | } 106 | return sprintf("%s%s", $title, $html); 107 | } 108 | } -------------------------------------------------------------------------------- /api/Slim/Middleware/SessionCookie.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Session Cookie 36 | * 37 | * This class provides an HTTP cookie storage mechanism 38 | * for session data. This class avoids using a PHP session 39 | * and instead serializes/unserializes the $_SESSION global 40 | * variable to/from an HTTP cookie. 41 | * 42 | * If a secret key is provided with this middleware, the HTTP 43 | * cookie will be checked for integrity to ensure the client-side 44 | * cookie is not changed. 45 | * 46 | * You should NEVER store sensitive data in a client-side cookie 47 | * in any format, encrypted or not. If you need to store sensitive 48 | * user information in a session, you should rely on PHP's native 49 | * session implementation, or use other middleware to store 50 | * session data in a database or alternative server-side cache. 51 | * 52 | * Because this class stores serialized session data in an HTTP cookie, 53 | * you are inherently limtied to 4 Kb. If you attempt to store 54 | * more than this amount, serialization will fail. 55 | * 56 | * @package Slim 57 | * @author Josh Lockhart 58 | * @since 1.5.2 59 | */ 60 | class Slim_Middleware_SessionCookie extends Slim_Middleware { 61 | /** 62 | * @var array 63 | */ 64 | protected $settings; 65 | 66 | /** 67 | * Constructor 68 | * 69 | * @param array $settings 70 | * @return void 71 | */ 72 | public function __construct( $settings = array() ) { 73 | $this->settings = array_merge(array( 74 | 'expires' => '20 minutes', 75 | 'path' => '/', 76 | 'domain' => null, 77 | 'secure' => false, 78 | 'httponly' => false, 79 | 'name' => 'slim_session', 80 | 'secret' => 'CHANGE_ME', 81 | 'cipher' => MCRYPT_RIJNDAEL_256, 82 | 'cipher_mode' => MCRYPT_MODE_CBC 83 | ), $settings); 84 | if ( is_string($this->settings['expires']) ) { 85 | $this->settings['expires'] = strtotime($this->settings['expires']); 86 | } 87 | } 88 | 89 | /** 90 | * Call 91 | * @return void 92 | */ 93 | public function call() { 94 | $this->loadSession(); 95 | $this->next->call(); 96 | $this->saveSession(); 97 | } 98 | 99 | /** 100 | * Load session 101 | * @param array $env 102 | * @return void 103 | */ 104 | protected function loadSession() { 105 | session_start(); 106 | $value = Slim_Http_Util::decodeSecureCookie( 107 | $this->app->request()->cookies($this->settings['name']), 108 | $this->settings['secret'], 109 | $this->settings['cipher'], 110 | $this->settings['cipher_mode'] 111 | ); 112 | if ( $value ) { 113 | $_SESSION = unserialize($value); 114 | } else { 115 | $_SESSION = array(); 116 | } 117 | } 118 | 119 | /** 120 | * Save session 121 | * @return void 122 | */ 123 | protected function saveSession() { 124 | $value = Slim_Http_Util::encodeSecureCookie( 125 | serialize($_SESSION), 126 | $this->settings['expires'], 127 | $this->settings['secret'], 128 | $this->settings['cipher'], 129 | $this->settings['cipher_mode'] 130 | ); 131 | if ( strlen($value) > 4096 ) { 132 | $this->app->getLog()->error('WARNING! Slim_Middleware_SessionCookie data size is larger than 4KB. Content save failed.'); 133 | } else { 134 | $this->app->response()->setCookie($this->settings['name'], array( 135 | 'value' => $value, 136 | 'domain' => $this->settings['domain'], 137 | 'path' => $this->settings['path'], 138 | 'expires' => $this->settings['expires'], 139 | 'secure' => $this->settings['secure'], 140 | 'httponly' => $this->settings['httponly'] 141 | )); 142 | } 143 | session_destroy(); 144 | } 145 | } -------------------------------------------------------------------------------- /api/Slim/Router.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Router 36 | * 37 | * This class organizes Route objects and, upon request, will 38 | * return an iterator for routes that match the HTTP request URI. 39 | * 40 | * @package Slim 41 | * @author Josh Lockhart 42 | * @since 1.0.0 43 | */ 44 | class Slim_Router implements IteratorAggregate { 45 | /** 46 | * @var Slim_Http_Request 47 | */ 48 | protected $request; 49 | 50 | /** 51 | * @var Slim_Http_Response 52 | */ 53 | protected $response; 54 | 55 | /** 56 | * @var array Lookup hash of all routes 57 | */ 58 | protected $routes; 59 | 60 | /** 61 | * @var array Lookup hash of named routes, keyed by route name 62 | */ 63 | protected $namedRoutes; 64 | 65 | /** 66 | * @var array Array of routes that match the Request URI (lazy-loaded) 67 | */ 68 | protected $matchedRoutes; 69 | 70 | /** 71 | * @var mixed Callable to be invoked if no matching routes are found 72 | */ 73 | protected $notFound; 74 | 75 | /** 76 | * @var mixed Callable to be invoked if application error 77 | */ 78 | protected $error; 79 | 80 | /** 81 | * Constructor 82 | * @param Slim_Http_Request $request The HTTP request object 83 | * @param Slim_Http_Response $response The HTTP response object 84 | */ 85 | public function __construct( Slim_Http_Request $request, Slim_Http_Response $response ) { 86 | $this->request = $request; 87 | $this->response = $response; 88 | $this->routes = array(); 89 | $this->namedRoutes = array(); 90 | } 91 | 92 | /** 93 | * Get Iterator 94 | * @return ArrayIterator 95 | */ 96 | public function getIterator() { 97 | return new ArrayIterator($this->getMatchedRoutes()); 98 | } 99 | 100 | /** 101 | * Get Request 102 | * @return Slim_Http_Request 103 | */ 104 | public function getRequest() { 105 | return $this->request; 106 | } 107 | 108 | /** 109 | * Get Response 110 | * @return Slim_Http_Response 111 | */ 112 | public function getResponse() { 113 | return $this->response; 114 | } 115 | 116 | /** 117 | * Return routes that match the current request 118 | * @return array[Slim_Route] 119 | */ 120 | public function getMatchedRoutes( $reload = false ) { 121 | if ( $reload || is_null($this->matchedRoutes) ) { 122 | $this->matchedRoutes = array(); 123 | foreach ( $this->routes as $route ) { 124 | if ( $route->matches($this->request->getResourceUri()) ) { 125 | $this->matchedRoutes[] = $route; 126 | } 127 | } 128 | } 129 | return $this->matchedRoutes; 130 | } 131 | 132 | /** 133 | * Map a route to a callback function 134 | * @param string $pattern The URL pattern (ie. "/books/:id") 135 | * @param mixed $callable Anything that returns TRUE for is_callable() 136 | * @return Slim_Route 137 | */ 138 | public function map( $pattern, $callable ) { 139 | $route = new Slim_Route($pattern, $callable); 140 | $route->setRouter($this); 141 | $this->routes[] = $route; 142 | return $route; 143 | } 144 | 145 | /** 146 | * Get URL for named route 147 | * @param string $name The name of the route 148 | * @param array Associative array of URL parameter names and values 149 | * @throws RuntimeException If named route not found 150 | * @return string The URL for the given route populated with the given parameters 151 | */ 152 | public function urlFor( $name, $params = array() ) { 153 | if ( !$this->hasNamedRoute($name) ) { 154 | throw new RuntimeException('Named route not found for name: ' . $name); 155 | } 156 | $pattern = $this->getNamedRoute($name)->getPattern(); 157 | $search = $replace = array(); 158 | foreach ( $params as $key => $value ) { 159 | $search[] = ':' . $key; 160 | $replace[] = $value; 161 | } 162 | $pattern = str_replace($search, $replace, $pattern); 163 | //Remove remnants of unpopulated, trailing optional pattern segments 164 | return preg_replace(array( 165 | '@\(\/?:.+\/??\)\??@', 166 | '@\?|\(|\)@' 167 | ), '', $this->request->getRootUri() . $pattern); 168 | } 169 | 170 | /** 171 | * Add named route 172 | * @param string $name The route name 173 | * @param Slim_Route $route The route object 174 | * @throws RuntimeException If a named route already exists with the same name 175 | * @return void 176 | */ 177 | public function addNamedRoute( $name, Slim_Route $route ) { 178 | if ( $this->hasNamedRoute($name) ) { 179 | throw new RuntimeException('Named route already exists with name: ' . $name); 180 | } 181 | $this->namedRoutes[(string)$name] = $route; 182 | } 183 | 184 | /** 185 | * Has named route 186 | * @param string $name The route name 187 | * @return bool 188 | */ 189 | public function hasNamedRoute( $name ) { 190 | return isset($this->namedRoutes[(string)$name]); 191 | } 192 | 193 | /** 194 | * Get named route 195 | * @param string $name 196 | * @return Slim_Route|null 197 | */ 198 | public function getNamedRoute( $name ) { 199 | if ( $this->hasNamedRoute($name) ) { 200 | return $this->namedRoutes[(string)$name]; 201 | } else { 202 | return null; 203 | } 204 | } 205 | 206 | /** 207 | * Get named routes 208 | * @return ArrayIterator 209 | */ 210 | public function getNamedRoutes() { 211 | return new ArrayIterator($this->namedRoutes); 212 | } 213 | 214 | /** 215 | * Register a 404 Not Found callback 216 | * @param mixed $callable Anything that returns TRUE for is_callable() 217 | * @return mixed 218 | */ 219 | public function notFound( $callable = null ) { 220 | if ( is_callable($callable) ) { 221 | $this->notFound = $callable; 222 | } 223 | return $this->notFound; 224 | } 225 | 226 | /** 227 | * Register a 500 Error callback 228 | * @param mixed $callable Anything that returns TRUE for is_callable() 229 | * @return mixed 230 | */ 231 | public function error( $callable = null ) { 232 | if ( is_callable($callable) ) { 233 | $this->error = $callable; 234 | } 235 | return $this->error; 236 | } 237 | } -------------------------------------------------------------------------------- /api/Slim/View.php: -------------------------------------------------------------------------------- 1 | 6 | * @copyright 2011 Josh Lockhart 7 | * @link http://www.slimframework.com 8 | * @license http://www.slimframework.com/license 9 | * @version 1.6.0 10 | * @package Slim 11 | * 12 | * MIT LICENSE 13 | * 14 | * Permission is hereby granted, free of charge, to any person obtaining 15 | * a copy of this software and associated documentation files (the 16 | * "Software"), to deal in the Software without restriction, including 17 | * without limitation the rights to use, copy, modify, merge, publish, 18 | * distribute, sublicense, and/or sell copies of the Software, and to 19 | * permit persons to whom the Software is furnished to do so, subject to 20 | * the following conditions: 21 | * 22 | * The above copyright notice and this permission notice shall be 23 | * included in all copies or substantial portions of the Software. 24 | * 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 29 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 30 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 31 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 32 | */ 33 | 34 | /** 35 | * Slim View 36 | * 37 | * The View is responsible for rendering and/or displaying a template. 38 | * It is recommended that you subclass View and re-implement the 39 | * `View::render` method to use a custom templating engine such as 40 | * Smarty, Twig, Mustache, etc. It is important that `View::render` 41 | * `return` the final template output. Do not `echo` the output. 42 | * 43 | * @package Slim 44 | * @author Josh Lockhart 45 | * @since 1.0.0 46 | */ 47 | class Slim_View { 48 | /** 49 | * @var array Key-value array of data available to the template 50 | */ 51 | protected $data = array(); 52 | 53 | /** 54 | * @var string Absolute or relative path to the templates directory 55 | */ 56 | protected $templatesDirectory; 57 | 58 | /** 59 | * Constructor 60 | * 61 | * This is empty but may be overridden in a subclass 62 | */ 63 | public function __construct() {} 64 | 65 | /** 66 | * Get data 67 | * @param string $key 68 | * @return array|mixed|null All View data if no $key, value of datum 69 | * if $key, or NULL if $key but datum 70 | * does not exist. 71 | */ 72 | public function getData( $key = null ) { 73 | if ( !is_null($key) ) { 74 | return isset($this->data[$key]) ? $this->data[$key] : null; 75 | } else { 76 | return $this->data; 77 | } 78 | } 79 | 80 | /** 81 | * Set data 82 | * 83 | * This method is overloaded to accept two different method signatures. 84 | * You may use this to set a specific key with a specfic value, 85 | * or you may use this to set all data to a specific array. 86 | * 87 | * USAGE: 88 | * 89 | * View::setData('color', 'red'); 90 | * View::setData(array('color' => 'red', 'number' => 1)); 91 | * 92 | * @param string|array 93 | * @param mixed Optional. Only use if first argument is a string. 94 | * @return void 95 | * @throws InvalidArgumentException If incorrect method signature 96 | */ 97 | public function setData() { 98 | $args = func_get_args(); 99 | if ( count($args) === 1 && is_array($args[0]) ) { 100 | $this->data = $args[0]; 101 | } else if ( count($args) === 2 ) { 102 | $this->data[(string)$args[0]] = $args[1]; 103 | } else { 104 | throw new InvalidArgumentException('Cannot set View data with provided arguments. Usage: `View::setData( $key, $value );` or `View::setData([ key => value, ... ]);`'); 105 | } 106 | } 107 | 108 | /** 109 | * Append data to existing View data 110 | * @param array $data 111 | * @return void 112 | */ 113 | public function appendData( array $data ) { 114 | $this->data = array_merge($this->data, $data); 115 | } 116 | 117 | /** 118 | * Get templates directory 119 | * @return string|null Path to templates directory without trailing slash 120 | */ 121 | public function getTemplatesDirectory() { 122 | return $this->templatesDirectory; 123 | } 124 | 125 | /** 126 | * Set templates directory 127 | * @param string $dir 128 | * @return void 129 | * @throws RuntimeException If directory is not a directory or does not exist 130 | */ 131 | public function setTemplatesDirectory( $dir ) { 132 | $this->templatesDirectory = rtrim($dir, '/'); 133 | } 134 | 135 | /** 136 | * Display template 137 | * 138 | * This method echoes the rendered template to the current output buffer 139 | * 140 | * @param string $template Path to template file relative to templates directoy 141 | * @return void 142 | */ 143 | public function display( $template ) { 144 | echo $this->render($template); 145 | } 146 | 147 | /** 148 | * Render template 149 | * @param string $template Path to template file relative to templates directory 150 | * @return string Rendered template 151 | * @throws RuntimeException If template does not exist 152 | */ 153 | public function render( $template ) { 154 | extract($this->data); 155 | $templatePath = $this->getTemplatesDirectory() . '/' . ltrim($template, '/'); 156 | if ( !file_exists($templatePath) ) { 157 | throw new RuntimeException('View cannot render template `' . $templatePath . '`. Template does not exist.'); 158 | } 159 | ob_start(); 160 | require $templatePath; 161 | return ob_get_clean(); 162 | } 163 | 164 | } -------------------------------------------------------------------------------- /api/index.php: -------------------------------------------------------------------------------- 1 | get('/employees', 'getEmployees'); 8 | $app->get('/employees/:id', 'getEmployee'); 9 | $app->get('/employees/:id/reports', 'getReports'); 10 | $app->get('/employees/search/:query', 'getEmployeesByName'); 11 | $app->get('/employees/modifiedsince/:timestamp', 'findByModifiedDate'); 12 | 13 | $app->run(); 14 | 15 | function getEmployees() { 16 | 17 | if (isset($_GET['name'])) { 18 | return getEmployeesByName($_GET['name']); 19 | } else if (isset($_GET['modifiedSince'])) { 20 | return getModifiedEmployees($_GET['modifiedSince']); 21 | } 22 | 23 | $sql = "select e.id, e.firstName, e.lastName, e.title, count(r.id) reportCount " . 24 | "from employee e left join employee r on r.managerId = e.id " . 25 | "group by e.id order by e.lastName, e.firstName"; 26 | try { 27 | $db = getConnection(); 28 | $stmt = $db->query($sql); 29 | $employees = $stmt->fetchAll(PDO::FETCH_OBJ); 30 | $db = null; 31 | 32 | // Include support for JSONP requests 33 | if (!isset($_GET['callback'])) { 34 | echo json_encode($employees); 35 | } else { 36 | echo $_GET['callback'] . '(' . json_encode($employees) . ');'; 37 | } 38 | 39 | } catch(PDOException $e) { 40 | echo '{"error":{"text":'. $e->getMessage() .'}}'; 41 | } 42 | } 43 | 44 | function getEmployee($id) { 45 | $sql = "select e.id, e.firstName, e.lastName, e.title, e.officePhone, e.cellPhone, e.email, e.managerId, e.twitterId, m.firstName managerFirstName, m.lastName managerLastName, count(r.id) reportCount " . 46 | "from employee e " . 47 | "left join employee r on r.managerId = e.id " . 48 | "left join employee m on e.managerId = m.id " . 49 | "where e.id=:id"; 50 | try { 51 | $db = getConnection(); 52 | $stmt = $db->prepare($sql); 53 | $stmt->bindParam("id", $id); 54 | $stmt->execute(); 55 | $employee = $stmt->fetchObject(); 56 | $db = null; 57 | 58 | // Include support for JSONP requests 59 | if (!isset($_GET['callback'])) { 60 | echo json_encode($employee); 61 | } else { 62 | echo $_GET['callback'] . '(' . json_encode($employee) . ');'; 63 | } 64 | 65 | } catch(PDOException $e) { 66 | echo '{"error":{"text":'. $e->getMessage() .'}}'; 67 | } 68 | } 69 | 70 | function getReports($id) { 71 | 72 | $sql = "select e.id, e.firstName, e.lastName, e.title, count(r.id) reportCount " . 73 | "from employee e left join employee r on r.managerId = e.id " . 74 | "where e.managerId=:id " . 75 | "group by e.id order by e.lastName, e.firstName"; 76 | 77 | try { 78 | $db = getConnection(); 79 | $stmt = $db->prepare($sql); 80 | $stmt->bindParam("id", $id); 81 | $stmt->execute(); 82 | $employees = $stmt->fetchAll(PDO::FETCH_OBJ); 83 | $db = null; 84 | 85 | // Include support for JSONP requests 86 | if (!isset($_GET['callback'])) { 87 | echo json_encode($employees); 88 | } else { 89 | echo $_GET['callback'] . '(' . json_encode($employees) . ');'; 90 | } 91 | 92 | } catch(PDOException $e) { 93 | echo '{"error":{"text":'. $e->getMessage() .'}}'; 94 | } 95 | } 96 | 97 | function getEmployeesByName($name) { 98 | $sql = "select e.id, e.firstName, e.lastName, e.title, count(r.id) reportCount " . 99 | "from employee e left join employee r on r.managerId = e.id " . 100 | "WHERE UPPER(CONCAT(e.firstName, ' ', e.lastName)) LIKE :name " . 101 | "group by e.id order by e.lastName, e.firstName"; 102 | try { 103 | $db = getConnection(); 104 | $stmt = $db->prepare($sql); 105 | $name = "%".$name."%"; 106 | $stmt->bindParam("name", $name); 107 | $stmt->execute(); 108 | $employees = $stmt->fetchAll(PDO::FETCH_OBJ); 109 | $db = null; 110 | 111 | // Include support for JSONP requests 112 | if (!isset($_GET['callback'])) { 113 | echo json_encode($employees); 114 | } else { 115 | echo $_GET['callback'] . '(' . json_encode($employees) . ');'; 116 | } 117 | 118 | } catch(PDOException $e) { 119 | echo '{"error":{"text":'. $e->getMessage() .'}}'; 120 | } 121 | } 122 | 123 | function getModifiedEmployees($modifiedSince) { 124 | if ($modifiedSince == 'null') { 125 | $modifiedSince = "1000-01-01"; 126 | } 127 | $sql = "select * from employee WHERE lastModified > :modifiedSince"; 128 | try { 129 | $db = getConnection(); 130 | $stmt = $db->prepare($sql); 131 | $stmt->bindParam("modifiedSince", $modifiedSince); 132 | $stmt->execute(); 133 | $employees = $stmt->fetchAll(PDO::FETCH_OBJ); 134 | $db = null; 135 | 136 | // Include support for JSONP requests 137 | if (!isset($_GET['callback'])) { 138 | echo json_encode($employees); 139 | } else { 140 | echo $_GET['callback'] . '(' . json_encode($employees) . ');'; 141 | } 142 | 143 | } catch(PDOException $e) { 144 | echo '{"error":{"text":'. $e->getMessage() .'}}'; 145 | } 146 | } 147 | 148 | function getConnection() { 149 | $dbhost="127.0.0.1"; 150 | $dbuser="root"; 151 | $dbpass=""; 152 | $dbname="directory"; 153 | $dbh = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass); 154 | $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 155 | return $dbh; 156 | } 157 | 158 | ?> -------------------------------------------------------------------------------- /directory.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 5.5.15, for osx10.6 (i386) 2 | -- 3 | -- Host: localhost Database: directory 4 | -- ------------------------------------------------------ 5 | -- Server version 5.5.15 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!40101 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `employee` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `employee`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!40101 SET character_set_client = utf8 */; 25 | CREATE TABLE `employee` ( 26 | `id` int(11) NOT NULL AUTO_INCREMENT, 27 | `firstName` varchar(30) NOT NULL, 28 | `lastName` varchar(30) NOT NULL, 29 | `managerId` int(11) NOT NULL, 30 | `title` varchar(45) NOT NULL, 31 | `department` varchar(45) NOT NULL, 32 | `officePhone` varchar(45) NOT NULL, 33 | `cellPhone` varchar(45) NOT NULL, 34 | `email` varchar(45) NOT NULL, 35 | `city` varchar(45) NOT NULL, 36 | `picture` varchar(250) NOT NULL, 37 | `twitterId` varchar(45) DEFAULT NULL, 38 | `blogURL` varchar(200) DEFAULT NULL, 39 | PRIMARY KEY (`id`) 40 | ) ENGINE=MyISAM AUTO_INCREMENT=22 DEFAULT CHARSET=latin1; 41 | /*!40101 SET character_set_client = @saved_cs_client */; 42 | 43 | -- 44 | -- Dumping data for table `employee` 45 | -- 46 | 47 | LOCK TABLES `employee` WRITE; 48 | /*!40000 ALTER TABLE `employee` DISABLE KEYS */; 49 | INSERT INTO `employee` VALUES (12,'Steven','Wells',4,'Software Architect','Engineering','617-000-0012','781-000-0012','swells@fakemail.com','Boston, MA','steven_wells.jpg','@fakeswells','http://coenraets.org'),(11,'Amy','Jones',5,'Sales Representative','Sales','617-000-0011','781-000-0011','ajones@fakemail.com','Boston, MA','amy_jones.jpg','@fakeajones','http://coenraets.org'),(10,'Kathleen','Byrne',5,'Sales Representative','Sales','617-000-0010','781-000-0010','kbyrne@fakemail.com','Boston, MA','kathleen_byrne.jpg','@fakekbyrne','http://coenraets.org'),(9,'Gary','Donovan',2,'Marketing','Marketing','617-000-0009','781-000-0009','gdonovan@fakemail.com','Boston, MA','gary_donovan.jpg','@fakegdonovan','http://coenraets.org'),(8,'Lisa','Wong',2,'Marketing Manager','Marketing','617-000-0008','781-000-0008','lwong@fakemail.com','Boston, MA','lisa_wong.jpg','@fakelwong','http://coenraets.org'),(7,'Paula','Gates',4,'Software Architect','Engineering','617-000-0007','781-000-0007','pgates@fakemail.com','Boston, MA','paula_gates.jpg','@fakepgates','http://coenraets.org'),(5,'Ray','Moore',1,'VP of Sales','Sales','617-000-0005','781-000-0005','rmoore@fakemail.com','Boston, MA','ray_moore.jpg','@fakermoore','http://coenraets.org'),(6,'Paul','Jones',4,'QA Manager','Engineering','617-000-0006','781-000-0006','pjones@fakemail.com','Boston, MA','paul_jones.jpg','@fakepjones','http://coenraets.org'),(3,'Eugene','Lee',1,'CFO','Accounting','617-000-0003','781-000-0003','elee@fakemail.com','Boston, MA','eugene_lee.jpg','@fakeelee','http://coenraets.org'),(4,'John','Williams',1,'VP of Engineering','Engineering','617-000-0004','781-000-0004','jwilliams@fakemail.com','Boston, MA','john_williams.jpg','@fakejwilliams','http://coenraets.org'),(2,'Julie','Taylor',1,'VP of Marketing','Marketing','617-000-0002','781-000-0002','jtaylor@fakemail.com','Boston, MA','julie_taylor.jpg','@fakejtaylor','http://coenraets.org'),(1,'James','King',0,'President and CEO','Corporate','617-000-0001','781-000-0001','jking@fakemail.com','Boston, MA','james_king.jpg','@fakejking','http://coenraets.org'); 50 | /*!40000 ALTER TABLE `employee` ENABLE KEYS */; 51 | UNLOCK TABLES; 52 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 53 | 54 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 55 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 56 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 57 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 58 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 59 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 60 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 61 | 62 | -- Dump completed on 2012-02-13 13:33:11 63 | -------------------------------------------------------------------------------- /iphone/css/images/activity-indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/activity-indicator.png -------------------------------------------------------------------------------- /iphone/css/images/back-button-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/back-button-active.png -------------------------------------------------------------------------------- /iphone/css/images/back-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/back-button.png -------------------------------------------------------------------------------- /iphone/css/images/button-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/button-active.png -------------------------------------------------------------------------------- /iphone/css/images/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/button.png -------------------------------------------------------------------------------- /iphone/css/images/call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/call.png -------------------------------------------------------------------------------- /iphone/css/images/comment-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/comment-arrow.png -------------------------------------------------------------------------------- /iphone/css/images/detail-disclosure-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/detail-disclosure-button.png -------------------------------------------------------------------------------- /iphone/css/images/disclosure-indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/disclosure-indicator.png -------------------------------------------------------------------------------- /iphone/css/images/mail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/mail.png -------------------------------------------------------------------------------- /iphone/css/images/manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/manager.png -------------------------------------------------------------------------------- /iphone/css/images/message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/message.png -------------------------------------------------------------------------------- /iphone/css/images/navbar-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/navbar-bg.png -------------------------------------------------------------------------------- /iphone/css/images/navbar-landscape-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/navbar-landscape-bg.png -------------------------------------------------------------------------------- /iphone/css/images/refresh-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/refresh-icon.png -------------------------------------------------------------------------------- /iphone/css/images/reports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/reports.png -------------------------------------------------------------------------------- /iphone/css/images/search-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/css/images/search-icon.png -------------------------------------------------------------------------------- /iphone/css/styles.css: -------------------------------------------------------------------------------- 1 | /* Many of the styles below come from the app documented in this article http://cheeaun.com/blog/2012/03/how-i-built-hacker-news-mobile-web-app */ 2 | 3 | html{ 4 | height: 100%; 5 | } 6 | body{ 7 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 8 | font-size: 16px; 9 | margin: 0; 10 | padding: 0; 11 | height: 100%; 12 | background-color: #fff; 13 | overflow: hidden; 14 | position: relative; 15 | } 16 | 17 | .header{ 18 | background: #b2bbca url(images/navbar-bg.png) repeat-x; 19 | -webkit-background-size: 1px 44px; 20 | -moz-background-size: 1px 44px; 21 | -ms-background-size: 1px 44px; 22 | -o-background-size: 1px 44px; 23 | background-size: 1px 44px; 24 | height: 44px; 25 | line-height: 44px; 26 | width: 100%; 27 | color: #fff; 28 | -webkit-user-select: none; 29 | -webkit-touch-callout: none; 30 | } 31 | 32 | .header-button{ 33 | position: absolute; 34 | top: 0; 35 | padding: 7px 5px; 36 | -webkit-tap-highlight-color: rgba(0,0,0,0); 37 | line-height: 1em; 38 | } 39 | 40 | .header-button button{ 41 | pointer-events: none; 42 | -webkit-box-sizing: border-box; 43 | -moz-box-sizing: border-box; 44 | box-sizing: border-box; 45 | min-width: 50px; 46 | height: 30px; 47 | line-height: 25px; 48 | font-weight: bold; 49 | font-size: 12px; 50 | text-align: center; 51 | color: #fff; 52 | text-shadow: 0 -1px rgba(0,0,0,.6); 53 | padding: 0 4px; 54 | margin: 0; 55 | text-decoration: none; 56 | border-width: 2px 5px; 57 | -webkit-border-image: url(images/button.png) 4 10 4 10; 58 | -moz-border-image: url(images/button.png) 4 10 4 10; 59 | -ms-border-image: url(images/button.png) 4 10 4 10; 60 | -o-border-image: url(images/button.png) 4 10 4 10; 61 | background: transparent url(images/button-active.png) no-repeat; 62 | -webkit-background-size: 0 0; 63 | -moz-background-size: 0 0; 64 | -ms-background-size: 0 0; 65 | -o-background-size: 0 0; 66 | background-size: 0 0; 67 | } 68 | 69 | .header-button-icon button{ 70 | min-width: 0; 71 | } 72 | 73 | .header-button-icon button img{ 74 | vertical-align: text-bottom; 75 | } 76 | 77 | .header-button.tappable-active button{ 78 | -webkit-border-image: url(images/button-active.png) 4 10 4 10; 79 | -moz-border-image: url(images/button-active.png) 4 10 4 10; 80 | -ms-border-image: url(images/button-active.png) 4 10 4 10; 81 | -o-border-image: url(images/button-active.png) 4 10 4 10; 82 | } 83 | 84 | .header-back-button button{ 85 | padding: 0 4px 0 0; 86 | border-width: 2px 4px 2px 13px; 87 | -webkit-border-image: url(images/back-button.png) 4 8 4 26; 88 | -moz-border-image: url(images/back-button.png) 4 8 4 26; 89 | -ms-border-image: url(images/back-button.png) 4 8 4 26; 90 | -o-border-image: url(images/back-button.png) 4 8 4 26; 91 | background-image: url(images/back-button-active.png); 92 | } 93 | .header-back-button.tappable-active button{ 94 | -webkit-border-image: url(images/back-button-active.png) 4 8 4 26; 95 | -moz-border-image: url(images/back-button-active.png) 4 8 4 26; 96 | -ms-border-image: url(images/back-button-active.png) 4 8 4 26; 97 | -o-border-image: url(images/back-button-active.png) 4 8 4 26; 98 | } 99 | 100 | .header-button-left{ 101 | left: 0; 102 | } 103 | 104 | .header-button-right{ 105 | right: 0; 106 | } 107 | 108 | .header h1{ 109 | padding: 0; 110 | text-align: center; 111 | font-size: 20px; 112 | text-shadow: 0 -1px rgba(0,0,0,.4); 113 | margin: 0; 114 | white-space: nowrap; 115 | text-overflow: ellipsis; 116 | overflow: hidden; 117 | -webkit-box-flex: 1; 118 | -moz-box-flex: 1; 119 | box-flex: 1; 120 | } 121 | 122 | .scroll{ 123 | -webkit-box-flex: 1; 124 | -moz-box-flex: 1; 125 | box-flex: 1; 126 | overflow: auto; 127 | -webkit-overflow-scrolling: touch; 128 | background-color: #e2e7ed; 129 | display: -webkit-box; 130 | display: -moz-box; 131 | display: box; 132 | -webkit-box-orient: vertical; 133 | -moz-box-orient: vertical; 134 | box-orient: vertical; 135 | position: absolute; 136 | top: 80px; 137 | bottom: 0px; 138 | left: 0px; 139 | right: 0px; 140 | } 141 | 142 | .scroll.striped{ 143 | background-color: #cbd2d8; 144 | background-image: -webkit-gradient(linear, left top, right top, from(#c5ccd4), color-stop(0.714, #c5ccd4), color-stop(0.714, #cbd2d8), to(#cbd2d8)); 145 | background-image: -webkit-linear-gradient(left, #c5ccd4, #c5ccd4 71.4%, #cbd2d8 71.5%, #cbd2d8); 146 | background-image: -moz-linear-gradient(left, #c5ccd4, #c5ccd4 71.4%, #cbd2d8 71.5%, #cbd2d8); 147 | background-image: -ms-linear-gradient(left, #c5ccd4, #c5ccd4 71.4%, #cbd2d8 71.5%, #cbd2d8); 148 | background-image: -o-linear-gradient(left, #c5ccd4, #c5ccd4 71.4%, #cbd2d8 71.5%, #cbd2d8); 149 | background-image: linear-gradient(left, #c5ccd4, #c5ccd4 71.4%, #cbd2d8 71.5%, #cbd2d8); 150 | -webkit-background-size: 7px 1px; 151 | -moz-background-size: 7px 1px; 152 | -ms-background-size: 7px 1px; 153 | -o-background-size: 7px 1px; 154 | background-size: 7px 1px; 155 | } 156 | 157 | .tableview{ 158 | margin: 0; 159 | padding: 0; 160 | list-style: none; 161 | background-color: #fff; 162 | border-bottom: 1px solid #e0e0e0; 163 | } 164 | .tableview li{ 165 | display: block; 166 | border-top: 1px solid #e0e0e0; 167 | padding: 10px; 168 | } 169 | 170 | .tableview-links li{ 171 | padding: 0; 172 | display: -webkit-box; 173 | display: -moz-box; 174 | display: box; 175 | width: 100%; 176 | } 177 | 178 | .tableview-links li>a{ 179 | font-size: 15px; 180 | line-height: 1.3em; 181 | color: #000; 182 | display: block; 183 | padding: 5px; 184 | text-decoration: none; 185 | -webkit-tap-highlight-color: rgba(0,0,0,0); 186 | display: -webkit-box; 187 | display: -moz-box; 188 | display: box; 189 | width: 100%; 190 | -webkit-box-flex: 1; 191 | -moz-box-flex: 1; 192 | box-flex: 1; 193 | -webkit-box-sizing: border-box; 194 | -moz-box-sizing: border-box; 195 | box-sizing: border-box; 196 | background-image: -webkit-gradient(linear, left top, left bottom, from(#4286f5), to(#194fdb)); 197 | background-image: -webkit-linear-gradient(top, #4286f5, #194fdb); 198 | background-image: -moz-linear-gradient(top, #4286f5, #194fdb); 199 | background-image: -ms-linear-gradient(top, #4286f5, #194fdb); 200 | background-image: -o-linear-gradient(top, #4286f5, #194fdb); 201 | background-image: linear-gradient(top, #4286f5, #194fdb); 202 | background-position: -10px 0; 203 | background-repeat: no-repeat; 204 | -webkit-background-size: 10px 100%; 205 | -moz-background-size: 10px 100%; 206 | -ms-background-size: 10px 100%; 207 | -o-background-size: 10px 100%; 208 | background-size: 10px 100%; 209 | } 210 | 211 | .tableview-links li>a *{ 212 | pointer-events: none; 213 | } 214 | 215 | .tableview-links li>a .metadata{ 216 | display: block; 217 | font-size: 13px; 218 | color: #666d74; 219 | line-height: 1.2em; 220 | } 221 | .tableview-links li>a.pad-right{ 222 | padding-right: 44px; 223 | } 224 | .tableview-links li>a.more-link{ 225 | cursor: pointer; 226 | -webkit-touch-callout: none; 227 | line-height: 3em; 228 | padding: 10px; 229 | display: block; 230 | color: #2960d9; 231 | text-align: center; 232 | font-weight: bold; 233 | } 234 | 235 | .tableview-links li>a.tappable-active{ 236 | color: #fff; 237 | background-color: #4286f5; 238 | background-repeat: repeat-x; 239 | } 240 | .tableview-links li>a.tappable-active *{ 241 | color: #fff; 242 | } 243 | .tableview-links li>a.detail-disclosure{ 244 | -webkit-touch-callout: none; 245 | padding: 0; 246 | width: 44px; 247 | margin: 0 0 0 -44px; 248 | -webkit-box-align: center; 249 | -moz-box-align: center; 250 | box-align: center; 251 | -webkit-box-pack: center; 252 | -moz-box-pack: center; 253 | box-pack: center; 254 | -webkit-box-flex: 0; 255 | -moz-box-flex: 0; 256 | box-flex: 0; 257 | } 258 | .tableview-links li>a.detail-disclosure.tappable-active{ 259 | background: transparent none; 260 | } 261 | .tableview-links li>a.detail-disclosure span{ 262 | display: inline-block; 263 | width: 29px; 264 | height: 31px; 265 | background: transparent url(images/detail-disclosure-button.png); 266 | -webkit-background-size: 58px 31px; 267 | -moz-background-size: 58px 31px; 268 | -ms-background-size: 58px 31px; 269 | -o-background-size: 58px 31px; 270 | background-size: 58px 31px; 271 | } 272 | .tableview-links li>a.detail-disclosure.tappable-active span{ 273 | background-position: top right; 274 | } 275 | 276 | .link-text{ 277 | color: #385487; 278 | font-weight: bold; 279 | } 280 | .inline-block{ 281 | display: inline-block; 282 | } 283 | 284 | 285 | #content { 286 | position: absolute; 287 | background: #ddd; 288 | width: 100%; 289 | height: 100%; 290 | overflow-x: hidden; 291 | overflow-y: auto; 292 | } 293 | 294 | .page { 295 | position: absolute; 296 | width: 100%; 297 | height: 100%; 298 | background-color: #ddd; 299 | -webkit-transform:translate3d(0,0,0); 300 | } 301 | 302 | .stage-center { 303 | top: 0; 304 | left: 0; 305 | } 306 | 307 | .stage-left { 308 | left: -100%; 309 | } 310 | 311 | .stage-right { 312 | left: 100%; 313 | } 314 | 315 | .transition { 316 | -moz-transition-duration: .375s; 317 | -webkit-transition-duration: .375s; 318 | -o-transition-duration: .375s; 319 | } 320 | 321 | .employee-summary header{ 322 | padding: 10px 8px; 323 | text-shadow: 0 1px rgba(255,255,255,.85); 324 | } 325 | .employee-summary header h1, 326 | .employee-summary header p{ 327 | margin: 0; 328 | padding: 0; 329 | } 330 | .employee-summary header h1 a{ 331 | display: block; 332 | } 333 | .employee-summary header h1 a .link-text{ 334 | font-size: 13px; 335 | } 336 | .employee-summary header .metadata{ 337 | font-size: 13px; 338 | color: #666d74; 339 | } 340 | .employee-summary header h1{ 341 | font-size: 17px; 342 | line-height: 1.2em; 343 | } 344 | .employee-summary header h1 a{ 345 | color: #000; 346 | text-decoration: none; 347 | } 348 | .employee-summary header + .grouped-tableview{ 349 | margin-top: 0; 350 | } 351 | .employee-summary{ 352 | padding-bottom: 1px; 353 | background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,0)), to(rgba(0,0,0,.12))); 354 | background-image: -webkit-linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,.12)); 355 | background-image: -moz-linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,.12)); 356 | background-image: -ms-linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,.12)); 357 | background-image: -o-linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,.12)); 358 | background-image: linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,.12)); 359 | -webkit-background-size: 1px 11px; 360 | -moz-background-size: 1px 11px; 361 | -ms-background-size: 1px 11px; 362 | -o-background-size: 1px 11px; 363 | background-size: 1px 11px; 364 | background-repeat: repeat-x; 365 | background-position: bottom; 366 | 367 | height: 120px; 368 | } 369 | 370 | .employee-summary img { 371 | float: left; 372 | margin-right: 12px; 373 | } 374 | 375 | .action-item { 376 | box-flex: 1; 377 | } 378 | 379 | .action-icon { 380 | position: absolute; 381 | right: 10px; 382 | width: 28px; 383 | } -------------------------------------------------------------------------------- /iphone/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Employee Directory 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /iphone/libs/underscore-min.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.3.2 2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. 3 | // Underscore is freely distributable under the MIT license. 4 | // Portions of Underscore are inspired or borrowed from Prototype, 5 | // Oliver Steele's Functional, and John Resig's Micro-Templating. 6 | // For all details and documentation: 7 | // http://documentcloud.github.com/underscore 8 | (function(){function r(a,c,d){if(a===c)return 0!==a||1/a==1/c;if(null==a||null==c)return a===c;a._chain&&(a=a._wrapped);c._chain&&(c=c._wrapped);if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return!1;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:0==a?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== 9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if("object"!=typeof a||"object"!=typeof c)return!1;for(var f=d.length;f--;)if(d[f]==a)return!0;d.push(a);var f=0,g=!0;if("[object Array]"==e){if(f=a.length,g=f==c.length)for(;f--&&(g=f in a==f in c&&r(a[f],c[f],d)););}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return!1;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,h)&&!f--)break; 10 | g=!f}}d.pop();return g}var s=this,I=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,J=k.unshift,l=p.toString,K=p.hasOwnProperty,y=k.forEach,z=k.map,A=k.reduce,B=k.reduceRight,C=k.filter,D=k.every,E=k.some,q=k.indexOf,F=k.lastIndexOf,p=Array.isArray,L=Object.keys,t=Function.prototype.bind,b=function(a){return new m(a)};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):s._=b;b.VERSION="1.3.2";var j=b.each=b.forEach=function(a, 11 | c,d){if(a!=null)if(y&&a.forEach===y)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==null&&(a=[]);if(A&& 12 | a.reduce===A){e&&(c=b.bind(c,e));return f?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,i){if(f)d=c.call(e,d,a,b,i);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(B&&a.reduceRight===B){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a, 13 | c,b){var e;G(a,function(a,g,h){if(c.call(b,a,g,h)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(C&&a.filter===C)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(D&&a.every===D)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b, 14 | a,g,h)))return o});return!!e};var G=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(E&&a.some===E)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(q&&a.indexOf===q)return a.indexOf(c)!=-1;return b=G(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= 15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]}; 17 | j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1),true);return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a= 20 | i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=L||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&& 25 | c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var c={};j(b.flatten(i.call(arguments,1)),function(b){b in a&&(c[b]=a[b])});return c};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty= 26 | function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFunction=function(a){return l.call(a)=="[object Function]"}; 27 | b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a, 28 | b){return K.call(a,b)};b.noConflict=function(){s._=I;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){M(c,b[c]=a[c])})};var N=0;b.uniqueId= 29 | function(a){var b=N++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/,n={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},v;for(v in n)n[n[v]]=v;var O=/\\|'|\r|\n|\t|\u2028|\u2029/g,P=/\\(\\|'|r|n|t|u2028|u2029)/g,w=function(a){return a.replace(P,function(a,b){return n[b]})};b.template=function(a,c,d){d=b.extend(b.templateSettings,d);a="__p+='"+a.replace(O,function(a){return"\\"+n[a]}).replace(d.escape|| 30 | u,function(a,b){return"'+\n_.escape("+w(b)+")+\n'"}).replace(d.interpolate||u,function(a,b){return"'+\n("+w(b)+")+\n'"}).replace(d.evaluate||u,function(a,b){return"';\n"+w(b)+"\n;__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");var a="var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n"+a+"return __p;\n",e=new Function(d.variable||"obj","_",a);if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c}; 31 | b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var x=function(a,c){return c?b(a).chain():a},M=function(a,c){m.prototype[a]=function(){var a=i.call(arguments);J.call(a,this._wrapped);return x(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return x(d, 32 | this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return x(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); 33 | -------------------------------------------------------------------------------- /iphone/pics/Andy_Bernard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Andy_Bernard.jpg -------------------------------------------------------------------------------- /iphone/pics/Angela_Martin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Angela_Martin.jpg -------------------------------------------------------------------------------- /iphone/pics/Creed_Bratton.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Creed_Bratton.jpg -------------------------------------------------------------------------------- /iphone/pics/Dwight_Schrute.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Dwight_Schrute.jpg -------------------------------------------------------------------------------- /iphone/pics/Jim_Halpert.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Jim_Halpert.jpg -------------------------------------------------------------------------------- /iphone/pics/Kelly_Kapoor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Kelly_Kapoor.jpg -------------------------------------------------------------------------------- /iphone/pics/Kevin_Malone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Kevin_Malone.jpg -------------------------------------------------------------------------------- /iphone/pics/Meredith_Palmer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Meredith_Palmer.jpg -------------------------------------------------------------------------------- /iphone/pics/Michael_Scott.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Michael_Scott.jpg -------------------------------------------------------------------------------- /iphone/pics/Oscar_Martinez.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Oscar_Martinez.jpg -------------------------------------------------------------------------------- /iphone/pics/Pamela_Beesly.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Pamela_Beesly.jpg -------------------------------------------------------------------------------- /iphone/pics/Phyllis_Lapin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Phyllis_Lapin.jpg -------------------------------------------------------------------------------- /iphone/pics/Ryan_Howard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Ryan_Howard.jpg -------------------------------------------------------------------------------- /iphone/pics/Stanley_Hudson.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Stanley_Hudson.jpg -------------------------------------------------------------------------------- /iphone/pics/Toby_Flenderson.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/iphone/pics/Toby_Flenderson.jpg -------------------------------------------------------------------------------- /iphone/tpl/employee-list-item.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | <%= firstName %> <%= lastName %> 5 | 9 |
10 |
11 | 12 | -------------------------------------------------------------------------------- /iphone/tpl/employee-page.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

Employee

10 |
11 | 12 |
13 |
14 |
15 | 16 | 17 |

<%= firstName %> <%= lastName %>

18 | <%= title %>
19 | 20 |
21 |
22 | 23 | 83 |
-------------------------------------------------------------------------------- /iphone/tpl/report-page.html: -------------------------------------------------------------------------------- 1 |
2 |

Direct Reports

3 | 4 | 5 |
6 | 7 |
8 |
9 | 11 |
12 |
-------------------------------------------------------------------------------- /iphone/tpl/search-page.html: -------------------------------------------------------------------------------- 1 |
2 |

Employee Directory

3 | 4 |
5 | 6 |
7 | 8 |
9 | 10 |
11 | 12 |
-------------------------------------------------------------------------------- /jquerymobile/css/images/ajax-loader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/css/images/ajax-loader.png -------------------------------------------------------------------------------- /jquerymobile/css/images/icons-18-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/css/images/icons-18-black.png -------------------------------------------------------------------------------- /jquerymobile/css/images/icons-18-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/css/images/icons-18-white.png -------------------------------------------------------------------------------- /jquerymobile/css/images/icons-36-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/css/images/icons-36-black.png -------------------------------------------------------------------------------- /jquerymobile/css/images/icons-36-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/css/images/icons-36-white.png -------------------------------------------------------------------------------- /jquerymobile/css/styles.css: -------------------------------------------------------------------------------- 1 | .employee-pic { 2 | float: left; 3 | padding-right: 10px; 4 | padding-bottom: 16px; 5 | } 6 | 7 | .employee-details p { 8 | margin-top: 0px; 9 | margin-bottom: 8px; 10 | } 11 | 12 | .action-list { 13 | clear: both; 14 | } -------------------------------------------------------------------------------- /jquerymobile/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/img/logo.png -------------------------------------------------------------------------------- /jquerymobile/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /jquerymobile/js/jqm-config.js: -------------------------------------------------------------------------------- 1 | $(document).bind("mobileinit", function () { 2 | console.log('mobileinit'); 3 | $.mobile.ajaxEnabled = false; 4 | $.mobile.linkBindingEnabled = false; 5 | $.mobile.hashListeningEnabled = false; 6 | $.mobile.pushStateEnabled = false; 7 | 8 | // Remove page from DOM when it's being replaced 9 | $('div[data-role="page"]').live('pagehide', function (event, ui) { 10 | $(event.currentTarget).remove(); 11 | }); 12 | }); -------------------------------------------------------------------------------- /jquerymobile/js/main.js: -------------------------------------------------------------------------------- 1 | var AppRouter = Backbone.Router.extend({ 2 | 3 | routes:{ 4 | "":"list", 5 | "list":"list", 6 | "employees/:id":"employeeDetails", 7 | "employees/:id/reports":"directReports" 8 | }, 9 | 10 | initialize:function () { 11 | $('.back').live('click', function(event) { 12 | window.history.back(); 13 | return false; 14 | }); 15 | this.firstPage = true; 16 | this.searchResults = new EmployeeCollection(); 17 | 18 | }, 19 | 20 | list:function () { 21 | this.changePage(new EmployeeListPage({model: this.searchResults})); 22 | }, 23 | 24 | employeeDetails:function (id) { 25 | var employee = new Employee({id:id}); 26 | var self = this; 27 | employee.fetch({ 28 | success:function (data) { 29 | self.changePage(new EmployeeView({model:data})); 30 | } 31 | }); 32 | }, 33 | 34 | directReports:function (id) { 35 | var employee = new Employee({id:id}); 36 | employee.reports.fetch(); 37 | this.changePage(new DirectReportPage({model:employee.reports})); 38 | }, 39 | 40 | changePage:function (page) { 41 | $(page.el).attr('data-role', 'page'); 42 | page.render(); 43 | $('body').append($(page.el)); 44 | var transition = $.mobile.defaultPageTransition; 45 | // We don't want to slide the first page 46 | if (this.firstPage) { 47 | transition = 'none'; 48 | this.firstPage = false; 49 | } 50 | $.mobile.changePage($(page.el), {changeHash:false, transition: transition}); 51 | } 52 | 53 | }); 54 | 55 | $(document).ready(function () { 56 | tpl.loadTemplates(['search-page', 'report-list', 'employee-details', 'employee-list-item'], 57 | function () { 58 | app = new AppRouter(); 59 | Backbone.history.start(); 60 | }); 61 | }); -------------------------------------------------------------------------------- /jquerymobile/js/models/employeemodel.js: -------------------------------------------------------------------------------- 1 | window.Employee = Backbone.Model.extend({ 2 | 3 | urlRoot:"../api/employees", 4 | 5 | initialize:function () { 6 | this.reports = new EmployeeCollection(); 7 | this.reports.url = '../api/employees/' + this.id + '/reports'; 8 | } 9 | 10 | }); 11 | 12 | window.EmployeeCollection = Backbone.Collection.extend({ 13 | 14 | model:Employee, 15 | 16 | url:"../api/employees", 17 | 18 | findByName:function (key) { 19 | var url = (key == '') ? '../api/employees' : "../api/employees/search/" + key; 20 | console.log('findByName: ' + key); 21 | var self = this; 22 | $.ajax({ 23 | url:url, 24 | dataType:"json", 25 | success:function (data) { 26 | console.log("search success: " + data.length); 27 | self.reset(data); 28 | } 29 | }); 30 | } 31 | 32 | }); -------------------------------------------------------------------------------- /jquerymobile/js/utils.js: -------------------------------------------------------------------------------- 1 | tpl = { 2 | 3 | // Hash of preloaded templates for the app 4 | templates:{}, 5 | 6 | // Recursively pre-load all the templates for the app. 7 | // This implementation should be changed in a production environment. All the template files should be 8 | // concatenated in a single file. 9 | loadTemplates:function (names, callback) { 10 | 11 | var that = this; 12 | 13 | var loadTemplate = function (index) { 14 | var name = names[index]; 15 | console.log('Loading template: ' + name); 16 | $.get('tpl/' + name + '.html', function (data) { 17 | that.templates[name] = data; 18 | index++; 19 | if (index < names.length) { 20 | loadTemplate(index); 21 | } else { 22 | callback(); 23 | } 24 | }); 25 | } 26 | 27 | loadTemplate(0); 28 | }, 29 | 30 | // Get template by name from hash of preloaded templates 31 | get:function (name) { 32 | return this.templates[name]; 33 | } 34 | 35 | }; -------------------------------------------------------------------------------- /jquerymobile/js/views/employeedetails.js: -------------------------------------------------------------------------------- 1 | window.EmployeeView = Backbone.View.extend({ 2 | 3 | initialize:function () { 4 | this.template = _.template(tpl.get('employee-details')); 5 | }, 6 | 7 | render:function (eventName) { 8 | $(this.el).html(this.template(this.model.toJSON())); 9 | return this; 10 | } 11 | 12 | }); -------------------------------------------------------------------------------- /jquerymobile/js/views/employeelist.js: -------------------------------------------------------------------------------- 1 | window.EmployeeListPage = Backbone.View.extend({ 2 | 3 | initialize:function () { 4 | this.template = _.template(tpl.get('search-page')); 5 | }, 6 | 7 | render:function (eventName) { 8 | $(this.el).html(this.template(this.model.toJSON())); 9 | this.listView = new EmployeeListView({el: $('ul', this.el), model: this.model}); 10 | this.listView.render(); 11 | return this; 12 | }, 13 | 14 | events:{ 15 | "keyup .search-query":"search" 16 | }, 17 | 18 | search:function (event) { 19 | var key = $('.search-query').val(); 20 | console.log('search ' + key); 21 | this.model.findByName(key); 22 | } 23 | }); 24 | 25 | window.DirectReportPage = Backbone.View.extend({ 26 | 27 | initialize:function () { 28 | this.template = _.template(tpl.get('report-list')); 29 | }, 30 | 31 | render:function (eventName) { 32 | $(this.el).html(this.template(this.model.toJSON())); 33 | this.listView = new EmployeeListView({el: $('ul', this.el), model: this.model}); 34 | return this; 35 | } 36 | 37 | }); 38 | 39 | window.EmployeeListView = Backbone.View.extend({ 40 | 41 | initialize:function () { 42 | this.model.bind("reset", this.render, this); 43 | }, 44 | 45 | render:function (eventName) { 46 | $(this.el).empty(); 47 | $('#welcome').remove(); 48 | _.each(this.model.models, function (employee) { 49 | $(this.el).append(new EmployeeListItemView({model:employee}).render().el); 50 | }, this); 51 | $('#myList').listview('refresh'); 52 | return this; 53 | } 54 | }); 55 | 56 | window.EmployeeListItemView = Backbone.View.extend({ 57 | 58 | tagName:"li", 59 | 60 | initialize:function () { 61 | this.template = _.template(tpl.get('employee-list-item')); 62 | this.model.bind("change", this.render, this); 63 | this.model.bind("destroy", this.close, this); 64 | }, 65 | 66 | render:function (eventName) { 67 | $(this.el).html(this.template(this.model.toJSON())); 68 | return this; 69 | } 70 | 71 | }); -------------------------------------------------------------------------------- /jquerymobile/lib/underscore-min.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.2.4 2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. 3 | // Underscore is freely distributable under the MIT license. 4 | // Portions of Underscore are inspired or borrowed from Prototype, 5 | // Oliver Steele's Functional, and John Resig's Micro-Templating. 6 | // For all details and documentation: 7 | // http://documentcloud.github.com/underscore 8 | (function(){function r(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== 9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&r(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(m.call(a,h)&&(f++,!(g=m.call(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(m.call(c, 10 | h)&&!f--)break;g=!f}}d.pop();return g}var s=this,G=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,H=k.unshift,l=p.toString,m=p.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,q=k.indexOf,D=k.lastIndexOf,p=Array.isArray,I=Object.keys,t=Function.prototype.bind,b=function(a){return new n(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else typeof define==="function"&&define.amd? 11 | define("underscore",function(){return b}):s._=b;b.VERSION="1.2.4";var j=b.each=b.forEach=function(a,c,b){if(a!=null)if(w&&a.forEach===w)a.forEach(c,b);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&& 13 | (c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e; 14 | if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b,a,g,h)))return o});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return q&&a.indexOf===q?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a, 15 | function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a, 16 | b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c= 17 | e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e= 20 | 0;e= 24 | 0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=I||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)m.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)b[d]!== 25 | void 0&&(a[d]=b[d])});return a};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(m.call(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)== 26 | "[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!m.call(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"}; 27 | b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.noConflict=function(){s._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")}; 28 | b.mixin=function(a){j(b.functions(a),function(c){J(c,b[c]=a[c])})};var K=0;b.uniqueId=function(a){var b=K++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/;b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||u,function(a,b){return"',_.escape("+b.replace(/\\'/g,"'")+"),'"}).replace(d.interpolate|| 29 | u,function(a,b){return"',"+b.replace(/\\'/g,"'")+",'"}).replace(d.evaluate||u,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ").replace(/\\\\/g,"\\")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var n=function(a){this._wrapped=a};b.prototype=n.prototype;var v=function(a,c){return c?b(a).chain(): 30 | a},J=function(a,c){n.prototype[a]=function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];n.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];n.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}}); 31 | n.prototype.chain=function(){this._chain=true;return this};n.prototype.value=function(){return this._wrapped}}).call(this); 32 | -------------------------------------------------------------------------------- /jquerymobile/pics/Amy_Jones.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Amy_Jones.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Amy_Jones100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Amy_Jones100.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Amy_Jones50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Amy_Jones50.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Eugene_Lee.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Eugene_Lee.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Eugene_Lee100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Eugene_Lee100.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Eugene_Lee50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Eugene_Lee50.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Gary_Donovan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Gary_Donovan.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Gary_Donovan100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Gary_Donovan100.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Gary_Donovan50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Gary_Donovan50.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/James_King.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/James_King.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/James_King100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/James_King100.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/James_King50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/James_King50.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/John_Williams.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/John_Williams.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/John_Williams100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/John_Williams100.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/John_Williams50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/John_Williams50.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Julie_Taylor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Julie_Taylor.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Julie_Taylor100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Julie_Taylor100.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Julie_Taylor50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Julie_Taylor50.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Kathleen_Byrne.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Kathleen_Byrne.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Kathleen_Byrne100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Kathleen_Byrne100.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Kathleen_Byrne50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Kathleen_Byrne50.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Lisa_Wong.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Lisa_Wong.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Lisa_Wong100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Lisa_Wong100.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Lisa_Wong50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Lisa_Wong50.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Paul_Jones.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Paul_Jones.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Paul_Jones100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Paul_Jones100.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Paul_Jones50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Paul_Jones50.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Paula_Gates.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Paula_Gates.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Paula_Gates100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Paula_Gates100.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Paula_Gates50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Paula_Gates50.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Ray_Moore.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Ray_Moore.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Ray_Moore100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Ray_Moore100.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Ray_Moore50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Ray_Moore50.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Steven_Wells.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Steven_Wells.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Steven_Wells100.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Steven_Wells100.jpg -------------------------------------------------------------------------------- /jquerymobile/pics/Steven_Wells50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/jquerymobile/pics/Steven_Wells50.jpg -------------------------------------------------------------------------------- /jquerymobile/tpl/employee-details.html: -------------------------------------------------------------------------------- 1 |
2 | Back 3 |

Employee Details

4 | Search 5 |
6 | 7 |
8 | 9 |
10 |

<%= firstName %> <%= lastName %>

11 |

<%= title %>

12 |
13 | 14 | 26 | 27 |
28 | -------------------------------------------------------------------------------- /jquerymobile/tpl/employee-list-item.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

<%= firstName %> <%= lastName %>

4 |

<%= title %>

5 | <%= reportCount %> 6 |
7 | 8 | -------------------------------------------------------------------------------- /jquerymobile/tpl/report-list.html: -------------------------------------------------------------------------------- 1 |
2 |

Direct Reports

3 | Back 4 | Search 5 |
6 | 7 |
8 |
    9 |
    -------------------------------------------------------------------------------- /jquerymobile/tpl/search-page.html: -------------------------------------------------------------------------------- 1 |
    2 |

    Directory

    3 |
    4 | 5 |
    6 | 7 |
    8 | 9 |
    10 |

    Welcome to Backbone Directory!

    11 | 12 |

    This is a sample app that demonstrates how to build applications with Backbone.js and jQuery Mobile.

    13 | 14 | 15 |
    16 | 17 |
    18 |
      19 |
      20 | -------------------------------------------------------------------------------- /localdb/css/images/activity-indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/activity-indicator.png -------------------------------------------------------------------------------- /localdb/css/images/back-button-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/back-button-active.png -------------------------------------------------------------------------------- /localdb/css/images/back-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/back-button.png -------------------------------------------------------------------------------- /localdb/css/images/button-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/button-active.png -------------------------------------------------------------------------------- /localdb/css/images/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/button.png -------------------------------------------------------------------------------- /localdb/css/images/call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/call.png -------------------------------------------------------------------------------- /localdb/css/images/comment-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/comment-arrow.png -------------------------------------------------------------------------------- /localdb/css/images/detail-disclosure-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/detail-disclosure-button.png -------------------------------------------------------------------------------- /localdb/css/images/disclosure-indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/disclosure-indicator.png -------------------------------------------------------------------------------- /localdb/css/images/mail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/mail.png -------------------------------------------------------------------------------- /localdb/css/images/manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/manager.png -------------------------------------------------------------------------------- /localdb/css/images/message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/message.png -------------------------------------------------------------------------------- /localdb/css/images/navbar-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/navbar-bg.png -------------------------------------------------------------------------------- /localdb/css/images/navbar-landscape-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/navbar-landscape-bg.png -------------------------------------------------------------------------------- /localdb/css/images/refresh-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/refresh-icon.png -------------------------------------------------------------------------------- /localdb/css/images/reports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/reports.png -------------------------------------------------------------------------------- /localdb/css/images/search-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/css/images/search-icon.png -------------------------------------------------------------------------------- /localdb/css/styles.css: -------------------------------------------------------------------------------- 1 | /* Many of the styles below come from the app documented in this article http://cheeaun.com/blog/2012/03/how-i-built-hacker-news-mobile-web-app */ 2 | 3 | html{ 4 | height: 100%; 5 | } 6 | body{ 7 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 8 | font-size: 16px; 9 | margin: 0; 10 | padding: 0; 11 | height: 100%; 12 | background-color: #fff; 13 | overflow: hidden; 14 | position: relative; 15 | } 16 | 17 | .header{ 18 | background: #b2bbca url(images/navbar-bg.png) repeat-x; 19 | -webkit-background-size: 1px 44px; 20 | -moz-background-size: 1px 44px; 21 | -ms-background-size: 1px 44px; 22 | -o-background-size: 1px 44px; 23 | background-size: 1px 44px; 24 | height: 44px; 25 | line-height: 44px; 26 | width: 100%; 27 | color: #fff; 28 | -webkit-user-select: none; 29 | -webkit-touch-callout: none; 30 | } 31 | 32 | .header-button{ 33 | position: absolute; 34 | top: 0; 35 | padding: 7px 5px; 36 | -webkit-tap-highlight-color: rgba(0,0,0,0); 37 | line-height: 1em; 38 | } 39 | 40 | .header-button button{ 41 | pointer-events: none; 42 | -webkit-box-sizing: border-box; 43 | -moz-box-sizing: border-box; 44 | box-sizing: border-box; 45 | min-width: 50px; 46 | height: 30px; 47 | line-height: 25px; 48 | font-weight: bold; 49 | font-size: 12px; 50 | text-align: center; 51 | color: #fff; 52 | text-shadow: 0 -1px rgba(0,0,0,.6); 53 | padding: 0 4px; 54 | margin: 0; 55 | text-decoration: none; 56 | border-width: 2px 5px; 57 | -webkit-border-image: url(images/button.png) 4 10 4 10; 58 | -moz-border-image: url(images/button.png) 4 10 4 10; 59 | -ms-border-image: url(images/button.png) 4 10 4 10; 60 | -o-border-image: url(images/button.png) 4 10 4 10; 61 | background: transparent url(images/button-active.png) no-repeat; 62 | -webkit-background-size: 0 0; 63 | -moz-background-size: 0 0; 64 | -ms-background-size: 0 0; 65 | -o-background-size: 0 0; 66 | background-size: 0 0; 67 | } 68 | 69 | .header-button-icon button{ 70 | min-width: 0; 71 | } 72 | 73 | .header-button-icon button img{ 74 | vertical-align: text-bottom; 75 | } 76 | 77 | .header-button.tappable-active button{ 78 | -webkit-border-image: url(images/button-active.png) 4 10 4 10; 79 | -moz-border-image: url(images/button-active.png) 4 10 4 10; 80 | -ms-border-image: url(images/button-active.png) 4 10 4 10; 81 | -o-border-image: url(images/button-active.png) 4 10 4 10; 82 | } 83 | 84 | .header-back-button button{ 85 | padding: 0 4px 0 0; 86 | border-width: 2px 4px 2px 13px; 87 | -webkit-border-image: url(images/back-button.png) 4 8 4 26; 88 | -moz-border-image: url(images/back-button.png) 4 8 4 26; 89 | -ms-border-image: url(images/back-button.png) 4 8 4 26; 90 | -o-border-image: url(images/back-button.png) 4 8 4 26; 91 | background-image: url(images/back-button-active.png); 92 | } 93 | .header-back-button.tappable-active button{ 94 | -webkit-border-image: url(images/back-button-active.png) 4 8 4 26; 95 | -moz-border-image: url(images/back-button-active.png) 4 8 4 26; 96 | -ms-border-image: url(images/back-button-active.png) 4 8 4 26; 97 | -o-border-image: url(images/back-button-active.png) 4 8 4 26; 98 | } 99 | 100 | .header-button-left{ 101 | left: 0; 102 | } 103 | 104 | .header-button-right{ 105 | right: 0; 106 | } 107 | 108 | .header h1{ 109 | padding: 0; 110 | text-align: center; 111 | font-size: 20px; 112 | text-shadow: 0 -1px rgba(0,0,0,.4); 113 | margin: 0; 114 | white-space: nowrap; 115 | text-overflow: ellipsis; 116 | overflow: hidden; 117 | -webkit-box-flex: 1; 118 | -moz-box-flex: 1; 119 | box-flex: 1; 120 | } 121 | 122 | .scroll{ 123 | -webkit-box-flex: 1; 124 | -moz-box-flex: 1; 125 | box-flex: 1; 126 | overflow: auto; 127 | -webkit-overflow-scrolling: touch; 128 | background-color: #e2e7ed; 129 | display: -webkit-box; 130 | display: -moz-box; 131 | display: box; 132 | -webkit-box-orient: vertical; 133 | -moz-box-orient: vertical; 134 | box-orient: vertical; 135 | position: absolute; 136 | top: 80px; 137 | bottom: 0px; 138 | left: 0px; 139 | right: 0px; 140 | } 141 | 142 | .scroll.striped{ 143 | background-color: #cbd2d8; 144 | background-image: -webkit-gradient(linear, left top, right top, from(#c5ccd4), color-stop(0.714, #c5ccd4), color-stop(0.714, #cbd2d8), to(#cbd2d8)); 145 | background-image: -webkit-linear-gradient(left, #c5ccd4, #c5ccd4 71.4%, #cbd2d8 71.5%, #cbd2d8); 146 | background-image: -moz-linear-gradient(left, #c5ccd4, #c5ccd4 71.4%, #cbd2d8 71.5%, #cbd2d8); 147 | background-image: -ms-linear-gradient(left, #c5ccd4, #c5ccd4 71.4%, #cbd2d8 71.5%, #cbd2d8); 148 | background-image: -o-linear-gradient(left, #c5ccd4, #c5ccd4 71.4%, #cbd2d8 71.5%, #cbd2d8); 149 | background-image: linear-gradient(left, #c5ccd4, #c5ccd4 71.4%, #cbd2d8 71.5%, #cbd2d8); 150 | -webkit-background-size: 7px 1px; 151 | -moz-background-size: 7px 1px; 152 | -ms-background-size: 7px 1px; 153 | -o-background-size: 7px 1px; 154 | background-size: 7px 1px; 155 | } 156 | 157 | .tableview{ 158 | margin: 0; 159 | padding: 0; 160 | list-style: none; 161 | background-color: #fff; 162 | border-bottom: 1px solid #e0e0e0; 163 | } 164 | .tableview li{ 165 | display: block; 166 | border-top: 1px solid #e0e0e0; 167 | padding: 10px; 168 | } 169 | 170 | .tableview-links li{ 171 | padding: 0; 172 | display: -webkit-box; 173 | display: -moz-box; 174 | display: box; 175 | width: 100%; 176 | } 177 | 178 | .tableview-links li>a{ 179 | font-size: 15px; 180 | line-height: 1.3em; 181 | color: #000; 182 | display: block; 183 | padding: 5px; 184 | text-decoration: none; 185 | -webkit-tap-highlight-color: rgba(0,0,0,0); 186 | display: -webkit-box; 187 | display: -moz-box; 188 | display: box; 189 | width: 100%; 190 | -webkit-box-flex: 1; 191 | -moz-box-flex: 1; 192 | box-flex: 1; 193 | -webkit-box-sizing: border-box; 194 | -moz-box-sizing: border-box; 195 | box-sizing: border-box; 196 | background-image: -webkit-gradient(linear, left top, left bottom, from(#4286f5), to(#194fdb)); 197 | background-image: -webkit-linear-gradient(top, #4286f5, #194fdb); 198 | background-image: -moz-linear-gradient(top, #4286f5, #194fdb); 199 | background-image: -ms-linear-gradient(top, #4286f5, #194fdb); 200 | background-image: -o-linear-gradient(top, #4286f5, #194fdb); 201 | background-image: linear-gradient(top, #4286f5, #194fdb); 202 | background-position: -10px 0; 203 | background-repeat: no-repeat; 204 | -webkit-background-size: 10px 100%; 205 | -moz-background-size: 10px 100%; 206 | -ms-background-size: 10px 100%; 207 | -o-background-size: 10px 100%; 208 | background-size: 10px 100%; 209 | } 210 | 211 | .tableview-links li>a *{ 212 | pointer-events: none; 213 | } 214 | 215 | .tableview-links li>a .metadata{ 216 | display: block; 217 | font-size: 13px; 218 | color: #666d74; 219 | line-height: 1.2em; 220 | } 221 | .tableview-links li>a.pad-right{ 222 | padding-right: 44px; 223 | } 224 | .tableview-links li>a.more-link{ 225 | cursor: pointer; 226 | -webkit-touch-callout: none; 227 | line-height: 3em; 228 | padding: 10px; 229 | display: block; 230 | color: #2960d9; 231 | text-align: center; 232 | font-weight: bold; 233 | } 234 | 235 | .tableview-links li>a.tappable-active{ 236 | color: #fff; 237 | background-color: #4286f5; 238 | background-repeat: repeat-x; 239 | } 240 | .tableview-links li>a.tappable-active *{ 241 | color: #fff; 242 | } 243 | .tableview-links li>a.detail-disclosure{ 244 | -webkit-touch-callout: none; 245 | padding: 0; 246 | width: 44px; 247 | margin: 0 0 0 -44px; 248 | -webkit-box-align: center; 249 | -moz-box-align: center; 250 | box-align: center; 251 | -webkit-box-pack: center; 252 | -moz-box-pack: center; 253 | box-pack: center; 254 | -webkit-box-flex: 0; 255 | -moz-box-flex: 0; 256 | box-flex: 0; 257 | } 258 | .tableview-links li>a.detail-disclosure.tappable-active{ 259 | background: transparent none; 260 | } 261 | .tableview-links li>a.detail-disclosure span{ 262 | display: inline-block; 263 | width: 29px; 264 | height: 31px; 265 | background: transparent url(images/detail-disclosure-button.png); 266 | -webkit-background-size: 58px 31px; 267 | -moz-background-size: 58px 31px; 268 | -ms-background-size: 58px 31px; 269 | -o-background-size: 58px 31px; 270 | background-size: 58px 31px; 271 | } 272 | .tableview-links li>a.detail-disclosure.tappable-active span{ 273 | background-position: top right; 274 | } 275 | 276 | .link-text{ 277 | color: #385487; 278 | font-weight: bold; 279 | } 280 | .inline-block{ 281 | display: inline-block; 282 | } 283 | 284 | 285 | #content { 286 | position: absolute; 287 | background: #ddd; 288 | width: 100%; 289 | height: 100%; 290 | overflow-x: hidden; 291 | overflow-y: auto; 292 | } 293 | 294 | .page { 295 | position: absolute; 296 | width: 100%; 297 | height: 100%; 298 | background-color: #ddd; 299 | -webkit-transform:translate3d(0,0,0); 300 | } 301 | 302 | .stage-center { 303 | top: 0; 304 | left: 0; 305 | } 306 | 307 | .stage-left { 308 | left: -100%; 309 | } 310 | 311 | .stage-right { 312 | left: 100%; 313 | } 314 | 315 | .transition { 316 | -moz-transition-duration: .375s; 317 | -webkit-transition-duration: .375s; 318 | -o-transition-duration: .375s; 319 | } 320 | 321 | .employee-summary header{ 322 | padding: 10px 8px; 323 | text-shadow: 0 1px rgba(255,255,255,.85); 324 | } 325 | .employee-summary header h1, 326 | .employee-summary header p{ 327 | margin: 0; 328 | padding: 0; 329 | } 330 | .employee-summary header h1 a{ 331 | display: block; 332 | } 333 | .employee-summary header h1 a .link-text{ 334 | font-size: 13px; 335 | } 336 | .employee-summary header .metadata{ 337 | font-size: 13px; 338 | color: #666d74; 339 | } 340 | .employee-summary header h1{ 341 | font-size: 17px; 342 | line-height: 1.2em; 343 | } 344 | .employee-summary header h1 a{ 345 | color: #000; 346 | text-decoration: none; 347 | } 348 | .employee-summary header + .grouped-tableview{ 349 | margin-top: 0; 350 | } 351 | .employee-summary{ 352 | padding-bottom: 1px; 353 | background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,0)), to(rgba(0,0,0,.12))); 354 | background-image: -webkit-linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,.12)); 355 | background-image: -moz-linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,.12)); 356 | background-image: -ms-linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,.12)); 357 | background-image: -o-linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,.12)); 358 | background-image: linear-gradient(top, rgba(0,0,0,0), rgba(0,0,0,.12)); 359 | -webkit-background-size: 1px 11px; 360 | -moz-background-size: 1px 11px; 361 | -ms-background-size: 1px 11px; 362 | -o-background-size: 1px 11px; 363 | background-size: 1px 11px; 364 | background-repeat: repeat-x; 365 | background-position: bottom; 366 | 367 | height: 120px; 368 | } 369 | 370 | .employee-summary img { 371 | float: left; 372 | margin-right: 12px; 373 | } 374 | 375 | .action-item { 376 | box-flex: 1; 377 | } 378 | 379 | .action-icon { 380 | position: absolute; 381 | right: 10px; 382 | width: 28px; 383 | } -------------------------------------------------------------------------------- /localdb/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Employee Directory 5 | 6 | 7 | 8 | 9 | 10 | 11 |
      12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /localdb/pics/Andy_Bernard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Andy_Bernard.jpg -------------------------------------------------------------------------------- /localdb/pics/Angela_Martin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Angela_Martin.jpg -------------------------------------------------------------------------------- /localdb/pics/Creed_Bratton.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Creed_Bratton.jpg -------------------------------------------------------------------------------- /localdb/pics/Dwight_Schrute.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Dwight_Schrute.jpg -------------------------------------------------------------------------------- /localdb/pics/Jim_Halpert.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Jim_Halpert.jpg -------------------------------------------------------------------------------- /localdb/pics/Kelly_Kapoor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Kelly_Kapoor.jpg -------------------------------------------------------------------------------- /localdb/pics/Kevin_Malone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Kevin_Malone.jpg -------------------------------------------------------------------------------- /localdb/pics/Meredith_Palmer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Meredith_Palmer.jpg -------------------------------------------------------------------------------- /localdb/pics/Michael_Scott.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Michael_Scott.jpg -------------------------------------------------------------------------------- /localdb/pics/Oscar_Martinez.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Oscar_Martinez.jpg -------------------------------------------------------------------------------- /localdb/pics/Pamela_Beesly.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Pamela_Beesly.jpg -------------------------------------------------------------------------------- /localdb/pics/Phyllis_Lapin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Phyllis_Lapin.jpg -------------------------------------------------------------------------------- /localdb/pics/Ryan_Howard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Ryan_Howard.jpg -------------------------------------------------------------------------------- /localdb/pics/Stanley_Hudson.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Stanley_Hudson.jpg -------------------------------------------------------------------------------- /localdb/pics/Toby_Flenderson.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/localdb/pics/Toby_Flenderson.jpg -------------------------------------------------------------------------------- /localdb/tpl/employee-list-item.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
      4 | <%= firstName %> <%= lastName %> 5 | 9 |
      10 |
      11 | 12 | -------------------------------------------------------------------------------- /localdb/tpl/employee-page.html: -------------------------------------------------------------------------------- 1 |
      2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |

      Employee

      10 |
      11 | 12 |
      13 |
      14 |
      15 | 16 | 17 |

      <%= firstName %> <%= lastName %>

      18 | <%= title %>
      19 | 20 |
      21 |
      22 | 23 | 83 |
      -------------------------------------------------------------------------------- /localdb/tpl/report-page.html: -------------------------------------------------------------------------------- 1 |
      2 |

      Direct Reports

      3 | 4 | 5 |
      6 | 7 |
      8 |
      9 | 11 |
      12 |
      -------------------------------------------------------------------------------- /localdb/tpl/search-page.html: -------------------------------------------------------------------------------- 1 |
      2 |

      Employee Directory

      3 | 4 |
      5 | 6 |
      7 | 8 |
      9 | 10 |
      11 | 12 |
      -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Update ## 2 | 3 | This directory is no longer maintained. A new and improved version of the application is available in [this repository] (https://github.com/ccoenraets/directory-backbone-bootstrap) 4 | 5 | 6 | # Backbone.js Employee Directory # 7 | 8 | "Backbone Directory" is a simple Employee Directory application built with [Backbone.js](http://documentcloud.github.com/backbone/). 9 | 10 | The application allows you to look up employees by name, view the details of an employee, and navigate up and down the Org Chart by clicking the employee’s manager or any of his/her direct reports. 11 | 12 | There are four versions of the application available in this repository: 13 | 14 | 1. Backbone.js + Twitter Bootstrap (located in the [/web](http://twitter.github.com/bootstrap/) directory). 15 | - Read more about this version [here](http://coenraets.org/blog/2012/02/sample-app-with-backbone-js-and-twitter-bootstrap/) 16 | - Try it [here](http://coenraets.org/directory/) 17 | 2. Backbone.js + jQuery Mobile (located in the [/jquerymobile](https://github.com/ccoenraets/backbone-directory/tree/master/jquerymobile) directory). 18 | - Read more about this version [here](http://coenraets.org/blog/2012/03/employee-directory-sample-app-with-backbone-js-and-jquery-mobile/) 19 | - Try it [here](http://coenraets.org/backbone/directory/jquerymobile/) 20 | 3. Backbone.js + native-looking iPhone skins (located in the [/iphone](https://github.com/ccoenraets/backbone-directory/tree/master/iphone) directory). 21 | - Read more about this version [here](http://coenraets.org/blog/2012/03/crafting-native-looking-ios-apps-with-html-backbone-js-and-phonegap/) 22 | - Try it [here](http://coenraets.org/backbone/directory/iphone/) 23 | 4. Backbone.js + native-looking iPhone skins and a local database implementation (located in the [/iphone](https://github.com/ccoenraets/backbone-directory/tree/master/localdb) directory). 24 | - Read more about this version [here](http://coenraets.org/blog/2012/04/building-mobile-apps-with-html-and-a-local-database/) 25 | - Try it [here](http://coenraets.org/backbone/directory/localdb/) 26 | 27 | The Twitter Bootstrap and jQuery Mobile versions use JSON services. Instructions to set up these services are provided below. The "native-looking iPhone" versions use sample in-memory data and don't have any dependency on external services. 28 | 29 | ## Set Up: ## 30 | 31 | 1. Create a MySQL database name "directory". 32 | 2. Execute directory.sql to create and populate the "employee" table: 33 | 34 | mysql directory -uroot < directory.sql 35 | 36 | ## Services: ## 37 | 38 | The application is available with a PHP or Java services: 39 | 40 | - The PHP services are available in the api directory of this repository. The RESTful services are implemented in PHP using the [Slim framework](http://www.slimframework.com/) (also included in the api directory). 41 | - The Java back-end will be available soon. 42 | -------------------------------------------------------------------------------- /web/css/styles.css: -------------------------------------------------------------------------------- 1 | .dropdown-menu { 2 | max-height: 400px; 3 | overflow-y: scroll; 4 | width: 220px; 5 | } 6 | 7 | .list-item { 8 | padding-top: 6px; 9 | padding-left: 56px; 10 | } 11 | 12 | .no-reports { 13 | display: none; 14 | } -------------------------------------------------------------------------------- /web/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /web/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /web/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/img/logo.png -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Backbone.js and Twitter Bootstrap Sample App 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
      22 | 23 |
      24 |
      25 |
      26 |
      27 | 28 |
      29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /web/js/main.js: -------------------------------------------------------------------------------- 1 | window.Router = Backbone.Router.extend({ 2 | 3 | routes: { 4 | "": "home", 5 | "contact": "contact", 6 | "employees/:id": "employeeDetails" 7 | }, 8 | 9 | initialize: function () { 10 | this.headerView = new HeaderView(); 11 | $('.header').html(this.headerView.render().el); 12 | 13 | // Close the search dropdown on click anywhere in the UI 14 | $('body').click(function () { 15 | $('.dropdown').removeClass("open"); 16 | }); 17 | }, 18 | 19 | home: function () { 20 | // Since the home view never changes, we instantiate it and render it only once 21 | if (!this.homeView) { 22 | this.homeView = new HomeView(); 23 | this.homeView.render(); 24 | } else { 25 | this.homeView.delegateEvents(); // delegate events when the view is recycled 26 | } 27 | $("#content").html(this.homeView.el); 28 | this.headerView.select('home-menu'); 29 | }, 30 | 31 | contact: function () { 32 | if (!this.contactView) { 33 | this.contactView = new ContactView(); 34 | this.contactView.render(); 35 | } 36 | $('#content').html(this.contactView.el); 37 | this.headerView.select('contact-menu'); 38 | }, 39 | 40 | employeeDetails: function (id) { 41 | var employee = new Employee({id: id}); 42 | employee.fetch({ 43 | success: function (data) { 44 | // Note that we could also 'recycle' the same instance of EmployeeFullView 45 | // instead of creating new instances 46 | $('#content').html(new EmployeeView({model: data}).render().el); 47 | } 48 | }); 49 | } 50 | 51 | }); 52 | 53 | templateLoader.load(["HomeView", "ContactView", "HeaderView", "EmployeeView", "EmployeeSummaryView", "EmployeeListItemView"], 54 | function () { 55 | app = new Router(); 56 | Backbone.history.start(); 57 | }); -------------------------------------------------------------------------------- /web/js/models/employeemodel.js: -------------------------------------------------------------------------------- 1 | window.Employee = Backbone.Model.extend({ 2 | 3 | urlRoot:"../api/employees", 4 | 5 | initialize:function () { 6 | this.reports = new EmployeeCollection(); 7 | this.reports.url = '../api/employees/' + this.id + '/reports'; 8 | } 9 | 10 | }); 11 | 12 | window.EmployeeCollection = Backbone.Collection.extend({ 13 | 14 | model: Employee, 15 | 16 | url:"../api/employees", 17 | 18 | findByName:function (key) { 19 | var url = (key == '') ? '../api/employees' : "../api/employees/search/" + key; 20 | console.log('findByName: ' + key); 21 | var self = this; 22 | $.ajax({ 23 | url:url, 24 | dataType:"json", 25 | success:function (data) { 26 | console.log("search success: " + data.length); 27 | self.reset(data); 28 | } 29 | }); 30 | } 31 | 32 | }); -------------------------------------------------------------------------------- /web/js/utils.js: -------------------------------------------------------------------------------- 1 | // The Template Loader. Used to asynchronously load templates located in separate .html files 2 | window.templateLoader = { 3 | 4 | load: function(views, callback) { 5 | 6 | var deferreds = []; 7 | 8 | $.each(views, function(index, view) { 9 | if (window[view]) { 10 | deferreds.push($.get('tpl/' + view + '.html', function(data) { 11 | window[view].prototype.template = _.template(data); 12 | }, 'html')); 13 | } else { 14 | alert(view + " not found"); 15 | } 16 | }); 17 | 18 | $.when.apply(null, deferreds).done(callback); 19 | } 20 | 21 | }; -------------------------------------------------------------------------------- /web/js/views/contact.js: -------------------------------------------------------------------------------- 1 | window.ContactView = Backbone.View.extend({ 2 | 3 | initialize:function () { 4 | console.log('Initializing Contact View'); 5 | // this.template = templates['Contact']; 6 | }, 7 | 8 | render:function () { 9 | $(this.el).html(this.template()); 10 | return this; 11 | } 12 | 13 | }); -------------------------------------------------------------------------------- /web/js/views/employeedetails.js: -------------------------------------------------------------------------------- 1 | window.EmployeeView = Backbone.View.extend({ 2 | 3 | tagName:"div", // Not required since 'div' is the default if no el or tagName specified 4 | 5 | initialize:function () { 6 | // this.template = templates['Employee']; 7 | }, 8 | 9 | render: function () { 10 | $(this.el).html(this.template(this.model.toJSON())); 11 | $('#details', this.el).html(new EmployeeSummaryView({model:this.model}).render().el); 12 | this.model.reports.fetch({ 13 | success:function (data) { 14 | if (data.length == 0) 15 | $('.no-reports').show(); 16 | } 17 | }); 18 | $('#reports', this.el).append(new EmployeeListView({model:this.model.reports}).render().el); 19 | return this; 20 | } 21 | }); 22 | 23 | window.EmployeeSummaryView = Backbone.View.extend({ 24 | 25 | tagName:"div", // Not required since 'div' is the default if no el or tagName specified 26 | 27 | initialize:function () { 28 | // this.template = templates['EmployeeSummary']; 29 | this.model.bind("change", this.render, this); 30 | }, 31 | 32 | render:function () { 33 | $(this.el).html(this.template(this.model.toJSON())); 34 | return this; 35 | } 36 | 37 | }); -------------------------------------------------------------------------------- /web/js/views/employeelist.js: -------------------------------------------------------------------------------- 1 | window.EmployeeListView = Backbone.View.extend({ 2 | 3 | tagName:'ul', 4 | 5 | className:'nav nav-list', 6 | 7 | initialize:function () { 8 | var self = this; 9 | this.model.bind("reset", this.render, this); 10 | this.model.bind("add", function (employee) { 11 | $(self.el).append(new EmployeeListItemView({model:employee}).render().el); 12 | }); 13 | }, 14 | 15 | render:function () { 16 | $(this.el).empty(); 17 | _.each(this.model.models, function (employee) { 18 | $(this.el).append(new EmployeeListItemView({model:employee}).render().el); 19 | }, this); 20 | return this; 21 | } 22 | }); 23 | 24 | window.EmployeeListItemView = Backbone.View.extend({ 25 | 26 | tagName:"li", 27 | 28 | initialize:function () { 29 | this.model.bind("change", this.render, this); 30 | this.model.bind("destroy", this.close, this); 31 | }, 32 | 33 | render:function () { 34 | $(this.el).html(this.template(this.model.toJSON())); 35 | return this; 36 | } 37 | 38 | }); -------------------------------------------------------------------------------- /web/js/views/header.js: -------------------------------------------------------------------------------- 1 | window.HeaderView = Backbone.View.extend({ 2 | 3 | initialize: function () { 4 | this.searchResults = new EmployeeCollection(); 5 | this.searchresultsView = new EmployeeListView({model: this.searchResults, className: 'dropdown-menu'}); 6 | }, 7 | 8 | render: function () { 9 | $(this.el).html(this.template()); 10 | $('.navbar-search', this.el).append(this.searchresultsView.render().el); 11 | return this; 12 | }, 13 | 14 | events: { 15 | "keyup .search-query": "search", 16 | "keypress .search-query": "onkeypress" 17 | }, 18 | 19 | search: function () { 20 | var key = $('#searchText').val(); 21 | console.log('search ' + key); 22 | this.searchResults.findByName(key); 23 | setTimeout(function () { 24 | $('.dropdown').addClass('open'); 25 | }); 26 | }, 27 | 28 | onkeypress: function (event) { 29 | if (event.keyCode == 13) { 30 | event.preventDefault(); 31 | } 32 | }, 33 | 34 | select: function(menuItem) { 35 | $('.nav li').removeClass('active'); 36 | $('.' + menuItem).addClass('active'); 37 | } 38 | 39 | }); -------------------------------------------------------------------------------- /web/js/views/home.js: -------------------------------------------------------------------------------- 1 | window.HomeView = Backbone.View.extend({ 2 | 3 | initialize:function () { 4 | console.log('Initializing Home View'); 5 | // this.template = _.template(directory.utils.templateLoader.get('home')); 6 | // this.template = templates['Home']; 7 | }, 8 | 9 | events:{ 10 | "click #showMeBtn":"showMeBtnClick" 11 | }, 12 | 13 | render:function () { 14 | $(this.el).html(this.template()); 15 | return this; 16 | }, 17 | 18 | showMeBtnClick:function () { 19 | app.headerView.search(); 20 | } 21 | 22 | }); -------------------------------------------------------------------------------- /web/lib/underscore-min.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.3.2 2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. 3 | // Underscore is freely distributable under the MIT license. 4 | // Portions of Underscore are inspired or borrowed from Prototype, 5 | // Oliver Steele's Functional, and John Resig's Micro-Templating. 6 | // For all details and documentation: 7 | // http://documentcloud.github.com/underscore 8 | (function(){function r(a,c,d){if(a===c)return 0!==a||1/a==1/c;if(null==a||null==c)return a===c;a._chain&&(a=a._wrapped);c._chain&&(c=c._wrapped);if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return!1;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:0==a?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source== 9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if("object"!=typeof a||"object"!=typeof c)return!1;for(var f=d.length;f--;)if(d[f]==a)return!0;d.push(a);var f=0,g=!0;if("[object Array]"==e){if(f=a.length,g=f==c.length)for(;f--&&(g=f in a==f in c&&r(a[f],c[f],d)););}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return!1;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,h)&&!f--)break; 10 | g=!f}}d.pop();return g}var s=this,I=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,J=k.unshift,l=p.toString,K=p.hasOwnProperty,y=k.forEach,z=k.map,A=k.reduce,B=k.reduceRight,C=k.filter,D=k.every,E=k.some,q=k.indexOf,F=k.lastIndexOf,p=Array.isArray,L=Object.keys,t=Function.prototype.bind,b=function(a){return new m(a)};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):s._=b;b.VERSION="1.3.2";var j=b.each=b.forEach=function(a, 11 | c,d){if(a!=null)if(y&&a.forEach===y)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==null&&(a=[]);if(A&& 12 | a.reduce===A){e&&(c=b.bind(c,e));return f?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,i){if(f)d=c.call(e,d,a,b,i);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(B&&a.reduceRight===B){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a, 13 | c,b){var e;G(a,function(a,g,h){if(c.call(b,a,g,h)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(C&&a.filter===C)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(D&&a.every===D)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b, 14 | a,g,h)))return o});return!!e};var G=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(E&&a.some===E)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(q&&a.indexOf===q)return a.indexOf(c)!=-1;return b=G(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck= 15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]}; 17 | j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1),true);return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a= 20 | i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=L||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&& 25 | c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var c={};j(b.flatten(i.call(arguments,1)),function(b){b in a&&(c[b]=a[b])});return c};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty= 26 | function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFunction=function(a){return l.call(a)=="[object Function]"}; 27 | b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a, 28 | b){return K.call(a,b)};b.noConflict=function(){s._=I;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){M(c,b[c]=a[c])})};var N=0;b.uniqueId= 29 | function(a){var b=N++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/,n={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},v;for(v in n)n[n[v]]=v;var O=/\\|'|\r|\n|\t|\u2028|\u2029/g,P=/\\(\\|'|r|n|t|u2028|u2029)/g,w=function(a){return a.replace(P,function(a,b){return n[b]})};b.template=function(a,c,d){d=b.extend(b.templateSettings,d);a="__p+='"+a.replace(O,function(a){return"\\"+n[a]}).replace(d.escape|| 30 | u,function(a,b){return"'+\n_.escape("+w(b)+")+\n'"}).replace(d.interpolate||u,function(a,b){return"'+\n("+w(b)+")+\n'"}).replace(d.evaluate||u,function(a,b){return"';\n"+w(b)+"\n;__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");var a="var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n"+a+"return __p;\n",e=new Function(d.variable||"obj","_",a);if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c}; 31 | b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var x=function(a,c){return c?b(a).chain():a},M=function(a,c){m.prototype[a]=function(){var a=i.call(arguments);J.call(a,this._wrapped);return x(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return x(d, 32 | this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return x(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=true;return this};m.prototype.value=function(){return this._wrapped}}).call(this); 33 | -------------------------------------------------------------------------------- /web/pics/Amy_Jones.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Amy_Jones.jpg -------------------------------------------------------------------------------- /web/pics/Amy_Jones50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Amy_Jones50.jpg -------------------------------------------------------------------------------- /web/pics/Eugene_Lee.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Eugene_Lee.jpg -------------------------------------------------------------------------------- /web/pics/Eugene_Lee50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Eugene_Lee50.jpg -------------------------------------------------------------------------------- /web/pics/Gary_Donovan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Gary_Donovan.jpg -------------------------------------------------------------------------------- /web/pics/Gary_Donovan50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Gary_Donovan50.jpg -------------------------------------------------------------------------------- /web/pics/James_King.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/James_King.jpg -------------------------------------------------------------------------------- /web/pics/James_King50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/James_King50.jpg -------------------------------------------------------------------------------- /web/pics/John_Williams.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/John_Williams.jpg -------------------------------------------------------------------------------- /web/pics/John_Williams50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/John_Williams50.jpg -------------------------------------------------------------------------------- /web/pics/Julie_Taylor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Julie_Taylor.jpg -------------------------------------------------------------------------------- /web/pics/Julie_Taylor50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Julie_Taylor50.jpg -------------------------------------------------------------------------------- /web/pics/Kathleen_Byrne.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Kathleen_Byrne.jpg -------------------------------------------------------------------------------- /web/pics/Kathleen_Byrne50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Kathleen_Byrne50.jpg -------------------------------------------------------------------------------- /web/pics/Lisa_Wong.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Lisa_Wong.jpg -------------------------------------------------------------------------------- /web/pics/Lisa_Wong50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Lisa_Wong50.jpg -------------------------------------------------------------------------------- /web/pics/Paul_Jones.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Paul_Jones.jpg -------------------------------------------------------------------------------- /web/pics/Paul_Jones50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Paul_Jones50.jpg -------------------------------------------------------------------------------- /web/pics/Paula_Gates.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Paula_Gates.jpg -------------------------------------------------------------------------------- /web/pics/Paula_Gates50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Paula_Gates50.jpg -------------------------------------------------------------------------------- /web/pics/Ray_Moore.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Ray_Moore.jpg -------------------------------------------------------------------------------- /web/pics/Ray_Moore50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Ray_Moore50.jpg -------------------------------------------------------------------------------- /web/pics/Steven_Wells.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Steven_Wells.jpg -------------------------------------------------------------------------------- /web/pics/Steven_Wells50.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ccoenraets/backbone-directory/c5654ab50002a7865da849fbc743e7cea750a54e/web/pics/Steven_Wells50.jpg -------------------------------------------------------------------------------- /web/tpl/ContactView.html: -------------------------------------------------------------------------------- 1 |

      Source Code

      2 | 3 |

      The source code for this application is available in this 4 | repository on GitHub.

      5 | 6 |

      Comments and Questions

      7 | 8 |

      You can post your questions and comments on the blog post associated with this application.

      9 | 10 |

      Related Backbone.js Tutorials

      11 | 12 |

      I also posted a series of Backbone.js tutorials here: 13 | part 1, 14 | part 2, 15 | part 3, 16 | and postface 17 |

      18 | 19 |

      20 | Thanks,
      21 |
      22 | Christophe Coenraets
      23 | Twitter: @ccoenraets
      24 | Blog: http://coenraets.org -------------------------------------------------------------------------------- /web/tpl/EmployeeListItemView.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

      <%= firstName %> <%= lastName %>
      <%= title %>

      4 |
      -------------------------------------------------------------------------------- /web/tpl/EmployeeSummaryView.html: -------------------------------------------------------------------------------- 1 |

      2 |

      <%= firstName %> <%= lastName %>

      3 |

      <%= title %>

      4 | 5 |
      6 |
      7 |
      8 | 9 | <% 10 | if (managerId>0) 11 | { 12 | %> 13 | 14 | 15 | 16 | 17 | <% 18 | } 19 | %> 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
      Manager:
      <%= managerFirstName %> <%= managerLastName %>
      Office Phone:
      <%= officePhone %>
      Cell Phone:
      <%= cellPhone %>
      Email:
      <%= email %>
      Twitter:
      <%= twitterId %>
      37 | 38 |
      39 |

      Warning

      40 | The phone numbers, email addresses, and Twitter handlers are fake. 41 |
      42 |
      43 |
      44 | -------------------------------------------------------------------------------- /web/tpl/EmployeeView.html: -------------------------------------------------------------------------------- 1 |
      2 |
      3 |
      4 |
      5 | 6 |
      7 |

      Info

      8 | <%= firstName %> <%= lastName %> has no direct reports 9 |
      10 |
      11 |
      12 |
      -------------------------------------------------------------------------------- /web/tpl/HeaderView.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/tpl/HomeView.html: -------------------------------------------------------------------------------- 1 |
      2 |

      Welcome to Backbone Directory !

      3 | 4 |

       

      5 | 6 | 7 | 8 |

      This is a sample app that demonstrates how to build applications 9 | with Backbone.js and Twitter Bootstrap. 11 |

      Learn more » 12 |

      13 | 14 |
      15 | 16 |
      17 |
      18 |

      Try It

      19 | 20 |

      Enter a few characters in the Search Box in the upper right corner of the screen, and select an employee. In 21 | the Employee view, you can navigate up and down the Org Chart by clicking either the Manager link, 22 | or one of the Direct Reports in the sidebar on the right of the screen.

      23 | 24 |

      Show Me »

      25 |
      26 |
      27 |

      Get It

      28 | 29 |

      The source code for this application is maintained in this repository on GitHub. In addition 31 | to the Backbone.js- and Twitter Bootstrap-powered client, the repository includes two versions of the 32 | back-end services: a Java and a PHP implementation.

      33 | 34 |

      Download »

      35 |
      36 |
      37 |

      Share It

      38 | 39 |

      If you think this sample is helpful, let other people know about it... 40 |
      41 | 42 |

      43 | 44 |

      45 | 56 | 57 |

      58 | 59 | 60 |

      61 | 62 |
      64 | 65 |
      66 | 74 | 75 | 76 |

      77 |
      78 |
      --------------------------------------------------------------------------------