Merge branch 'dev' into doucovanineratovice.cz
@@ -17,34 +17,42 @@ class FileManager
|
|||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'image':
|
case 'image':
|
||||||
|
|
||||||
// try to check if file have thumbnail
|
$url = Template::thumbnail($file->filename);
|
||||||
if (file_exists(config('app.thumbnail_url') . '/' . $file->filename)) {
|
|
||||||
$url = config('app.thumbnail_url') . '/' . $file->filename;
|
|
||||||
} else {
|
|
||||||
$url = config('app.upload_url') . '/' . $file->filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
return '<img src="' . $url . '" alt="' . $file->description . '" />';
|
return '<img src="' . $url . '" alt="' . $file->description . '" />';
|
||||||
break;
|
break;
|
||||||
case 'text':
|
case 'text':
|
||||||
return '<i class="fa fa-2x fa-file-text-o"></i>';
|
return self::getIcon($file, 'fa-file-text-o');
|
||||||
break;
|
break;
|
||||||
case 'application':
|
case 'application':
|
||||||
switch ($subtype) {
|
switch ($subtype) {
|
||||||
case 'pdf':
|
case 'pdf':
|
||||||
return '<i class="fa fa-2x fa-file-pdf-o"></i>';
|
return self::getIcon($file, 'fa-file-pdf-o');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return '<i class="fa fa-2x fa-newspaper-o"></i>';
|
return self::getIcon($file, 'fa-newspaper-o');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return '<i class="fa fa-2x fa-question"></i>';
|
return self::getIcon($file, 'fa-question');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut for displaying icons
|
||||||
|
*
|
||||||
|
* @param $file
|
||||||
|
* @param $icon
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected static function getIcon($file, $icon)
|
||||||
|
{
|
||||||
|
return '<p><i class="fa fa-2x ' . $icon . '"></i><br /><span>' . e(str_limit($file->original_filename, 15)) . '</span></p>';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@@ -83,7 +91,6 @@ class FileManager
|
|||||||
return '<img src="' . $url . '" alt="' . $file->description . '" />';
|
return '<img src="' . $url . '" alt="' . $file->description . '" />';
|
||||||
break;
|
break;
|
||||||
case 'text':
|
case 'text':
|
||||||
|
|
||||||
$string = '<pre><code>';
|
$string = '<pre><code>';
|
||||||
$string .= htmlspecialchars(file_get_contents($path));
|
$string .= htmlspecialchars(file_get_contents($path));
|
||||||
$string .= '</pre></code>';
|
$string .= '</pre></code>';
|
||||||
@@ -91,15 +98,8 @@ class FileManager
|
|||||||
return $string;
|
return $string;
|
||||||
break;
|
break;
|
||||||
case 'application':
|
case 'application':
|
||||||
switch ($subtype) {
|
return '<iframe src = "'.asset('resources/assets/admin/js/viewerJs/').'/#'.Template::upload($file->filename).'" style="width: 100%; height: 50em" allowfullscreen webkitallowfullscreen></iframe>';
|
||||||
case 'pdf':
|
break;
|
||||||
return '<i class="fa fa-file-pdf-o"></i>';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return '<i class="fa fa-newspaper-o"></i>';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
return self::getPreview($file);
|
return self::getPreview($file);
|
||||||
break;
|
break;
|
||||||
@@ -119,19 +119,12 @@ class FileManager
|
|||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'text':
|
case 'text':
|
||||||
|
return [trans('admin/fileManager.encoding') => mb_detect_encoding(file_get_contents($path))];
|
||||||
return [
|
|
||||||
trans('admin/fileManager.encoding') => mb_detect_encoding(file_get_contents($path))
|
|
||||||
];
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'image':
|
case 'image':
|
||||||
list ($width, $height) = getimagesize($path);
|
list ($width, $height) = getimagesize($path);
|
||||||
|
return [trans('admin/fileManager.resolution') => $height . ' x ' . $width,];
|
||||||
return [
|
|
||||||
trans('admin/fileManager.resolution') => $height . ' x ' . $width,
|
|
||||||
];
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,18 @@ class Template
|
|||||||
return config('app.upload_url') . '/' . $filename;
|
return config('app.upload_url') . '/' . $filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function thumbnail($filename)
|
||||||
|
{
|
||||||
|
// try to check if file have thumbnail
|
||||||
|
if (file_exists(config('app.thumbnail_path') . '/' . $filename)) {
|
||||||
|
$url = config('app.thumbnail_url') . '/' . $filename;
|
||||||
|
} else {
|
||||||
|
$url = self::upload($filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get path to given asset
|
* Get path to given asset
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -147,7 +147,11 @@ class EditContent extends Controller
|
|||||||
$request->url = Str::slug($request->url);
|
$request->url = Str::slug($request->url);
|
||||||
$request->parentPage = $request->parentPage ? $request->parentPage : null;
|
$request->parentPage = $request->parentPage ? $request->parentPage : null;
|
||||||
|
|
||||||
$request->titlePhotoFilename = $file ? $file['filename'] : null;
|
if (!$file) {
|
||||||
|
$request->titlePhotoFilename = empty($request->existingTitlePhoto) ? null : $request->existingTitlePhoto;
|
||||||
|
} else {
|
||||||
|
$request->titlePhotoFilename = $file['filename'];
|
||||||
|
}
|
||||||
|
|
||||||
// array of fields in database and fields from request
|
// array of fields in database and fields from request
|
||||||
$fields = [
|
$fields = [
|
||||||
|
|||||||
@@ -4,9 +4,13 @@ namespace App\Models;
|
|||||||
|
|
||||||
use App\Events\UploadFile;
|
use App\Events\UploadFile;
|
||||||
use App\Http\Requests\Request;
|
use App\Http\Requests\Request;
|
||||||
|
use Franzose\ClosureTable\Extensions\Str;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
|
use Illuminate\Support\Facades\File as FileFacade;
|
||||||
|
use Intervention\Image\Constraint;
|
||||||
|
use Intervention\Image\Facades\Image;
|
||||||
use Symfony\Component\HttpFoundation\File\File as SymphonyFile;
|
use Symfony\Component\HttpFoundation\File\File as SymphonyFile;
|
||||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||||
|
|
||||||
@@ -63,6 +67,12 @@ class File extends Model
|
|||||||
// save file into physical location (local FS)
|
// save file into physical location (local FS)
|
||||||
$uploadedFile = $file->move($destination, $filename);
|
$uploadedFile = $file->move($destination, $filename);
|
||||||
|
|
||||||
|
// is uploaded file an image?
|
||||||
|
if (Str::startsWith($uploadedFile->getMimeType(), 'image')) {
|
||||||
|
// yes, create thumbnail
|
||||||
|
$this->createThumbnail($uploadedFile);
|
||||||
|
}
|
||||||
|
|
||||||
// insert record into database
|
// insert record into database
|
||||||
$id = $this->saveIntoDatabase($uploadedFile, $request, $file->getClientOriginalName());
|
$id = $this->saveIntoDatabase($uploadedFile, $request, $file->getClientOriginalName());
|
||||||
|
|
||||||
@@ -118,4 +128,29 @@ class File extends Model
|
|||||||
|
|
||||||
return $newFile->id;
|
return $newFile->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create thumbnail of given image
|
||||||
|
*
|
||||||
|
* @param SymphonyFile $file
|
||||||
|
*/
|
||||||
|
private function createThumbnail(SymphonyFile $file)
|
||||||
|
{
|
||||||
|
// does thumbnail directory exist?
|
||||||
|
if (!is_dir(config('app.thumbnail_path'))) {
|
||||||
|
FileFacade::makeDirectory(config('app.thumbnail_path'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// get image instance
|
||||||
|
$image = Image::make(config('app.upload_path') . DIRECTORY_SEPARATOR . $file->getFilename());
|
||||||
|
|
||||||
|
// resize image and keep aspect ration
|
||||||
|
$image->resize(env('THUMBNAIL_WIDTH', 300), null, function (Constraint $constraint) {
|
||||||
|
$constraint->aspectRatio();
|
||||||
|
$constraint->upsize();
|
||||||
|
});
|
||||||
|
|
||||||
|
// save thumbnail with lower quality
|
||||||
|
$image->save(config('app.thumbnail_path') . DIRECTORY_SEPARATOR . $file->getFilename(), 75);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ class GlobalViewDataProvider extends ServiceProvider
|
|||||||
return preg_replace($pattern, $code, $view);
|
return preg_replace($pattern, $code, $view);
|
||||||
});
|
});
|
||||||
|
|
||||||
// shortcut for loading uploaded images
|
// shortcut for loading uploaded files
|
||||||
Blade::extend(function ($view) {
|
Blade::extend(function ($view) {
|
||||||
$pattern = $this->createPattern('upload');
|
$pattern = $this->createPattern('upload');
|
||||||
$code = '<?php echo \App\Helpers\Template::upload($2); ?>';
|
$code = '<?php echo \App\Helpers\Template::upload($2); ?>';
|
||||||
@@ -73,6 +73,14 @@ class GlobalViewDataProvider extends ServiceProvider
|
|||||||
return preg_replace($pattern, $code, $view);
|
return preg_replace($pattern, $code, $view);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// shortcut for loading thumbnails of uploaded images
|
||||||
|
Blade::extend(function ($view) {
|
||||||
|
$pattern = $this->createPattern('upload');
|
||||||
|
$code = '<?php echo \App\Helpers\Template::thumbnail($2); ?>';
|
||||||
|
|
||||||
|
return preg_replace($pattern, $code, $view);
|
||||||
|
});
|
||||||
|
|
||||||
// shortcut for displaying Gravatar
|
// shortcut for displaying Gravatar
|
||||||
Blade::extend(function ($view) {
|
Blade::extend(function ($view) {
|
||||||
$pattern = $this->createPattern('gravatar');
|
$pattern = $this->createPattern('gravatar');
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
"pingpong/menus": "^2.2",
|
"pingpong/menus": "^2.2",
|
||||||
"watson/sitemap": "^2.0",
|
"watson/sitemap": "^2.0",
|
||||||
"mcamara/laravel-localization": "^1.1",
|
"mcamara/laravel-localization": "^1.1",
|
||||||
"franzose/closure-table": "^4.1"
|
"franzose/closure-table": "^4.1",
|
||||||
|
"intervention/image": "^2.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fzaninotto/faker": "~1.4",
|
"fzaninotto/faker": "~1.4",
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"hash": "34fec17afe62b99ed90d0f72d3536a7b",
|
"hash": "066078c74cc6b8d99111c0e9b4b385d6",
|
||||||
"content-hash": "58f7e332f9be3faf1f8d481191cf1bb1",
|
"content-hash": "1574402e32047ac8589b6fc08d6d744c",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "classpreloader/classpreloader",
|
"name": "classpreloader/classpreloader",
|
||||||
@@ -704,6 +704,133 @@
|
|||||||
],
|
],
|
||||||
"time": "2016-07-08 08:19:46"
|
"time": "2016-07-08 08:19:46"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "guzzlehttp/psr7",
|
||||||
|
"version": "dev-master",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/guzzle/psr7.git",
|
||||||
|
"reference": "64862e854f876bc5aee2996cab2f552db8586065"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/guzzle/psr7/zipball/64862e854f876bc5aee2996cab2f552db8586065",
|
||||||
|
"reference": "64862e854f876bc5aee2996cab2f552db8586065",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.4.0",
|
||||||
|
"psr/http-message": "~1.0"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"psr/http-message-implementation": "1.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "~4.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.4-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"GuzzleHttp\\Psr7\\": "src/"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/functions_include.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Michael Dowling",
|
||||||
|
"email": "mtdowling@gmail.com",
|
||||||
|
"homepage": "https://github.com/mtdowling"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tobias Schultze",
|
||||||
|
"homepage": "https://github.com/Tobion"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PSR-7 message implementation that also provides common utility methods",
|
||||||
|
"keywords": [
|
||||||
|
"http",
|
||||||
|
"message",
|
||||||
|
"request",
|
||||||
|
"response",
|
||||||
|
"stream",
|
||||||
|
"uri",
|
||||||
|
"url"
|
||||||
|
],
|
||||||
|
"time": "2016-08-03 09:33:34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "intervention/image",
|
||||||
|
"version": "dev-master",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Intervention/image.git",
|
||||||
|
"reference": "4064a980324f6c3bfa2bd981dfb247afa705ec3c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Intervention/image/zipball/4064a980324f6c3bfa2bd981dfb247afa705ec3c",
|
||||||
|
"reference": "4064a980324f6c3bfa2bd981dfb247afa705ec3c",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-fileinfo": "*",
|
||||||
|
"guzzlehttp/psr7": "~1.1",
|
||||||
|
"php": ">=5.4.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "~0.9.2",
|
||||||
|
"phpunit/phpunit": "3.*"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-gd": "to use GD library based image processing.",
|
||||||
|
"ext-imagick": "to use Imagick based image processing.",
|
||||||
|
"intervention/imagecache": "Caching extension for the Intervention Image library"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "2.3-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Intervention\\Image\\": "src/Intervention/Image"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Oliver Vogel",
|
||||||
|
"email": "oliver@olivervogel.net",
|
||||||
|
"homepage": "http://olivervogel.net/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Image handling and manipulation library with support for Laravel integration",
|
||||||
|
"homepage": "http://image.intervention.io/",
|
||||||
|
"keywords": [
|
||||||
|
"gd",
|
||||||
|
"image",
|
||||||
|
"imagick",
|
||||||
|
"laravel",
|
||||||
|
"thumbnail",
|
||||||
|
"watermark"
|
||||||
|
],
|
||||||
|
"time": "2016-09-01 17:04:03"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "jakub-onderka/php-console-color",
|
"name": "jakub-onderka/php-console-color",
|
||||||
"version": "0.1",
|
"version": "0.1",
|
||||||
@@ -1632,6 +1759,56 @@
|
|||||||
"description": "Support Component of Pingpong Sky Package",
|
"description": "Support Component of Pingpong Sky Package",
|
||||||
"time": "2016-01-07 08:23:04"
|
"time": "2016-01-07 08:23:04"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "psr/http-message",
|
||||||
|
"version": "dev-master",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-fig/http-message.git",
|
||||||
|
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||||
|
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Psr\\Http\\Message\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "PHP-FIG",
|
||||||
|
"homepage": "http://www.php-fig.org/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Common interface for HTTP messages",
|
||||||
|
"homepage": "https://github.com/php-fig/http-message",
|
||||||
|
"keywords": [
|
||||||
|
"http",
|
||||||
|
"http-message",
|
||||||
|
"psr",
|
||||||
|
"psr-7",
|
||||||
|
"request",
|
||||||
|
"response"
|
||||||
|
],
|
||||||
|
"time": "2016-08-06 14:39:51"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/log",
|
"name": "psr/log",
|
||||||
"version": "dev-master",
|
"version": "dev-master",
|
||||||
|
|||||||
@@ -17,4 +17,5 @@
|
|||||||
!services.php
|
!services.php
|
||||||
!session.php
|
!session.php
|
||||||
!sitemap.php
|
!sitemap.php
|
||||||
|
!image.php
|
||||||
!view.php
|
!view.php
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ return [
|
|||||||
App\Providers\SubmodulesManager::class,
|
App\Providers\SubmodulesManager::class,
|
||||||
Franzose\ClosureTable\ClosureTableServiceProvider::class,
|
Franzose\ClosureTable\ClosureTableServiceProvider::class,
|
||||||
\Watson\Sitemap\SitemapServiceProvider::class,
|
\Watson\Sitemap\SitemapServiceProvider::class,
|
||||||
|
Intervention\Image\ImageServiceProvider::class,
|
||||||
/*
|
/*
|
||||||
* Application Service Providers...
|
* Application Service Providers...
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return array(
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Image Driver
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Intervention Image supports "GD Library" and "Imagick" to process images
|
||||||
|
| internally. You may choose one of them according to your PHP
|
||||||
|
| configuration. By default PHP's "GD Library" implementation is used.
|
||||||
|
|
|
||||||
|
| Supported: "gd", "imagick"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'driver' => 'gd'
|
||||||
|
|
||||||
|
);
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class RemoveOnUpdateCurrentTimestampFromContentsUpdatedAt extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
DB::statement('ALTER TABLE `contents`
|
||||||
|
CHANGE `updated_at` `updated_at` timestamp NULL AFTER `created_at`;');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14390,4 +14390,21 @@ img {
|
|||||||
|
|
||||||
.card .card-header .title small {
|
.card .card-header .title small {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
.card.file-preview .card-block {
|
||||||
|
padding: 0;
|
||||||
|
height: 6em;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.file-preview .card-block p {
|
||||||
|
padding: 1em 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.file-preview .card-footer {
|
||||||
|
padding: 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.file-preview .card-block img {
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,577 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||||
|
/* Copyright 2012 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
/* globals VBArray, PDFJS */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Initializing PDFJS global object here, it case if we need to change/disable
|
||||||
|
// some PDF.js features, e.g. range requests
|
||||||
|
if (typeof PDFJS === 'undefined') {
|
||||||
|
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checking if the typed arrays are supported
|
||||||
|
// Support: iOS<6.0 (subarray), IE<10, Android<4.0
|
||||||
|
(function checkTypedArrayCompatibility() {
|
||||||
|
if (typeof Uint8Array !== 'undefined') {
|
||||||
|
// Support: iOS<6.0
|
||||||
|
if (typeof Uint8Array.prototype.subarray === 'undefined') {
|
||||||
|
Uint8Array.prototype.subarray = function subarray(start, end) {
|
||||||
|
return new Uint8Array(this.slice(start, end));
|
||||||
|
};
|
||||||
|
Float32Array.prototype.subarray = function subarray(start, end) {
|
||||||
|
return new Float32Array(this.slice(start, end));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support: Android<4.1
|
||||||
|
if (typeof Float64Array === 'undefined') {
|
||||||
|
window.Float64Array = Float32Array;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function subarray(start, end) {
|
||||||
|
return new TypedArray(this.slice(start, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setArrayOffset(array, offset) {
|
||||||
|
if (arguments.length < 2) {
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
for (var i = 0, n = array.length; i < n; ++i, ++offset) {
|
||||||
|
this[offset] = array[i] & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function TypedArray(arg1) {
|
||||||
|
var result, i, n;
|
||||||
|
if (typeof arg1 === 'number') {
|
||||||
|
result = [];
|
||||||
|
for (i = 0; i < arg1; ++i) {
|
||||||
|
result[i] = 0;
|
||||||
|
}
|
||||||
|
} else if ('slice' in arg1) {
|
||||||
|
result = arg1.slice(0);
|
||||||
|
} else {
|
||||||
|
result = [];
|
||||||
|
for (i = 0, n = arg1.length; i < n; ++i) {
|
||||||
|
result[i] = arg1[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.subarray = subarray;
|
||||||
|
result.buffer = result;
|
||||||
|
result.byteLength = result.length;
|
||||||
|
result.set = setArrayOffset;
|
||||||
|
|
||||||
|
if (typeof arg1 === 'object' && arg1.buffer) {
|
||||||
|
result.buffer = arg1.buffer;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.Uint8Array = TypedArray;
|
||||||
|
window.Int8Array = TypedArray;
|
||||||
|
|
||||||
|
// we don't need support for set, byteLength for 32-bit array
|
||||||
|
// so we can use the TypedArray as well
|
||||||
|
window.Uint32Array = TypedArray;
|
||||||
|
window.Int32Array = TypedArray;
|
||||||
|
window.Uint16Array = TypedArray;
|
||||||
|
window.Float32Array = TypedArray;
|
||||||
|
window.Float64Array = TypedArray;
|
||||||
|
})();
|
||||||
|
|
||||||
|
// URL = URL || webkitURL
|
||||||
|
// Support: Safari<7, Android 4.2+
|
||||||
|
(function normalizeURLObject() {
|
||||||
|
if (!window.URL) {
|
||||||
|
window.URL = window.webkitURL;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Object.defineProperty()?
|
||||||
|
// Support: Android<4.0, Safari<5.1
|
||||||
|
(function checkObjectDefinePropertyCompatibility() {
|
||||||
|
if (typeof Object.defineProperty !== 'undefined') {
|
||||||
|
var definePropertyPossible = true;
|
||||||
|
try {
|
||||||
|
// some browsers (e.g. safari) cannot use defineProperty() on DOM objects
|
||||||
|
// and thus the native version is not sufficient
|
||||||
|
Object.defineProperty(new Image(), 'id', { value: 'test' });
|
||||||
|
// ... another test for android gb browser for non-DOM objects
|
||||||
|
var Test = function Test() {};
|
||||||
|
Test.prototype = { get id() { } };
|
||||||
|
Object.defineProperty(new Test(), 'id',
|
||||||
|
{ value: '', configurable: true, enumerable: true, writable: false });
|
||||||
|
} catch (e) {
|
||||||
|
definePropertyPossible = false;
|
||||||
|
}
|
||||||
|
if (definePropertyPossible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty = function objectDefineProperty(obj, name, def) {
|
||||||
|
delete obj[name];
|
||||||
|
if ('get' in def) {
|
||||||
|
obj.__defineGetter__(name, def['get']);
|
||||||
|
}
|
||||||
|
if ('set' in def) {
|
||||||
|
obj.__defineSetter__(name, def['set']);
|
||||||
|
}
|
||||||
|
if ('value' in def) {
|
||||||
|
obj.__defineSetter__(name, function objectDefinePropertySetter(value) {
|
||||||
|
this.__defineGetter__(name, function objectDefinePropertyGetter() {
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
obj[name] = def.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
// No XMLHttpRequest#response?
|
||||||
|
// Support: IE<11, Android <4.0
|
||||||
|
(function checkXMLHttpRequestResponseCompatibility() {
|
||||||
|
var xhrPrototype = XMLHttpRequest.prototype;
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
if (!('overrideMimeType' in xhr)) {
|
||||||
|
// IE10 might have response, but not overrideMimeType
|
||||||
|
// Support: IE10
|
||||||
|
Object.defineProperty(xhrPrototype, 'overrideMimeType', {
|
||||||
|
value: function xmlHttpRequestOverrideMimeType(mimeType) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if ('responseType' in xhr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The worker will be using XHR, so we can save time and disable worker.
|
||||||
|
PDFJS.disableWorker = true;
|
||||||
|
|
||||||
|
Object.defineProperty(xhrPrototype, 'responseType', {
|
||||||
|
get: function xmlHttpRequestGetResponseType() {
|
||||||
|
return this._responseType || 'text';
|
||||||
|
},
|
||||||
|
set: function xmlHttpRequestSetResponseType(value) {
|
||||||
|
if (value === 'text' || value === 'arraybuffer') {
|
||||||
|
this._responseType = value;
|
||||||
|
if (value === 'arraybuffer' &&
|
||||||
|
typeof this.overrideMimeType === 'function') {
|
||||||
|
this.overrideMimeType('text/plain; charset=x-user-defined');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Support: IE9
|
||||||
|
if (typeof VBArray !== 'undefined') {
|
||||||
|
Object.defineProperty(xhrPrototype, 'response', {
|
||||||
|
get: function xmlHttpRequestResponseGet() {
|
||||||
|
if (this.responseType === 'arraybuffer') {
|
||||||
|
return new Uint8Array(new VBArray(this.responseBody).toArray());
|
||||||
|
} else {
|
||||||
|
return this.responseText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(xhrPrototype, 'response', {
|
||||||
|
get: function xmlHttpRequestResponseGet() {
|
||||||
|
if (this.responseType !== 'arraybuffer') {
|
||||||
|
return this.responseText;
|
||||||
|
}
|
||||||
|
var text = this.responseText;
|
||||||
|
var i, n = text.length;
|
||||||
|
var result = new Uint8Array(n);
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
result[i] = text.charCodeAt(i) & 0xFF;
|
||||||
|
}
|
||||||
|
return result.buffer;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
// window.btoa (base64 encode function) ?
|
||||||
|
// Support: IE<10
|
||||||
|
(function checkWindowBtoaCompatibility() {
|
||||||
|
if ('btoa' in window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var digits =
|
||||||
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||||
|
|
||||||
|
window.btoa = function windowBtoa(chars) {
|
||||||
|
var buffer = '';
|
||||||
|
var i, n;
|
||||||
|
for (i = 0, n = chars.length; i < n; i += 3) {
|
||||||
|
var b1 = chars.charCodeAt(i) & 0xFF;
|
||||||
|
var b2 = chars.charCodeAt(i + 1) & 0xFF;
|
||||||
|
var b3 = chars.charCodeAt(i + 2) & 0xFF;
|
||||||
|
var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
|
||||||
|
var d3 = i + 1 < n ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
|
||||||
|
var d4 = i + 2 < n ? (b3 & 0x3F) : 64;
|
||||||
|
buffer += (digits.charAt(d1) + digits.charAt(d2) +
|
||||||
|
digits.charAt(d3) + digits.charAt(d4));
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
// window.atob (base64 encode function)?
|
||||||
|
// Support: IE<10
|
||||||
|
(function checkWindowAtobCompatibility() {
|
||||||
|
if ('atob' in window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/davidchambers/Base64.js
|
||||||
|
var digits =
|
||||||
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||||
|
window.atob = function (input) {
|
||||||
|
input = input.replace(/=+$/, '');
|
||||||
|
if (input.length % 4 === 1) {
|
||||||
|
throw new Error('bad atob input');
|
||||||
|
}
|
||||||
|
for (
|
||||||
|
// initialize result and counters
|
||||||
|
var bc = 0, bs, buffer, idx = 0, output = '';
|
||||||
|
// get next character
|
||||||
|
buffer = input.charAt(idx++);
|
||||||
|
// character found in table?
|
||||||
|
// initialize bit storage and add its ascii value
|
||||||
|
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
|
||||||
|
// and if not first of each 4 characters,
|
||||||
|
// convert the first 8 bits to one ascii character
|
||||||
|
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
|
||||||
|
) {
|
||||||
|
// try to find character in table (0-63, not found => -1)
|
||||||
|
buffer = digits.indexOf(buffer);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Function.prototype.bind?
|
||||||
|
// Support: Android<4.0, iOS<6.0
|
||||||
|
(function checkFunctionPrototypeBindCompatibility() {
|
||||||
|
if (typeof Function.prototype.bind !== 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Function.prototype.bind = function functionPrototypeBind(obj) {
|
||||||
|
var fn = this, headArgs = Array.prototype.slice.call(arguments, 1);
|
||||||
|
var bound = function functionPrototypeBindBound() {
|
||||||
|
var args = headArgs.concat(Array.prototype.slice.call(arguments));
|
||||||
|
return fn.apply(obj, args);
|
||||||
|
};
|
||||||
|
return bound;
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
// HTMLElement dataset property
|
||||||
|
// Support: IE<11, Safari<5.1, Android<4.0
|
||||||
|
(function checkDatasetProperty() {
|
||||||
|
var div = document.createElement('div');
|
||||||
|
if ('dataset' in div) {
|
||||||
|
return; // dataset property exists
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(HTMLElement.prototype, 'dataset', {
|
||||||
|
get: function() {
|
||||||
|
if (this._dataset) {
|
||||||
|
return this._dataset;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dataset = {};
|
||||||
|
for (var j = 0, jj = this.attributes.length; j < jj; j++) {
|
||||||
|
var attribute = this.attributes[j];
|
||||||
|
if (attribute.name.substring(0, 5) !== 'data-') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var key = attribute.name.substring(5).replace(/\-([a-z])/g,
|
||||||
|
function(all, ch) {
|
||||||
|
return ch.toUpperCase();
|
||||||
|
});
|
||||||
|
dataset[key] = attribute.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(this, '_dataset', {
|
||||||
|
value: dataset,
|
||||||
|
writable: false,
|
||||||
|
enumerable: false
|
||||||
|
});
|
||||||
|
return dataset;
|
||||||
|
},
|
||||||
|
enumerable: true
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
// HTMLElement classList property
|
||||||
|
// Support: IE<10, Android<4.0, iOS<5.0
|
||||||
|
(function checkClassListProperty() {
|
||||||
|
var div = document.createElement('div');
|
||||||
|
if ('classList' in div) {
|
||||||
|
return; // classList property exists
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeList(element, itemName, add, remove) {
|
||||||
|
var s = element.className || '';
|
||||||
|
var list = s.split(/\s+/g);
|
||||||
|
if (list[0] === '') {
|
||||||
|
list.shift();
|
||||||
|
}
|
||||||
|
var index = list.indexOf(itemName);
|
||||||
|
if (index < 0 && add) {
|
||||||
|
list.push(itemName);
|
||||||
|
}
|
||||||
|
if (index >= 0 && remove) {
|
||||||
|
list.splice(index, 1);
|
||||||
|
}
|
||||||
|
element.className = list.join(' ');
|
||||||
|
return (index >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var classListPrototype = {
|
||||||
|
add: function(name) {
|
||||||
|
changeList(this.element, name, true, false);
|
||||||
|
},
|
||||||
|
contains: function(name) {
|
||||||
|
return changeList(this.element, name, false, false);
|
||||||
|
},
|
||||||
|
remove: function(name) {
|
||||||
|
changeList(this.element, name, false, true);
|
||||||
|
},
|
||||||
|
toggle: function(name) {
|
||||||
|
changeList(this.element, name, true, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperty(HTMLElement.prototype, 'classList', {
|
||||||
|
get: function() {
|
||||||
|
if (this._classList) {
|
||||||
|
return this._classList;
|
||||||
|
}
|
||||||
|
|
||||||
|
var classList = Object.create(classListPrototype, {
|
||||||
|
element: {
|
||||||
|
value: this,
|
||||||
|
writable: false,
|
||||||
|
enumerable: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.defineProperty(this, '_classList', {
|
||||||
|
value: classList,
|
||||||
|
writable: false,
|
||||||
|
enumerable: false
|
||||||
|
});
|
||||||
|
return classList;
|
||||||
|
},
|
||||||
|
enumerable: true
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Check console compatibility
|
||||||
|
// In older IE versions the console object is not available
|
||||||
|
// unless console is open.
|
||||||
|
// Support: IE<10
|
||||||
|
(function checkConsoleCompatibility() {
|
||||||
|
if (!('console' in window)) {
|
||||||
|
window.console = {
|
||||||
|
log: function() {},
|
||||||
|
error: function() {},
|
||||||
|
warn: function() {}
|
||||||
|
};
|
||||||
|
} else if (!('bind' in console.log)) {
|
||||||
|
// native functions in IE9 might not have bind
|
||||||
|
console.log = (function(fn) {
|
||||||
|
return function(msg) { return fn(msg); };
|
||||||
|
})(console.log);
|
||||||
|
console.error = (function(fn) {
|
||||||
|
return function(msg) { return fn(msg); };
|
||||||
|
})(console.error);
|
||||||
|
console.warn = (function(fn) {
|
||||||
|
return function(msg) { return fn(msg); };
|
||||||
|
})(console.warn);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Check onclick compatibility in Opera
|
||||||
|
// Support: Opera<15
|
||||||
|
(function checkOnClickCompatibility() {
|
||||||
|
// workaround for reported Opera bug DSK-354448:
|
||||||
|
// onclick fires on disabled buttons with opaque content
|
||||||
|
function ignoreIfTargetDisabled(event) {
|
||||||
|
if (isDisabled(event.target)) {
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isDisabled(node) {
|
||||||
|
return node.disabled || (node.parentNode && isDisabled(node.parentNode));
|
||||||
|
}
|
||||||
|
if (navigator.userAgent.indexOf('Opera') !== -1) {
|
||||||
|
// use browser detection since we cannot feature-check this bug
|
||||||
|
document.addEventListener('click', ignoreIfTargetDisabled, true);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Checks if possible to use URL.createObjectURL()
|
||||||
|
// Support: IE
|
||||||
|
(function checkOnBlobSupport() {
|
||||||
|
// sometimes IE loosing the data created with createObjectURL(), see #3977
|
||||||
|
if (navigator.userAgent.indexOf('Trident') >= 0) {
|
||||||
|
PDFJS.disableCreateObjectURL = true;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Checks if navigator.language is supported
|
||||||
|
(function checkNavigatorLanguage() {
|
||||||
|
if ('language' in navigator) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PDFJS.locale = navigator.userLanguage || 'en-US';
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function checkRangeRequests() {
|
||||||
|
// Safari has issues with cached range requests see:
|
||||||
|
// https://github.com/mozilla/pdf.js/issues/3260
|
||||||
|
// Last tested with version 6.0.4.
|
||||||
|
// Support: Safari 6.0+
|
||||||
|
var isSafari = Object.prototype.toString.call(
|
||||||
|
window.HTMLElement).indexOf('Constructor') > 0;
|
||||||
|
|
||||||
|
// Older versions of Android (pre 3.0) has issues with range requests, see:
|
||||||
|
// https://github.com/mozilla/pdf.js/issues/3381.
|
||||||
|
// Make sure that we only match webkit-based Android browsers,
|
||||||
|
// since Firefox/Fennec works as expected.
|
||||||
|
// Support: Android<3.0
|
||||||
|
var regex = /Android\s[0-2][^\d]/;
|
||||||
|
var isOldAndroid = regex.test(navigator.userAgent);
|
||||||
|
|
||||||
|
// Range requests are broken in Chrome 39 and 40, https://crbug.com/442318
|
||||||
|
var isChromeWithRangeBug = /Chrome\/(39|40)\./.test(navigator.userAgent);
|
||||||
|
|
||||||
|
if (isSafari || isOldAndroid || isChromeWithRangeBug) {
|
||||||
|
PDFJS.disableRange = true;
|
||||||
|
PDFJS.disableStream = true;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Check if the browser supports manipulation of the history.
|
||||||
|
// Support: IE<10, Android<4.2
|
||||||
|
(function checkHistoryManipulation() {
|
||||||
|
// Android 2.x has so buggy pushState support that it was removed in
|
||||||
|
// Android 3.0 and restored as late as in Android 4.2.
|
||||||
|
// Support: Android 2.x
|
||||||
|
if (!history.pushState || navigator.userAgent.indexOf('Android 2.') >= 0) {
|
||||||
|
PDFJS.disableHistory = true;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Support: IE<11, Chrome<21, Android<4.4, Safari<6
|
||||||
|
(function checkSetPresenceInImageData() {
|
||||||
|
// IE < 11 will use window.CanvasPixelArray which lacks set function.
|
||||||
|
if (window.CanvasPixelArray) {
|
||||||
|
if (typeof window.CanvasPixelArray.prototype.set !== 'function') {
|
||||||
|
window.CanvasPixelArray.prototype.set = function(arr) {
|
||||||
|
for (var i = 0, ii = this.length; i < ii; i++) {
|
||||||
|
this[i] = arr[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Old Chrome and Android use an inaccessible CanvasPixelArray prototype.
|
||||||
|
// Because we cannot feature detect it, we rely on user agent parsing.
|
||||||
|
var polyfill = false, versionMatch;
|
||||||
|
if (navigator.userAgent.indexOf('Chrom') >= 0) {
|
||||||
|
versionMatch = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
|
||||||
|
// Chrome < 21 lacks the set function.
|
||||||
|
polyfill = versionMatch && parseInt(versionMatch[2]) < 21;
|
||||||
|
} else if (navigator.userAgent.indexOf('Android') >= 0) {
|
||||||
|
// Android < 4.4 lacks the set function.
|
||||||
|
// Android >= 4.4 will contain Chrome in the user agent,
|
||||||
|
// thus pass the Chrome check above and not reach this block.
|
||||||
|
polyfill = /Android\s[0-4][^\d]/g.test(navigator.userAgent);
|
||||||
|
} else if (navigator.userAgent.indexOf('Safari') >= 0) {
|
||||||
|
versionMatch = navigator.userAgent.
|
||||||
|
match(/Version\/([0-9]+)\.([0-9]+)\.([0-9]+) Safari\//);
|
||||||
|
// Safari < 6 lacks the set function.
|
||||||
|
polyfill = versionMatch && parseInt(versionMatch[1]) < 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (polyfill) {
|
||||||
|
var contextPrototype = window.CanvasRenderingContext2D.prototype;
|
||||||
|
contextPrototype._createImageData = contextPrototype.createImageData;
|
||||||
|
contextPrototype.createImageData = function(w, h) {
|
||||||
|
var imageData = this._createImageData(w, h);
|
||||||
|
imageData.data.set = function(arr) {
|
||||||
|
for (var i = 0, ii = this.length; i < ii; i++) {
|
||||||
|
this[i] = arr[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return imageData;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Support: IE<10, Android<4.0, iOS
|
||||||
|
(function checkRequestAnimationFrame() {
|
||||||
|
function fakeRequestAnimationFrame(callback) {
|
||||||
|
window.setTimeout(callback, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
|
||||||
|
if (isIOS) {
|
||||||
|
// requestAnimationFrame on iOS is broken, replacing with fake one.
|
||||||
|
window.requestAnimationFrame = fakeRequestAnimationFrame;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ('requestAnimationFrame' in window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.requestAnimationFrame =
|
||||||
|
window.mozRequestAnimationFrame ||
|
||||||
|
window.webkitRequestAnimationFrame ||
|
||||||
|
fakeRequestAnimationFrame;
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function checkCanvasSizeLimitation() {
|
||||||
|
var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
|
||||||
|
var isAndroid = /Android/g.test(navigator.userAgent);
|
||||||
|
if (isIOS || isAndroid) {
|
||||||
|
// 5MP
|
||||||
|
PDFJS.maxCanvasPixels = 5242880;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Disable fullscreen support for certain problematic configurations.
|
||||||
|
// Support: IE11+ (when embedded).
|
||||||
|
(function checkFullscreenSupport() {
|
||||||
|
var isEmbeddedIE = (navigator.userAgent.indexOf('Trident') >= 0 &&
|
||||||
|
window.parent !== window);
|
||||||
|
if (isEmbeddedIE) {
|
||||||
|
PDFJS.disableFullscreen = true;
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/* This is just a sample file with CSS rules. You should write your own @font-face declarations
|
||||||
|
* to add support for your desired fonts.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Novecentowide Book';
|
||||||
|
src: url("/ViewerJS/fonts/Novecentowide-Bold-webfont.eot");
|
||||||
|
src: url("/ViewerJS/fonts/Novecentowide-Bold-webfont.eot?#iefix") format("embedded-opentype"),
|
||||||
|
url("/ViewerJS/fonts/Novecentowide-Bold-webfont.woff") format("woff"),
|
||||||
|
url("/fonts/Novecentowide-Bold-webfont.ttf") format("truetype"),
|
||||||
|
url("/fonts/Novecentowide-Bold-webfont.svg#NovecentowideBookBold") format("svg");
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'exotica';
|
||||||
|
src: url('/ViewerJS/fonts/Exotica-webfont.eot');
|
||||||
|
src: url('/ViewerJS/fonts/Exotica-webfont.eot?#iefix') format('embedded-opentype'),
|
||||||
|
url('/ViewerJS/fonts/Exotica-webfont.woff') format('woff'),
|
||||||
|
url('/ViewerJS/fonts/Exotica-webfont.ttf') format('truetype'),
|
||||||
|
url('/ViewerJS/fonts/Exotica-webfont.svg#exoticamedium') format('svg');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 512 B |
|
After Width: | Height: | Size: 491 B |
|
After Width: | Height: | Size: 237 B |
|
After Width: | Height: | Size: 353 B |
|
After Width: | Height: | Size: 344 B |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 228 B |
|
After Width: | Height: | Size: 143 B |
@@ -0,0 +1 @@
|
|||||||
|
var /**@const{!string}*/pdfjs_version = "v1.1.114";
|
||||||
@@ -0,0 +1,419 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* Copyright 2012 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
/* globals CustomStyle, PDFJS */
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var MAX_TEXT_DIVS_TO_RENDER = 100000;
|
||||||
|
|
||||||
|
var NonWhitespaceRegexp = /\S/;
|
||||||
|
|
||||||
|
function isAllWhitespace(str) {
|
||||||
|
return !NonWhitespaceRegexp.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} TextLayerBuilderOptions
|
||||||
|
* @property {HTMLDivElement} textLayerDiv - The text layer container.
|
||||||
|
* @property {number} pageIndex - The page index.
|
||||||
|
* @property {PageViewport} viewport - The viewport of the text layer.
|
||||||
|
* @property {PDFFindController} findController
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TextLayerBuilder provides text-selection functionality for the PDF.
|
||||||
|
* It does this by creating overlay divs over the PDF text. These divs
|
||||||
|
* contain text that matches the PDF text they are overlaying. This object
|
||||||
|
* also provides a way to highlight text that is being searched for.
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
var TextLayerBuilder = (function TextLayerBuilderClosure() {
|
||||||
|
function TextLayerBuilder(options) {
|
||||||
|
this.textLayerDiv = options.textLayerDiv;
|
||||||
|
this.renderingDone = false;
|
||||||
|
this.divContentDone = false;
|
||||||
|
this.pageIdx = options.pageIndex;
|
||||||
|
this.pageNumber = this.pageIdx + 1;
|
||||||
|
this.matches = [];
|
||||||
|
this.viewport = options.viewport;
|
||||||
|
this.textDivs = [];
|
||||||
|
this.findController = options.findController || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextLayerBuilder.prototype = {
|
||||||
|
_finishRendering: function TextLayerBuilder_finishRendering() {
|
||||||
|
this.renderingDone = true;
|
||||||
|
|
||||||
|
var event = document.createEvent('CustomEvent');
|
||||||
|
event.initCustomEvent('textlayerrendered', true, true, {
|
||||||
|
pageNumber: this.pageNumber
|
||||||
|
});
|
||||||
|
this.textLayerDiv.dispatchEvent(event);
|
||||||
|
},
|
||||||
|
|
||||||
|
renderLayer: function TextLayerBuilder_renderLayer() {
|
||||||
|
var textLayerFrag = document.createDocumentFragment();
|
||||||
|
var textDivs = this.textDivs;
|
||||||
|
var textDivsLength = textDivs.length;
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
var ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
// No point in rendering many divs as it would make the browser
|
||||||
|
// unusable even after the divs are rendered.
|
||||||
|
if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) {
|
||||||
|
this._finishRendering();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastFontSize;
|
||||||
|
var lastFontFamily;
|
||||||
|
for (var i = 0; i < textDivsLength; i++) {
|
||||||
|
var textDiv = textDivs[i];
|
||||||
|
if (textDiv.dataset.isWhitespace !== undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fontSize = textDiv.style.fontSize;
|
||||||
|
var fontFamily = textDiv.style.fontFamily;
|
||||||
|
|
||||||
|
// Only build font string and set to context if different from last.
|
||||||
|
if (fontSize !== lastFontSize || fontFamily !== lastFontFamily) {
|
||||||
|
ctx.font = fontSize + ' ' + fontFamily;
|
||||||
|
lastFontSize = fontSize;
|
||||||
|
lastFontFamily = fontFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
var width = ctx.measureText(textDiv.textContent).width;
|
||||||
|
if (width > 0) {
|
||||||
|
textLayerFrag.appendChild(textDiv);
|
||||||
|
var transform;
|
||||||
|
if (textDiv.dataset.canvasWidth !== undefined) {
|
||||||
|
// Dataset values come of type string.
|
||||||
|
var textScale = textDiv.dataset.canvasWidth / width;
|
||||||
|
transform = 'scaleX(' + textScale + ')';
|
||||||
|
} else {
|
||||||
|
transform = '';
|
||||||
|
}
|
||||||
|
var rotation = textDiv.dataset.angle;
|
||||||
|
if (rotation) {
|
||||||
|
transform = 'rotate(' + rotation + 'deg) ' + transform;
|
||||||
|
}
|
||||||
|
if (transform) {
|
||||||
|
CustomStyle.setProp('transform' , textDiv, transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.textLayerDiv.appendChild(textLayerFrag);
|
||||||
|
this._finishRendering();
|
||||||
|
this.updateMatches();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the text layer.
|
||||||
|
* @param {number} timeout (optional) if specified, the rendering waits
|
||||||
|
* for specified amount of ms.
|
||||||
|
*/
|
||||||
|
render: function TextLayerBuilder_render(timeout) {
|
||||||
|
if (!this.divContentDone || this.renderingDone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.renderTimer) {
|
||||||
|
clearTimeout(this.renderTimer);
|
||||||
|
this.renderTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!timeout) { // Render right away
|
||||||
|
this.renderLayer();
|
||||||
|
} else { // Schedule
|
||||||
|
var self = this;
|
||||||
|
this.renderTimer = setTimeout(function() {
|
||||||
|
self.renderLayer();
|
||||||
|
self.renderTimer = null;
|
||||||
|
}, timeout);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
appendText: function TextLayerBuilder_appendText(geom, styles) {
|
||||||
|
var style = styles[geom.fontName];
|
||||||
|
var textDiv = document.createElement('div');
|
||||||
|
this.textDivs.push(textDiv);
|
||||||
|
if (isAllWhitespace(geom.str)) {
|
||||||
|
textDiv.dataset.isWhitespace = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var tx = PDFJS.Util.transform(this.viewport.transform, geom.transform);
|
||||||
|
var angle = Math.atan2(tx[1], tx[0]);
|
||||||
|
if (style.vertical) {
|
||||||
|
angle += Math.PI / 2;
|
||||||
|
}
|
||||||
|
var fontHeight = Math.sqrt((tx[2] * tx[2]) + (tx[3] * tx[3]));
|
||||||
|
var fontAscent = fontHeight;
|
||||||
|
if (style.ascent) {
|
||||||
|
fontAscent = style.ascent * fontAscent;
|
||||||
|
} else if (style.descent) {
|
||||||
|
fontAscent = (1 + style.descent) * fontAscent;
|
||||||
|
}
|
||||||
|
|
||||||
|
var left;
|
||||||
|
var top;
|
||||||
|
if (angle === 0) {
|
||||||
|
left = tx[4];
|
||||||
|
top = tx[5] - fontAscent;
|
||||||
|
} else {
|
||||||
|
left = tx[4] + (fontAscent * Math.sin(angle));
|
||||||
|
top = tx[5] - (fontAscent * Math.cos(angle));
|
||||||
|
}
|
||||||
|
textDiv.style.left = left + 'px';
|
||||||
|
textDiv.style.top = top + 'px';
|
||||||
|
textDiv.style.fontSize = fontHeight + 'px';
|
||||||
|
textDiv.style.fontFamily = style.fontFamily;
|
||||||
|
|
||||||
|
textDiv.textContent = geom.str;
|
||||||
|
// |fontName| is only used by the Font Inspector. This test will succeed
|
||||||
|
// when e.g. the Font Inspector is off but the Stepper is on, but it's
|
||||||
|
// not worth the effort to do a more accurate test.
|
||||||
|
if (PDFJS.pdfBug) {
|
||||||
|
textDiv.dataset.fontName = geom.fontName;
|
||||||
|
}
|
||||||
|
// Storing into dataset will convert number into string.
|
||||||
|
if (angle !== 0) {
|
||||||
|
textDiv.dataset.angle = angle * (180 / Math.PI);
|
||||||
|
}
|
||||||
|
// We don't bother scaling single-char text divs, because it has very
|
||||||
|
// little effect on text highlighting. This makes scrolling on docs with
|
||||||
|
// lots of such divs a lot faster.
|
||||||
|
if (textDiv.textContent.length > 1) {
|
||||||
|
if (style.vertical) {
|
||||||
|
textDiv.dataset.canvasWidth = geom.height * this.viewport.scale;
|
||||||
|
} else {
|
||||||
|
textDiv.dataset.canvasWidth = geom.width * this.viewport.scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setTextContent: function TextLayerBuilder_setTextContent(textContent) {
|
||||||
|
this.textContent = textContent;
|
||||||
|
|
||||||
|
var textItems = textContent.items;
|
||||||
|
for (var i = 0, len = textItems.length; i < len; i++) {
|
||||||
|
this.appendText(textItems[i], textContent.styles);
|
||||||
|
}
|
||||||
|
this.divContentDone = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
convertMatches: function TextLayerBuilder_convertMatches(matches) {
|
||||||
|
var i = 0;
|
||||||
|
var iIndex = 0;
|
||||||
|
var bidiTexts = this.textContent.items;
|
||||||
|
var end = bidiTexts.length - 1;
|
||||||
|
var queryLen = (this.findController === null ?
|
||||||
|
0 : this.findController.state.query.length);
|
||||||
|
var ret = [];
|
||||||
|
|
||||||
|
for (var m = 0, len = matches.length; m < len; m++) {
|
||||||
|
// Calculate the start position.
|
||||||
|
var matchIdx = matches[m];
|
||||||
|
|
||||||
|
// Loop over the divIdxs.
|
||||||
|
while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) {
|
||||||
|
iIndex += bidiTexts[i].str.length;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i === bidiTexts.length) {
|
||||||
|
console.error('Could not find a matching mapping');
|
||||||
|
}
|
||||||
|
|
||||||
|
var match = {
|
||||||
|
begin: {
|
||||||
|
divIdx: i,
|
||||||
|
offset: matchIdx - iIndex
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate the end position.
|
||||||
|
matchIdx += queryLen;
|
||||||
|
|
||||||
|
// Somewhat the same array as above, but use > instead of >= to get
|
||||||
|
// the end position right.
|
||||||
|
while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) {
|
||||||
|
iIndex += bidiTexts[i].str.length;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
match.end = {
|
||||||
|
divIdx: i,
|
||||||
|
offset: matchIdx - iIndex
|
||||||
|
};
|
||||||
|
ret.push(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
|
||||||
|
renderMatches: function TextLayerBuilder_renderMatches(matches) {
|
||||||
|
// Early exit if there is nothing to render.
|
||||||
|
if (matches.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bidiTexts = this.textContent.items;
|
||||||
|
var textDivs = this.textDivs;
|
||||||
|
var prevEnd = null;
|
||||||
|
var pageIdx = this.pageIdx;
|
||||||
|
var isSelectedPage = (this.findController === null ?
|
||||||
|
false : (pageIdx === this.findController.selected.pageIdx));
|
||||||
|
var selectedMatchIdx = (this.findController === null ?
|
||||||
|
-1 : this.findController.selected.matchIdx);
|
||||||
|
var highlightAll = (this.findController === null ?
|
||||||
|
false : this.findController.state.highlightAll);
|
||||||
|
var infinity = {
|
||||||
|
divIdx: -1,
|
||||||
|
offset: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
function beginText(begin, className) {
|
||||||
|
var divIdx = begin.divIdx;
|
||||||
|
textDivs[divIdx].textContent = '';
|
||||||
|
appendTextToDiv(divIdx, 0, begin.offset, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendTextToDiv(divIdx, fromOffset, toOffset, className) {
|
||||||
|
var div = textDivs[divIdx];
|
||||||
|
var content = bidiTexts[divIdx].str.substring(fromOffset, toOffset);
|
||||||
|
var node = document.createTextNode(content);
|
||||||
|
if (className) {
|
||||||
|
var span = document.createElement('span');
|
||||||
|
span.className = className;
|
||||||
|
span.appendChild(node);
|
||||||
|
div.appendChild(span);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
div.appendChild(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
var i0 = selectedMatchIdx, i1 = i0 + 1;
|
||||||
|
if (highlightAll) {
|
||||||
|
i0 = 0;
|
||||||
|
i1 = matches.length;
|
||||||
|
} else if (!isSelectedPage) {
|
||||||
|
// Not highlighting all and this isn't the selected page, so do nothing.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = i0; i < i1; i++) {
|
||||||
|
var match = matches[i];
|
||||||
|
var begin = match.begin;
|
||||||
|
var end = match.end;
|
||||||
|
var isSelected = (isSelectedPage && i === selectedMatchIdx);
|
||||||
|
var highlightSuffix = (isSelected ? ' selected' : '');
|
||||||
|
|
||||||
|
if (this.findController) {
|
||||||
|
this.findController.updateMatchPosition(pageIdx, i, textDivs,
|
||||||
|
begin.divIdx, end.divIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match inside new div.
|
||||||
|
if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
|
||||||
|
// If there was a previous div, then add the text at the end.
|
||||||
|
if (prevEnd !== null) {
|
||||||
|
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
|
||||||
|
}
|
||||||
|
// Clear the divs and set the content until the starting point.
|
||||||
|
beginText(begin);
|
||||||
|
} else {
|
||||||
|
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (begin.divIdx === end.divIdx) {
|
||||||
|
appendTextToDiv(begin.divIdx, begin.offset, end.offset,
|
||||||
|
'highlight' + highlightSuffix);
|
||||||
|
} else {
|
||||||
|
appendTextToDiv(begin.divIdx, begin.offset, infinity.offset,
|
||||||
|
'highlight begin' + highlightSuffix);
|
||||||
|
for (var n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) {
|
||||||
|
textDivs[n0].className = 'highlight middle' + highlightSuffix;
|
||||||
|
}
|
||||||
|
beginText(end, 'highlight end' + highlightSuffix);
|
||||||
|
}
|
||||||
|
prevEnd = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevEnd) {
|
||||||
|
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateMatches: function TextLayerBuilder_updateMatches() {
|
||||||
|
// Only show matches when all rendering is done.
|
||||||
|
if (!this.renderingDone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all matches.
|
||||||
|
var matches = this.matches;
|
||||||
|
var textDivs = this.textDivs;
|
||||||
|
var bidiTexts = this.textContent.items;
|
||||||
|
var clearedUntilDivIdx = -1;
|
||||||
|
|
||||||
|
// Clear all current matches.
|
||||||
|
for (var i = 0, len = matches.length; i < len; i++) {
|
||||||
|
var match = matches[i];
|
||||||
|
var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
|
||||||
|
for (var n = begin, end = match.end.divIdx; n <= end; n++) {
|
||||||
|
var div = textDivs[n];
|
||||||
|
div.textContent = bidiTexts[n].str;
|
||||||
|
div.className = '';
|
||||||
|
}
|
||||||
|
clearedUntilDivIdx = match.end.divIdx + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.findController === null || !this.findController.active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the matches on the page controller into the match format
|
||||||
|
// used for the textLayer.
|
||||||
|
this.matches = this.convertMatches(this.findController === null ?
|
||||||
|
[] : (this.findController.pageMatches[this.pageIdx] || []));
|
||||||
|
this.renderMatches(this.matches);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return TextLayerBuilder;
|
||||||
|
})();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @implements IPDFTextLayerFactory
|
||||||
|
*/
|
||||||
|
function DefaultTextLayerFactory() {}
|
||||||
|
DefaultTextLayerFactory.prototype = {
|
||||||
|
/**
|
||||||
|
* @param {HTMLDivElement} textLayerDiv
|
||||||
|
* @param {number} pageIndex
|
||||||
|
* @param {PageViewport} viewport
|
||||||
|
* @returns {TextLayerBuilder}
|
||||||
|
*/
|
||||||
|
createTextLayerBuilder: function (textLayerDiv, pageIndex, viewport) {
|
||||||
|
return new TextLayerBuilder({
|
||||||
|
textLayerDiv: textLayerDiv,
|
||||||
|
pageIndex: pageIndex,
|
||||||
|
viewport: viewport
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,394 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* Copyright 2012 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var CSS_UNITS = 96.0 / 72.0;
|
||||||
|
var DEFAULT_SCALE = 'auto';
|
||||||
|
var UNKNOWN_SCALE = 0;
|
||||||
|
var MAX_AUTO_SCALE = 1.25;
|
||||||
|
var SCROLLBAR_PADDING = 40;
|
||||||
|
var VERTICAL_PADDING = 5;
|
||||||
|
|
||||||
|
// optimised CSS custom property getter/setter
|
||||||
|
var CustomStyle = (function CustomStyleClosure() {
|
||||||
|
|
||||||
|
// As noted on: http://www.zachstronaut.com/posts/2009/02/17/
|
||||||
|
// animate-css-transforms-firefox-webkit.html
|
||||||
|
// in some versions of IE9 it is critical that ms appear in this list
|
||||||
|
// before Moz
|
||||||
|
var prefixes = ['ms', 'Moz', 'Webkit', 'O'];
|
||||||
|
var _cache = {};
|
||||||
|
|
||||||
|
function CustomStyle() {}
|
||||||
|
|
||||||
|
CustomStyle.getProp = function get(propName, element) {
|
||||||
|
// check cache only when no element is given
|
||||||
|
if (arguments.length === 1 && typeof _cache[propName] === 'string') {
|
||||||
|
return _cache[propName];
|
||||||
|
}
|
||||||
|
|
||||||
|
element = element || document.documentElement;
|
||||||
|
var style = element.style, prefixed, uPropName;
|
||||||
|
|
||||||
|
// test standard property first
|
||||||
|
if (typeof style[propName] === 'string') {
|
||||||
|
return (_cache[propName] = propName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// capitalize
|
||||||
|
uPropName = propName.charAt(0).toUpperCase() + propName.slice(1);
|
||||||
|
|
||||||
|
// test vendor specific properties
|
||||||
|
for (var i = 0, l = prefixes.length; i < l; i++) {
|
||||||
|
prefixed = prefixes[i] + uPropName;
|
||||||
|
if (typeof style[prefixed] === 'string') {
|
||||||
|
return (_cache[propName] = prefixed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if all fails then set to undefined
|
||||||
|
return (_cache[propName] = 'undefined');
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomStyle.setProp = function set(propName, element, str) {
|
||||||
|
var prop = this.getProp(propName);
|
||||||
|
if (prop !== 'undefined') {
|
||||||
|
element.style[prop] = str;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return CustomStyle;
|
||||||
|
})();
|
||||||
|
|
||||||
|
function getFileName(url) {
|
||||||
|
var anchor = url.indexOf('#');
|
||||||
|
var query = url.indexOf('?');
|
||||||
|
var end = Math.min(
|
||||||
|
anchor > 0 ? anchor : url.length,
|
||||||
|
query > 0 ? query : url.length);
|
||||||
|
return url.substring(url.lastIndexOf('/', end) + 1, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns scale factor for the canvas. It makes sense for the HiDPI displays.
|
||||||
|
* @return {Object} The object with horizontal (sx) and vertical (sy)
|
||||||
|
scales. The scaled property is set to false if scaling is
|
||||||
|
not required, true otherwise.
|
||||||
|
*/
|
||||||
|
function getOutputScale(ctx) {
|
||||||
|
var devicePixelRatio = window.devicePixelRatio || 1;
|
||||||
|
var backingStoreRatio = ctx.webkitBackingStorePixelRatio ||
|
||||||
|
ctx.mozBackingStorePixelRatio ||
|
||||||
|
ctx.msBackingStorePixelRatio ||
|
||||||
|
ctx.oBackingStorePixelRatio ||
|
||||||
|
ctx.backingStorePixelRatio || 1;
|
||||||
|
var pixelRatio = devicePixelRatio / backingStoreRatio;
|
||||||
|
return {
|
||||||
|
sx: pixelRatio,
|
||||||
|
sy: pixelRatio,
|
||||||
|
scaled: pixelRatio !== 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scrolls specified element into view of its parent.
|
||||||
|
* element {Object} The element to be visible.
|
||||||
|
* spot {Object} An object with optional top and left properties,
|
||||||
|
* specifying the offset from the top left edge.
|
||||||
|
*/
|
||||||
|
function scrollIntoView(element, spot) {
|
||||||
|
// Assuming offsetParent is available (it's not available when viewer is in
|
||||||
|
// hidden iframe or object). We have to scroll: if the offsetParent is not set
|
||||||
|
// producing the error. See also animationStartedClosure.
|
||||||
|
var parent = element.offsetParent;
|
||||||
|
var offsetY = element.offsetTop + element.clientTop;
|
||||||
|
var offsetX = element.offsetLeft + element.clientLeft;
|
||||||
|
if (!parent) {
|
||||||
|
console.error('offsetParent is not set -- cannot scroll');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (parent.clientHeight === parent.scrollHeight) {
|
||||||
|
if (parent.dataset._scaleY) {
|
||||||
|
offsetY /= parent.dataset._scaleY;
|
||||||
|
offsetX /= parent.dataset._scaleX;
|
||||||
|
}
|
||||||
|
offsetY += parent.offsetTop;
|
||||||
|
offsetX += parent.offsetLeft;
|
||||||
|
parent = parent.offsetParent;
|
||||||
|
if (!parent) {
|
||||||
|
return; // no need to scroll
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (spot) {
|
||||||
|
if (spot.top !== undefined) {
|
||||||
|
offsetY += spot.top;
|
||||||
|
}
|
||||||
|
if (spot.left !== undefined) {
|
||||||
|
offsetX += spot.left;
|
||||||
|
parent.scrollLeft = offsetX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parent.scrollTop = offsetY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to start monitoring the scroll event and converting them into
|
||||||
|
* PDF.js friendly one: with scroll debounce and scroll direction.
|
||||||
|
*/
|
||||||
|
function watchScroll(viewAreaElement, callback) {
|
||||||
|
var debounceScroll = function debounceScroll(evt) {
|
||||||
|
if (rAF) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// schedule an invocation of scroll for next animation frame.
|
||||||
|
rAF = window.requestAnimationFrame(function viewAreaElementScrolled() {
|
||||||
|
rAF = null;
|
||||||
|
|
||||||
|
var currentY = viewAreaElement.scrollTop;
|
||||||
|
var lastY = state.lastY;
|
||||||
|
if (currentY !== lastY) {
|
||||||
|
state.down = currentY > lastY;
|
||||||
|
}
|
||||||
|
state.lastY = currentY;
|
||||||
|
callback(state);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var state = {
|
||||||
|
down: true,
|
||||||
|
lastY: viewAreaElement.scrollTop,
|
||||||
|
_eventHandler: debounceScroll
|
||||||
|
};
|
||||||
|
|
||||||
|
var rAF = null;
|
||||||
|
viewAreaElement.addEventListener('scroll', debounceScroll, true);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use binary search to find the index of the first item in a given array which
|
||||||
|
* passes a given condition. The items are expected to be sorted in the sense
|
||||||
|
* that if the condition is true for one item in the array, then it is also true
|
||||||
|
* for all following items.
|
||||||
|
*
|
||||||
|
* @returns {Number} Index of the first array element to pass the test,
|
||||||
|
* or |items.length| if no such element exists.
|
||||||
|
*/
|
||||||
|
function binarySearchFirstItem(items, condition) {
|
||||||
|
var minIndex = 0;
|
||||||
|
var maxIndex = items.length - 1;
|
||||||
|
|
||||||
|
if (items.length === 0 || !condition(items[maxIndex])) {
|
||||||
|
return items.length;
|
||||||
|
}
|
||||||
|
if (condition(items[minIndex])) {
|
||||||
|
return minIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (minIndex < maxIndex) {
|
||||||
|
var currentIndex = (minIndex + maxIndex) >> 1;
|
||||||
|
var currentItem = items[currentIndex];
|
||||||
|
if (condition(currentItem)) {
|
||||||
|
maxIndex = currentIndex;
|
||||||
|
} else {
|
||||||
|
minIndex = currentIndex + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return minIndex; /* === maxIndex */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic helper to find out what elements are visible within a scroll pane.
|
||||||
|
*/
|
||||||
|
function getVisibleElements(scrollEl, views, sortByVisibility) {
|
||||||
|
var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight;
|
||||||
|
var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth;
|
||||||
|
|
||||||
|
function isElementBottomBelowViewTop(view) {
|
||||||
|
var element = view.div;
|
||||||
|
var elementBottom =
|
||||||
|
element.offsetTop + element.clientTop + element.clientHeight;
|
||||||
|
return elementBottom > top;
|
||||||
|
}
|
||||||
|
|
||||||
|
var visible = [], view, element;
|
||||||
|
var currentHeight, viewHeight, hiddenHeight, percentHeight;
|
||||||
|
var currentWidth, viewWidth;
|
||||||
|
var firstVisibleElementInd = (views.length === 0) ? 0 :
|
||||||
|
binarySearchFirstItem(views, isElementBottomBelowViewTop);
|
||||||
|
|
||||||
|
for (var i = firstVisibleElementInd, ii = views.length; i < ii; i++) {
|
||||||
|
view = views[i];
|
||||||
|
element = view.div;
|
||||||
|
currentHeight = element.offsetTop + element.clientTop;
|
||||||
|
viewHeight = element.clientHeight;
|
||||||
|
|
||||||
|
if (currentHeight > bottom) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentWidth = element.offsetLeft + element.clientLeft;
|
||||||
|
viewWidth = element.clientWidth;
|
||||||
|
if (currentWidth + viewWidth < left || currentWidth > right) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
hiddenHeight = Math.max(0, top - currentHeight) +
|
||||||
|
Math.max(0, currentHeight + viewHeight - bottom);
|
||||||
|
percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0;
|
||||||
|
|
||||||
|
visible.push({
|
||||||
|
id: view.id,
|
||||||
|
x: currentWidth,
|
||||||
|
y: currentHeight,
|
||||||
|
view: view,
|
||||||
|
percent: percentHeight
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var first = visible[0];
|
||||||
|
var last = visible[visible.length - 1];
|
||||||
|
|
||||||
|
if (sortByVisibility) {
|
||||||
|
visible.sort(function(a, b) {
|
||||||
|
var pc = a.percent - b.percent;
|
||||||
|
if (Math.abs(pc) > 0.001) {
|
||||||
|
return -pc;
|
||||||
|
}
|
||||||
|
return a.id - b.id; // ensure stability
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return {first: first, last: last, views: visible};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler to suppress context menu.
|
||||||
|
*/
|
||||||
|
function noContextMenuHandler(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the filename or guessed filename from the url (see issue 3455).
|
||||||
|
* url {String} The original PDF location.
|
||||||
|
* @return {String} Guessed PDF file name.
|
||||||
|
*/
|
||||||
|
function getPDFFileNameFromURL(url) {
|
||||||
|
var reURI = /^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
|
||||||
|
// SCHEME HOST 1.PATH 2.QUERY 3.REF
|
||||||
|
// Pattern to get last matching NAME.pdf
|
||||||
|
var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
|
||||||
|
var splitURI = reURI.exec(url);
|
||||||
|
var suggestedFilename = reFilename.exec(splitURI[1]) ||
|
||||||
|
reFilename.exec(splitURI[2]) ||
|
||||||
|
reFilename.exec(splitURI[3]);
|
||||||
|
if (suggestedFilename) {
|
||||||
|
suggestedFilename = suggestedFilename[0];
|
||||||
|
if (suggestedFilename.indexOf('%') !== -1) {
|
||||||
|
// URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf
|
||||||
|
try {
|
||||||
|
suggestedFilename =
|
||||||
|
reFilename.exec(decodeURIComponent(suggestedFilename))[0];
|
||||||
|
} catch(e) { // Possible (extremely rare) errors:
|
||||||
|
// URIError "Malformed URI", e.g. for "%AA.pdf"
|
||||||
|
// TypeError "null has no properties", e.g. for "%2F.pdf"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return suggestedFilename || 'document.pdf';
|
||||||
|
}
|
||||||
|
|
||||||
|
var ProgressBar = (function ProgressBarClosure() {
|
||||||
|
|
||||||
|
function clamp(v, min, max) {
|
||||||
|
return Math.min(Math.max(v, min), max);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ProgressBar(id, opts) {
|
||||||
|
this.visible = true;
|
||||||
|
|
||||||
|
// Fetch the sub-elements for later.
|
||||||
|
this.div = document.querySelector(id + ' .progress');
|
||||||
|
|
||||||
|
// Get the loading bar element, so it can be resized to fit the viewer.
|
||||||
|
this.bar = this.div.parentNode;
|
||||||
|
|
||||||
|
// Get options, with sensible defaults.
|
||||||
|
this.height = opts.height || 100;
|
||||||
|
this.width = opts.width || 100;
|
||||||
|
this.units = opts.units || '%';
|
||||||
|
|
||||||
|
// Initialize heights.
|
||||||
|
this.div.style.height = this.height + this.units;
|
||||||
|
this.percent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressBar.prototype = {
|
||||||
|
|
||||||
|
updateBar: function ProgressBar_updateBar() {
|
||||||
|
if (this._indeterminate) {
|
||||||
|
this.div.classList.add('indeterminate');
|
||||||
|
this.div.style.width = this.width + this.units;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.div.classList.remove('indeterminate');
|
||||||
|
var progressSize = this.width * this._percent / 100;
|
||||||
|
this.div.style.width = progressSize + this.units;
|
||||||
|
},
|
||||||
|
|
||||||
|
get percent() {
|
||||||
|
return this._percent;
|
||||||
|
},
|
||||||
|
|
||||||
|
set percent(val) {
|
||||||
|
this._indeterminate = isNaN(val);
|
||||||
|
this._percent = clamp(val, 0, 100);
|
||||||
|
this.updateBar();
|
||||||
|
},
|
||||||
|
|
||||||
|
setWidth: function ProgressBar_setWidth(viewer) {
|
||||||
|
if (viewer) {
|
||||||
|
var container = viewer.parentNode;
|
||||||
|
var scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
|
||||||
|
if (scrollbarWidth > 0) {
|
||||||
|
this.bar.setAttribute('style', 'width: calc(100% - ' +
|
||||||
|
scrollbarWidth + 'px);');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
hide: function ProgressBar_hide() {
|
||||||
|
if (!this.visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.visible = false;
|
||||||
|
this.bar.classList.add('hidden');
|
||||||
|
document.body.classList.remove('loadingInProgress');
|
||||||
|
},
|
||||||
|
|
||||||
|
show: function ProgressBar_show() {
|
||||||
|
if (this.visible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.visible = true;
|
||||||
|
document.body.classList.add('loadingInProgress');
|
||||||
|
this.bar.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return ProgressBar;
|
||||||
|
})();
|
||||||
@@ -53,5 +53,6 @@ return [
|
|||||||
'status' => 'Status',
|
'status' => 'Status',
|
||||||
'moduleName' => 'Module',
|
'moduleName' => 'Module',
|
||||||
'actions' => 'Actions',
|
'actions' => 'Actions',
|
||||||
'invalidTemplateSelected' => 'Invalid template selected! This page cannot be rendered!'
|
'invalidTemplateSelected' => 'Invalid template selected! This page cannot be rendered!',
|
||||||
|
'deleteTitlePhoto' => 'Delete title photo'
|
||||||
];
|
];
|
||||||
@@ -1,7 +1,14 @@
|
|||||||
@if($page->title_photo)
|
@if($page->title_photo)
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12 title-photo text-center">
|
<div id="titlePhotoContainer"
|
||||||
<img src="{{config('app.upload_url')}}/{{$page->title_photo}}" alt="" />
|
class="col-lg-4 col-lg-offset-4 col-md-6 col-md-offset-3 col-sm-12 title-photo text-center">
|
||||||
|
<input type="hidden" id="existingTitlePhoto" value="{{$page->title_photo}}" name="existingTitlePhoto">
|
||||||
|
<p><img src="{{config('app.upload_url')}}/{{$page->title_photo}}" alt="" /></p>
|
||||||
|
<p>
|
||||||
|
<a href="javascript:void(0)" id="removeTitlePhoto" class="btn btn-warning" data-toggle="tooltip"
|
||||||
|
title="@lang('admin/contents.deleteTitlePhoto')"><i
|
||||||
|
class="fa fa-trash"></i></a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@@ -11,7 +18,7 @@
|
|||||||
<label class="control-label">
|
<label class="control-label">
|
||||||
@lang('admin/contents.uploadTitleImage')
|
@lang('admin/contents.uploadTitleImage')
|
||||||
</label>
|
</label>
|
||||||
<input type="file" id="titlePhoto" name="titlePhoto" class="form-control" />
|
<input type="file" id="titlePhoto" accept=".jpg,.jpeg,.png" name="titlePhoto" class="form-control" />
|
||||||
|
|
||||||
@include('admin.snippets.hasError', ['field' => 'titlePhoto'])
|
@include('admin.snippets.hasError', ['field' => 'titlePhoto'])
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,6 +6,13 @@
|
|||||||
<textarea name="description" class="form-control" placeholder="@lang('admin/fileManager.directoryDescription')"
|
<textarea name="description" class="form-control" placeholder="@lang('admin/fileManager.directoryDescription')"
|
||||||
rows="3">{{old('description', $directory->description)}}</textarea>
|
rows="3">{{old('description', $directory->description)}}</textarea>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">@lang('admin/fileManager.editDirectory')</button>
|
<button type="submit" class="btn btn-primary">
|
||||||
|
@if ($directory->id)
|
||||||
|
@lang('admin/fileManager.editDirectory')
|
||||||
|
@else
|
||||||
|
@lang('admin/fileManager.newDirectory')
|
||||||
|
@endif
|
||||||
|
|
||||||
|
</button>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
@@ -1,26 +1,17 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
@forelse($files as $file)
|
@forelse($files as $file)
|
||||||
<div class="col-sm-4 col-md-2 text-center file-preview">
|
|
||||||
<div class="preview">
|
|
||||||
<a href="{{route('upload.detail', ['id' => $file->id])}}">
|
|
||||||
{!! \App\Helpers\FileManager::getPreview($file) !!}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div class="col-sm-4 col-md-3 text-center">
|
||||||
<a href="{{route('upload.detail', ['id' => $file->id])}}">
|
@include('admin.snippets.card', [
|
||||||
{{str_limit($file->original_filename, 10)}}
|
'body' => '<a href="'.route('upload.detail', ['id' => $file->id]).'">'.\App\Helpers\FileManager::getPreview($file).'</a>',
|
||||||
</a>
|
'footerClass' => 'text-right',
|
||||||
</div>
|
'cardClass' => 'file-preview',
|
||||||
|
'footer' => (!isset($hideDelete) || !$hideDelete) ? '<a href="'.route('upload.delete', ['id' => $file->id]).'" data-toggle="tooltip"
|
||||||
|
class="btn btn-sm btn-danger confirm"
|
||||||
@if(!isset($hideDelete) || !$hideDelete)
|
title="'.trans('admin/fileManager.delete').'">
|
||||||
<a href="{{route('upload.delete', ['id' => $file->id])}}" data-toggle="tooltip"
|
|
||||||
class="btn btn-sm rounded btn-danger confirm"
|
|
||||||
title="@lang('admin/fileManager.delete')">
|
|
||||||
<i class="fa fa-trash"></i>
|
<i class="fa fa-trash"></i>
|
||||||
</a>
|
</a>' : '',
|
||||||
@endif
|
])
|
||||||
</div>
|
</div>
|
||||||
@empty
|
@empty
|
||||||
<div class="alert alert-info">
|
<div class="alert alert-info">
|
||||||
|
|||||||
@@ -60,40 +60,11 @@
|
|||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
<div id="new-dir" class="panel-collapse collapse" role="tabpanel"
|
<div id="new-dir" class="panel-collapse collapse" role="tabpanel"
|
||||||
aria-labelledby="new-file-title">
|
aria-labelledby="new-dir-title">
|
||||||
@include('admin.fileManager.directories.form', ['directory' => new \App\Models\Directory(), 'action' => route('upload.postEditDirectory', ['id' => $directory->id])])
|
@include('admin.fileManager.directories.form', ['directory' => new \App\Models\Directory(), 'action' => route('upload.postNewDirectory')])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{{--<ul class="accordion" data-accordion data-allow-all-closed="true">--}}
|
|
||||||
{{--<li class="accordion-item is-active" data-accordion-item>--}}
|
|
||||||
{{--<a href="#" class="accordion-title">@lang('admin/fileManager.newFile')</a>--}}
|
|
||||||
|
|
||||||
{{--<div class="accordion-content" data-tab-content>--}}
|
|
||||||
{{--@include('admin.fileManager.newFileForm')--}}
|
|
||||||
{{--</div>--}}
|
|
||||||
{{--</li>--}}
|
|
||||||
{{--<li class="accordion-item" data-accordion-item>--}}
|
|
||||||
{{--<a href="#" class="accordion-title">@lang('admin/fileManager.editDirectory')</a>--}}
|
|
||||||
|
|
||||||
{{--<div class="accordion-content" data-tab-content>--}}
|
|
||||||
{{--@include('admin.fileManager.directories.editForm')--}}
|
|
||||||
{{--</div>--}}
|
|
||||||
{{--</li>--}}
|
|
||||||
{{--@endif--}}
|
|
||||||
{{--<li class="accordion-item" data-accordion-item>--}}
|
|
||||||
{{--<a href="#" class="accordion-title">@lang('admin/fileManager.newDirectory')</a>--}}
|
|
||||||
|
|
||||||
{{--<div class="accordion-content" data-tab-content>--}}
|
|
||||||
{{--@include('admin.fileManager.directories.newForm')--}}
|
|
||||||
{{--</div>--}}
|
|
||||||
{{--</li>--}}
|
|
||||||
{{--</ul>--}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@endsection
|
||||||
@stop
|
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
<div class="card {{isset($type) ? 'card-'.$type : 'card-default'}}">
|
<div class="card {{isset($type) ? 'card-'.$type : 'card-default'}} {{$cardClass or ''}}">
|
||||||
|
@if(!empty($title))
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="header-block">
|
<div class="header-block">
|
||||||
<p class="title"> {!! $title !!} </p>
|
<p class="title"> {!! $title !!} </p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
<div class="card-block">
|
<div class="card-block">
|
||||||
{!! $body !!}
|
{!! $body !!}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||