├── public ├── favicon.ico ├── packages │ └── .gitkeep ├── robots.txt ├── images │ ├── remove.png │ ├── resize-bigger.png │ └── resize-smaller.png ├── uploads │ ├── colorful6.jpg │ ├── dashboard.jpg │ ├── composer search.png │ ├── 1277878_check_list.jpg │ ├── 1395179514colorful6.jpg │ ├── Screenshot_on_2.3.2014_at_3.21.57_PM.png │ └── creating mobile apps with jquery mobile.jpg ├── .htaccess ├── index.php ├── css │ ├── style.css │ ├── medium-editor-insert.css │ ├── medium-editor.css │ └── themes │ │ └── default.css └── js │ ├── main.js │ ├── medium-editor-insert.js │ └── medium-editor.js ├── app ├── commands │ └── .gitkeep ├── config │ ├── packages │ │ └── .gitkeep │ ├── compile.php │ ├── testing │ │ ├── cache.php │ │ └── session.php │ ├── workbench.php │ ├── view.php │ ├── remote.php │ ├── queue.php │ ├── auth.php │ ├── cache.php │ ├── database.php │ ├── mail.php │ ├── session.php │ └── app.php ├── controllers │ ├── .gitkeep │ ├── BaseController.php │ ├── HomeController.php │ └── PostsController.php ├── database │ ├── seeds │ │ ├── .gitkeep │ │ └── DatabaseSeeder.php │ ├── migrations │ │ ├── .gitkeep │ │ └── 2014_03_03_190147_create_posts_table.php │ └── production.sqlite ├── start │ ├── local.php │ ├── artisan.php │ └── global.php ├── storage │ ├── .gitignore │ ├── cache │ │ └── .gitignore │ ├── logs │ │ └── .gitignore │ ├── meta │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ └── views │ │ └── .gitignore ├── models │ ├── Post.php │ └── User.php ├── views │ ├── emails │ │ └── auth │ │ │ └── reminder.blade.php │ ├── partials │ │ └── editor.blade.php │ ├── posts │ │ ├── show.blade.php │ │ ├── create.blade.php │ │ ├── edit.blade.php │ │ └── index.blade.php │ ├── layouts │ │ ├── layout.blade.php │ │ └── layout_editor.blade.php │ └── hello.php ├── tests │ ├── ExampleTest.php │ └── TestCase.php ├── lang │ └── en │ │ ├── pagination.php │ │ ├── reminders.php │ │ └── validation.php ├── routes.php └── filters.php ├── .gitattributes ├── .gitignore ├── CONTRIBUTING.md ├── readme.md ├── server.php ├── phpunit.xml ├── composer.json ├── bootstrap ├── paths.php ├── start.php └── autoload.php └── artisan /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/commands/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /app/config/packages/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/database/seeds/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/packages/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/database/migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/database/production.sqlite: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/start/local.php: -------------------------------------------------------------------------------- 1 | 'required', 8 | 'body' => 'required' 9 | ); 10 | } -------------------------------------------------------------------------------- /app/database/seeds/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call('UserTableSeeder'); 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /app/views/emails/auth/reminder.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Password Reset

8 | 9 |
10 | To reset your password, complete this form: {{ URL::to('password/reset', array($token)) }}. 11 |
12 | 13 | -------------------------------------------------------------------------------- /app/views/partials/editor.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/tests/ExampleTest.php: -------------------------------------------------------------------------------- 1 | client->request('GET', '/'); 13 | 14 | $this->assertTrue($this->client->getResponse()->isOk()); 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /app/controllers/BaseController.php: -------------------------------------------------------------------------------- 1 | layout)) 13 | { 14 | $this->layout = View::make($this->layout); 15 | } 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /app/views/posts/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.layout_editor') 2 | 3 | @section('title', 'View Post') 4 | 5 | @section('main') 6 | 7 |

{{ link_to_route('posts.index', 'Return to all posts') }}

8 | 9 |
{{ $post->title }}
10 | 11 |
{{ $post->body }}
12 | 13 | @stop -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Redirect Trailing Slashes... 9 | RewriteRule ^(.*)/$ /$1 [L,R=301] 10 | 11 | # Handle Front Controller... 12 | RewriteCond %{REQUEST_FILENAME} !-d 13 | RewriteCond %{REQUEST_FILENAME} !-f 14 | RewriteRule ^ index.php [L] 15 | 16 | -------------------------------------------------------------------------------- /app/tests/TestCase.php: -------------------------------------------------------------------------------- 1 | 8 |
9 | 10 | {{ Form::open(array('route' => 'posts.store')) }} 11 |

Enter post title

12 |

Enter post body

13 | {{ Form::submit('Save Post', array('class' => 'btn btn-primary', 'id' => 'form-submit')) }} 14 | 15 | {{ Form::close() }} 16 | 17 | @stop -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 18 | 'next' => 'Next »', 19 | 20 | ); -------------------------------------------------------------------------------- /app/config/testing/cache.php: -------------------------------------------------------------------------------- 1 | 'array', 19 | 20 | ); -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./app/tests/ 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/config/testing/session.php: -------------------------------------------------------------------------------- 1 | 'array', 20 | 21 | ); -------------------------------------------------------------------------------- /app/views/posts/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.layout_editor') 2 | 3 | @section('title', 'Edit post') 4 | 5 | @section('main') 6 | 7 |
8 |
9 | 10 | {{ Form::open(array('method' => 'PATCH', 'route' => array('posts.update', $post->id))) }} 11 |
{{ $post->title }}
12 |
{{ $post->body }}
13 | 14 | {{ Form::submit('Update Post', array('class' => 'btn btn-primary', 'id' => 'form-update')) }} 15 | 16 | {{ Form::close() }} 17 | 18 | @stop -------------------------------------------------------------------------------- /app/controllers/HomeController.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('title'); 18 | $table->text('body'); 19 | $table->timestamps(); 20 | }); 21 | } 22 | 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::drop('posts'); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/lang/en/reminders.php: -------------------------------------------------------------------------------- 1 | "Passwords must be at least six characters and match the confirmation.", 17 | 18 | "user" => "We can't find a user with that e-mail address.", 19 | 20 | "token" => "This password reset token is invalid.", 21 | 22 | "sent" => "Password reminder sent!", 23 | 24 | ); 25 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel/laravel", 3 | "description": "The Laravel Framework.", 4 | "keywords": ["framework", "laravel"], 5 | "license": "MIT", 6 | "require": { 7 | "laravel/framework": "4.1.*" 8 | }, 9 | "autoload": { 10 | "classmap": [ 11 | "app/commands", 12 | "app/controllers", 13 | "app/models", 14 | "app/database/migrations", 15 | "app/database/seeds", 16 | "app/tests/TestCase.php" 17 | ] 18 | }, 19 | "scripts": { 20 | "post-install-cmd": [ 21 | "php artisan clear-compiled", 22 | "php artisan optimize" 23 | ], 24 | "post-update-cmd": [ 25 | "php artisan clear-compiled", 26 | "php artisan optimize" 27 | ], 28 | "post-create-project-cmd": [ 29 | "php artisan key:generate" 30 | ] 31 | }, 32 | "config": { 33 | "preferred-install": "dist" 34 | }, 35 | "minimum-stability": "stable" 36 | } 37 | -------------------------------------------------------------------------------- /app/config/workbench.php: -------------------------------------------------------------------------------- 1 | '', 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Workbench Author E-Mail Address 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Like the option above, your e-mail address is used when generating new 24 | | workbench packages. The e-mail is placed in your composer.json file 25 | | automatically after the package is created by the workbench tool. 26 | | 27 | */ 28 | 29 | 'email' => '', 30 | 31 | ); -------------------------------------------------------------------------------- /app/views/layouts/layout.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | @yield('title') - Laravel Medium editor demo on Codeforest 6 | 7 | 8 | 9 | 15 | 16 | 17 | 18 | 19 |
20 | @if (Session::has('message')) 21 |
22 |

{{ Session::get('message') }}

23 |
24 | @endif 25 | 26 | @yield('main') 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /app/config/view.php: -------------------------------------------------------------------------------- 1 | array(__DIR__.'/../views'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Pagination View 21 | |-------------------------------------------------------------------------- 22 | | 23 | | This view will be used to render the pagination link output, and can 24 | | be easily customized here to show any view you like. A clean view 25 | | compatible with Twitter's Bootstrap is given to you by default. 26 | | 27 | */ 28 | 29 | 'pagination' => 'pagination::slider-3', 30 | 31 | ); 32 | -------------------------------------------------------------------------------- /app/models/User.php: -------------------------------------------------------------------------------- 1 | getKey(); 30 | } 31 | 32 | /** 33 | * Get the password for the user. 34 | * 35 | * @return string 36 | */ 37 | public function getAuthPassword() 38 | { 39 | return $this->password; 40 | } 41 | 42 | /** 43 | * Get the e-mail address where password reminders are sent. 44 | * 45 | * @return string 46 | */ 47 | public function getReminderEmail() 48 | { 49 | return $this->email; 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /app/views/layouts/layout_editor.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | @yield('title') - Laravel Medium editor demo on Codeforest 6 | 7 | 8 | 9 | 10 | 11 | 12 | 18 | 19 | 20 | 21 | 22 |
23 | @if (Session::has('message')) 24 |
25 |

{{ Session::get('message') }}

26 |
27 | @endif 28 | 29 | @yield('main') 30 |
31 | @include('partials.editor') 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/views/posts/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.layout') 2 | 3 | @section('title', 'Posts') 4 | 5 | @section('main') 6 | 7 |

All Posts

8 | 9 |

{{ link_to_route('posts.create', 'Add new post') }}

10 | 11 | @if ($posts->count()) 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | @foreach ($posts as $post) 25 | 26 | 27 | 28 | 29 | 30 | 35 | 36 | @endforeach 37 | 38 |
TitleBody
{{{ strip_tags($post->title) }}}{{{ strip_tags(Str::words($post->body, 20)) }}}{{ link_to_route('posts.show', 'View', array($post->id), array('class' => 'btn btn-info')) }}{{ link_to_route('posts.edit', 'Edit', array($post->id), array('class' => 'btn btn-info')) }} 31 | {{ Form::open(array('method' => 'DELETE', 'route' => array('posts.destroy', $post->id))) }} 32 | {{ Form::submit('Delete', array('class' => 'btn btn-danger')) }} 33 | {{ Form::close() }} 34 |
39 | @else 40 | There are no posts 41 | @endif 42 | 43 | @stop 44 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | /* 10 | |-------------------------------------------------------------------------- 11 | | Register The Auto Loader 12 | |-------------------------------------------------------------------------- 13 | | 14 | | Composer provides a convenient, automatically generated class loader 15 | | for our application. We just need to utilize it! We'll require it 16 | | into the script here so that we do not have to worry about the 17 | | loading of any our classes "manually". Feels great to relax. 18 | | 19 | */ 20 | 21 | require __DIR__.'/../bootstrap/autoload.php'; 22 | 23 | /* 24 | |-------------------------------------------------------------------------- 25 | | Turn On The Lights 26 | |-------------------------------------------------------------------------- 27 | | 28 | | We need to illuminate PHP development, so let's turn on the lights. 29 | | This bootstraps the framework and gets it ready for use, then it 30 | | will load up this application so that we can run it and send 31 | | the responses back to the browser and delight these users. 32 | | 33 | */ 34 | 35 | $app = require_once __DIR__.'/../bootstrap/start.php'; 36 | 37 | /* 38 | |-------------------------------------------------------------------------- 39 | | Run The Application 40 | |-------------------------------------------------------------------------- 41 | | 42 | | Once we have the application, we can simply call the run method, 43 | | which will execute the request and send the response back to 44 | | the client's browser allowing them to enjoy the creative 45 | | and wonderful application we have whipped up for them. 46 | | 47 | */ 48 | 49 | $app->run(); 50 | -------------------------------------------------------------------------------- /app/config/remote.php: -------------------------------------------------------------------------------- 1 | 'production', 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Remote Server Connections 21 | |-------------------------------------------------------------------------- 22 | | 23 | | These are the servers that will be accessible via the SSH task runner 24 | | facilities of Laravel. This feature radically simplifies executing 25 | | tasks on your servers, such as deploying out these applications. 26 | | 27 | */ 28 | 29 | 'connections' => array( 30 | 31 | 'production' => array( 32 | 'host' => '', 33 | 'username' => '', 34 | 'password' => '', 35 | 'key' => '', 36 | 'keyphrase' => '', 37 | 'root' => '/var/www', 38 | ), 39 | 40 | ), 41 | 42 | /* 43 | |-------------------------------------------------------------------------- 44 | | Remote Server Groups 45 | |-------------------------------------------------------------------------- 46 | | 47 | | Here you may list connections under a single group name, which allows 48 | | you to easily access all of the servers at once using a short name 49 | | that is extremely easy to remember, such as "web" or "database". 50 | | 51 | */ 52 | 53 | 'groups' => array( 54 | 55 | 'web' => array('production') 56 | 57 | ), 58 | 59 | ); -------------------------------------------------------------------------------- /public/css/style.css: -------------------------------------------------------------------------------- 1 | *:focus { 2 | outline: none; 3 | } 4 | body { 5 | font-family: Georgia, Cambria, "Times New Roman", Times, serif; 6 | font-size: 22px; 7 | font-style: normal; 8 | font-weight: 400; 9 | letter-spacing: 0.01rem; 10 | line-height: 1.5; 11 | margin-bottom: 30px; 12 | } 13 | 14 | .top-bar { 15 | position: fixed; 16 | top: 0; 17 | left: 0; 18 | width: auto; 19 | z-index: 10; 20 | padding: 10px; 21 | background-color: #000; 22 | background-color: rgba(0, 0, 0, .8); 23 | box-shadow: 0 0 4px #000; 24 | box-sizing: border-box; 25 | color: #ccc; 26 | font-size: 12px; 27 | font-weight: bold; 28 | text-align: center; 29 | text-transform: uppercase; 30 | } 31 | 32 | #container { 33 | width: 960px; 34 | margin: 90px auto; 35 | } 36 | 37 | h1 { 38 | font-family: Georgia, Cambria, "Times New Roman", Times, serif; 39 | font-size: 60px; 40 | font-weight: normal; 41 | text-align: center; 42 | margin-bottom: 40px; 43 | padding-bottom: 40px; 44 | letter-spacing: -2px; 45 | border-bottom: 1px solid #dbdbdb; 46 | } 47 | 48 | p { 49 | margin-bottom: 40px; 50 | } 51 | 52 | b { 53 | font-family: Georgia, Cambria, "Times New Roman", Times, serif; 54 | } 55 | 56 | blockquote { 57 | display: block; 58 | padding-left: 20px; 59 | border-left: 6px solid #df0d32; 60 | } 61 | 62 | .title-editable, .body-editable { 63 | margin-bottom: 30px; 64 | } 65 | .mediumInsert .mediumInsert-buttons { 66 | top: -20px !important; 67 | } 68 | 69 | .mediumInsert .mediumInsert-placeholder .mediumInsert-images img { 70 | margin-bottom: 40px !important; 71 | } 72 | 73 | .table > thead > tr > th, 74 | .table > tbody > tr > th, 75 | .table > tfoot > tr > th, 76 | .table > thead > tr > td, 77 | .table > tbody > tr > td, 78 | .table > tfoot > tr > td { 79 | vertical-align: middle; 80 | } 81 | -------------------------------------------------------------------------------- /bootstrap/paths.php: -------------------------------------------------------------------------------- 1 | __DIR__.'/../app', 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Public Path 21 | |-------------------------------------------------------------------------- 22 | | 23 | | The public path contains the assets for your web application, such as 24 | | your JavaScript and CSS files, and also contains the primary entry 25 | | point for web requests into these applications from the outside. 26 | | 27 | */ 28 | 29 | 'public' => __DIR__.'/../public', 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Base Path 34 | |-------------------------------------------------------------------------- 35 | | 36 | | The base path is the root of the Laravel installation. Most likely you 37 | | will not need to change this value. But, if for some wild reason it 38 | | is necessary you will do so here, just proceed with some caution. 39 | | 40 | */ 41 | 42 | 'base' => __DIR__.'/..', 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Storage Path 47 | |-------------------------------------------------------------------------- 48 | | 49 | | The storage path is used by Laravel to store cached Blade views, logs 50 | | and other pieces of information. You may modify the path here when 51 | | you want to change the location of this directory for your apps. 52 | | 53 | */ 54 | 55 | 'storage' => __DIR__.'/../app/storage', 56 | 57 | ); 58 | -------------------------------------------------------------------------------- /app/config/queue.php: -------------------------------------------------------------------------------- 1 | 'sync', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Queue Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may configure the connection information for each server that 26 | | is used by your application. A default configuration has been added 27 | | for each back-end shipped with Laravel. You are free to add more. 28 | | 29 | */ 30 | 31 | 'connections' => array( 32 | 33 | 'sync' => array( 34 | 'driver' => 'sync', 35 | ), 36 | 37 | 'beanstalkd' => array( 38 | 'driver' => 'beanstalkd', 39 | 'host' => 'localhost', 40 | 'queue' => 'default', 41 | ), 42 | 43 | 'sqs' => array( 44 | 'driver' => 'sqs', 45 | 'key' => 'your-public-key', 46 | 'secret' => 'your-secret-key', 47 | 'queue' => 'your-queue-url', 48 | 'region' => 'us-east-1', 49 | ), 50 | 51 | 'iron' => array( 52 | 'driver' => 'iron', 53 | 'project' => 'your-project-id', 54 | 'token' => 'your-token', 55 | 'queue' => 'your-queue-name', 56 | ), 57 | 58 | 'redis' => array( 59 | 'driver' => 'redis', 60 | 'queue' => 'default', 61 | ), 62 | 63 | ), 64 | 65 | /* 66 | |-------------------------------------------------------------------------- 67 | | Failed Queue Jobs 68 | |-------------------------------------------------------------------------- 69 | | 70 | | These options configure the behavior of failed queue job logging so you 71 | | can control which database and table are used to store the jobs that 72 | | have failed. You may change them to any database / table you wish. 73 | | 74 | */ 75 | 76 | 'failed' => array( 77 | 78 | 'database' => 'mysql', 'table' => 'failed_jobs', 79 | 80 | ), 81 | 82 | ); 83 | -------------------------------------------------------------------------------- /app/config/auth.php: -------------------------------------------------------------------------------- 1 | 'eloquent', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Authentication Model 23 | |-------------------------------------------------------------------------- 24 | | 25 | | When using the "Eloquent" authentication driver, we need to know which 26 | | Eloquent model should be used to retrieve your users. Of course, it 27 | | is often just the "User" model but you may use whatever you like. 28 | | 29 | */ 30 | 31 | 'model' => 'User', 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | Authentication Table 36 | |-------------------------------------------------------------------------- 37 | | 38 | | When using the "Database" authentication driver, we need to know which 39 | | table should be used to retrieve your users. We have chosen a basic 40 | | default value but you may easily change it to any table you like. 41 | | 42 | */ 43 | 44 | 'table' => 'users', 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Password Reminder Settings 49 | |-------------------------------------------------------------------------- 50 | | 51 | | Here you may set the settings for password reminders, including a view 52 | | that should be used as your password reminder e-mail. You will also 53 | | be able to set the name of the table that holds the reset tokens. 54 | | 55 | | The "expire" time is the number of minutes that the reminder should be 56 | | considered valid. This security feature keeps tokens short-lived so 57 | | they have less time to be guessed. You may change this as needed. 58 | | 59 | */ 60 | 61 | 'reminder' => array( 62 | 63 | 'email' => 'emails.auth.reminder', 64 | 65 | 'table' => 'password_reminders', 66 | 67 | 'expire' => 60, 68 | 69 | ), 70 | 71 | ); 72 | -------------------------------------------------------------------------------- /app/filters.php: -------------------------------------------------------------------------------- 1 | detectEnvironment(array( 28 | 29 | 'local' => array('your-machine-name'), 30 | 31 | )); 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | Bind Paths 36 | |-------------------------------------------------------------------------- 37 | | 38 | | Here we are binding the paths configured in paths.php to the app. You 39 | | should not be changing these here. If you need to change these you 40 | | may do so within the paths.php file and they will be bound here. 41 | | 42 | */ 43 | 44 | $app->bindInstallPaths(require __DIR__.'/paths.php'); 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Load The Application 49 | |-------------------------------------------------------------------------- 50 | | 51 | | Here we will load this Illuminate application. We will keep this in a 52 | | separate location so we can isolate the creation of an application 53 | | from the actual running of the application with a given request. 54 | | 55 | */ 56 | 57 | $framework = $app['path.base'].'/vendor/laravel/framework/src'; 58 | 59 | require $framework.'/Illuminate/Foundation/start.php'; 60 | 61 | /* 62 | |-------------------------------------------------------------------------- 63 | | Return The Application 64 | |-------------------------------------------------------------------------- 65 | | 66 | | This script returns the application instance. The instance is given to 67 | | the calling script so we can separate the building of the instances 68 | | from the actual running of the application and sending responses. 69 | | 70 | */ 71 | 72 | return $app; 73 | -------------------------------------------------------------------------------- /artisan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | setRequestForConsoleEnvironment(); 45 | 46 | $artisan = Illuminate\Console\Application::start($app); 47 | 48 | /* 49 | |-------------------------------------------------------------------------- 50 | | Run The Artisan Application 51 | |-------------------------------------------------------------------------- 52 | | 53 | | When we run the console application, the current CLI command will be 54 | | executed in this console and the response sent back to a terminal 55 | | or another output device for the developers. Here goes nothing! 56 | | 57 | */ 58 | 59 | $status = $artisan->run(); 60 | 61 | /* 62 | |-------------------------------------------------------------------------- 63 | | Shutdown The Application 64 | |-------------------------------------------------------------------------- 65 | | 66 | | Once Artisan has finished running. We will fire off the shutdown events 67 | | so that any final work may be done by the application before we shut 68 | | down the process. This is the last thing to happen to the request. 69 | | 70 | */ 71 | 72 | $app->shutdown(); 73 | 74 | exit($status); -------------------------------------------------------------------------------- /bootstrap/autoload.php: -------------------------------------------------------------------------------- 1 | 'file', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | File Cache Location 23 | |-------------------------------------------------------------------------- 24 | | 25 | | When using the "file" cache driver, we need a location where the cache 26 | | files may be stored. A sensible default has been specified, but you 27 | | are free to change it to any other place on disk that you desire. 28 | | 29 | */ 30 | 31 | 'path' => storage_path().'/cache', 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | Database Cache Connection 36 | |-------------------------------------------------------------------------- 37 | | 38 | | When using the "database" cache driver you may specify the connection 39 | | that should be used to store the cached items. When this option is 40 | | null the default database connection will be utilized for cache. 41 | | 42 | */ 43 | 44 | 'connection' => null, 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Database Cache Table 49 | |-------------------------------------------------------------------------- 50 | | 51 | | When using the "database" cache driver we need to know the table that 52 | | should be used to store the cached items. A default table name has 53 | | been provided but you're free to change it however you deem fit. 54 | | 55 | */ 56 | 57 | 'table' => 'cache', 58 | 59 | /* 60 | |-------------------------------------------------------------------------- 61 | | Memcached Servers 62 | |-------------------------------------------------------------------------- 63 | | 64 | | Now you may specify an array of your Memcached servers that should be 65 | | used when utilizing the Memcached cache driver. All of the servers 66 | | should contain a value for "host", "port", and "weight" options. 67 | | 68 | */ 69 | 70 | 'memcached' => array( 71 | 72 | array('host' => '127.0.0.1', 'port' => 11211, 'weight' => 100), 73 | 74 | ), 75 | 76 | /* 77 | |-------------------------------------------------------------------------- 78 | | Cache Key Prefix 79 | |-------------------------------------------------------------------------- 80 | | 81 | | When utilizing a RAM based store such as APC or Memcached, there might 82 | | be other applications utilizing the same cache. So, we'll specify a 83 | | value to get prefixed to all our keys so we can avoid collisions. 84 | | 85 | */ 86 | 87 | 'prefix' => 'laravel', 88 | 89 | ); 90 | -------------------------------------------------------------------------------- /app/config/database.php: -------------------------------------------------------------------------------- 1 | PDO::FETCH_CLASS, 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Default Database Connection Name 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may specify which of the database connections below you wish 24 | | to use as your default connection for all database work. Of course 25 | | you may use many connections at once using the Database library. 26 | | 27 | */ 28 | 29 | 'default' => 'mysql', 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Database Connections 34 | |-------------------------------------------------------------------------- 35 | | 36 | | Here are each of the database connections setup for your application. 37 | | Of course, examples of configuring each database platform that is 38 | | supported by Laravel is shown below to make development simple. 39 | | 40 | | 41 | | All database work in Laravel is done through the PHP PDO facilities 42 | | so make sure you have the driver for your particular database of 43 | | choice installed on your machine before you begin development. 44 | | 45 | */ 46 | 47 | 'connections' => array( 48 | 49 | 'sqlite' => array( 50 | 'driver' => 'sqlite', 51 | 'database' => __DIR__.'/../database/production.sqlite', 52 | 'prefix' => '', 53 | ), 54 | 55 | 'mysql' => array( 56 | 'driver' => 'mysql', 57 | 'host' => 'localhost', 58 | 'database' => 'privat_summernote', 59 | 'username' => 'root', 60 | 'password' => '', 61 | 'charset' => 'utf8', 62 | 'collation' => 'utf8_unicode_ci', 63 | 'prefix' => '', 64 | ), 65 | 66 | 'pgsql' => array( 67 | 'driver' => 'pgsql', 68 | 'host' => 'localhost', 69 | 'database' => 'database', 70 | 'username' => 'root', 71 | 'password' => '', 72 | 'charset' => 'utf8', 73 | 'prefix' => '', 74 | 'schema' => 'public', 75 | ), 76 | 77 | 'sqlsrv' => array( 78 | 'driver' => 'sqlsrv', 79 | 'host' => 'localhost', 80 | 'database' => 'database', 81 | 'username' => 'root', 82 | 'password' => '', 83 | 'prefix' => '', 84 | ), 85 | 86 | ), 87 | 88 | /* 89 | |-------------------------------------------------------------------------- 90 | | Migration Repository Table 91 | |-------------------------------------------------------------------------- 92 | | 93 | | This table keeps track of all the migrations that have already run for 94 | | your application. Using this information, we can determine which of 95 | | the migrations on disk haven't actually been run in the database. 96 | | 97 | */ 98 | 99 | 'migrations' => 'migrations', 100 | 101 | /* 102 | |-------------------------------------------------------------------------- 103 | | Redis Databases 104 | |-------------------------------------------------------------------------- 105 | | 106 | | Redis is an open source, fast, and advanced key-value store that also 107 | | provides a richer set of commands than a typical key-value systems 108 | | such as APC or Memcached. Laravel makes it easy to dig right in. 109 | | 110 | */ 111 | 112 | 'redis' => array( 113 | 114 | 'cluster' => false, 115 | 116 | 'default' => array( 117 | 'host' => '127.0.0.1', 118 | 'port' => 6379, 119 | 'database' => 0, 120 | ), 121 | 122 | ), 123 | 124 | ); 125 | -------------------------------------------------------------------------------- /app/controllers/PostsController.php: -------------------------------------------------------------------------------- 1 | post = $post; 15 | } 16 | 17 | /** 18 | * Display a listing of the resource. 19 | * 20 | * @return Response 21 | */ 22 | public function index() 23 | { 24 | $posts = $this->post->all(); 25 | 26 | return View::make('posts.index', compact('posts')); 27 | } 28 | 29 | /** 30 | * Show the form for creating a new resource. 31 | * 32 | * @return Response 33 | */ 34 | public function create() 35 | { 36 | return View::make('posts.create'); 37 | } 38 | 39 | /** 40 | * Store a newly created resource in storage. 41 | * 42 | * @return Response 43 | */ 44 | public function store() 45 | { 46 | $input = Input::all(); 47 | $validation = Validator::make($input, Post::$rules); 48 | 49 | if ($validation->passes()) 50 | { 51 | $this->post->create($input); 52 | return Response::json(array('success' => true, 'errors' => '', 'message' => 'Post created successfully.')); 53 | } 54 | return Response::json(array('success' => false, 'errors' => $validation, 'message' => 'All fields are required.')); 55 | } 56 | 57 | /** 58 | * Display the specified resource. 59 | * 60 | * @param int $id 61 | * @return Response 62 | */ 63 | public function show($id) 64 | { 65 | $post = $this->post->findOrFail($id); 66 | 67 | return View::make('posts.show', compact('post')); 68 | } 69 | 70 | /** 71 | * Show the form for editing the specified resource. 72 | * 73 | * @param int $id 74 | * @return Response 75 | */ 76 | public function edit($id) 77 | { 78 | $post = $this->post->find($id); 79 | 80 | if (is_null($post)) 81 | { 82 | return Redirect::route('posts.index'); 83 | } 84 | 85 | return View::make('posts.edit', compact('post')); 86 | } 87 | 88 | /** 89 | * Update the specified resource in storage. 90 | * 91 | * @param int $id 92 | * @return Response 93 | */ 94 | public function update($id) 95 | { 96 | $input = array_except(Input::all(), '_method'); 97 | $validation = Validator::make($input, Post::$rules); 98 | 99 | if ($validation->passes()) 100 | { 101 | $post = Post::find($id); 102 | $post->update($input); 103 | 104 | return Response::json(array('success' => true, 'errors' => '', 'message' => 'Post updated successfully.')); 105 | } 106 | 107 | return Response::json(array('success' => false, 'errors' => $validation, 'message' => 'All fields are required.')); 108 | } 109 | 110 | /** 111 | * Remove the specified resource from storage. 112 | * 113 | * @param int $id 114 | * @return Response 115 | */ 116 | public function destroy($id) 117 | { 118 | $this->post->find($id)->delete(); 119 | 120 | return Redirect::route('posts.index'); 121 | } 122 | 123 | public function upload() 124 | { 125 | $file = Input::file('file'); 126 | $input = array('image' => $file); 127 | $rules = array( 128 | 'image' => 'image' 129 | ); 130 | $validator = Validator::make($input, $rules); 131 | if ( $validator->fails()) { 132 | return Response::json(array('success' => false, 'errors' => $validator->getMessageBag()->toArray())); 133 | } 134 | 135 | $fileName = time() . '-' . $file->getClientOriginalName(); 136 | $destination = public_path() . '/uploads/'; 137 | $file->move($destination, $fileName); 138 | 139 | echo url('/uploads/'. $fileName); 140 | } 141 | } -------------------------------------------------------------------------------- /app/config/mail.php: -------------------------------------------------------------------------------- 1 | 'smtp', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | SMTP Host Address 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may provide the host address of the SMTP server used by your 26 | | applications. A default option is provided that is compatible with 27 | | the Postmark mail service, which will provide reliable delivery. 28 | | 29 | */ 30 | 31 | 'host' => 'smtp.mailgun.org', 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | SMTP Host Port 36 | |-------------------------------------------------------------------------- 37 | | 38 | | This is the SMTP port used by your application to delivery e-mails to 39 | | users of your application. Like the host we have set this value to 40 | | stay compatible with the Postmark e-mail application by default. 41 | | 42 | */ 43 | 44 | 'port' => 587, 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Global "From" Address 49 | |-------------------------------------------------------------------------- 50 | | 51 | | You may wish for all e-mails sent by your application to be sent from 52 | | the same address. Here, you may specify a name and address that is 53 | | used globally for all e-mails that are sent by your application. 54 | | 55 | */ 56 | 57 | 'from' => array('address' => null, 'name' => null), 58 | 59 | /* 60 | |-------------------------------------------------------------------------- 61 | | E-Mail Encryption Protocol 62 | |-------------------------------------------------------------------------- 63 | | 64 | | Here you may specify the encryption protocol that should be used when 65 | | the application send e-mail messages. A sensible default using the 66 | | transport layer security protocol should provide great security. 67 | | 68 | */ 69 | 70 | 'encryption' => 'tls', 71 | 72 | /* 73 | |-------------------------------------------------------------------------- 74 | | SMTP Server Username 75 | |-------------------------------------------------------------------------- 76 | | 77 | | If your SMTP server requires a username for authentication, you should 78 | | set it here. This will get used to authenticate with your server on 79 | | connection. You may also set the "password" value below this one. 80 | | 81 | */ 82 | 83 | 'username' => null, 84 | 85 | /* 86 | |-------------------------------------------------------------------------- 87 | | SMTP Server Password 88 | |-------------------------------------------------------------------------- 89 | | 90 | | Here you may set the password required by your SMTP server to send out 91 | | messages from your application. This will be given to the server on 92 | | connection so that the application will be able to send messages. 93 | | 94 | */ 95 | 96 | 'password' => null, 97 | 98 | /* 99 | |-------------------------------------------------------------------------- 100 | | Sendmail System Path 101 | |-------------------------------------------------------------------------- 102 | | 103 | | When using the "sendmail" driver to send e-mails, we will need to know 104 | | the path to where Sendmail lives on this server. A default path has 105 | | been provided here, which will work well on most of your systems. 106 | | 107 | */ 108 | 109 | 'sendmail' => '/usr/sbin/sendmail -bs', 110 | 111 | /* 112 | |-------------------------------------------------------------------------- 113 | | Mail "Pretend" 114 | |-------------------------------------------------------------------------- 115 | | 116 | | When this option is enabled, e-mail will not actually be sent over the 117 | | web and will instead be written to your application's logs files so 118 | | you may inspect the message. This is great for local development. 119 | | 120 | */ 121 | 122 | 'pretend' => false, 123 | 124 | ); -------------------------------------------------------------------------------- /app/lang/en/validation.php: -------------------------------------------------------------------------------- 1 | "The :attribute must be accepted.", 17 | "active_url" => "The :attribute is not a valid URL.", 18 | "after" => "The :attribute must be a date after :date.", 19 | "alpha" => "The :attribute may only contain letters.", 20 | "alpha_dash" => "The :attribute may only contain letters, numbers, and dashes.", 21 | "alpha_num" => "The :attribute may only contain letters and numbers.", 22 | "array" => "The :attribute must be an array.", 23 | "before" => "The :attribute must be a date before :date.", 24 | "between" => array( 25 | "numeric" => "The :attribute must be between :min and :max.", 26 | "file" => "The :attribute must be between :min and :max kilobytes.", 27 | "string" => "The :attribute must be between :min and :max characters.", 28 | "array" => "The :attribute must have between :min and :max items.", 29 | ), 30 | "confirmed" => "The :attribute confirmation does not match.", 31 | "date" => "The :attribute is not a valid date.", 32 | "date_format" => "The :attribute does not match the format :format.", 33 | "different" => "The :attribute and :other must be different.", 34 | "digits" => "The :attribute must be :digits digits.", 35 | "digits_between" => "The :attribute must be between :min and :max digits.", 36 | "email" => "The :attribute format is invalid.", 37 | "exists" => "The selected :attribute is invalid.", 38 | "image" => "The :attribute must be an image.", 39 | "in" => "The selected :attribute is invalid.", 40 | "integer" => "The :attribute must be an integer.", 41 | "ip" => "The :attribute must be a valid IP address.", 42 | "max" => array( 43 | "numeric" => "The :attribute may not be greater than :max.", 44 | "file" => "The :attribute may not be greater than :max kilobytes.", 45 | "string" => "The :attribute may not be greater than :max characters.", 46 | "array" => "The :attribute may not have more than :max items.", 47 | ), 48 | "mimes" => "The :attribute must be a file of type: :values.", 49 | "min" => array( 50 | "numeric" => "The :attribute must be at least :min.", 51 | "file" => "The :attribute must be at least :min kilobytes.", 52 | "string" => "The :attribute must be at least :min characters.", 53 | "array" => "The :attribute must have at least :min items.", 54 | ), 55 | "not_in" => "The selected :attribute is invalid.", 56 | "numeric" => "The :attribute must be a number.", 57 | "regex" => "The :attribute format is invalid.", 58 | "required" => "The :attribute field is required.", 59 | "required_if" => "The :attribute field is required when :other is :value.", 60 | "required_with" => "The :attribute field is required when :values is present.", 61 | "required_without" => "The :attribute field is required when :values is not present.", 62 | "same" => "The :attribute and :other must match.", 63 | "size" => array( 64 | "numeric" => "The :attribute must be :size.", 65 | "file" => "The :attribute must be :size kilobytes.", 66 | "string" => "The :attribute must be :size characters.", 67 | "array" => "The :attribute must contain :size items.", 68 | ), 69 | "unique" => "The :attribute has already been taken.", 70 | "url" => "The :attribute format is invalid.", 71 | 72 | /* 73 | |-------------------------------------------------------------------------- 74 | | Custom Validation Language Lines 75 | |-------------------------------------------------------------------------- 76 | | 77 | | Here you may specify custom validation messages for attributes using the 78 | | convention "attribute.rule" to name the lines. This makes it quick to 79 | | specify a specific custom language line for a given attribute rule. 80 | | 81 | */ 82 | 83 | 'custom' => array(), 84 | 85 | /* 86 | |-------------------------------------------------------------------------- 87 | | Custom Validation Attributes 88 | |-------------------------------------------------------------------------- 89 | | 90 | | The following language lines are used to swap attribute place-holders 91 | | with something more reader friendly such as E-Mail Address instead 92 | | of "email". This simply helps us make messages a little cleaner. 93 | | 94 | */ 95 | 96 | 'attributes' => array(), 97 | 98 | ); 99 | -------------------------------------------------------------------------------- /app/config/session.php: -------------------------------------------------------------------------------- 1 | 'file', 20 | 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | Session Lifetime 24 | |-------------------------------------------------------------------------- 25 | | 26 | | Here you may specify the number of minutes that you wish the session 27 | | to be allowed to remain idle before it expires. If you want them 28 | | to immediately expire on the browser closing, set that option. 29 | | 30 | */ 31 | 32 | 'lifetime' => 120, 33 | 34 | 'expire_on_close' => false, 35 | 36 | /* 37 | |-------------------------------------------------------------------------- 38 | | Session File Location 39 | |-------------------------------------------------------------------------- 40 | | 41 | | When using the native session driver, we need a location where session 42 | | files may be stored. A default has been set for you but a different 43 | | location may be specified. This is only needed for file sessions. 44 | | 45 | */ 46 | 47 | 'files' => storage_path().'/sessions', 48 | 49 | /* 50 | |-------------------------------------------------------------------------- 51 | | Session Database Connection 52 | |-------------------------------------------------------------------------- 53 | | 54 | | When using the "database" or "redis" session drivers, you may specify a 55 | | connection that should be used to manage these sessions. This should 56 | | correspond to a connection in your database configuration options. 57 | | 58 | */ 59 | 60 | 'connection' => null, 61 | 62 | /* 63 | |-------------------------------------------------------------------------- 64 | | Session Database Table 65 | |-------------------------------------------------------------------------- 66 | | 67 | | When using the "database" session driver, you may specify the table we 68 | | should use to manage the sessions. Of course, a sensible default is 69 | | provided for you; however, you are free to change this as needed. 70 | | 71 | */ 72 | 73 | 'table' => 'sessions', 74 | 75 | /* 76 | |-------------------------------------------------------------------------- 77 | | Session Sweeping Lottery 78 | |-------------------------------------------------------------------------- 79 | | 80 | | Some session drivers must manually sweep their storage location to get 81 | | rid of old sessions from storage. Here are the chances that it will 82 | | happen on a given request. By default, the odds are 2 out of 100. 83 | | 84 | */ 85 | 86 | 'lottery' => array(2, 100), 87 | 88 | /* 89 | |-------------------------------------------------------------------------- 90 | | Session Cookie Name 91 | |-------------------------------------------------------------------------- 92 | | 93 | | Here you may change the name of the cookie used to identify a session 94 | | instance by ID. The name specified here will get used every time a 95 | | new session cookie is created by the framework for every driver. 96 | | 97 | */ 98 | 99 | 'cookie' => 'laravel_session', 100 | 101 | /* 102 | |-------------------------------------------------------------------------- 103 | | Session Cookie Path 104 | |-------------------------------------------------------------------------- 105 | | 106 | | The session cookie path determines the path for which the cookie will 107 | | be regarded as available. Typically, this will be the root path of 108 | | your application but you are free to change this when necessary. 109 | | 110 | */ 111 | 112 | 'path' => '/', 113 | 114 | /* 115 | |-------------------------------------------------------------------------- 116 | | Session Cookie Domain 117 | |-------------------------------------------------------------------------- 118 | | 119 | | Here you may change the domain of the cookie used to identify a session 120 | | in your application. This will determine which domains the cookie is 121 | | available to in your application. A sensible default has been set. 122 | | 123 | */ 124 | 125 | 'domain' => null, 126 | 127 | /* 128 | |-------------------------------------------------------------------------- 129 | | HTTPS Only Cookies 130 | |-------------------------------------------------------------------------- 131 | | 132 | | By setting this option to true, session cookies will only be sent back 133 | | to the server if the browser has a HTTPS connection. This will keep 134 | | the cookie from being sent to you if it can not be done securely. 135 | | 136 | */ 137 | 138 | 'secure' => false, 139 | 140 | ); 141 | -------------------------------------------------------------------------------- /app/views/hello.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Laravel PHP Framework 6 | 35 | 36 | 37 |
38 | 39 |

You have arrived.

40 |
41 | 42 | 43 | -------------------------------------------------------------------------------- /app/config/app.php: -------------------------------------------------------------------------------- 1 | true, 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Application URL 21 | |-------------------------------------------------------------------------- 22 | | 23 | | This URL is used by the console to properly generate URLs when using 24 | | the Artisan command line tool. You should set this to the root of 25 | | your application so that it is used when running Artisan tasks. 26 | | 27 | */ 28 | 29 | 'url' => 'http://localhost', 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Application Timezone 34 | |-------------------------------------------------------------------------- 35 | | 36 | | Here you may specify the default timezone for your application, which 37 | | will be used by the PHP date and date-time functions. We have gone 38 | | ahead and set this to a sensible default for you out of the box. 39 | | 40 | */ 41 | 42 | 'timezone' => 'UTC', 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Application Locale Configuration 47 | |-------------------------------------------------------------------------- 48 | | 49 | | The application locale determines the default locale that will be used 50 | | by the translation service provider. You are free to set this value 51 | | to any of the locales which will be supported by the application. 52 | | 53 | */ 54 | 55 | 'locale' => 'en', 56 | 57 | /* 58 | |-------------------------------------------------------------------------- 59 | | Encryption Key 60 | |-------------------------------------------------------------------------- 61 | | 62 | | This key is used by the Illuminate encrypter service and should be set 63 | | to a random, 32 character string, otherwise these encrypted strings 64 | | will not be safe. Please do this before deploying an application! 65 | | 66 | */ 67 | 68 | 'key' => 'IcXP1BKomWWqLI3z7OCdCOCljk438uVl', 69 | 70 | /* 71 | |-------------------------------------------------------------------------- 72 | | Autoloaded Service Providers 73 | |-------------------------------------------------------------------------- 74 | | 75 | | The service providers listed here will be automatically loaded on the 76 | | request to your application. Feel free to add your own services to 77 | | this array to grant expanded functionality to your applications. 78 | | 79 | */ 80 | 81 | 'providers' => array( 82 | 83 | 'Illuminate\Foundation\Providers\ArtisanServiceProvider', 84 | 'Illuminate\Auth\AuthServiceProvider', 85 | 'Illuminate\Cache\CacheServiceProvider', 86 | 'Illuminate\Session\CommandsServiceProvider', 87 | 'Illuminate\Foundation\Providers\ConsoleSupportServiceProvider', 88 | 'Illuminate\Routing\ControllerServiceProvider', 89 | 'Illuminate\Cookie\CookieServiceProvider', 90 | 'Illuminate\Database\DatabaseServiceProvider', 91 | 'Illuminate\Encryption\EncryptionServiceProvider', 92 | 'Illuminate\Filesystem\FilesystemServiceProvider', 93 | 'Illuminate\Hashing\HashServiceProvider', 94 | 'Illuminate\Html\HtmlServiceProvider', 95 | 'Illuminate\Log\LogServiceProvider', 96 | 'Illuminate\Mail\MailServiceProvider', 97 | 'Illuminate\Database\MigrationServiceProvider', 98 | 'Illuminate\Pagination\PaginationServiceProvider', 99 | 'Illuminate\Queue\QueueServiceProvider', 100 | 'Illuminate\Redis\RedisServiceProvider', 101 | 'Illuminate\Remote\RemoteServiceProvider', 102 | 'Illuminate\Auth\Reminders\ReminderServiceProvider', 103 | 'Illuminate\Database\SeedServiceProvider', 104 | 'Illuminate\Session\SessionServiceProvider', 105 | 'Illuminate\Translation\TranslationServiceProvider', 106 | 'Illuminate\Validation\ValidationServiceProvider', 107 | 'Illuminate\View\ViewServiceProvider', 108 | 'Illuminate\Workbench\WorkbenchServiceProvider', 109 | 'Way\Generators\GeneratorsServiceProvider' 110 | ), 111 | 112 | /* 113 | |-------------------------------------------------------------------------- 114 | | Service Provider Manifest 115 | |-------------------------------------------------------------------------- 116 | | 117 | | The service provider manifest is used by Laravel to lazy load service 118 | | providers which are not needed for each request, as well to keep a 119 | | list of all of the services. Here, you may set its storage spot. 120 | | 121 | */ 122 | 123 | 'manifest' => storage_path().'/meta', 124 | 125 | /* 126 | |-------------------------------------------------------------------------- 127 | | Class Aliases 128 | |-------------------------------------------------------------------------- 129 | | 130 | | This array of class aliases will be registered when this application 131 | | is started. However, feel free to register as many as you wish as 132 | | the aliases are "lazy" loaded so they don't hinder performance. 133 | | 134 | */ 135 | 136 | 'aliases' => array( 137 | 138 | 'App' => 'Illuminate\Support\Facades\App', 139 | 'Artisan' => 'Illuminate\Support\Facades\Artisan', 140 | 'Auth' => 'Illuminate\Support\Facades\Auth', 141 | 'Blade' => 'Illuminate\Support\Facades\Blade', 142 | 'Cache' => 'Illuminate\Support\Facades\Cache', 143 | 'ClassLoader' => 'Illuminate\Support\ClassLoader', 144 | 'Config' => 'Illuminate\Support\Facades\Config', 145 | 'Controller' => 'Illuminate\Routing\Controller', 146 | 'Cookie' => 'Illuminate\Support\Facades\Cookie', 147 | 'Crypt' => 'Illuminate\Support\Facades\Crypt', 148 | 'DB' => 'Illuminate\Support\Facades\DB', 149 | 'Eloquent' => 'Illuminate\Database\Eloquent\Model', 150 | 'Event' => 'Illuminate\Support\Facades\Event', 151 | 'File' => 'Illuminate\Support\Facades\File', 152 | 'Form' => 'Illuminate\Support\Facades\Form', 153 | 'Hash' => 'Illuminate\Support\Facades\Hash', 154 | 'HTML' => 'Illuminate\Support\Facades\HTML', 155 | 'Input' => 'Illuminate\Support\Facades\Input', 156 | 'Lang' => 'Illuminate\Support\Facades\Lang', 157 | 'Log' => 'Illuminate\Support\Facades\Log', 158 | 'Mail' => 'Illuminate\Support\Facades\Mail', 159 | 'Paginator' => 'Illuminate\Support\Facades\Paginator', 160 | 'Password' => 'Illuminate\Support\Facades\Password', 161 | 'Queue' => 'Illuminate\Support\Facades\Queue', 162 | 'Redirect' => 'Illuminate\Support\Facades\Redirect', 163 | 'Redis' => 'Illuminate\Support\Facades\Redis', 164 | 'Request' => 'Illuminate\Support\Facades\Request', 165 | 'Response' => 'Illuminate\Support\Facades\Response', 166 | 'Route' => 'Illuminate\Support\Facades\Route', 167 | 'Schema' => 'Illuminate\Support\Facades\Schema', 168 | 'Seeder' => 'Illuminate\Database\Seeder', 169 | 'Session' => 'Illuminate\Support\Facades\Session', 170 | 'SSH' => 'Illuminate\Support\Facades\SSH', 171 | 'Str' => 'Illuminate\Support\Str', 172 | 'URL' => 'Illuminate\Support\Facades\URL', 173 | 'Validator' => 'Illuminate\Support\Facades\Validator', 174 | 'View' => 'Illuminate\Support\Facades\View', 175 | 176 | ), 177 | 178 | ); 179 | -------------------------------------------------------------------------------- /public/css/medium-editor.css: -------------------------------------------------------------------------------- 1 | .clearfix:after{display:block;visibility:hidden;clear:both;height:0;content:" ";font-size:0}@-webkit-keyframes pop-upwards{0%{-webkit-transform:matrix(0.97, 0, 0, 1, 0, 12);-moz-transform:matrix(0.97, 0, 0, 1, 0, 12);-ms-transform:matrix(0.97, 0, 0, 1, 0, 12);-o-transform:matrix(0.97, 0, 0, 1, 0, 12);transform:matrix(0.97, 0, 0, 1, 0, 12);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0}20%{-webkit-transform:matrix(0.99, 0, 0, 1, 0, 2);-moz-transform:matrix(0.99, 0, 0, 1, 0, 2);-ms-transform:matrix(0.99, 0, 0, 1, 0, 2);-o-transform:matrix(0.99, 0, 0, 1, 0, 2);transform:matrix(0.99, 0, 0, 1, 0, 2);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=70);opacity:0.7}40%{-webkit-transform:matrix(1, 0, 0, 1, 0, -1);-moz-transform:matrix(1, 0, 0, 1, 0, -1);-ms-transform:matrix(1, 0, 0, 1, 0, -1);-o-transform:matrix(1, 0, 0, 1, 0, -1);transform:matrix(1, 0, 0, 1, 0, -1);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}70%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}100%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}}@-moz-keyframes pop-upwards{0%{-webkit-transform:matrix(0.97, 0, 0, 1, 0, 12);-moz-transform:matrix(0.97, 0, 0, 1, 0, 12);-ms-transform:matrix(0.97, 0, 0, 1, 0, 12);-o-transform:matrix(0.97, 0, 0, 1, 0, 12);transform:matrix(0.97, 0, 0, 1, 0, 12);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0}20%{-webkit-transform:matrix(0.99, 0, 0, 1, 0, 2);-moz-transform:matrix(0.99, 0, 0, 1, 0, 2);-ms-transform:matrix(0.99, 0, 0, 1, 0, 2);-o-transform:matrix(0.99, 0, 0, 1, 0, 2);transform:matrix(0.99, 0, 0, 1, 0, 2);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=70);opacity:0.7}40%{-webkit-transform:matrix(1, 0, 0, 1, 0, -1);-moz-transform:matrix(1, 0, 0, 1, 0, -1);-ms-transform:matrix(1, 0, 0, 1, 0, -1);-o-transform:matrix(1, 0, 0, 1, 0, -1);transform:matrix(1, 0, 0, 1, 0, -1);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}70%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}100%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}}@-o-keyframes pop-upwards{0%{-webkit-transform:matrix(0.97, 0, 0, 1, 0, 12);-moz-transform:matrix(0.97, 0, 0, 1, 0, 12);-ms-transform:matrix(0.97, 0, 0, 1, 0, 12);-o-transform:matrix(0.97, 0, 0, 1, 0, 12);transform:matrix(0.97, 0, 0, 1, 0, 12);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0}20%{-webkit-transform:matrix(0.99, 0, 0, 1, 0, 2);-moz-transform:matrix(0.99, 0, 0, 1, 0, 2);-ms-transform:matrix(0.99, 0, 0, 1, 0, 2);-o-transform:matrix(0.99, 0, 0, 1, 0, 2);transform:matrix(0.99, 0, 0, 1, 0, 2);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=70);opacity:0.7}40%{-webkit-transform:matrix(1, 0, 0, 1, 0, -1);-moz-transform:matrix(1, 0, 0, 1, 0, -1);-ms-transform:matrix(1, 0, 0, 1, 0, -1);-o-transform:matrix(1, 0, 0, 1, 0, -1);transform:matrix(1, 0, 0, 1, 0, -1);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}70%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}100%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}}@keyframes pop-upwards{0%{-webkit-transform:matrix(0.97, 0, 0, 1, 0, 12);-moz-transform:matrix(0.97, 0, 0, 1, 0, 12);-ms-transform:matrix(0.97, 0, 0, 1, 0, 12);-o-transform:matrix(0.97, 0, 0, 1, 0, 12);transform:matrix(0.97, 0, 0, 1, 0, 12);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0}20%{-webkit-transform:matrix(0.99, 0, 0, 1, 0, 2);-moz-transform:matrix(0.99, 0, 0, 1, 0, 2);-ms-transform:matrix(0.99, 0, 0, 1, 0, 2);-o-transform:matrix(0.99, 0, 0, 1, 0, 2);transform:matrix(0.99, 0, 0, 1, 0, 2);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=70);opacity:0.7}40%{-webkit-transform:matrix(1, 0, 0, 1, 0, -1);-moz-transform:matrix(1, 0, 0, 1, 0, -1);-ms-transform:matrix(1, 0, 0, 1, 0, -1);-o-transform:matrix(1, 0, 0, 1, 0, -1);transform:matrix(1, 0, 0, 1, 0, -1);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}70%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}100%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}}.medium-toolbar-arrow-under:after,.medium-toolbar-arrow-over:before{position:absolute;left:50%;display:block;margin-left:-8px;width:0;height:0;border-style:solid;content:""}.medium-toolbar-arrow-under:after{border-width:8px 8px 0 8px}.medium-toolbar-arrow-over:before{top:-8px;border-width:0 8px 8px 8px}.medium-editor-toolbar{position:absolute;top:0;left:0;z-index:2000;visibility:hidden;font-size:16px;font-family:HelveticaNeue, Helvetica, Arial, sans-serif}.medium-editor-toolbar ul{margin:0;padding:0}.medium-editor-toolbar li{float:left;margin:0;padding:0;list-style:none}.medium-editor-toolbar li button{display:block;margin:0;padding:15px;text-decoration:none;font-size:14px;cursor:pointer;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.medium-editor-toolbar li .medium-editor-action-underline{text-decoration:underline}.medium-editor-toolbar li .medium-editor-action-pre{padding:15px 0;font-weight:100;font-size:12px;font-family:'Menlo', monospace}.medium-editor-toolbar-active{visibility:visible;-webkit-animation:pop-upwards 160ms forwards linear;-moz-animation:pop-upwards 160ms forwards linear;-ms-animation:pop-upwards 160ms forwards linear;-o-animation:pop-upwards 160ms forwards linear;animation:pop-upwards 160ms forwards linear;-webkit-transition:top 0.075s ease-out,left 0.075s ease-out;-moz-transition:top 0.075s ease-out,left 0.075s ease-out;-o-transition:top 0.075s ease-out,left 0.075s ease-out;transition:top 0.075s ease-out,left 0.075s ease-out}.medium-editor-action-bold{font-weight:bolder}.medium-editor-action-italic{font-style:italic}.medium-editor-toolbar-form-anchor{display:none}.medium-editor-toolbar-form-anchor input,.medium-editor-toolbar-form-anchor a{font-family:HelveticaNeue, Helvetica, Arial, sans-serif}.medium-editor-toolbar-form-anchor input{margin:0;padding:6px;width:316px;border:none;font-size:14px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.medium-editor-toolbar-form-anchor input:focus{outline:0;border:none;box-shadow:none;-webkit-appearance:none;-moz-appearance:none}.medium-editor-toolbar-form-anchor a{display:inline-block;margin:0 10px;text-decoration:none;font-weight:bolder;font-size:24px}.medium-editor-placeholder{position:relative}.medium-editor-placeholder:after{position:absolute;top:0;left:0;content:attr(data-placeholder);font-style:italic} 2 | -------------------------------------------------------------------------------- /public/css/themes/default.css: -------------------------------------------------------------------------------- 1 | .clearfix:after{display:block;visibility:hidden;clear:both;height:0;content:" ";font-size:0}@-webkit-keyframes pop-upwards{0%{-webkit-transform:matrix(0.97, 0, 0, 1, 0, 12);-moz-transform:matrix(0.97, 0, 0, 1, 0, 12);-ms-transform:matrix(0.97, 0, 0, 1, 0, 12);-o-transform:matrix(0.97, 0, 0, 1, 0, 12);transform:matrix(0.97, 0, 0, 1, 0, 12);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0}20%{-webkit-transform:matrix(0.99, 0, 0, 1, 0, 2);-moz-transform:matrix(0.99, 0, 0, 1, 0, 2);-ms-transform:matrix(0.99, 0, 0, 1, 0, 2);-o-transform:matrix(0.99, 0, 0, 1, 0, 2);transform:matrix(0.99, 0, 0, 1, 0, 2);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=70);opacity:0.7}40%{-webkit-transform:matrix(1, 0, 0, 1, 0, -1);-moz-transform:matrix(1, 0, 0, 1, 0, -1);-ms-transform:matrix(1, 0, 0, 1, 0, -1);-o-transform:matrix(1, 0, 0, 1, 0, -1);transform:matrix(1, 0, 0, 1, 0, -1);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}70%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}100%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}}@-moz-keyframes pop-upwards{0%{-webkit-transform:matrix(0.97, 0, 0, 1, 0, 12);-moz-transform:matrix(0.97, 0, 0, 1, 0, 12);-ms-transform:matrix(0.97, 0, 0, 1, 0, 12);-o-transform:matrix(0.97, 0, 0, 1, 0, 12);transform:matrix(0.97, 0, 0, 1, 0, 12);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0}20%{-webkit-transform:matrix(0.99, 0, 0, 1, 0, 2);-moz-transform:matrix(0.99, 0, 0, 1, 0, 2);-ms-transform:matrix(0.99, 0, 0, 1, 0, 2);-o-transform:matrix(0.99, 0, 0, 1, 0, 2);transform:matrix(0.99, 0, 0, 1, 0, 2);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=70);opacity:0.7}40%{-webkit-transform:matrix(1, 0, 0, 1, 0, -1);-moz-transform:matrix(1, 0, 0, 1, 0, -1);-ms-transform:matrix(1, 0, 0, 1, 0, -1);-o-transform:matrix(1, 0, 0, 1, 0, -1);transform:matrix(1, 0, 0, 1, 0, -1);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}70%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}100%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}}@-o-keyframes pop-upwards{0%{-webkit-transform:matrix(0.97, 0, 0, 1, 0, 12);-moz-transform:matrix(0.97, 0, 0, 1, 0, 12);-ms-transform:matrix(0.97, 0, 0, 1, 0, 12);-o-transform:matrix(0.97, 0, 0, 1, 0, 12);transform:matrix(0.97, 0, 0, 1, 0, 12);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0}20%{-webkit-transform:matrix(0.99, 0, 0, 1, 0, 2);-moz-transform:matrix(0.99, 0, 0, 1, 0, 2);-ms-transform:matrix(0.99, 0, 0, 1, 0, 2);-o-transform:matrix(0.99, 0, 0, 1, 0, 2);transform:matrix(0.99, 0, 0, 1, 0, 2);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=70);opacity:0.7}40%{-webkit-transform:matrix(1, 0, 0, 1, 0, -1);-moz-transform:matrix(1, 0, 0, 1, 0, -1);-ms-transform:matrix(1, 0, 0, 1, 0, -1);-o-transform:matrix(1, 0, 0, 1, 0, -1);transform:matrix(1, 0, 0, 1, 0, -1);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}70%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}100%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}}@keyframes pop-upwards{0%{-webkit-transform:matrix(0.97, 0, 0, 1, 0, 12);-moz-transform:matrix(0.97, 0, 0, 1, 0, 12);-ms-transform:matrix(0.97, 0, 0, 1, 0, 12);-o-transform:matrix(0.97, 0, 0, 1, 0, 12);transform:matrix(0.97, 0, 0, 1, 0, 12);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0}20%{-webkit-transform:matrix(0.99, 0, 0, 1, 0, 2);-moz-transform:matrix(0.99, 0, 0, 1, 0, 2);-ms-transform:matrix(0.99, 0, 0, 1, 0, 2);-o-transform:matrix(0.99, 0, 0, 1, 0, 2);transform:matrix(0.99, 0, 0, 1, 0, 2);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=70);opacity:0.7}40%{-webkit-transform:matrix(1, 0, 0, 1, 0, -1);-moz-transform:matrix(1, 0, 0, 1, 0, -1);-ms-transform:matrix(1, 0, 0, 1, 0, -1);-o-transform:matrix(1, 0, 0, 1, 0, -1);transform:matrix(1, 0, 0, 1, 0, -1);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}70%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}100%{-webkit-transform:matrix(1, 0, 0, 1, 0, 0);-moz-transform:matrix(1, 0, 0, 1, 0, 0);-ms-transform:matrix(1, 0, 0, 1, 0, 0);-o-transform:matrix(1, 0, 0, 1, 0, 0);transform:matrix(1, 0, 0, 1, 0, 0);filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}}.medium-toolbar-arrow-under:after{top:50px;border-color:#242424 transparent transparent transparent}.medium-toolbar-arrow-over:before{top:-8px;border-color:transparent transparent #242424 transparent}.medium-editor-toolbar{border:1px solid #000;background-color:#242424;background:-webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(0%, #242424), color-stop(100%, rgba(36,36,36,0.75)));background:-webkit-linear-gradient(bottom, #242424,rgba(36,36,36,0.75));background:-moz-linear-gradient(bottom, #242424,rgba(36,36,36,0.75));background:-o-linear-gradient(bottom, #242424,rgba(36,36,36,0.75));background:linear-gradient(bottom, #242424,rgba(36,36,36,0.75));-webkit-border-radius:5px;-moz-border-radius:5px;-ms-border-radius:5px;-o-border-radius:5px;border-radius:5px;-webkit-box-shadow:0 0 3px #000;-moz-box-shadow:0 0 3px #000;box-shadow:0 0 3px #000;-webkit-transition:top 0.075s ease-out,left 0.075s ease-out;-moz-transition:top 0.075s ease-out,left 0.075s ease-out;-o-transition:top 0.075s ease-out,left 0.075s ease-out;transition:top 0.075s ease-out,left 0.075s ease-out}.medium-editor-toolbar li button{min-width:50px;height:50px;border:0;border-right:1px solid #000;border-left:1px solid #333;border-left:1px solid rgba(255,255,255,0.1);background-color:#242424;color:#fff;background:-webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(0%, #242424), color-stop(100%, rgba(36,36,36,0.89)));background:-webkit-linear-gradient(bottom, #242424,rgba(36,36,36,0.89));background:-moz-linear-gradient(bottom, #242424,rgba(36,36,36,0.89));background:-o-linear-gradient(bottom, #242424,rgba(36,36,36,0.89));background:linear-gradient(bottom, #242424,rgba(36,36,36,0.89));-webkit-box-shadow:0 2px 2px rgba(0,0,0,0.3);-moz-box-shadow:0 2px 2px rgba(0,0,0,0.3);box-shadow:0 2px 2px rgba(0,0,0,0.3);-webkit-transition:background-color 0.2s ease-in;-moz-transition:background-color 0.2s ease-in;-o-transition:background-color 0.2s ease-in;transition:background-color 0.2s ease-in}.medium-editor-toolbar li button:hover{background-color:#000;color:yellow}.medium-editor-toolbar li .medium-editor-button-first{-moz-border-radius-topleft:5px;-webkit-border-top-left-radius:5px;border-top-left-radius:5px;-moz-border-radius-bottomleft:5px;-webkit-border-bottom-left-radius:5px;border-bottom-left-radius:5px}.medium-editor-toolbar li .medium-editor-button-last{-moz-border-radius-topright:5px;-webkit-border-top-right-radius:5px;border-top-right-radius:5px;-moz-border-radius-bottomright:5px;-webkit-border-bottom-right-radius:5px;border-bottom-right-radius:5px}.medium-editor-toolbar li .medium-editor-button-active{background-color:#000;color:#fff;background:-webkit-gradient(linear, 50% 100%, 50% 0%, color-stop(0%, #242424), color-stop(100%, rgba(0,0,0,0.89)));background:-webkit-linear-gradient(bottom, #242424,rgba(0,0,0,0.89));background:-moz-linear-gradient(bottom, #242424,rgba(0,0,0,0.89));background:-o-linear-gradient(bottom, #242424,rgba(0,0,0,0.89));background:linear-gradient(bottom, #242424,rgba(0,0,0,0.89))}.medium-editor-toolbar-form-anchor{background:#242424;color:#999;-webkit-border-radius:5px;-moz-border-radius:5px;-ms-border-radius:5px;-o-border-radius:5px;border-radius:5px}.medium-editor-toolbar-form-anchor input{height:50px;background:#242424;color:#ccc;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.medium-editor-toolbar-form-anchor a{color:#fff}.medium-editor-placeholder:after{color:#b3b3b1} -------------------------------------------------------------------------------- /public/js/medium-editor-insert.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * medium-editor-insert-plugin v0.1.1 - jQuery insert plugin for MediumEditor 3 | * 4 | * https://github.com/orthes/medium-editor-images-plugin 5 | * 6 | * Copyright (c) 2013 Pavel Linkesch (http://linkesch.sk) 7 | * Released under the MIT license 8 | */ 9 | 10 | !function(a){MediumEditor.prototype.serialize=function(){var b,c,d,e,f,g,h,i,j={};for(b=0;bImage',e='Map';a.fn.mediumInsert.settings.images===!0&&a.fn.mediumInsert.settings.maps===!0?c='Insert":a.fn.mediumInsert.settings.images===!0?c=d:a.fn.mediumInsert.settings.maps===!0&&(c=e),""!==c&&(c='
'+c+'
',b.is(":empty")&&b.html("


"),b.keyup(function(){var d=0;b.children("p").each(function(){a(this).next().hasClass("mediumInsert")===!1&&(a(this).after(c),a(this).next(".mediumInsert").attr("id","mediumInsert-"+d)),d++})}).keyup())},setEvents:function(){var b=this,c=a.fn.mediumInsert.insert.$el;c.on("selectstart",".mediumInsert",function(a){return a.preventDefault(),!1}),c.on("blur",function(){var b,c=a(this).clone();c.find(".mediumInsert").remove(),b=c.html().replace(/^\s+|\s+$/g,""),(""===b||"


"===b)&&a(this).addClass("medium-editor-placeholder")}),c.on("click",".mediumInsert-buttons a.mediumInsert-buttonsShow",function(){var c=a(this).siblings(".mediumInsert-buttonsOptions"),d=a(this).parent().siblings(".mediumInsert-placeholder");a(this).hasClass("active")?(a(this).removeClass("active"),c.hide(),a("a",c).show()):(a(this).addClass("active"),c.show(),a("a",c).each(function(){var b=a(this).attr("class").split("action-")[1],e=b.split("-")[0];a(".mediumInsert-"+e,d).length>0&&a("a:not(.action-"+b+")",c).hide()})),b.deselect()}),c.on("mouseleave",".mediumInsert",function(){a("a.mediumInsert-buttonsShow",this).removeClass("active"),a(".mediumInsert-buttonsOptions",this).hide()}),c.on("click",".mediumInsert-buttons .mediumInsert-action",function(){var b=a(this).attr("class").split("action-")[1].split("-"),c=a(this).parents(".mediumInsert-buttons").siblings(".mediumInsert-placeholder");a.fn.mediumInsert[b[0]]&&a.fn.mediumInsert[b[0]][b[1]]&&a.fn.mediumInsert[b[0]][b[1]](c),a(this).parents(".mediumInsert").mouseleave()})}}}(jQuery),function(a){a.fn.mediumInsert.images={init:function(){this.$el=a.fn.mediumInsert.insert.$el,this.options=a.extend(this.default,a.fn.mediumInsert.settings.imagesPlugin),this.setImageEvents(),this.setDragAndDropEvents(),this.preparePreviousImages()},"default":{formatData:function(a){var b=new FormData;return b.append("file",a),b}},preparePreviousImages:function(){this.$el.find(".mediumInsert-images").each(function(){var b=a(this).parent();b.html('
'+b.html()+"
")})},add:function(b){var c,d,e=this;return c=a('').click(),c.change(function(){d=this.files,e.uploadFiles(b,d)}),a.fn.mediumInsert.insert.deselect(),c},updateProgressBar:function(b){var c,d=a(".progress:first",this.$el);b.lengthComputable&&(c=b.loaded/b.total*100|0,d.attr("value",c),d.html(c))},uploadCompleted:function(b){var c,d=a(".progress:first",this.$el);d.attr("value",100),d.html(100),d.before('
'),c=d.siblings("img"),d.remove(),c.load(function(){c.parent().mouseleave().mouseenter()})},uploadFiles:function(b,c){for(var d={"image/png":!0,"image/jpeg":!0,"image/gif":!0},e=this,f=function(){var a=new XMLHttpRequest;return a.upload.onprogress=e.updateProgressBar,a},g=0;g0'),a.ajax({type:"post",url:a.fn.mediumInsert.settings.imagesUploadScript,xhr:f,cache:!1,contentType:!1,complete:this.uploadCompleted,processData:!1,data:this.options.formatData(h)}))}},setImageEvents:function(){this.$el.on("mouseenter",".mediumInsert-images",function(){var b,c,d=a("img",this);a.fn.mediumInsert.settings.enabled!==!1&&d.length>0&&(a(this).append(''),a(this).parent().parent().hasClass("small")?a(this).append(''):a(this).append(''),b=d.position().top+parseInt(d.css("margin-top"),10),c=d.position().left+d.width()-30,a(".mediumInsert-imageRemove",this).css({right:"auto",top:b,left:c}),a(".mediumInsert-imageResizeBigger, .mediumInsert-imageResizeSmaller",this).css({right:"auto",top:b,left:c-31}))}),this.$el.on("mouseleave",".mediumInsert-images",function(){a(".mediumInsert-imageRemove, .mediumInsert-imageResizeSmaller, .mediumInsert-imageResizeBigger",this).remove()}),this.$el.on("click",".mediumInsert-imageResizeSmaller",function(){a(this).parent().parent().parent().addClass("small"),a(this).parent().mouseleave().mouseleave(),a.fn.mediumInsert.insert.deselect()}),this.$el.on("click",".mediumInsert-imageResizeBigger",function(){a(this).parent().parent().parent().removeClass("small"),a(this).parent().mouseleave().mouseleave(),a.fn.mediumInsert.insert.deselect()}),this.$el.on("click",".mediumInsert-imageRemove",function(){0===a(this).parent().siblings().length&&a(this).parent().parent().parent().removeClass("small"),a(this).parent().remove(),a.fn.mediumInsert.insert.deselect()})},setDragAndDropEvents:function(){var b,c,d=this,e=!1,f=!1;a(document).on("dragover","body",function(){a.fn.mediumInsert.settings.enabled!==!1&&a(this).addClass("hover")}),a(document).on("dragend","body",function(){a.fn.mediumInsert.settings.enabled!==!1&&a(this).removeClass("hover")}),this.$el.on("dragover",".mediumInsert",function(){a.fn.mediumInsert.settings.enabled!==!1&&(a(this).addClass("hover"),a(this).attr("contenteditable",!0))}),this.$el.on("dragleave",".mediumInsert",function(){a.fn.mediumInsert.settings.enabled!==!1&&(a(this).removeClass("hover"),a(this).attr("contenteditable",!1))}),this.$el.on("dragstart",".mediumInsert .mediumInsert-images img",function(){a.fn.mediumInsert.settings.enabled!==!1&&(b=a(this).parent().index(),c=a(this).parent().parent().parent().attr("id"))}),this.$el.on("dragend",".mediumInsert .mediumInsert-images img",function(b){a.fn.mediumInsert.settings.enabled!==!1&&e===!0&&(0===a(b.originalEvent.target.parentNode).siblings().length&&a(b.originalEvent.target.parentNode).parent().parent().removeClass("small"),a(b.originalEvent.target.parentNode).mouseleave(),a(b.originalEvent.target.parentNode).remove(),e=!1,f=!1)}),this.$el.on("dragover",".mediumInsert .mediumInsert-images img",function(b){a.fn.mediumInsert.settings.enabled!==!1&&b.preventDefault()}),this.$el.on("drop",".mediumInsert .mediumInsert-images img",function(){var d,e,g;if(a.fn.mediumInsert.settings.enabled!==!1){if(c!==a(this).parent().parent().parent().attr("id"))return f=!1,b=c=null,void 0;d=parseInt(b,10),e=a(this).parent().parent().find(".mediumInsert-images:nth-child("+(d+1)+")"),g=a(this).parent().index(),g>d?e.insertAfter(a(this).parent()):d>g&&e.insertBefore(a(this).parent()),e.mouseleave(),f=!0,b=null}}),this.$el.on("drop",".mediumInsert",function(b){var c;b.preventDefault(),a.fn.mediumInsert.settings.enabled!==!1&&(a(this).removeClass("hover"),a("body").removeClass("hover"),a(this).attr("contenteditable",!1),c=b.originalEvent.dataTransfer.files,c.length>0?d.uploadFiles(a(".mediumInsert-placeholder",this),c):f===!0?f=!1:(a(".mediumInsert-placeholder",this).append('
'+b.originalEvent.dataTransfer.getData("text/html")+"
"),a("meta",this).remove(),e=!0))})}}}(jQuery),function(a){a.fn.mediumInsert.maps={init:function(){this.$el=a.fn.mediumInsert.insert.$el},add:function(b){a.fn.mediumInsert.insert.deselect(),b.append('
Map - Coming soon...
')}}}(jQuery); -------------------------------------------------------------------------------- /public/js/medium-editor.js: -------------------------------------------------------------------------------- 1 | function MediumEditor(elements, options) { 2 | 'use strict'; 3 | return this.init(elements, options); 4 | } 5 | 6 | if (typeof module === 'object') { 7 | module.exports = MediumEditor; 8 | } 9 | 10 | (function (window, document) { 11 | 'use strict'; 12 | 13 | function extend(b, a) { 14 | var prop; 15 | if (b === undefined) { 16 | return a; 17 | } 18 | for (prop in a) { 19 | if (a.hasOwnProperty(prop) && b.hasOwnProperty(prop) === false) { 20 | b[prop] = a[prop]; 21 | } 22 | } 23 | return b; 24 | } 25 | 26 | // http://stackoverflow.com/questions/5605401/insert-link-in-contenteditable-element 27 | // by Tim Down 28 | function saveSelection() { 29 | var i, 30 | len, 31 | ranges, 32 | sel = window.getSelection(); 33 | if (sel.getRangeAt && sel.rangeCount) { 34 | ranges = []; 35 | for (i = 0, len = sel.rangeCount; i < len; i += 1) { 36 | ranges.push(sel.getRangeAt(i)); 37 | } 38 | return ranges; 39 | } 40 | return null; 41 | } 42 | 43 | function restoreSelection(savedSel) { 44 | var i, 45 | len, 46 | sel = window.getSelection(); 47 | if (savedSel) { 48 | sel.removeAllRanges(); 49 | for (i = 0, len = savedSel.length; i < len; i += 1) { 50 | sel.addRange(savedSel[i]); 51 | } 52 | } 53 | } 54 | 55 | // http://stackoverflow.com/questions/1197401/how-can-i-get-the-element-the-caret-is-in-with-javascript-when-using-contentedi 56 | // by You 57 | function getSelectionStart() { 58 | var node = document.getSelection().anchorNode, 59 | startNode = (node && node.nodeType === 3 ? node.parentNode : node); 60 | return startNode; 61 | } 62 | 63 | // http://stackoverflow.com/questions/4176923/html-of-selected-text 64 | // by Tim Down 65 | function getSelectionHtml() { 66 | var i, 67 | html = '', 68 | sel, 69 | len, 70 | container; 71 | if (window.getSelection !== undefined) { 72 | sel = window.getSelection(); 73 | if (sel.rangeCount) { 74 | container = document.createElement('div'); 75 | for (i = 0, len = sel.rangeCount; i < len; i += 1) { 76 | container.appendChild(sel.getRangeAt(i).cloneContents()); 77 | } 78 | html = container.innerHTML; 79 | } 80 | } else if (document.selection !== undefined) { 81 | if (document.selection.type === 'Text') { 82 | html = document.selection.createRange().htmlText; 83 | } 84 | } 85 | return html; 86 | } 87 | 88 | MediumEditor.prototype = { 89 | defaults: { 90 | allowMultiParagraphSelection: true, 91 | anchorInputPlaceholder: 'Paste or type a link', 92 | buttons: ['bold', 'italic', 'underline', 'anchor', 'header1', 'header2', 'quote'], 93 | buttonLabels: false, 94 | delay: 0, 95 | diffLeft: 0, 96 | diffTop: -10, 97 | disableReturn: false, 98 | disableToolbar: false, 99 | firstHeader: 'h3', 100 | forcePlainText: true, 101 | placeholder: 'Type your text', 102 | secondHeader: 'h4', 103 | targetBlank: false 104 | }, 105 | 106 | init: function (elements, options) { 107 | this.elements = typeof elements === 'string' ? document.querySelectorAll(elements) : elements; 108 | if (this.elements.length === 0) { 109 | return; 110 | } 111 | this.isActive = true; 112 | this.parentElements = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'pre']; 113 | this.id = document.querySelectorAll('.medium-editor-toolbar').length + 1; 114 | this.options = extend(options, this.defaults); 115 | return this.initElements() 116 | .bindSelect() 117 | .bindPaste() 118 | .setPlaceholders() 119 | .bindWindowActions(); 120 | }, 121 | 122 | initElements: function () { 123 | var i, 124 | addToolbar = false; 125 | for (i = 0; i < this.elements.length; i += 1) { 126 | this.elements[i].setAttribute('contentEditable', true); 127 | if (!this.elements[i].getAttribute('data-placeholder')) { 128 | this.elements[i].setAttribute('data-placeholder', this.options.placeholder); 129 | } 130 | this.elements[i].setAttribute('data-medium-element', true); 131 | this.bindParagraphCreation(i).bindReturn(i).bindTab(i); 132 | if (!this.options.disableToolbar && !this.elements[i].getAttribute('data-disable-toolbar')) { 133 | addToolbar = true; 134 | } 135 | } 136 | // Init toolbar 137 | if (addToolbar) { 138 | this.initToolbar() 139 | .bindButtons() 140 | .bindAnchorForm(); 141 | } 142 | return this; 143 | }, 144 | 145 | serialize: function () { 146 | var i, 147 | elementid, 148 | content = {}; 149 | for (i = 0; i < this.elements.length; i += 1) { 150 | elementid = (this.elements[i].id !== '') ? this.elements[i].id : 'element-' + i; 151 | content[elementid] = { 152 | value: this.elements[i].innerHTML.trim() 153 | }; 154 | } 155 | return content; 156 | }, 157 | 158 | bindParagraphCreation: function (index) { 159 | var self = this; 160 | this.elements[index].addEventListener('keyup', function (e) { 161 | var node = getSelectionStart(), 162 | tagName; 163 | if (node && node.getAttribute('data-medium-element') && node.children.length === 0 && 164 | !(self.options.disableReturn || node.getAttribute('data-disable-return'))) { 165 | document.execCommand('formatBlock', false, 'p'); 166 | } 167 | if (e.which === 13 && !e.shiftKey) { 168 | node = getSelectionStart(); 169 | tagName = node.tagName.toLowerCase(); 170 | if (!(self.options.disableReturn || this.getAttribute('data-disable-return')) && 171 | tagName !== 'li' && !self.isListItemChild(node)) { 172 | document.execCommand('formatBlock', false, 'p'); 173 | if (tagName === 'a') { 174 | document.execCommand('unlink', false, null); 175 | } 176 | } 177 | } 178 | }); 179 | return this; 180 | }, 181 | 182 | isListItemChild: function (node) { 183 | var parentNode = node.parentNode, 184 | tagName = parentNode.tagName.toLowerCase(); 185 | while (this.parentElements.indexOf(tagName) === -1 && tagName !== 'div') { 186 | if (tagName === 'li') { 187 | return true; 188 | } 189 | parentNode = parentNode.parentNode; 190 | if (parentNode && parentNode.tagName) { 191 | tagName = parentNode.tagName.toLowerCase(); 192 | } else { 193 | return false; 194 | } 195 | } 196 | return false; 197 | }, 198 | 199 | bindReturn: function (index) { 200 | var self = this; 201 | this.elements[index].addEventListener('keypress', function (e) { 202 | if (e.which === 13) { 203 | if (self.options.disableReturn || this.getAttribute('data-disable-return')) { 204 | e.preventDefault(); 205 | } 206 | } 207 | }); 208 | return this; 209 | }, 210 | 211 | bindTab: function (index) { 212 | this.elements[index].addEventListener('keydown', function (e) { 213 | if (e.which === 9) { 214 | // Override tab only for pre nodes 215 | var tag = getSelectionStart().tagName.toLowerCase(); 216 | if (tag === "pre") { 217 | e.preventDefault(); 218 | document.execCommand('insertHtml', null, ' '); 219 | } 220 | } 221 | }); 222 | }, 223 | 224 | buttonTemplate: function (btnType) { 225 | var buttonLabels = this.getButtonLabels(this.options.buttonLabels), 226 | buttonTemplates = { 227 | 'bold': '
  • ', 228 | 'italic': '
  • ', 229 | 'underline': '
  • ', 230 | 'strikethrough': '
  • ', 231 | 'superscript': '
  • ', 232 | 'subscript': '
  • ', 233 | 'anchor': '
  • ', 234 | 'image': '
  • ', 235 | 'header1': '
  • ', 236 | 'header2': '
  • ', 237 | 'quote': '
  • ', 238 | 'orderedlist': '
  • ', 239 | 'unorderedlist': '
  • ', 240 | 'pre': '
  • ' 241 | }; 242 | return buttonTemplates[btnType] || false; 243 | }, 244 | 245 | // TODO: break method 246 | getButtonLabels: function (buttonLabelType) { 247 | var customButtonLabels, 248 | attrname, 249 | buttonLabels = { 250 | 'bold': 'B', 251 | 'italic' : 'I', 252 | 'underline': 'U', 253 | 'superscript': 'x1', 254 | 'subscript': 'x1', 255 | 'anchor': '#', 256 | 'image': 'image', 257 | 'header1': 'H1', 258 | 'header2': 'H2', 259 | 'quote': '', 260 | 'orderedlist': '1.', 261 | 'unorderedlist': '', 262 | 'pre': '0101' 263 | }; 264 | if (buttonLabelType === 'fontawesome') { 265 | customButtonLabels = { 266 | 'bold': '', 267 | 'italic' : '', 268 | 'underline': '', 269 | 'superscript': '', 270 | 'subscript': '', 271 | 'anchor': '', 272 | 'image': '', 273 | 'quote': '', 274 | 'orderedlist': '', 275 | 'unorderedlist': '', 276 | 'pre': '' 277 | }; 278 | } else if (typeof buttonLabelType === 'object') { 279 | customButtonLabels = buttonLabelType; 280 | } 281 | if (typeof customButtonLabels === 'object') { 282 | for (attrname in customButtonLabels) { 283 | if (customButtonLabels.hasOwnProperty(attrname)) { 284 | buttonLabels[attrname] = customButtonLabels[attrname]; 285 | } 286 | } 287 | } 288 | return buttonLabels; 289 | }, 290 | 291 | //TODO: actionTemplate 292 | toolbarTemplate: function () { 293 | var btns = this.options.buttons, 294 | html = '' + 305 | '
    ' + 306 | ' ' + 307 | ' ×' + 308 | '
    '; 309 | return html; 310 | }, 311 | 312 | initToolbar: function () { 313 | if (this.toolbar) { 314 | return this; 315 | } 316 | this.toolbar = this.createToolbar(); 317 | this.keepToolbarAlive = false; 318 | this.anchorForm = this.toolbar.querySelector('.medium-editor-toolbar-form-anchor'); 319 | this.anchorInput = this.anchorForm.querySelector('input'); 320 | this.toolbarActions = this.toolbar.querySelector('.medium-editor-toolbar-actions'); 321 | return this; 322 | }, 323 | 324 | createToolbar: function () { 325 | var toolbar = document.createElement('div'); 326 | toolbar.id = 'medium-editor-toolbar-' + this.id; 327 | toolbar.className = 'medium-editor-toolbar'; 328 | toolbar.innerHTML = this.toolbarTemplate(); 329 | document.getElementsByTagName('body')[0].appendChild(toolbar); 330 | return toolbar; 331 | }, 332 | 333 | bindSelect: function () { 334 | var self = this, 335 | timer = '', 336 | i; 337 | this.checkSelectionWrapper = function () { 338 | clearTimeout(timer); 339 | timer = setTimeout(function () { 340 | self.checkSelection(); 341 | }, self.options.delay); 342 | }; 343 | 344 | document.documentElement.addEventListener('mouseup', this.checkSelectionWrapper); 345 | 346 | for (i = 0; i < this.elements.length; i += 1) { 347 | this.elements[i].addEventListener('keyup', this.checkSelectionWrapper); 348 | this.elements[i].addEventListener('blur', this.checkSelectionWrapper); 349 | } 350 | return this; 351 | }, 352 | 353 | checkSelection: function () { 354 | var newSelection, 355 | selectionElement; 356 | if (this.keepToolbarAlive !== true && !this.options.disableToolbar) { 357 | newSelection = window.getSelection(); 358 | if (newSelection.toString().trim() === '' || 359 | (this.options.allowMultiParagraphSelection === false && this.hasMultiParagraphs())) { 360 | this.hideToolbarActions(); 361 | } else { 362 | selectionElement = this.getSelectionElement(); 363 | if (!selectionElement || selectionElement.getAttribute('data-disable-toolbar')) { 364 | this.hideToolbarActions(); 365 | } else { 366 | this.checkSelectionElement(newSelection, selectionElement); 367 | } 368 | } 369 | } 370 | return this; 371 | }, 372 | 373 | hasMultiParagraphs: function () { 374 | var selectionHtml = getSelectionHtml().replace(/<[\S]+><\/[\S]+>/gim, ''), 375 | hasMultiParagraphs = selectionHtml.match(/<(p|h[0-6]|blockquote)>([\s\S]*?)<\/(p|h[0-6]|blockquote)>/g); 376 | 377 | return (hasMultiParagraphs ? hasMultiParagraphs.length : 0); 378 | }, 379 | 380 | checkSelectionElement: function (newSelection, selectionElement) { 381 | var i; 382 | this.selection = newSelection; 383 | this.selectionRange = this.selection.getRangeAt(0); 384 | for (i = 0; i < this.elements.length; i += 1) { 385 | if (this.elements[i] === selectionElement) { 386 | this.setToolbarButtonStates() 387 | .setToolbarPosition() 388 | .showToolbarActions(); 389 | return; 390 | } 391 | } 392 | this.hideToolbarActions(); 393 | }, 394 | 395 | getSelectionElement: function () { 396 | var selection = window.getSelection(), 397 | range = selection.getRangeAt(0), 398 | current = range.commonAncestorContainer, 399 | parent = current.parentNode, 400 | result, 401 | getMediumElement = function(e) { 402 | var parent = e; 403 | try { 404 | while (!parent.getAttribute('data-medium-element')) { 405 | parent = parent.parentNode; 406 | } 407 | } catch (errb) { 408 | return false; 409 | } 410 | return parent; 411 | }; 412 | // First try on current node 413 | try { 414 | if (current.getAttribute('data-medium-element')) { 415 | result = current; 416 | } else { 417 | result = getMediumElement(parent); 418 | } 419 | // If not search in the parent nodes. 420 | } catch (err) { 421 | result = getMediumElement(parent); 422 | } 423 | return result; 424 | }, 425 | 426 | setToolbarPosition: function () { 427 | var buttonHeight = 50, 428 | selection = window.getSelection(), 429 | range = selection.getRangeAt(0), 430 | boundary = range.getBoundingClientRect(), 431 | defaultLeft = (this.options.diffLeft) - (this.toolbar.offsetWidth / 2), 432 | middleBoundary = (boundary.left + boundary.right) / 2, 433 | halfOffsetWidth = this.toolbar.offsetWidth / 2; 434 | if (boundary.top < buttonHeight) { 435 | this.toolbar.classList.add('medium-toolbar-arrow-over'); 436 | this.toolbar.classList.remove('medium-toolbar-arrow-under'); 437 | this.toolbar.style.top = buttonHeight + boundary.bottom - this.options.diffTop + window.pageYOffset - this.toolbar.offsetHeight + 'px'; 438 | } else { 439 | this.toolbar.classList.add('medium-toolbar-arrow-under'); 440 | this.toolbar.classList.remove('medium-toolbar-arrow-over'); 441 | this.toolbar.style.top = boundary.top + this.options.diffTop + window.pageYOffset - this.toolbar.offsetHeight + 'px'; 442 | } 443 | if (middleBoundary < halfOffsetWidth) { 444 | this.toolbar.style.left = defaultLeft + halfOffsetWidth + 'px'; 445 | } else if ((window.innerWidth - middleBoundary) < halfOffsetWidth) { 446 | this.toolbar.style.left = window.innerWidth + defaultLeft - halfOffsetWidth + 'px'; 447 | } else { 448 | this.toolbar.style.left = defaultLeft + middleBoundary + 'px'; 449 | } 450 | return this; 451 | }, 452 | 453 | setToolbarButtonStates: function () { 454 | var buttons = this.toolbarActions.querySelectorAll('button'), 455 | i; 456 | for (i = 0; i < buttons.length; i += 1) { 457 | buttons[i].classList.remove('medium-editor-button-active'); 458 | } 459 | this.checkActiveButtons(); 460 | return this; 461 | }, 462 | 463 | checkActiveButtons: function () { 464 | var parentNode = this.selection.anchorNode; 465 | if (!parentNode.tagName) { 466 | parentNode = this.selection.anchorNode.parentNode; 467 | } 468 | while (parentNode.tagName !== undefined && this.parentElements.indexOf(parentNode.tagName) === -1) { 469 | this.activateButton(parentNode.tagName.toLowerCase()); 470 | parentNode = parentNode.parentNode; 471 | } 472 | }, 473 | 474 | activateButton: function (tag) { 475 | var el = this.toolbar.querySelector('[data-element="' + tag + '"]'); 476 | if (el !== null && el.className.indexOf('medium-editor-button-active') === -1) { 477 | el.className += ' medium-editor-button-active'; 478 | } 479 | }, 480 | 481 | bindButtons: function () { 482 | var buttons = this.toolbar.querySelectorAll('button'), 483 | i, 484 | self = this, 485 | triggerAction = function (e) { 486 | e.preventDefault(); 487 | e.stopPropagation(); 488 | if (self.selection === undefined) { 489 | self.checkSelection(); 490 | } 491 | if (this.className.indexOf('medium-editor-button-active') > -1) { 492 | this.classList.remove('medium-editor-button-active'); 493 | } else { 494 | this.className += ' medium-editor-button-active'; 495 | } 496 | self.execAction(this.getAttribute('data-action'), e); 497 | }; 498 | for (i = 0; i < buttons.length; i += 1) { 499 | buttons[i].addEventListener('click', triggerAction); 500 | } 501 | this.setFirstAndLastItems(buttons); 502 | return this; 503 | }, 504 | 505 | setFirstAndLastItems: function (buttons) { 506 | buttons[0].className += ' medium-editor-button-first'; 507 | buttons[buttons.length - 1].className += ' medium-editor-button-last'; 508 | return this; 509 | }, 510 | 511 | execAction: function (action, e) { 512 | if (action.indexOf('append-') > -1) { 513 | this.execFormatBlock(action.replace('append-', '')); 514 | this.setToolbarPosition(); 515 | this.setToolbarButtonStates(); 516 | } else if (action === 'anchor') { 517 | this.triggerAnchorAction(e); 518 | } else if (action === 'image') { 519 | document.execCommand('insertImage', false, window.getSelection()); 520 | } else { 521 | document.execCommand(action, false, null); 522 | this.setToolbarPosition(); 523 | } 524 | }, 525 | 526 | triggerAnchorAction: function () { 527 | if (this.selection.anchorNode.parentNode.tagName.toLowerCase() === 'a') { 528 | document.execCommand('unlink', false, null); 529 | } else { 530 | if (this.anchorForm.style.display === 'block') { 531 | this.showToolbarActions(); 532 | } else { 533 | this.showAnchorForm(); 534 | } 535 | } 536 | return this; 537 | }, 538 | 539 | execFormatBlock: function (el) { 540 | var selectionData = this.getSelectionData(this.selection.anchorNode); 541 | // FF handles blockquote differently on formatBlock 542 | // allowing nesting, we need to use outdent 543 | // https://developer.mozilla.org/en-US/docs/Rich-Text_Editing_in_Mozilla 544 | if (el === 'blockquote' && selectionData.el && 545 | selectionData.el.parentNode.tagName.toLowerCase() === 'blockquote') { 546 | return document.execCommand('outdent', false, null); 547 | } 548 | if (selectionData.tagName === el) { 549 | el = 'p'; 550 | } 551 | return document.execCommand('formatBlock', false, el); 552 | }, 553 | 554 | getSelectionData: function (el) { 555 | var tagName; 556 | 557 | if (el && el.tagName) { 558 | tagName = el.tagName.toLowerCase(); 559 | } 560 | 561 | while (el && this.parentElements.indexOf(tagName) === -1) { 562 | el = el.parentNode; 563 | if (el && el.tagName) { 564 | tagName = el.tagName.toLowerCase(); 565 | } 566 | } 567 | 568 | return { 569 | el: el, 570 | tagName: tagName 571 | }; 572 | }, 573 | 574 | getFirstChild: function (el) { 575 | var firstChild = el.firstChild; 576 | while (firstChild !== null && firstChild.nodeType !== 1) { 577 | firstChild = firstChild.nextSibling; 578 | } 579 | return firstChild; 580 | }, 581 | 582 | bindElementToolbarEvents: function (el) { 583 | var self = this; 584 | el.addEventListener('mouseup', function () { 585 | self.checkSelection(); 586 | }); 587 | el.addEventListener('keyup', function () { 588 | self.checkSelection(); 589 | }); 590 | }, 591 | 592 | hideToolbarActions: function () { 593 | this.keepToolbarAlive = false; 594 | this.toolbar.classList.remove('medium-editor-toolbar-active'); 595 | }, 596 | 597 | showToolbarActions: function () { 598 | var self = this, 599 | timer; 600 | this.anchorForm.style.display = 'none'; 601 | this.toolbarActions.style.display = 'block'; 602 | this.keepToolbarAlive = false; 603 | clearTimeout(timer); 604 | timer = setTimeout(function() { 605 | if (!self.toolbar.classList.contains('medium-editor-toolbar-active')) { 606 | self.toolbar.classList.add('medium-editor-toolbar-active'); 607 | } 608 | }, 100); 609 | }, 610 | 611 | showAnchorForm: function () { 612 | this.toolbarActions.style.display = 'none'; 613 | this.savedSelection = saveSelection(); 614 | this.anchorForm.style.display = 'block'; 615 | this.keepToolbarAlive = true; 616 | this.anchorInput.focus(); 617 | this.anchorInput.value = ''; 618 | }, 619 | 620 | bindAnchorForm: function () { 621 | var linkCancel = this.anchorForm.querySelector('a'), 622 | self = this; 623 | this.anchorForm.addEventListener('click', function (e) { 624 | e.stopPropagation(); 625 | }); 626 | this.anchorInput.addEventListener('keyup', function (e) { 627 | if (e.keyCode === 13) { 628 | e.preventDefault(); 629 | self.createLink(this); 630 | } 631 | }); 632 | this.anchorInput.addEventListener('blur', function () { 633 | self.keepToolbarAlive = false; 634 | self.checkSelection(); 635 | }); 636 | linkCancel.addEventListener('click', function (e) { 637 | e.preventDefault(); 638 | self.showToolbarActions(); 639 | restoreSelection(self.savedSelection); 640 | }); 641 | return this; 642 | }, 643 | 644 | setTargetBlank: function () { 645 | var el = getSelectionStart(), 646 | i; 647 | if (el.tagName.toLowerCase() === 'a') { 648 | el.target = '_blank'; 649 | } else { 650 | el = el.getElementsByTagName('a'); 651 | for (i = 0; i < el.length; i += 1) { 652 | el[i].target = '_blank'; 653 | } 654 | } 655 | }, 656 | 657 | createLink: function (input) { 658 | restoreSelection(this.savedSelection); 659 | document.execCommand('createLink', false, input.value); 660 | if (this.options.targetBlank) { 661 | this.setTargetBlank(); 662 | } 663 | this.showToolbarActions(); 664 | input.value = ''; 665 | }, 666 | 667 | bindWindowActions: function () { 668 | var timerResize, 669 | self = this; 670 | this.windowResizeHandler = function () { 671 | clearTimeout(timerResize); 672 | timerResize = setTimeout(function () { 673 | if (self.toolbar.classList.contains('medium-editor-toolbar-active')) { 674 | self.setToolbarPosition(); 675 | } 676 | }, 100); 677 | }; 678 | window.addEventListener('resize', this.windowResizeHandler); 679 | return this; 680 | }, 681 | 682 | activate: function () { 683 | var i; 684 | if (this.isActive) { 685 | return; 686 | } 687 | 688 | if (this.toolbar !== undefined) { 689 | this.toolbar.style.display = 'block'; 690 | } 691 | 692 | this.isActive = true; 693 | for (i = 0; i < this.elements.length; i += 1) { 694 | this.elements[i].setAttribute('contentEditable', true); 695 | } 696 | 697 | this.bindWindowActions() 698 | .bindSelect(); 699 | }, 700 | 701 | deactivate: function () { 702 | var i; 703 | if (!this.isActive) { 704 | return; 705 | } 706 | this.isActive = false; 707 | 708 | if (this.toolbar !== undefined) { 709 | this.toolbar.style.display = 'none'; 710 | } 711 | 712 | document.documentElement.removeEventListener('mouseup', this.checkSelectionWrapper); 713 | window.removeEventListener('resize', this.windowResizeHandler); 714 | 715 | for (i = 0; i < this.elements.length; i += 1) { 716 | this.elements[i].removeEventListener('keyup', this.checkSelectionWrapper); 717 | this.elements[i].removeEventListener('blur', this.checkSelectionWrapper); 718 | this.elements[i].removeAttribute('contentEditable'); 719 | } 720 | }, 721 | 722 | bindPaste: function () { 723 | if (!this.options.forcePlainText) { 724 | return this; 725 | } 726 | var i, 727 | self = this, 728 | pasteWrapper = function (e) { 729 | var paragraphs, 730 | html = '', 731 | p; 732 | this.classList.remove('medium-editor-placeholder'); 733 | if (e.clipboardData && e.clipboardData.getData) { 734 | e.preventDefault(); 735 | if (!self.options.disableReturn) { 736 | paragraphs = e.clipboardData.getData('text/plain').split(/[\r\n]/g); 737 | for (p = 0; p < paragraphs.length; p += 1) { 738 | if (paragraphs[p] !== '') { 739 | html += '

    ' + paragraphs[p] + '

    '; 740 | } 741 | } 742 | document.execCommand('insertHTML', false, html); 743 | } else { 744 | document.execCommand('insertHTML', false, e.clipboardData.getData('text/plain')); 745 | } 746 | } 747 | }; 748 | for (i = 0; i < this.elements.length; i += 1) { 749 | this.elements[i].addEventListener('paste', pasteWrapper); 750 | } 751 | return this; 752 | }, 753 | 754 | setPlaceholders: function () { 755 | var i, 756 | activatePlaceholder = function (el) { 757 | if (el.textContent.replace(/^\s+|\s+$/g, '') === '') { 758 | el.classList.add('medium-editor-placeholder'); 759 | } 760 | }, 761 | placeholderWrapper = function (e) { 762 | this.classList.remove('medium-editor-placeholder'); 763 | if (e.type !== 'keypress') { 764 | activatePlaceholder(this); 765 | } 766 | }; 767 | for (i = 0; i < this.elements.length; i += 1) { 768 | activatePlaceholder(this.elements[i]); 769 | this.elements[i].addEventListener('blur', placeholderWrapper); 770 | this.elements[i].addEventListener('keypress', placeholderWrapper); 771 | } 772 | return this; 773 | } 774 | 775 | }; 776 | 777 | }(window, document)); --------------------------------------------------------------------------------