diff --git a/app/Console/Commands/TranslateAll.php b/app/Console/Commands/TranslateAll.php
index 26635d17..508802fc 100644
--- a/app/Console/Commands/TranslateAll.php
+++ b/app/Console/Commands/TranslateAll.php
@@ -29,15 +29,32 @@ class TranslateAll extends Command
/**
* Execute the console command.
- * @return mixed
*/
public function handle()
{
$this->call('translate:dir', ['dir' => 'resources/lang']);
-
- $modules = File::directories('modules');
- foreach ($modules as $module) {
- $this->call('translate:dir', ['dir' => $module.'/Resources/lang']);
+
+ $this->crawlDirectory('modules');
+ $this->crawlDirectory('templates', ['templates/Base']);
+ $this->crawlDirectory('templates/Base');
+ }
+
+ /**
+ * Crawl directories and search for directories with translations
+ *
+ * @param $directory
+ * @param array $ignoredDirectories
+ */
+ protected function crawlDirectory($directory, $ignoredDirectories = [])
+ {
+ $directories = File::directories($directory);
+ foreach ($directories as $dir) {
+
+ if (in_array($dir, $ignoredDirectories)) {
+ continue;
+ }
+
+ $this->call('translate:dir', ['dir' => $dir . '/Resources/lang']);
}
}
}
\ No newline at end of file
diff --git a/app/Console/Commands/Translations.php b/app/Console/Commands/TranslateDirectory.php
similarity index 94%
rename from app/Console/Commands/Translations.php
rename to app/Console/Commands/TranslateDirectory.php
index 333cb971..22e1bcf5 100644
--- a/app/Console/Commands/Translations.php
+++ b/app/Console/Commands/TranslateDirectory.php
@@ -6,7 +6,7 @@ use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
-class Translations extends Command
+class TranslateDirectory extends Command
{
/**
* The name and signature of the console command.
@@ -25,7 +25,6 @@ class Translations extends Command
/**
* Execute the console command.
- * @return mixed
*/
public function handle()
{
@@ -33,15 +32,16 @@ class Translations extends Command
$defaultLocales = config('app.fallback_locale');
$currentLocales = config('app.locale');
- $defaultLocalesDir = $dir . '/' . $defaultLocales;
- $currentLocalesDir = $dir . '/' . $currentLocales;
+ $defaultLocalesDir = base_path($dir . '/' . $defaultLocales);
+ $currentLocalesDir = base_path($dir . '/' . $currentLocales);
if (!is_dir($defaultLocalesDir)) {
// this is the place for checking for submodules
$modulePath = dirname(dirname($dir));
- if (file_exists($modulePath . '/info.php')) {
+ // does exist directory with translations?
+ if (is_dir(base_path($modulePath . '/Resources/lang')) || file_exists(base_path($modulePath.DIRECTORY_SEPARATOR.'info.php'))) {
$modules = File::directories($modulePath);
foreach ($modules as $module) {
$this->call('translate:dir', ['dir' => $module . '/Resources/lang']);
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
index 962299bc..4c3aadf1 100644
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -18,7 +18,7 @@ class Kernel extends ConsoleKernel
Commands\ChangePassword::class,
Commands\InstallModule::class,
Commands\InstallAllModules::class,
- Commands\Translations::class,
+ Commands\TranslateDirectory::class,
Commands\TranslateAll::class,
Commands\InitDatabaseSchema::class,
Commands\SetTemplate::class,
diff --git a/app/Enumerations/ActiveContentStatuses.php b/app/Enumerations/ActiveContentStatuses.php
deleted file mode 100644
index ed48c909..00000000
--- a/app/Enumerations/ActiveContentStatuses.php
+++ /dev/null
@@ -1,18 +0,0 @@
- $value) {
- if ($key == Content::STATUS_DELETED) {
- continue;
- }
-
- self::push($key, $value);
- }
- }
-}
\ No newline at end of file
diff --git a/app/Enumerations/ContentStatuses.php b/app/Enumerations/ContentStatuses.php
index 8ed34f9f..9ed89887 100644
--- a/app/Enumerations/ContentStatuses.php
+++ b/app/Enumerations/ContentStatuses.php
@@ -9,7 +9,6 @@ class ContentStatuses extends BaseEnumeration
{
$roles = [
Content::STATUS_DRAFT => 'admin/contents.status_' . Content::STATUS_DRAFT,
- Content::STATUS_DELETED => 'admin/contents.status_' . Content::STATUS_DELETED,
Content::STATUS_PROTECTED => 'admin/contents.status_' . Content::STATUS_PROTECTED,
Content::STATUS_PUBLIC => 'admin/contents.status_' . Content::STATUS_PUBLIC
];
diff --git a/app/Enumerations/UserStates.php b/app/Enumerations/UserStates.php
index a693dce9..e28d4662 100644
--- a/app/Enumerations/UserStates.php
+++ b/app/Enumerations/UserStates.php
@@ -15,7 +15,6 @@ class UserStates extends BaseEnumeration
public static function init()
{
$items = [
- User::STATE_DELETED => 'admin/userManagement.status_' . User::STATE_DELETED,
User::STATE_BLOCKED => 'admin/userManagement.status_' . User::STATE_BLOCKED,
User::STATE_ACTIVE => 'admin/userManagement.status_' . User::STATE_ACTIVE
];
diff --git a/app/Events/DeleteContent.php b/app/Events/DeleteContent.php
index fe1f555a..47e2a7ff 100644
--- a/app/Events/DeleteContent.php
+++ b/app/Events/DeleteContent.php
@@ -12,7 +12,6 @@ class DeleteContent extends Event
* @var Content
*/
public $page;
- public $revision;
/**
* Create a new event instance.
@@ -20,9 +19,8 @@ class DeleteContent extends Event
* @param Content $page
* @param $revision
*/
- public function __construct(Content $page, $revision)
+ public function __construct(Content $page)
{
$this->page = $page;
- $this->revision = $revision;
}
}
diff --git a/app/Handlers/Contracts/BaseModuleHandler.php b/app/Handlers/Contracts/BaseModuleHandler.php
index dab8a282..9cd17c6b 100644
--- a/app/Handlers/Contracts/BaseModuleHandler.php
+++ b/app/Handlers/Contracts/BaseModuleHandler.php
@@ -5,8 +5,6 @@ use App\Models\User;
interface BaseModuleHandler
{
-// public static function getModuleId();
-
/**
* Register admin menu (or multiple ones)
*
@@ -18,9 +16,10 @@ interface BaseModuleHandler
public static function registerAdminMenu(User $user);
/**
- * Install module
+ * Install module.
*
- * @return mixed
+ * This method is called after inserting info about module into database. It can be called only using Artisan in
+ * CLI.
*/
public static function install();
}
\ No newline at end of file
diff --git a/app/Handlers/Contracts/ContentTitles.php b/app/Handlers/Contracts/ContentTitles.php
new file mode 100644
index 00000000..5d44f24f
--- /dev/null
+++ b/app/Handlers/Contracts/ContentTitles.php
@@ -0,0 +1,40 @@
+template, ['page' => $content, 'extra' => $parameters]);
+ }
+
public static function getExtendedFormSections()
{
return [
diff --git a/app/Handlers/Registrators/TemplateRegistrator.php b/app/Handlers/Registrators/TemplateRegistrator.php
index 1d0f5257..b2cd83db 100644
--- a/app/Handlers/Registrators/TemplateRegistrator.php
+++ b/app/Handlers/Registrators/TemplateRegistrator.php
@@ -28,6 +28,10 @@ class TemplateRegistrator
* @var int ID of module
*/
protected $moduleId;
+ /**
+ * @var array list of all registered template paths
+ */
+ protected $paths = [];
/**
* Set base path
@@ -64,7 +68,7 @@ class TemplateRegistrator
*/
public function setNamespace($namespace)
{
- $this->namespace = $namespace . '::';
+ $this->namespace = $namespace;
}
/**
@@ -80,24 +84,45 @@ class TemplateRegistrator
* Registers new template path.
* This method registeres given path itself with all subdirectories
*
+ * @param $baseDirectory
* @param string $path path relatively to root of the project
* @param string $name human readable identification of given template path
*
* @throws \Exception
*/
- public function register($path, $name)
+ public function register($baseDirectory, $path, $name)
{
- // check if base directory was set
- if (!$this->baseDirectory || !is_dir($this->baseDirectory)) {
- throw new \Exception('Set $baseDirectory before registering template path.');
+ $this->paths[] = [
+ 'namespace' => $this->namespace,
+ 'moduleId' => $this->moduleId,
+ 'baseDirectory' => $baseDirectory,
+ 'path' => $this->baseDirectory . DIRECTORY_SEPARATOR . $path,
+ 'name' => $name
+ ];
+ $this->unsetNamespace();
+ }
+
+ /**
+ * Save templates into database
+ */
+ public function saveTemplates()
+ {
+ if (!is_array($this->paths) || empty($this->paths)) {
+ return;
}
- $this->registeredPath = $this->baseDirectory . DIRECTORY_SEPARATOR . $path;
+ foreach ($this->paths as $path) {
+ if (!empty($path['namespace'])) {
+ $this->setNamespace($path['namespace'] . '::');
+ }
+ $this->setModuleId($path['moduleId']);
+ $this->setBaseDirectory($path['baseDirectory']);
- // register path
- $this->registerPath($this->registeredPath, $name);
-
- $this->unsetNamespace();
+ $this->registeredPath = $this->baseDirectory . DIRECTORY_SEPARATOR . $path['path'];
+ // register path
+ $this->registerPath($this->registeredPath, $path['name']);
+ $this->unsetNamespace();
+ }
}
/**
@@ -146,7 +171,7 @@ class TemplateRegistrator
Template::ASSETS_DIRECTORY,
Template::MODULES_DIRECTORY
];
-
+
if (in_array($dirName, $ignoredDirectories)) {
return;
}
diff --git a/app/Handlers/Registrators/WidgetRegistrator.php b/app/Handlers/Registrators/WidgetRegistrator.php
index e70cf9ee..f97aaef4 100644
--- a/app/Handlers/Registrators/WidgetRegistrator.php
+++ b/app/Handlers/Registrators/WidgetRegistrator.php
@@ -3,44 +3,56 @@ namespace App\Handlers\Registrators;
use App\Enumerations\WidgetTypesWithHandlers;
use App\Models\WidgetType;
-use App\Widgets\Contracts\PublicWidget;
-use Symfony\Component\Process\Exception\InvalidArgumentException;
class WidgetRegistrator
{
- protected $widgets;
+ protected $registeredWidgets = [];
- function __construct()
- {
- $this->widgets = WidgetTypesWithHandlers::getSimple();
- }
/**
* Method used for registering new widgets
*
- * @param $classname
+ * @param $classname
+ * @param null $templateId
+ * @param null $moduleId
*/
- public function register($classname)
+ public function register($classname, $templateId = null, $moduleId = null)
{
- $class = new $classname;
- if (!$class instanceof PublicWidget) {
- throw new InvalidArgumentException($class . ' must implement PublicWidget interface.');
- }
+ $this->registeredWidgets[] = [
+ 'class' => $classname,
+ 'templateId' => $templateId,
+ 'moduleId' => $moduleId
+ ];
+ }
- // register widget as new widget type
- if (!in_array($classname, $this->widgets)) {
- $widgetName = call_user_func($classname . '::getName');
- $widgetDescription = call_user_func($classname . '::getDescription');
+ /**
+ * Install all non-installed widgets
+ */
+ public function installWidgets()
+ {
+ $installed = WidgetTypesWithHandlers::getSimple();
+ foreach ($this->registeredWidgets as $registeredWidget) {
+ $classname = $registeredWidget['class'];
+ $templateId = $registeredWidget['templateId'];
+ $moduleId = $registeredWidget['moduleId'];
- // create row in widget types
- WidgetType::create([
- 'handler' => $classname,
- 'name' => $widgetName,
- 'description' => $widgetDescription
- ]);
+ // register widget as new widget type
+ if (!in_array($classname, $installed)) {
+ $widgetName = call_user_func($classname . '::getName');
+ $widgetDescription = call_user_func($classname . '::getDescription');
- // install widget (if neccessary)
- call_user_func($classname . '::install');
+ // create row in widget types
+ WidgetType::create([
+ 'handler' => $classname,
+ 'name' => $widgetName,
+ 'module_id' => $moduleId,
+ 'template_id' => $templateId,
+ 'description' => $widgetDescription
+ ]);
+
+ // install widget (if neccessary)
+ call_user_func($classname . '::install');
+ }
}
}
}
diff --git a/app/Handlers/Search/Files.php b/app/Handlers/Search/Files.php
index 5105b3c5..79d66bce 100644
--- a/app/Handlers/Search/Files.php
+++ b/app/Handlers/Search/Files.php
@@ -27,6 +27,7 @@ class Files extends Search
$token = $this->tokenize($term);
return File::where('original_filename', 'LIKE', $token)
+ ->orWhere('name', 'LIKE', $token)
->orWhere('keywords', 'LIKE', $token)
->orWhere('description', 'LIKE', $token)
->orWhere('mime_type', 'LIKE', $token)
diff --git a/app/Helpers/CurrentTemplate.php b/app/Helpers/CurrentTemplate.php
new file mode 100644
index 00000000..9f88dd88
--- /dev/null
+++ b/app/Helpers/CurrentTemplate.php
@@ -0,0 +1,57 @@
+where('enabled', true)
+ ->first();
+
+ if (self::$template) {
+ self::$template->module_settings = json_decode(self::$template->module_settings);
+ }
+
+ self::$initialized = true;
+ }
+
+ return self::$template;
+ }
+
+ /**
+ * Shortcut for getting template handler
+ *
+ * @return string
+ * @throws \ErrorException
+ */
+ public static function handler()
+ {
+ $template = self::get();
+
+ if (!$template) {
+ throw new \ErrorException('No template selected, no handler available!');
+ }
+
+ return $template->handler;
+ }
+
+ /**
+ * Reset currently set template and load another one on next call of get() method.
+ */
+ public static function reset()
+ {
+ self::$initialized = false;
+ }
+}
\ No newline at end of file
diff --git a/app/Helpers/FileManager.php b/app/Helpers/FileManager.php
index 568411d9..01459d13 100644
--- a/app/Helpers/FileManager.php
+++ b/app/Helpers/FileManager.php
@@ -17,34 +17,42 @@ class FileManager
switch ($type) {
case 'image':
- // try to check if file have thumbnail
- if (file_exists(config('app.thumbnail_url') . '/' . $file->filename)) {
- $url = config('app.thumbnail_url') . '/' . $file->filename;
- } else {
- $url = config('app.upload_url') . '/' . $file->filename;
- }
+ $url = Template::thumbnail($file->filename);
return '
';
break;
case 'text':
- return '';
+ return self::getIcon($file, 'fa-file-text-o');
break;
case 'application':
switch ($subtype) {
case 'pdf':
- return '';
+ return self::getIcon($file, 'fa-file-pdf-o');
break;
default:
- return '';
+ return self::getIcon($file, 'fa-newspaper-o');
break;
}
break;
default:
- return '';
+ return self::getIcon($file, 'fa-question');
break;
}
}
+ /**
+ * Shortcut for displaying icons
+ *
+ * @param $file
+ * @param $icon
+ *
+ * @return string
+ */
+ protected static function getIcon($file, $icon)
+ {
+ return '
diff --git a/modules/Blog/ArticleList/Handlers/ArticleList.php b/modules/Blog/ArticleList/Handlers/ArticleList.php
index 555464cf..84bdbcfe 100644
--- a/modules/Blog/ArticleList/Handlers/ArticleList.php
+++ b/modules/Blog/ArticleList/Handlers/ArticleList.php
@@ -98,7 +98,7 @@ class ArticleList extends Handler
$articles = $articles->orderBy('created_at', 'DESC')
->paginate(20);
- return Controller::VisitorsView($content->template, ['page' => $content, 'articles' => $articles]);
+ return Controller::VisitorsView($content->template, ['page' => $content, 'articles' => $articles, 'extra' => $parameters]);
}
public static function getModuleId()
diff --git a/modules/Blog/ArticleList/Http/routes.php b/modules/Blog/ArticleList/Http/routes.php
index 001beb8b..b3d9bbc7 100644
--- a/modules/Blog/ArticleList/Http/routes.php
+++ b/modules/Blog/ArticleList/Http/routes.php
@@ -1,6 +1 @@
'web', 'prefix' => 'articlelist', 'namespace' => 'Modules\Blog\ArticleList\Http\Controllers'], function()
-{
- Route::get('/', 'ArticleListController@index');
-});
\ No newline at end of file
diff --git a/modules/Categories/Http/routes.php b/modules/Categories/Http/routes.php
index 825dd9f8..52ff9a1a 100644
--- a/modules/Categories/Http/routes.php
+++ b/modules/Categories/Http/routes.php
@@ -1,17 +1,23 @@
['web', 'auth', 'adminMenu'],
- 'prefix' => 'admin/categories',
+ 'prefix' => LaravelLocalization::setLocale() . '/admin/categories',
+ 'middleware' => ['admin'],
'namespace' => 'Modules\Categories\Http\Controllers'
], function () {
- Route::get('/', 'CategoriesOverview@getOverview')->name('categories.overview');
+ Route::get('/', 'CategoriesOverview@getOverview')
+ ->name('categories.overview');
- Route::get('/new', 'CreateNewCategory@getNew')->name('categories.new');
- Route::post('/new', 'CreateNewCategory@postNew')->name('categories.postNew');
+ Route::get('/new', 'CreateNewCategory@getNew')
+ ->name('categories.new');
+ Route::post('/new', 'CreateNewCategory@postNew')
+ ->name('categories.postNew');
- Route::get('/edit/{id}', 'EditCategory@getEdit')->name('categories.edit');
- Route::post('/edit/{id}', 'EditCategory@postEdit')->name('categories.postEdit');
+ Route::get('/edit/{id}', 'EditCategory@getEdit')
+ ->name('categories.edit');
+ Route::post('/edit/{id}', 'EditCategory@postEdit')
+ ->name('categories.postEdit');
- Route::get('/delete/{id}', 'EditCategory@delete')->name('categories.delete');
+ Route::get('/delete/{id}', 'EditCategory@delete')
+ ->name('categories.delete');
});
\ No newline at end of file
diff --git a/modules/ContactForm/Handlers/ContactForm.php b/modules/ContactForm/Handlers/ContactForm.php
index 4c7c4a85..76f0adc4 100644
--- a/modules/ContactForm/Handlers/ContactForm.php
+++ b/modules/ContactForm/Handlers/ContactForm.php
@@ -2,30 +2,15 @@
namespace Modules\ContactForm\Handlers;
use App\Enumerations\ModulesHandlerToId;
+use App\Handlers\Contracts\ContentTitles;
use App\Handlers\Handler;
-use App\Http\Controllers\Admin\EditContent;
-use App\Http\Controllers\Controller;
+use App\Http\Controllers\Admin\Contents\EditContent;
use App\Http\Requests\Request;
use App\Models\Content;
use App\Models\User;
-class ContactForm extends Handler
+class ContactForm extends Handler implements ContentTitles
{
- /**
- * Render given module into visitor area.
- *
- * @param Content $content DB model from table contents
- * @param array $parameters parameters used for modifications/custom settings of given model
- *
- * @return mixed
- */
- public function render(Content $content, $parameters)
- {
- $content->module_settings = json_decode($content->module_settings);
-
- return Controller::VisitorsView($content->template, ['page' => $content]);
- }
-
public static function getHistoryHandler()
{
return ContactFormHistory::class;
@@ -45,7 +30,7 @@ class ContactForm extends Handler
$settings = [
'phone' => $request->phone,
'email' => $request->email,
- 'contactEmail' => $request->ContactEmail,
+ 'contactEmail' => $request->contactEmail,
'subject' => $request->subject,
'companyName' => $request->companyName,
'address' => $request->address,
@@ -174,7 +159,6 @@ class ContactForm extends Handler
*/
public static function install()
{
- // TODO: Implement install() method.
}
/**
@@ -188,4 +172,38 @@ class ContactForm extends Handler
{
// nothing to do
}
+
+ /**
+ * Get translated title for pages overview of given type.
+ *
+ * This value is used for rendering list of all content pages of given type in administration.
+ *
+ * @return string
+ */
+ public static function getOverviewTitle()
+ {
+ return trans('contactform::module.allForms');
+ }
+
+ /**
+ * Title displayed above for for creating new content page
+ *
+ * @return string
+ */
+ public static function getCreateNewTitle()
+ {
+ return trans('contactform::module.newForm');
+ }
+
+ /**
+ * Title for form displayed for editin content page
+ *
+ * @param Content $content
+ *
+ * @return mixed
+ */
+ public static function getEditTitle(Content $content)
+ {
+ return trans('contactform::module.editForm');
+ }
}
\ No newline at end of file
diff --git a/modules/ContactForm/Http/routes.php b/modules/ContactForm/Http/routes.php
index 8387a5db..2ff17cff 100644
--- a/modules/ContactForm/Http/routes.php
+++ b/modules/ContactForm/Http/routes.php
@@ -1,24 +1,12 @@
['web', 'auth', 'adminMenu'],
- 'namespace' => '\Modules\ContactForm\Http\Controllers\Admin',
- 'prefix' => 'admin/contactform'
- ], function () {
- Route::get('messsages/sent', 'SentMessagesOverview@getList')
- ->name('emails.sent');
-});
-
Route::group([
'middleware' => ['web'],
'namespace' => '\Modules\ContactForm\Http\Controllers\Visitor',
- 'prefix' => 'contactform'
+ 'prefix' => LaravelLocalization::setLocale() . '/contactform'
], function () {
-
-
+
// method for sending new message
-
+
Route::post('/message/{formId}', 'CreateNewMessage@postMessage')
->name('email.send');
});
\ No newline at end of file
diff --git a/modules/ContactForm/Resources/lang/cs/module.php b/modules/ContactForm/Resources/lang/cs/module.php
index cc9a1388..c76b9420 100644
--- a/modules/ContactForm/Resources/lang/cs/module.php
+++ b/modules/ContactForm/Resources/lang/cs/module.php
@@ -1,5 +1,8 @@
"Všechny formuláře",
"description" => "Jednoduchý kontaktní formulář",
+"editForm" => "Upravuji formulář",
"name" => "Kontaktní formulář",
+"newForm" => "Vytvořit nový kontaktní formulář",
];
diff --git a/modules/ContactForm/Resources/lang/en/module.php b/modules/ContactForm/Resources/lang/en/module.php
index 63e4708e..3e9d374e 100644
--- a/modules/ContactForm/Resources/lang/en/module.php
+++ b/modules/ContactForm/Resources/lang/en/module.php
@@ -1,5 +1,8 @@
'Contact form',
- 'description' => 'Simple contact form'
+ 'description' => 'Simple contact form',
+ 'allForms' => 'All contact forms',
+ 'newForm' => 'Create new contact form',
+ 'editForm' => 'Editing contact form'
];
\ No newline at end of file
diff --git a/modules/Gallery/Handlers/Gallery.php b/modules/Gallery/Handlers/Gallery.php
index 59a1f502..4f911737 100644
--- a/modules/Gallery/Handlers/Gallery.php
+++ b/modules/Gallery/Handlers/Gallery.php
@@ -28,11 +28,6 @@ class Gallery implements AppHandler
*/
public function render(Content $content, $parameters)
{
- // if settings is still string, convert it into object
- if (is_string($content->module_settings)) {
- $content->module_settings = json_decode($content->module_settings);
- }
-
// get directory ID
$directoryId = $content->module_settings->directoryId;
@@ -42,7 +37,11 @@ class Gallery implements AppHandler
->get();
// render content
- return Controller::VisitorsView($content->template, ['images' => $images, 'page' => $content]);
+ return Controller::VisitorsView($content->template, [
+ 'images' => $images,
+ 'page' => $content,
+ 'extra' => $parameters
+ ]);
}
public static function getHistoryHandler()
diff --git a/modules/Gallery/Http/routes.php b/modules/Gallery/Http/routes.php
index 3aa33d49..258f049b 100644
--- a/modules/Gallery/Http/routes.php
+++ b/modules/Gallery/Http/routes.php
@@ -1,8 +1,8 @@
['web', 'auth', 'adminMenu'],
+ 'middleware' => ['admin'],
'namespace' => 'Modules\Gallery\Http\Controllers\Admin',
- 'prefix' => 'admin/gallery'
+ 'prefix' => LaravelLocalization::setLocale() . 'admin/gallery'
], function () {
// method for creating slider from photogallery
diff --git a/modules/StaticPages/Handlers/StaticPage.php b/modules/StaticPages/Handlers/StaticPage.php
index 011f7d56..128dac6b 100644
--- a/modules/StaticPages/Handlers/StaticPage.php
+++ b/modules/StaticPages/Handlers/StaticPage.php
@@ -2,13 +2,14 @@
namespace Modules\StaticPages\Handlers;
use App\Enumerations\ModulesHandlerToId;
+use App\Handlers\Contracts\ContentTitles;
use App\Handlers\Handler;
use App\Http\Controllers\Controller;
use App\Http\Requests\Request;
use App\Models\Content;
use App\Models\User;
-class StaticPage extends Handler
+class StaticPage extends Handler implements ContentTitles
{
public static function registerAdminMenu(User $user)
{
@@ -33,19 +34,6 @@ class StaticPage extends Handler
return $moduleId;
}
- /**
- * Render given module into visitor area.
- *
- * @param Content $content DB model from table contents
- * @param array $parameters parameters used for modifications/custom settings of given model
- *
- * @return mixed
- */
- public function render(Content $content, $parameters)
- {
- return Controller::VisitorsView($content->template, ['page' => $content]);
- }
-
/**
* Does given module manage content? Or is it just module with widgets/something internal/something absolutely else?
*
@@ -110,4 +98,39 @@ class StaticPage extends Handler
{
// nothing to do
}
+
+
+ /**
+ * Get translated title for pages overview of given type.
+ *
+ * This value is used for rendering list of all content pages of given type in administration.
+ *
+ * @return string
+ */
+ public static function getOverviewTitle()
+ {
+ return trans('staticpages::module.allPages');
+ }
+
+ /**
+ * Title displayed above for for creating new content page
+ *
+ * @return string
+ */
+ public static function getCreateNewTitle()
+ {
+ return trans('staticpages::module.newPage');
+ }
+
+ /**
+ * Title for form displayed for editin content page
+ *
+ * @param Content $content
+ *
+ * @return mixed
+ */
+ public static function getEditTitle(Content $content)
+ {
+ return trans('staticpages::module.editPage');
+ }
}
\ No newline at end of file
diff --git a/modules/StaticPages/Providers/StaticPagesServiceProvider.php b/modules/StaticPages/Providers/StaticPagesServiceProvider.php
index 5b9e181b..5e38229e 100644
--- a/modules/StaticPages/Providers/StaticPagesServiceProvider.php
+++ b/modules/StaticPages/Providers/StaticPagesServiceProvider.php
@@ -1,12 +1,6 @@
publishes([$config => config_path('staticpages.php')]);
$this->mergeConfigFrom($config, 'staticpages');
}
diff --git a/modules/StaticPages/Resources/lang/cs/module.php b/modules/StaticPages/Resources/lang/cs/module.php
index a7e99f44..e0dfbbeb 100644
--- a/modules/StaticPages/Resources/lang/cs/module.php
+++ b/modules/StaticPages/Resources/lang/cs/module.php
@@ -1,5 +1,8 @@
"Všechny statické stránky",
"description" => "Statické stránky jsou určeny k zobrazování statického obsahu na stránkách.",
+"editPage" => "Upravuji statickou stránku",
"name" => "Statické stránky",
+"newPage" => "Vytvářím novou stránku",
];
diff --git a/modules/StaticPages/Resources/lang/en/module.php b/modules/StaticPages/Resources/lang/en/module.php
index a263fd12..db22a5b4 100644
--- a/modules/StaticPages/Resources/lang/en/module.php
+++ b/modules/StaticPages/Resources/lang/en/module.php
@@ -1,5 +1,8 @@
'Static pages',
- 'description' => 'Static pages are intended for displaying static content on webpage.'
+ 'description' => 'Static pages are intended for displaying static content on webpage.',
+ 'allPages' => 'All static pages',
+ 'editPage' => 'Editing static page',
+ 'newPage' => 'Create new static page'
];
\ No newline at end of file
diff --git a/resources/assets/admin/css/app-blue.css b/resources/assets/admin/css/app-blue.css
index 3b20bbcf..7237a046 100644
--- a/resources/assets/admin/css/app-blue.css
+++ b/resources/assets/admin/css/app-blue.css
@@ -2770,3 +2770,7 @@ span a {
@media (max-width: 767px) {
.header .header-block-nav .profile-dropdown-menu {
margin-top: 8px; } }
+
+.tag-primary {
+ background-color: #52BCD3;
+}
\ No newline at end of file
diff --git a/resources/assets/admin/css/app-custom.css b/resources/assets/admin/css/app-custom.css
index a3b1afec..911a3880 100644
--- a/resources/assets/admin/css/app-custom.css
+++ b/resources/assets/admin/css/app-custom.css
@@ -2770,3 +2770,7 @@ span a {
@media (max-width: 767px) {
.header .header-block-nav .profile-dropdown-menu {
margin-top: 8px; } }
+
+.tag-primary {
+ background-color: #59c2e6;
+}
\ No newline at end of file
diff --git a/resources/assets/admin/css/app-green.css b/resources/assets/admin/css/app-green.css
index 3e24e7c9..476f3d9a 100644
--- a/resources/assets/admin/css/app-green.css
+++ b/resources/assets/admin/css/app-green.css
@@ -2770,3 +2770,7 @@ span a {
@media (max-width: 767px) {
.header .header-block-nav .profile-dropdown-menu {
margin-top: 8px; } }
+
+.tag-primary {
+ background-color: #85CE36;
+}
\ No newline at end of file
diff --git a/resources/assets/admin/css/app-orange.css b/resources/assets/admin/css/app-orange.css
index 45a0126d..c2cd5d37 100644
--- a/resources/assets/admin/css/app-orange.css
+++ b/resources/assets/admin/css/app-orange.css
@@ -2770,3 +2770,7 @@ span a {
@media (max-width: 767px) {
.header .header-block-nav .profile-dropdown-menu {
margin-top: 8px; } }
+
+.tag-primary {
+ background-color: #fe821d;
+}
diff --git a/resources/assets/admin/css/app-purple.css b/resources/assets/admin/css/app-purple.css
index 0085c195..50087170 100644
--- a/resources/assets/admin/css/app-purple.css
+++ b/resources/assets/admin/css/app-purple.css
@@ -2770,3 +2770,7 @@ span a {
@media (max-width: 767px) {
.header .header-block-nav .profile-dropdown-menu {
margin-top: 8px; } }
+
+.tag-primary {
+ background-color: #7867A7;
+}
diff --git a/resources/assets/admin/css/app-red.css b/resources/assets/admin/css/app-red.css
index f6e5779a..324bed45 100644
--- a/resources/assets/admin/css/app-red.css
+++ b/resources/assets/admin/css/app-red.css
@@ -2770,3 +2770,7 @@ span a {
@media (max-width: 767px) {
.header .header-block-nav .profile-dropdown-menu {
margin-top: 8px; } }
+
+.tag-primary {
+ background-color: #FF6161;
+}
\ No newline at end of file
diff --git a/resources/assets/admin/css/app-seagreen.css b/resources/assets/admin/css/app-seagreen.css
index dbab0aad..74c368c6 100644
--- a/resources/assets/admin/css/app-seagreen.css
+++ b/resources/assets/admin/css/app-seagreen.css
@@ -2770,3 +2770,7 @@ span a {
@media (max-width: 767px) {
.header .header-block-nav .profile-dropdown-menu {
margin-top: 8px; } }
+
+.tag-primary {
+ background-color: #4bcf99;
+}
diff --git a/resources/assets/admin/css/app.css b/resources/assets/admin/css/app.css
index 961db791..d0d926ad 100644
--- a/resources/assets/admin/css/app.css
+++ b/resources/assets/admin/css/app.css
@@ -2883,3 +2883,7 @@ pre {
@media (max-width: 767px) {
.header .header-block-nav .profile-dropdown-menu {
margin-top: 8px; } }
+
+.tag-primary {
+ background-color: #85CE36;
+}
\ No newline at end of file
diff --git a/resources/assets/admin/css/vendor.css b/resources/assets/admin/css/vendor.css
index 85fc56f3..747d0f87 100644
--- a/resources/assets/admin/css/vendor.css
+++ b/resources/assets/admin/css/vendor.css
@@ -14375,11 +14375,113 @@ img {
.bold {
font-weight: bold;
}
-
+.m-l-10 {
+ margin-left: 10px;
+}
.m-t-15 {
margin-top: 15px;
}
.p-tb-15 {
padding-top: 15px;
padding-bottom: 15px;
+}
+
+.card .card-header .title {
+ line-height: 1.5em;
+}
+
+.card .card-header .title small {
+ 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%;
+}
+
+
+.tag {
+ display: inline-block;
+ padding: 0.25em 0.4em;
+ font-size: 75%;
+ font-weight: bold;
+ line-height: 1;
+ color: #fff;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: 0.25rem;
+}
+
+.tag:empty {
+ display: none;
+}
+
+.btn .tag {
+ position: relative;
+ top: -1px;
+}
+
+a.tag:focus, a.tag:hover {
+ color: #fff;
+ text-decoration: none;
+ cursor: pointer;
+}
+
+.tag-pill {
+ padding-right: 0.6em;
+ padding-left: 0.6em;
+ border-radius: 10rem;
+}
+
+.tag-default {
+ background-color: #818a91;
+}
+
+.tag-default[href]:focus, .tag-default[href]:hover {
+ background-color: #687077;
+}
+
+.tag-success {
+ background-color: #5cb85c;
+}
+
+.tag-success[href]:focus, .tag-success[href]:hover {
+ background-color: #449d44;
+}
+
+.tag-info {
+ background-color: #5bc0de;
+}
+
+.tag-info[href]:focus, .tag-info[href]:hover {
+ background-color: #31b0d5;
+}
+
+.tag-warning {
+ background-color: #f0ad4e;
+}
+
+.tag-warning[href]:focus, .tag-warning[href]:hover {
+ background-color: #ec971f;
+}
+
+.tag-danger {
+ background-color: #d9534f;
+}
+
+.tag-danger[href]:focus, .tag-danger[href]:hover {
+ background-color: #c9302c;
}
\ No newline at end of file
diff --git a/resources/assets/admin/js/app.js b/resources/assets/admin/js/app.js
index 4b10be8d..5ef8ea0d 100644
--- a/resources/assets/admin/js/app.js
+++ b/resources/assets/admin/js/app.js
@@ -152,179 +152,179 @@ $ (function () {
$el.addClass ('visible');
}, 1000);
-})
-//LoginForm validation
-$ (function () {
- if (!$ ('#login-form').length) {
- return false;
- }
-
- var loginValidationSettings = {
- rules: {
- username: {
- required: true,
- email: true
- },
- password: "required",
- agree: "required"
- },
- messages: {
- username: {
- required: "Please enter username",
- email: "Please enter a valid email address"
- },
- password: "Please enter password",
- agree: "Please accept our policy"
- },
- invalidHandler: function () {
- animate ({
- name: 'shake',
- selector: '.auth-container > .card'
- });
- }
- }
-
- $.extend (loginValidationSettings, config.validations);
-
- $ ('#login-form').validate (loginValidationSettings);
-})
-//LoginForm validation
-$ (function () {
- if (!$ ('#reset-form').length) {
- return false;
- }
-
- var resetValidationSettings = {
- rules: {
- email1: {
- required: true,
- email: true
- }
- },
- messages: {
- email1: {
- required: "Please enter email address",
- email: "Please enter a valid email address"
- }
- },
- invalidHandler: function () {
- animate ({
- name: 'shake',
- selector: '.auth-container > .card'
- });
- }
- }
-
- $.extend (resetValidationSettings, config.validations);
-
- $ ('#reset-form').validate (resetValidationSettings);
-})
-//LoginForm validation
-$ (function () {
- if (!$ ('#signup-form').length) {
- return false;
- }
-
- var signupValidationSettings = {
- rules: {
- firstname: {
- required: true,
- },
- lastname: {
- required: true,
- },
- email: {
- required: true,
- email: true
- },
- password: {
- required: true,
- minlength: 8
- },
- retype_password: {
- required: true,
- minlength: 8,
- equalTo: "#password"
- },
- agree: {
- required: true,
- }
- },
- groups: {
- name: "firstname lastname",
- pass: "password retype_password",
- },
- errorPlacement: function (error, element) {
- if (
- element.attr ("name") == "firstname" ||
- element.attr ("name") == "lastname"
- ) {
- error.insertAfter ($ ("#lastname").closest ('.row'));
- element.parents ("div.form-group")
- .addClass ('has-error');
- }
- else if (
- element.attr ("name") == "password" ||
- element.attr ("name") == "retype_password"
- ) {
- error.insertAfter ($ ("#retype_password").closest ('.row'));
- element.parents ("div.form-group")
- .addClass ('has-error');
- }
- else if (element.attr ("name") == "agree") {
- error.insertAfter ("#agree-text");
- }
- else {
- error.insertAfter (element);
- }
- },
- messages: {
- firstname: "Please enter firstname and lastname",
- lastname: "Please enter firstname and lastname",
- email: {
- required: "Please enter email",
- email: "Please enter a valid email address"
- },
- password: {
- required: "Please enter password fields.",
- minlength: "Passwords should be at least 8 characters."
- },
- retype_password: {
- required: "Please enter password fields.",
- minlength: "Passwords should be at least 8 characters."
- },
- agree: "Please accept our policy"
- },
- invalidHandler: function () {
- animate ({
- name: 'shake',
- selector: '.auth-container > .card'
- });
- }
- }
-
- $.extend (signupValidationSettings, config.validations);
-
- $ ('#signup-form').validate (signupValidationSettings);
-});
-$ (function () {
-
- $ (".wyswyg").each (function () {
-
- var $toolbar = $ (this).find (".toolbar");
- var $editor = $ (this).find (".editor");
-
- var editor = new Quill ($editor.get (0), {
- theme: 'snow'
- });
-
- editor.addModule ('toolbar', {
- container: $toolbar.get (0) // Selector for toolbar container
- });
-
- });
-
});
+// //LoginForm validation
+// $ (function () {
+// if (!$ ('#login-form').length) {
+// return false;
+// }
+//
+// var loginValidationSettings = {
+// rules: {
+// username: {
+// required: true,
+// email: true
+// },
+// password: "required",
+// agree: "required"
+// },
+// messages: {
+// username: {
+// required: "Please enter username",
+// email: "Please enter a valid email address"
+// },
+// password: "Please enter password",
+// agree: "Please accept our policy"
+// },
+// invalidHandler: function () {
+// animate ({
+// name: 'shake',
+// selector: '.auth-container > .card'
+// });
+// }
+// };
+//
+// $.extend (loginValidationSettings, config.validations);
+//
+// $ ('#login-form').validate (loginValidationSettings);
+// })
+// //LoginForm validation
+// $ (function () {
+// if (!$ ('#reset-form').length) {
+// return false;
+// }
+//
+// var resetValidationSettings = {
+// rules: {
+// email1: {
+// required: true,
+// email: true
+// }
+// },
+// messages: {
+// email1: {
+// required: "Please enter email address",
+// email: "Please enter a valid email address"
+// }
+// },
+// invalidHandler: function () {
+// animate ({
+// name: 'shake',
+// selector: '.auth-container > .card'
+// });
+// }
+// }
+//
+// $.extend (resetValidationSettings, config.validations);
+//
+// $ ('#reset-form').validate (resetValidationSettings);
+// })
+// //LoginForm validation
+// $ (function () {
+// if (!$ ('#signup-form').length) {
+// return false;
+// }
+//
+// var signupValidationSettings = {
+// rules: {
+// firstname: {
+// required: true,
+// },
+// lastname: {
+// required: true,
+// },
+// email: {
+// required: true,
+// email: true
+// },
+// password: {
+// required: true,
+// minlength: 8
+// },
+// retype_password: {
+// required: true,
+// minlength: 8,
+// equalTo: "#password"
+// },
+// agree: {
+// required: true,
+// }
+// },
+// groups: {
+// name: "firstname lastname",
+// pass: "password retype_password",
+// },
+// errorPlacement: function (error, element) {
+// if (
+// element.attr ("name") == "firstname" ||
+// element.attr ("name") == "lastname"
+// ) {
+// error.insertAfter ($ ("#lastname").closest ('.row'));
+// element.parents ("div.form-group")
+// .addClass ('has-error');
+// }
+// else if (
+// element.attr ("name") == "password" ||
+// element.attr ("name") == "retype_password"
+// ) {
+// error.insertAfter ($ ("#retype_password").closest ('.row'));
+// element.parents ("div.form-group")
+// .addClass ('has-error');
+// }
+// else if (element.attr ("name") == "agree") {
+// error.insertAfter ("#agree-text");
+// }
+// else {
+// error.insertAfter (element);
+// }
+// },
+// messages: {
+// firstname: "Please enter firstname and lastname",
+// lastname: "Please enter firstname and lastname",
+// email: {
+// required: "Please enter email",
+// email: "Please enter a valid email address"
+// },
+// password: {
+// required: "Please enter password fields.",
+// minlength: "Passwords should be at least 8 characters."
+// },
+// retype_password: {
+// required: "Please enter password fields.",
+// minlength: "Passwords should be at least 8 characters."
+// },
+// agree: "Please accept our policy"
+// },
+// invalidHandler: function () {
+// animate ({
+// name: 'shake',
+// selector: '.auth-container > .card'
+// });
+// }
+// }
+//
+// $.extend (signupValidationSettings, config.validations);
+//
+// $ ('#signup-form').validate (signupValidationSettings);
+// });
+// $ (function () {
+//
+// $ (".wyswyg").each (function () {
+//
+// var $toolbar = $ (this).find (".toolbar");
+// var $editor = $ (this).find (".editor");
+//
+// var editor = new Quill ($editor.get (0), {
+// theme: 'snow'
+// });
+//
+// editor.addModule ('toolbar', {
+// container: $toolbar.get (0) // Selector for toolbar container
+// });
+//
+// });
+//
+// });
$ (function () {
$ ('#sidebar-menu, #customize-menu').metisMenu ({
@@ -665,398 +665,398 @@ $ (function () {
// });
//
// });
-$ (function () {
-
- if (!$ ('#morris-one-line-chart').length) {
- return false;
- }
-
- function drawMorrisCharts() {
-
- $ ('#morris-one-line-chart').empty ();
-
- Morris.Line ({
- element: 'morris-one-line-chart',
- data: [
- {year: '2008', value: 5},
- {year: '2009', value: 10},
- {year: '2010', value: 8},
- {year: '2011', value: 22},
- {year: '2012', value: 8},
- {year: '2014', value: 10},
- {year: '2015', value: 5}
- ],
- xkey: 'year',
- ykeys: ['value'],
- resize: true,
- lineWidth: 4,
- labels: ['Value'],
- lineColors: [config.chart.colorPrimary.toString ()],
- pointSize: 5,
- });
-
- $ ('#morris-area-chart').empty ();
-
- Morris.Area ({
- element: 'morris-area-chart',
- data: [{period: '2010 Q1', iphone: 2666, ipad: null, itouch: 2647},
- {period: '2010 Q2', iphone: 2778, ipad: 2294, itouch: 2441},
- {period: '2010 Q3', iphone: 4912, ipad: 1969, itouch: 2501},
- {period: '2010 Q4', iphone: 3767, ipad: 3597, itouch: 5689},
- {period: '2011 Q1', iphone: 6810, ipad: 1914, itouch: 2293},
- {period: '2011 Q2', iphone: 5670, ipad: 4293, itouch: 1881},
- {period: '2011 Q3', iphone: 4820, ipad: 3795, itouch: 1588},
- {period: '2011 Q4', iphone: 15073, ipad: 5967, itouch: 5175},
- {period: '2012 Q1', iphone: 10687, ipad: 4460, itouch: 2028},
- {period: '2012 Q2', iphone: 8432, ipad: 5713, itouch: 1791}],
- xkey: 'period',
- ykeys: ['iphone', 'ipad', 'itouch'],
- labels: ['iPhone', 'iPad', 'iPod Touch'],
- pointSize: 2,
- hideHover: 'auto',
- resize: true,
- lineColors: [
- tinycolor (config.chart.colorPrimary.toString ()).lighten (10).toString (),
- tinycolor (config.chart.colorPrimary.toString ()).darken (10).toString (),
- config.chart.colorPrimary.toString ()
- ],
- lineWidth: 2,
- pointSize: 1,
- });
-
- $ ('#morris-donut-chart').empty ();
-
- Morris.Donut ({
- element: 'morris-donut-chart',
- data: [{label: "Download Sales", value: 12},
- {label: "In-Store Sales", value: 30},
- {label: "Mail-Order Sales", value: 20}],
- resize: true,
- colors: [
- tinycolor (config.chart.colorPrimary.toString ()).lighten (10).toString (),
- tinycolor (config.chart.colorPrimary.toString ()).darken (10).toString (),
- config.chart.colorPrimary.toString ()
- ],
- });
-
- $ ('#morris-bar-chart').empty ();
-
- Morris.Bar ({
- element: 'morris-bar-chart',
- data: [{y: '2006', a: 60, b: 50},
- {y: '2007', a: 75, b: 65},
- {y: '2008', a: 50, b: 40},
- {y: '2009', a: 75, b: 65},
- {y: '2010', a: 50, b: 40},
- {y: '2011', a: 75, b: 65},
- {y: '2012', a: 100, b: 90}],
- xkey: 'y',
- ykeys: ['a', 'b'],
- labels: ['Series A', 'Series B'],
- hideHover: 'auto',
- resize: true,
- barColors: [
- config.chart.colorPrimary.toString (),
- tinycolor (config.chart.colorPrimary.toString ()).darken (10).toString ()
- ],
- });
-
- $ ('#morris-line-chart').empty ();
-
- Morris.Line ({
- element: 'morris-line-chart',
- data: [{y: '2006', a: 100, b: 90},
- {y: '2007', a: 75, b: 65},
- {y: '2008', a: 50, b: 40},
- {y: '2009', a: 75, b: 65},
- {y: '2010', a: 50, b: 40},
- {y: '2011', a: 75, b: 65},
- {y: '2012', a: 100, b: 90}],
- xkey: 'y',
- ykeys: ['a', 'b'],
- labels: ['Series A', 'Series B'],
- hideHover: 'auto',
- resize: true,
- lineColors: [
- config.chart.colorPrimary.toString (),
- tinycolor (config.chart.colorPrimary.toString ()).darken (10).toString ()
- ],
- });
- }
-
- drawMorrisCharts ();
-
- $ (document).on ("themechange", function () {
- drawMorrisCharts ();
- });
-});
-$ (function () {
-
- if (!$ ('#dashboard-visits-chart').length) {
- return false;
- }
-
- // drawing visits chart
- drawVisitsChart ();
-
- var el = null;
- var item = 'visits';
-
- $ ('a[data-toggle="tab"]').on ('shown.bs.tab', function (e) {
-
- el = e.target;
- item = $ (el).attr ('href').replace ('#', '');
- switchHistoryCharts (item);
-
- });
-
- $ (document).on ("themechange", function () {
- switchHistoryCharts (item);
- });
-
- function switchHistoryCharts(item) {
- var chartSelector = "#dashboard-" + item + "-chart";
-
- if ($ (chartSelector).has ('svg').length) {
- $ (chartSelector).empty ();
- }
-
- switch (item) {
- case 'visits':
- drawVisitsChart ();
- break;
- case 'downloads':
- drawDownloadsChart ();
- break;
- }
- }
-
- function drawVisitsChart() {
- var dataVisits = [
- {x: '2015-09-01', y: 70},
- {x: '2015-09-02', y: 75},
- {x: '2015-09-03', y: 50},
- {x: '2015-09-04', y: 75},
- {x: '2015-09-05', y: 50},
- {x: '2015-09-06', y: 75},
- {x: '2015-09-07', y: 86}
- ];
-
- Morris.Line ({
- element: 'dashboard-visits-chart',
- data: dataVisits,
- xkey: 'x',
- ykeys: ['y'],
- ymin: 'auto 40',
- labels: ['Visits'],
- xLabels: "day",
- hideHover: 'auto',
- yLabelFormat: function (y) {
- // Only integers
- if (y === parseInt (y, 10)) {
- return y;
- }
- else {
- return '';
- }
- },
- resize: true,
- lineColors: [
- config.chart.colorSecondary.toString (),
- ],
- pointFillColors: [
- config.chart.colorPrimary.toString (),
- ]
- });
- }
-
- function drawDownloadsChart() {
-
- var dataDownloads = [
- {
- year: '2006',
- downloads: 1300
- },
- {
- year: '2007',
- downloads: 1526
- },
- {
- year: '2008',
- downloads: 2000
- },
- {
- year: '2009',
- downloads: 1800
- },
- {
- year: '2010',
- downloads: 1650
- },
- {
- year: '2011',
- downloads: 620
- },
- {
- year: '2012',
- downloads: 1000
- },
- {
- year: '2013',
- downloads: 1896
- },
- {
- year: '2014',
- downloads: 850
- },
- {
- year: '2015',
- downloads: 1500
- }
- ];
-
- Morris.Bar ({
- element: 'dashboard-downloads-chart',
- data: dataDownloads,
- xkey: 'year',
- ykeys: ['downloads'],
- labels: ['Downloads'],
- hideHover: 'auto',
- resize: true,
- barColors: [
- config.chart.colorPrimary.toString (),
- tinycolor (config.chart.colorPrimary.toString ()).darken (10).toString ()
- ],
- });
- }
-});
-
-$ (function () {
-
- function drawDashboardItemsListSparklines() {
- $ (".dashboard-page .items .sparkline").each (function () {
- var type = $ (this).data ('type');
-
- // There is predefined data
- if ($ (this).data ('data')) {
- var data = $ (this).data ('data').split (',').map (function (item) {
- if (item.indexOf (":") > 0) {
- return item.split (":");
- }
- else {
- return item;
- }
- });
- }
- // Generate random data
- else {
- var data = [];
- for (var i = 0; i < 17; i++) {
- data.push (Math.round (100 * Math.random ()));
- }
- }
-
- $ (this).sparkline (data, {
- barColor: config.chart.colorPrimary.toString (),
- height: $ (this).height (),
- type: type
- });
- });
- }
-
- drawDashboardItemsListSparklines ();
-
- $ (document).on ("themechange", function () {
- drawDashboardItemsListSparklines ();
- });
-});
-$ (function () {
-
- var $dashboardSalesBreakdownChart = $ ('#dashboard-sales-breakdown-chart');
-
- if (!$dashboardSalesBreakdownChart.length) {
- return false;
- }
-
- function drawSalesChart() {
-
- $dashboardSalesBreakdownChart.empty ();
-
- Morris.Donut ({
- element: 'dashboard-sales-breakdown-chart',
- data: [{label: "Download Sales", value: 12},
- {label: "In-Store Sales", value: 30},
- {label: "Mail-Order Sales", value: 20}],
- resize: true,
- colors: [
- tinycolor (config.chart.colorPrimary.toString ()).lighten (10).toString (),
- tinycolor (config.chart.colorPrimary.toString ()).darken (8).toString (),
- config.chart.colorPrimary.toString ()
- ],
- });
-
- var $sameheightContainer = $dashboardSalesBreakdownChart.closest (".sameheight-container");
-
- setSameHeights ($sameheightContainer);
- }
-
- drawSalesChart ();
-
- $ (document).on ("themechange", function () {
- drawSalesChart ();
- });
-
-})
-$ (function () {
-
- var $dashboardSalesMap = $ ('#dashboard-sales-map');
-
- if (!$dashboardSalesMap.length) {
- return false;
- }
-
- function drawSalesMap() {
-
- $dashboardSalesMap.empty ();
-
- var color = config.chart.colorPrimary.toHexString ();
- var darkColor = tinycolor (config.chart.colorPrimary.toString ()).darken (40).toHexString ();
- var selectedColor = tinycolor (config.chart.colorPrimary.toString ()).darken (10).toHexString ();
-
- var sales_data = {
- us: 2000,
- ru: 2000,
- gb: 10000,
- fr: 10000,
- de: 10000,
- cn: 10000,
- in: 10000,
- sa: 10000,
- ca: 10000,
- br: 5000,
- au: 5000
- };
-
- $dashboardSalesMap.vectorMap ({
- map: 'world_en',
- backgroundColor: 'transparent',
- color: '#E5E3E5',
- hoverOpacity: 0.7,
- selectedColor: selectedColor,
- enableZoom: true,
- showTooltip: true,
- values: sales_data,
- scaleColors: [color, darkColor],
- normalizeFunction: 'linear'
- });
- }
-
- drawSalesMap ();
-
- $ (document).on ("themechange", function () {
- drawSalesMap ();
- });
-});
+// $ (function () {
+//
+// if (!$ ('#morris-one-line-chart').length) {
+// return false;
+// }
+//
+// function drawMorrisCharts() {
+//
+// $ ('#morris-one-line-chart').empty ();
+//
+// Morris.Line ({
+// element: 'morris-one-line-chart',
+// data: [
+// {year: '2008', value: 5},
+// {year: '2009', value: 10},
+// {year: '2010', value: 8},
+// {year: '2011', value: 22},
+// {year: '2012', value: 8},
+// {year: '2014', value: 10},
+// {year: '2015', value: 5}
+// ],
+// xkey: 'year',
+// ykeys: ['value'],
+// resize: true,
+// lineWidth: 4,
+// labels: ['Value'],
+// lineColors: [config.chart.colorPrimary.toString ()],
+// pointSize: 5,
+// });
+//
+// $ ('#morris-area-chart').empty ();
+//
+// Morris.Area ({
+// element: 'morris-area-chart',
+// data: [{period: '2010 Q1', iphone: 2666, ipad: null, itouch: 2647},
+// {period: '2010 Q2', iphone: 2778, ipad: 2294, itouch: 2441},
+// {period: '2010 Q3', iphone: 4912, ipad: 1969, itouch: 2501},
+// {period: '2010 Q4', iphone: 3767, ipad: 3597, itouch: 5689},
+// {period: '2011 Q1', iphone: 6810, ipad: 1914, itouch: 2293},
+// {period: '2011 Q2', iphone: 5670, ipad: 4293, itouch: 1881},
+// {period: '2011 Q3', iphone: 4820, ipad: 3795, itouch: 1588},
+// {period: '2011 Q4', iphone: 15073, ipad: 5967, itouch: 5175},
+// {period: '2012 Q1', iphone: 10687, ipad: 4460, itouch: 2028},
+// {period: '2012 Q2', iphone: 8432, ipad: 5713, itouch: 1791}],
+// xkey: 'period',
+// ykeys: ['iphone', 'ipad', 'itouch'],
+// labels: ['iPhone', 'iPad', 'iPod Touch'],
+// pointSize: 2,
+// hideHover: 'auto',
+// resize: true,
+// lineColors: [
+// tinycolor (config.chart.colorPrimary.toString ()).lighten (10).toString (),
+// tinycolor (config.chart.colorPrimary.toString ()).darken (10).toString (),
+// config.chart.colorPrimary.toString ()
+// ],
+// lineWidth: 2,
+// pointSize: 1,
+// });
+//
+// $ ('#morris-donut-chart').empty ();
+//
+// Morris.Donut ({
+// element: 'morris-donut-chart',
+// data: [{label: "Download Sales", value: 12},
+// {label: "In-Store Sales", value: 30},
+// {label: "Mail-Order Sales", value: 20}],
+// resize: true,
+// colors: [
+// tinycolor (config.chart.colorPrimary.toString ()).lighten (10).toString (),
+// tinycolor (config.chart.colorPrimary.toString ()).darken (10).toString (),
+// config.chart.colorPrimary.toString ()
+// ],
+// });
+//
+// $ ('#morris-bar-chart').empty ();
+//
+// Morris.Bar ({
+// element: 'morris-bar-chart',
+// data: [{y: '2006', a: 60, b: 50},
+// {y: '2007', a: 75, b: 65},
+// {y: '2008', a: 50, b: 40},
+// {y: '2009', a: 75, b: 65},
+// {y: '2010', a: 50, b: 40},
+// {y: '2011', a: 75, b: 65},
+// {y: '2012', a: 100, b: 90}],
+// xkey: 'y',
+// ykeys: ['a', 'b'],
+// labels: ['Series A', 'Series B'],
+// hideHover: 'auto',
+// resize: true,
+// barColors: [
+// config.chart.colorPrimary.toString (),
+// tinycolor (config.chart.colorPrimary.toString ()).darken (10).toString ()
+// ],
+// });
+//
+// $ ('#morris-line-chart').empty ();
+//
+// Morris.Line ({
+// element: 'morris-line-chart',
+// data: [{y: '2006', a: 100, b: 90},
+// {y: '2007', a: 75, b: 65},
+// {y: '2008', a: 50, b: 40},
+// {y: '2009', a: 75, b: 65},
+// {y: '2010', a: 50, b: 40},
+// {y: '2011', a: 75, b: 65},
+// {y: '2012', a: 100, b: 90}],
+// xkey: 'y',
+// ykeys: ['a', 'b'],
+// labels: ['Series A', 'Series B'],
+// hideHover: 'auto',
+// resize: true,
+// lineColors: [
+// config.chart.colorPrimary.toString (),
+// tinycolor (config.chart.colorPrimary.toString ()).darken (10).toString ()
+// ],
+// });
+// }
+//
+// drawMorrisCharts ();
+//
+// $ (document).on ("themechange", function () {
+// drawMorrisCharts ();
+// });
+// });
+// $ (function () {
+//
+// if (!$ ('#dashboard-visits-chart').length) {
+// return false;
+// }
+//
+// // drawing visits chart
+// drawVisitsChart ();
+//
+// var el = null;
+// var item = 'visits';
+//
+// $ ('a[data-toggle="tab"]').on ('shown.bs.tab', function (e) {
+//
+// el = e.target;
+// item = $ (el).attr ('href').replace ('#', '');
+// switchHistoryCharts (item);
+//
+// });
+//
+// $ (document).on ("themechange", function () {
+// switchHistoryCharts (item);
+// });
+//
+// function switchHistoryCharts(item) {
+// var chartSelector = "#dashboard-" + item + "-chart";
+//
+// if ($ (chartSelector).has ('svg').length) {
+// $ (chartSelector).empty ();
+// }
+//
+// switch (item) {
+// case 'visits':
+// drawVisitsChart ();
+// break;
+// case 'downloads':
+// drawDownloadsChart ();
+// break;
+// }
+// }
+//
+// function drawVisitsChart() {
+// var dataVisits = [
+// {x: '2015-09-01', y: 70},
+// {x: '2015-09-02', y: 75},
+// {x: '2015-09-03', y: 50},
+// {x: '2015-09-04', y: 75},
+// {x: '2015-09-05', y: 50},
+// {x: '2015-09-06', y: 75},
+// {x: '2015-09-07', y: 86}
+// ];
+//
+// Morris.Line ({
+// element: 'dashboard-visits-chart',
+// data: dataVisits,
+// xkey: 'x',
+// ykeys: ['y'],
+// ymin: 'auto 40',
+// labels: ['Visits'],
+// xLabels: "day",
+// hideHover: 'auto',
+// yLabelFormat: function (y) {
+// // Only integers
+// if (y === parseInt (y, 10)) {
+// return y;
+// }
+// else {
+// return '';
+// }
+// },
+// resize: true,
+// lineColors: [
+// config.chart.colorSecondary.toString (),
+// ],
+// pointFillColors: [
+// config.chart.colorPrimary.toString (),
+// ]
+// });
+// }
+//
+// function drawDownloadsChart() {
+//
+// var dataDownloads = [
+// {
+// year: '2006',
+// downloads: 1300
+// },
+// {
+// year: '2007',
+// downloads: 1526
+// },
+// {
+// year: '2008',
+// downloads: 2000
+// },
+// {
+// year: '2009',
+// downloads: 1800
+// },
+// {
+// year: '2010',
+// downloads: 1650
+// },
+// {
+// year: '2011',
+// downloads: 620
+// },
+// {
+// year: '2012',
+// downloads: 1000
+// },
+// {
+// year: '2013',
+// downloads: 1896
+// },
+// {
+// year: '2014',
+// downloads: 850
+// },
+// {
+// year: '2015',
+// downloads: 1500
+// }
+// ];
+//
+// Morris.Bar ({
+// element: 'dashboard-downloads-chart',
+// data: dataDownloads,
+// xkey: 'year',
+// ykeys: ['downloads'],
+// labels: ['Downloads'],
+// hideHover: 'auto',
+// resize: true,
+// barColors: [
+// config.chart.colorPrimary.toString (),
+// tinycolor (config.chart.colorPrimary.toString ()).darken (10).toString ()
+// ],
+// });
+// }
+// });
+//
+// $ (function () {
+//
+// function drawDashboardItemsListSparklines() {
+// $ (".dashboard-page .items .sparkline").each (function () {
+// var type = $ (this).data ('type');
+//
+// // There is predefined data
+// if ($ (this).data ('data')) {
+// var data = $ (this).data ('data').split (',').map (function (item) {
+// if (item.indexOf (":") > 0) {
+// return item.split (":");
+// }
+// else {
+// return item;
+// }
+// });
+// }
+// // Generate random data
+// else {
+// var data = [];
+// for (var i = 0; i < 17; i++) {
+// data.push (Math.round (100 * Math.random ()));
+// }
+// }
+//
+// $ (this).sparkline (data, {
+// barColor: config.chart.colorPrimary.toString (),
+// height: $ (this).height (),
+// type: type
+// });
+// });
+// }
+//
+// drawDashboardItemsListSparklines ();
+//
+// $ (document).on ("themechange", function () {
+// drawDashboardItemsListSparklines ();
+// });
+// });
+// $ (function () {
+//
+// var $dashboardSalesBreakdownChart = $ ('#dashboard-sales-breakdown-chart');
+//
+// if (!$dashboardSalesBreakdownChart.length) {
+// return false;
+// }
+//
+// function drawSalesChart() {
+//
+// $dashboardSalesBreakdownChart.empty ();
+//
+// Morris.Donut ({
+// element: 'dashboard-sales-breakdown-chart',
+// data: [{label: "Download Sales", value: 12},
+// {label: "In-Store Sales", value: 30},
+// {label: "Mail-Order Sales", value: 20}],
+// resize: true,
+// colors: [
+// tinycolor (config.chart.colorPrimary.toString ()).lighten (10).toString (),
+// tinycolor (config.chart.colorPrimary.toString ()).darken (8).toString (),
+// config.chart.colorPrimary.toString ()
+// ],
+// });
+//
+// var $sameheightContainer = $dashboardSalesBreakdownChart.closest (".sameheight-container");
+//
+// setSameHeights ($sameheightContainer);
+// }
+//
+// drawSalesChart ();
+//
+// $ (document).on ("themechange", function () {
+// drawSalesChart ();
+// });
+//
+// })
+// $ (function () {
+//
+// var $dashboardSalesMap = $ ('#dashboard-sales-map');
+//
+// if (!$dashboardSalesMap.length) {
+// return false;
+// }
+//
+// function drawSalesMap() {
+//
+// $dashboardSalesMap.empty ();
+//
+// var color = config.chart.colorPrimary.toHexString ();
+// var darkColor = tinycolor (config.chart.colorPrimary.toString ()).darken (40).toHexString ();
+// var selectedColor = tinycolor (config.chart.colorPrimary.toString ()).darken (10).toHexString ();
+//
+// var sales_data = {
+// us: 2000,
+// ru: 2000,
+// gb: 10000,
+// fr: 10000,
+// de: 10000,
+// cn: 10000,
+// in: 10000,
+// sa: 10000,
+// ca: 10000,
+// br: 5000,
+// au: 5000
+// };
+//
+// $dashboardSalesMap.vectorMap ({
+// map: 'world_en',
+// backgroundColor: 'transparent',
+// color: '#E5E3E5',
+// hoverOpacity: 0.7,
+// selectedColor: selectedColor,
+// enableZoom: true,
+// showTooltip: true,
+// values: sales_data,
+// scaleColors: [color, darkColor],
+// normalizeFunction: 'linear'
+// });
+// }
+//
+// drawSalesMap ();
+//
+// $ (document).on ("themechange", function () {
+// drawSalesMap ();
+// });
+// });
$ (function () {
$ ('.actions-list > li').on ('click', '.check', function (e) {
@@ -1460,6 +1460,11 @@ $ (document).ready (function () {
$ ("#" + tabCard.prop ('id') + "-tab").addClass ('tab-with-error');
});
+
+ $('#removeTitlePhoto').click(function () {
+ $('#titlePhotoContainer').remove();
+ // $('existingTitlePhoto').val(null);
+ });
});
/***********************************************
diff --git a/resources/assets/admin/js/viewerJs/compatibility.js b/resources/assets/admin/js/viewerJs/compatibility.js
new file mode 100644
index 00000000..06f54bff
--- /dev/null
+++ b/resources/assets/admin/js/viewerJs/compatibility.js
@@ -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;
+ }
+})();
diff --git a/resources/assets/admin/js/viewerJs/example.local.css b/resources/assets/admin/js/viewerJs/example.local.css
new file mode 100644
index 00000000..034347d4
--- /dev/null
+++ b/resources/assets/admin/js/viewerJs/example.local.css
@@ -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;
+
+}
+
diff --git a/resources/assets/admin/js/viewerJs/images/kogmbh.png b/resources/assets/admin/js/viewerJs/images/kogmbh.png
new file mode 100644
index 00000000..00e8f4de
Binary files /dev/null and b/resources/assets/admin/js/viewerJs/images/kogmbh.png differ
diff --git a/resources/assets/admin/js/viewerJs/images/nlnet.png b/resources/assets/admin/js/viewerJs/images/nlnet.png
new file mode 100644
index 00000000..e75ab2e8
Binary files /dev/null and b/resources/assets/admin/js/viewerJs/images/nlnet.png differ
diff --git a/resources/assets/admin/js/viewerJs/images/texture.png b/resources/assets/admin/js/viewerJs/images/texture.png
new file mode 100644
index 00000000..df008649
Binary files /dev/null and b/resources/assets/admin/js/viewerJs/images/texture.png differ
diff --git a/resources/assets/admin/js/viewerJs/images/toolbarButton-download.png b/resources/assets/admin/js/viewerJs/images/toolbarButton-download.png
new file mode 100644
index 00000000..8676d8e2
Binary files /dev/null and b/resources/assets/admin/js/viewerJs/images/toolbarButton-download.png differ
diff --git a/resources/assets/admin/js/viewerJs/images/toolbarButton-fullscreen.png b/resources/assets/admin/js/viewerJs/images/toolbarButton-fullscreen.png
new file mode 100644
index 00000000..fa730955
Binary files /dev/null and b/resources/assets/admin/js/viewerJs/images/toolbarButton-fullscreen.png differ
diff --git a/resources/assets/admin/js/viewerJs/images/toolbarButton-menuArrows.png b/resources/assets/admin/js/viewerJs/images/toolbarButton-menuArrows.png
new file mode 100644
index 00000000..31b06b5a
Binary files /dev/null and b/resources/assets/admin/js/viewerJs/images/toolbarButton-menuArrows.png differ
diff --git a/resources/assets/admin/js/viewerJs/images/toolbarButton-pageDown.png b/resources/assets/admin/js/viewerJs/images/toolbarButton-pageDown.png
new file mode 100644
index 00000000..762ac43e
Binary files /dev/null and b/resources/assets/admin/js/viewerJs/images/toolbarButton-pageDown.png differ
diff --git a/resources/assets/admin/js/viewerJs/images/toolbarButton-pageUp.png b/resources/assets/admin/js/viewerJs/images/toolbarButton-pageUp.png
new file mode 100644
index 00000000..3155b8bd
Binary files /dev/null and b/resources/assets/admin/js/viewerJs/images/toolbarButton-pageUp.png differ
diff --git a/resources/assets/admin/js/viewerJs/images/toolbarButton-presentation.png b/resources/assets/admin/js/viewerJs/images/toolbarButton-presentation.png
new file mode 100644
index 00000000..0f224232
Binary files /dev/null and b/resources/assets/admin/js/viewerJs/images/toolbarButton-presentation.png differ
diff --git a/resources/assets/admin/js/viewerJs/images/toolbarButton-zoomIn.png b/resources/assets/admin/js/viewerJs/images/toolbarButton-zoomIn.png
new file mode 100644
index 00000000..670acd93
Binary files /dev/null and b/resources/assets/admin/js/viewerJs/images/toolbarButton-zoomIn.png differ
diff --git a/resources/assets/admin/js/viewerJs/images/toolbarButton-zoomOut.png b/resources/assets/admin/js/viewerJs/images/toolbarButton-zoomOut.png
new file mode 100644
index 00000000..810fbf98
Binary files /dev/null and b/resources/assets/admin/js/viewerJs/images/toolbarButton-zoomOut.png differ
diff --git a/resources/assets/admin/js/viewerJs/index.html b/resources/assets/admin/js/viewerJs/index.html
new file mode 100644
index 00000000..2eb1fd47
--- /dev/null
+++ b/resources/assets/admin/js/viewerJs/index.html
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
ViewerJS
+
+
+
+
+
+
+
+
+
diff --git a/resources/assets/admin/js/viewerJs/pdf.js b/resources/assets/admin/js/viewerJs/pdf.js
new file mode 100644
index 00000000..463d7d0f
--- /dev/null
+++ b/resources/assets/admin/js/viewerJs/pdf.js
@@ -0,0 +1,8052 @@
+/* -*- 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.
+ */
+/*jshint globalstrict: false */
+/* globals PDFJS */
+
+// Initializing PDFJS global object (if still undefined)
+if (typeof PDFJS === 'undefined') {
+ (typeof window !== 'undefined' ? window : this).PDFJS = {};
+}
+
+PDFJS.version = '1.1.114';
+PDFJS.build = '3fd44fd';
+
+(function pdfjsWrapper() {
+ // Use strict in our context only - users might not want it
+ 'use strict';
+
+/* -*- 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 Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL,
+ Promise */
+
+'use strict';
+
+var globalScope = (typeof window === 'undefined') ? this : window;
+
+var isWorker = (typeof window === 'undefined');
+
+var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
+
+var TextRenderingMode = {
+ FILL: 0,
+ STROKE: 1,
+ FILL_STROKE: 2,
+ INVISIBLE: 3,
+ FILL_ADD_TO_PATH: 4,
+ STROKE_ADD_TO_PATH: 5,
+ FILL_STROKE_ADD_TO_PATH: 6,
+ ADD_TO_PATH: 7,
+ FILL_STROKE_MASK: 3,
+ ADD_TO_PATH_FLAG: 4
+};
+
+var ImageKind = {
+ GRAYSCALE_1BPP: 1,
+ RGB_24BPP: 2,
+ RGBA_32BPP: 3
+};
+
+var AnnotationType = {
+ WIDGET: 1,
+ TEXT: 2,
+ LINK: 3
+};
+
+var StreamType = {
+ UNKNOWN: 0,
+ FLATE: 1,
+ LZW: 2,
+ DCT: 3,
+ JPX: 4,
+ JBIG: 5,
+ A85: 6,
+ AHX: 7,
+ CCF: 8,
+ RL: 9
+};
+
+var FontType = {
+ UNKNOWN: 0,
+ TYPE1: 1,
+ TYPE1C: 2,
+ CIDFONTTYPE0: 3,
+ CIDFONTTYPE0C: 4,
+ TRUETYPE: 5,
+ CIDFONTTYPE2: 6,
+ TYPE3: 7,
+ OPENTYPE: 8,
+ TYPE0: 9,
+ MMTYPE1: 10
+};
+
+// The global PDFJS object exposes the API
+// In production, it will be declared outside a global wrapper
+// In development, it will be declared here
+if (!globalScope.PDFJS) {
+ globalScope.PDFJS = {};
+}
+
+globalScope.PDFJS.pdfBug = false;
+
+PDFJS.VERBOSITY_LEVELS = {
+ errors: 0,
+ warnings: 1,
+ infos: 5
+};
+
+// All the possible operations for an operator list.
+var OPS = PDFJS.OPS = {
+ // Intentionally start from 1 so it is easy to spot bad operators that will be
+ // 0's.
+ dependency: 1,
+ setLineWidth: 2,
+ setLineCap: 3,
+ setLineJoin: 4,
+ setMiterLimit: 5,
+ setDash: 6,
+ setRenderingIntent: 7,
+ setFlatness: 8,
+ setGState: 9,
+ save: 10,
+ restore: 11,
+ transform: 12,
+ moveTo: 13,
+ lineTo: 14,
+ curveTo: 15,
+ curveTo2: 16,
+ curveTo3: 17,
+ closePath: 18,
+ rectangle: 19,
+ stroke: 20,
+ closeStroke: 21,
+ fill: 22,
+ eoFill: 23,
+ fillStroke: 24,
+ eoFillStroke: 25,
+ closeFillStroke: 26,
+ closeEOFillStroke: 27,
+ endPath: 28,
+ clip: 29,
+ eoClip: 30,
+ beginText: 31,
+ endText: 32,
+ setCharSpacing: 33,
+ setWordSpacing: 34,
+ setHScale: 35,
+ setLeading: 36,
+ setFont: 37,
+ setTextRenderingMode: 38,
+ setTextRise: 39,
+ moveText: 40,
+ setLeadingMoveText: 41,
+ setTextMatrix: 42,
+ nextLine: 43,
+ showText: 44,
+ showSpacedText: 45,
+ nextLineShowText: 46,
+ nextLineSetSpacingShowText: 47,
+ setCharWidth: 48,
+ setCharWidthAndBounds: 49,
+ setStrokeColorSpace: 50,
+ setFillColorSpace: 51,
+ setStrokeColor: 52,
+ setStrokeColorN: 53,
+ setFillColor: 54,
+ setFillColorN: 55,
+ setStrokeGray: 56,
+ setFillGray: 57,
+ setStrokeRGBColor: 58,
+ setFillRGBColor: 59,
+ setStrokeCMYKColor: 60,
+ setFillCMYKColor: 61,
+ shadingFill: 62,
+ beginInlineImage: 63,
+ beginImageData: 64,
+ endInlineImage: 65,
+ paintXObject: 66,
+ markPoint: 67,
+ markPointProps: 68,
+ beginMarkedContent: 69,
+ beginMarkedContentProps: 70,
+ endMarkedContent: 71,
+ beginCompat: 72,
+ endCompat: 73,
+ paintFormXObjectBegin: 74,
+ paintFormXObjectEnd: 75,
+ beginGroup: 76,
+ endGroup: 77,
+ beginAnnotations: 78,
+ endAnnotations: 79,
+ beginAnnotation: 80,
+ endAnnotation: 81,
+ paintJpegXObject: 82,
+ paintImageMaskXObject: 83,
+ paintImageMaskXObjectGroup: 84,
+ paintImageXObject: 85,
+ paintInlineImageXObject: 86,
+ paintInlineImageXObjectGroup: 87,
+ paintImageXObjectRepeat: 88,
+ paintImageMaskXObjectRepeat: 89,
+ paintSolidColorImageMask: 90,
+ constructPath: 91
+};
+
+// A notice for devs. These are good for things that are helpful to devs, such
+// as warning that Workers were disabled, which is important to devs but not
+// end users.
+function info(msg) {
+ if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) {
+ console.log('Info: ' + msg);
+ }
+}
+
+// Non-fatal warnings.
+function warn(msg) {
+ if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) {
+ console.log('Warning: ' + msg);
+ }
+}
+
+// Fatal errors that should trigger the fallback UI and halt execution by
+// throwing an exception.
+function error(msg) {
+ if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.errors) {
+ console.log('Error: ' + msg);
+ console.log(backtrace());
+ }
+ UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown);
+ throw new Error(msg);
+}
+
+function backtrace() {
+ try {
+ throw new Error();
+ } catch (e) {
+ return e.stack ? e.stack.split('\n').slice(2).join('\n') : '';
+ }
+}
+
+function assert(cond, msg) {
+ if (!cond) {
+ error(msg);
+ }
+}
+
+var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = {
+ unknown: 'unknown',
+ forms: 'forms',
+ javaScript: 'javaScript',
+ smask: 'smask',
+ shadingPattern: 'shadingPattern',
+ font: 'font'
+};
+
+var UnsupportedManager = PDFJS.UnsupportedManager =
+ (function UnsupportedManagerClosure() {
+ var listeners = [];
+ return {
+ listen: function (cb) {
+ listeners.push(cb);
+ },
+ notify: function (featureId) {
+ warn('Unsupported feature "' + featureId + '"');
+ for (var i = 0, ii = listeners.length; i < ii; i++) {
+ listeners[i](featureId);
+ }
+ }
+ };
+})();
+
+// Combines two URLs. The baseUrl shall be absolute URL. If the url is an
+// absolute URL, it will be returned as is.
+function combineUrl(baseUrl, url) {
+ if (!url) {
+ return baseUrl;
+ }
+ if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) {
+ return url;
+ }
+ var i;
+ if (url.charAt(0) === '/') {
+ // absolute path
+ i = baseUrl.indexOf('://');
+ if (url.charAt(1) === '/') {
+ ++i;
+ } else {
+ i = baseUrl.indexOf('/', i + 3);
+ }
+ return baseUrl.substring(0, i) + url;
+ } else {
+ // relative path
+ var pathLength = baseUrl.length;
+ i = baseUrl.lastIndexOf('#');
+ pathLength = i >= 0 ? i : pathLength;
+ i = baseUrl.lastIndexOf('?', pathLength);
+ pathLength = i >= 0 ? i : pathLength;
+ var prefixLength = baseUrl.lastIndexOf('/', pathLength);
+ return baseUrl.substring(0, prefixLength + 1) + url;
+ }
+}
+
+// Validates if URL is safe and allowed, e.g. to avoid XSS.
+function isValidUrl(url, allowRelative) {
+ if (!url) {
+ return false;
+ }
+ // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1)
+ // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
+ var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url);
+ if (!protocol) {
+ return allowRelative;
+ }
+ protocol = protocol[0].toLowerCase();
+ switch (protocol) {
+ case 'http':
+ case 'https':
+ case 'ftp':
+ case 'mailto':
+ case 'tel':
+ return true;
+ default:
+ return false;
+ }
+}
+PDFJS.isValidUrl = isValidUrl;
+
+function shadow(obj, prop, value) {
+ Object.defineProperty(obj, prop, { value: value,
+ enumerable: true,
+ configurable: true,
+ writable: false });
+ return value;
+}
+PDFJS.shadow = shadow;
+
+var PasswordResponses = PDFJS.PasswordResponses = {
+ NEED_PASSWORD: 1,
+ INCORRECT_PASSWORD: 2
+};
+
+var PasswordException = (function PasswordExceptionClosure() {
+ function PasswordException(msg, code) {
+ this.name = 'PasswordException';
+ this.message = msg;
+ this.code = code;
+ }
+
+ PasswordException.prototype = new Error();
+ PasswordException.constructor = PasswordException;
+
+ return PasswordException;
+})();
+PDFJS.PasswordException = PasswordException;
+
+var UnknownErrorException = (function UnknownErrorExceptionClosure() {
+ function UnknownErrorException(msg, details) {
+ this.name = 'UnknownErrorException';
+ this.message = msg;
+ this.details = details;
+ }
+
+ UnknownErrorException.prototype = new Error();
+ UnknownErrorException.constructor = UnknownErrorException;
+
+ return UnknownErrorException;
+})();
+PDFJS.UnknownErrorException = UnknownErrorException;
+
+var InvalidPDFException = (function InvalidPDFExceptionClosure() {
+ function InvalidPDFException(msg) {
+ this.name = 'InvalidPDFException';
+ this.message = msg;
+ }
+
+ InvalidPDFException.prototype = new Error();
+ InvalidPDFException.constructor = InvalidPDFException;
+
+ return InvalidPDFException;
+})();
+PDFJS.InvalidPDFException = InvalidPDFException;
+
+var MissingPDFException = (function MissingPDFExceptionClosure() {
+ function MissingPDFException(msg) {
+ this.name = 'MissingPDFException';
+ this.message = msg;
+ }
+
+ MissingPDFException.prototype = new Error();
+ MissingPDFException.constructor = MissingPDFException;
+
+ return MissingPDFException;
+})();
+PDFJS.MissingPDFException = MissingPDFException;
+
+var UnexpectedResponseException =
+ (function UnexpectedResponseExceptionClosure() {
+ function UnexpectedResponseException(msg, status) {
+ this.name = 'UnexpectedResponseException';
+ this.message = msg;
+ this.status = status;
+ }
+
+ UnexpectedResponseException.prototype = new Error();
+ UnexpectedResponseException.constructor = UnexpectedResponseException;
+
+ return UnexpectedResponseException;
+})();
+PDFJS.UnexpectedResponseException = UnexpectedResponseException;
+
+var NotImplementedException = (function NotImplementedExceptionClosure() {
+ function NotImplementedException(msg) {
+ this.message = msg;
+ }
+
+ NotImplementedException.prototype = new Error();
+ NotImplementedException.prototype.name = 'NotImplementedException';
+ NotImplementedException.constructor = NotImplementedException;
+
+ return NotImplementedException;
+})();
+
+var MissingDataException = (function MissingDataExceptionClosure() {
+ function MissingDataException(begin, end) {
+ this.begin = begin;
+ this.end = end;
+ this.message = 'Missing data [' + begin + ', ' + end + ')';
+ }
+
+ MissingDataException.prototype = new Error();
+ MissingDataException.prototype.name = 'MissingDataException';
+ MissingDataException.constructor = MissingDataException;
+
+ return MissingDataException;
+})();
+
+var XRefParseException = (function XRefParseExceptionClosure() {
+ function XRefParseException(msg) {
+ this.message = msg;
+ }
+
+ XRefParseException.prototype = new Error();
+ XRefParseException.prototype.name = 'XRefParseException';
+ XRefParseException.constructor = XRefParseException;
+
+ return XRefParseException;
+})();
+
+
+function bytesToString(bytes) {
+ assert(bytes !== null && typeof bytes === 'object' &&
+ bytes.length !== undefined, 'Invalid argument for bytesToString');
+ var length = bytes.length;
+ var MAX_ARGUMENT_COUNT = 8192;
+ if (length < MAX_ARGUMENT_COUNT) {
+ return String.fromCharCode.apply(null, bytes);
+ }
+ var strBuf = [];
+ for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
+ var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
+ var chunk = bytes.subarray(i, chunkEnd);
+ strBuf.push(String.fromCharCode.apply(null, chunk));
+ }
+ return strBuf.join('');
+}
+
+function stringToBytes(str) {
+ assert(typeof str === 'string', 'Invalid argument for stringToBytes');
+ var length = str.length;
+ var bytes = new Uint8Array(length);
+ for (var i = 0; i < length; ++i) {
+ bytes[i] = str.charCodeAt(i) & 0xFF;
+ }
+ return bytes;
+}
+
+function string32(value) {
+ return String.fromCharCode((value >> 24) & 0xff, (value >> 16) & 0xff,
+ (value >> 8) & 0xff, value & 0xff);
+}
+
+function log2(x) {
+ var n = 1, i = 0;
+ while (x > n) {
+ n <<= 1;
+ i++;
+ }
+ return i;
+}
+
+function readInt8(data, start) {
+ return (data[start] << 24) >> 24;
+}
+
+function readUint16(data, offset) {
+ return (data[offset] << 8) | data[offset + 1];
+}
+
+function readUint32(data, offset) {
+ return ((data[offset] << 24) | (data[offset + 1] << 16) |
+ (data[offset + 2] << 8) | data[offset + 3]) >>> 0;
+}
+
+// Lazy test the endianness of the platform
+// NOTE: This will be 'true' for simulated TypedArrays
+function isLittleEndian() {
+ var buffer8 = new Uint8Array(2);
+ buffer8[0] = 1;
+ var buffer16 = new Uint16Array(buffer8.buffer);
+ return (buffer16[0] === 1);
+}
+
+Object.defineProperty(PDFJS, 'isLittleEndian', {
+ configurable: true,
+ get: function PDFJS_isLittleEndian() {
+ return shadow(PDFJS, 'isLittleEndian', isLittleEndian());
+ }
+});
+
+//#if !(FIREFOX || MOZCENTRAL || B2G || CHROME)
+//// Lazy test if the userAgant support CanvasTypedArrays
+function hasCanvasTypedArrays() {
+ var canvas = document.createElement('canvas');
+ canvas.width = canvas.height = 1;
+ var ctx = canvas.getContext('2d');
+ var imageData = ctx.createImageData(1, 1);
+ return (typeof imageData.data.buffer !== 'undefined');
+}
+
+Object.defineProperty(PDFJS, 'hasCanvasTypedArrays', {
+ configurable: true,
+ get: function PDFJS_hasCanvasTypedArrays() {
+ return shadow(PDFJS, 'hasCanvasTypedArrays', hasCanvasTypedArrays());
+ }
+});
+
+var Uint32ArrayView = (function Uint32ArrayViewClosure() {
+
+ function Uint32ArrayView(buffer, length) {
+ this.buffer = buffer;
+ this.byteLength = buffer.length;
+ this.length = length === undefined ? (this.byteLength >> 2) : length;
+ ensureUint32ArrayViewProps(this.length);
+ }
+ Uint32ArrayView.prototype = Object.create(null);
+
+ var uint32ArrayViewSetters = 0;
+ function createUint32ArrayProp(index) {
+ return {
+ get: function () {
+ var buffer = this.buffer, offset = index << 2;
+ return (buffer[offset] | (buffer[offset + 1] << 8) |
+ (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24)) >>> 0;
+ },
+ set: function (value) {
+ var buffer = this.buffer, offset = index << 2;
+ buffer[offset] = value & 255;
+ buffer[offset + 1] = (value >> 8) & 255;
+ buffer[offset + 2] = (value >> 16) & 255;
+ buffer[offset + 3] = (value >>> 24) & 255;
+ }
+ };
+ }
+
+ function ensureUint32ArrayViewProps(length) {
+ while (uint32ArrayViewSetters < length) {
+ Object.defineProperty(Uint32ArrayView.prototype,
+ uint32ArrayViewSetters,
+ createUint32ArrayProp(uint32ArrayViewSetters));
+ uint32ArrayViewSetters++;
+ }
+ }
+
+ return Uint32ArrayView;
+})();
+//#else
+//PDFJS.hasCanvasTypedArrays = true;
+//#endif
+
+var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
+
+var Util = PDFJS.Util = (function UtilClosure() {
+ function Util() {}
+
+ var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')'];
+
+ // makeCssRgb() can be called thousands of times. Using |rgbBuf| avoids
+ // creating many intermediate strings.
+ Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
+ rgbBuf[1] = r;
+ rgbBuf[3] = g;
+ rgbBuf[5] = b;
+ return rgbBuf.join('');
+ };
+
+ // Concatenates two transformation matrices together and returns the result.
+ Util.transform = function Util_transform(m1, m2) {
+ return [
+ m1[0] * m2[0] + m1[2] * m2[1],
+ m1[1] * m2[0] + m1[3] * m2[1],
+ m1[0] * m2[2] + m1[2] * m2[3],
+ m1[1] * m2[2] + m1[3] * m2[3],
+ m1[0] * m2[4] + m1[2] * m2[5] + m1[4],
+ m1[1] * m2[4] + m1[3] * m2[5] + m1[5]
+ ];
+ };
+
+ // For 2d affine transforms
+ Util.applyTransform = function Util_applyTransform(p, m) {
+ var xt = p[0] * m[0] + p[1] * m[2] + m[4];
+ var yt = p[0] * m[1] + p[1] * m[3] + m[5];
+ return [xt, yt];
+ };
+
+ Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
+ var d = m[0] * m[3] - m[1] * m[2];
+ var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
+ var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
+ return [xt, yt];
+ };
+
+ // Applies the transform to the rectangle and finds the minimum axially
+ // aligned bounding box.
+ Util.getAxialAlignedBoundingBox =
+ function Util_getAxialAlignedBoundingBox(r, m) {
+
+ var p1 = Util.applyTransform(r, m);
+ var p2 = Util.applyTransform(r.slice(2, 4), m);
+ var p3 = Util.applyTransform([r[0], r[3]], m);
+ var p4 = Util.applyTransform([r[2], r[1]], m);
+ return [
+ Math.min(p1[0], p2[0], p3[0], p4[0]),
+ Math.min(p1[1], p2[1], p3[1], p4[1]),
+ Math.max(p1[0], p2[0], p3[0], p4[0]),
+ Math.max(p1[1], p2[1], p3[1], p4[1])
+ ];
+ };
+
+ Util.inverseTransform = function Util_inverseTransform(m) {
+ var d = m[0] * m[3] - m[1] * m[2];
+ return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d,
+ (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
+ };
+
+ // Apply a generic 3d matrix M on a 3-vector v:
+ // | a b c | | X |
+ // | d e f | x | Y |
+ // | g h i | | Z |
+ // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i],
+ // with v as [X,Y,Z]
+ Util.apply3dTransform = function Util_apply3dTransform(m, v) {
+ return [
+ m[0] * v[0] + m[1] * v[1] + m[2] * v[2],
+ m[3] * v[0] + m[4] * v[1] + m[5] * v[2],
+ m[6] * v[0] + m[7] * v[1] + m[8] * v[2]
+ ];
+ };
+
+ // This calculation uses Singular Value Decomposition.
+ // The SVD can be represented with formula A = USV. We are interested in the
+ // matrix S here because it represents the scale values.
+ Util.singularValueDecompose2dScale =
+ function Util_singularValueDecompose2dScale(m) {
+
+ var transpose = [m[0], m[2], m[1], m[3]];
+
+ // Multiply matrix m with its transpose.
+ var a = m[0] * transpose[0] + m[1] * transpose[2];
+ var b = m[0] * transpose[1] + m[1] * transpose[3];
+ var c = m[2] * transpose[0] + m[3] * transpose[2];
+ var d = m[2] * transpose[1] + m[3] * transpose[3];
+
+ // Solve the second degree polynomial to get roots.
+ var first = (a + d) / 2;
+ var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
+ var sx = first + second || 1;
+ var sy = first - second || 1;
+
+ // Scale values are the square roots of the eigenvalues.
+ return [Math.sqrt(sx), Math.sqrt(sy)];
+ };
+
+ // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2)
+ // For coordinate systems whose origin lies in the bottom-left, this
+ // means normalization to (BL,TR) ordering. For systems with origin in the
+ // top-left, this means (TL,BR) ordering.
+ Util.normalizeRect = function Util_normalizeRect(rect) {
+ var r = rect.slice(0); // clone rect
+ if (rect[0] > rect[2]) {
+ r[0] = rect[2];
+ r[2] = rect[0];
+ }
+ if (rect[1] > rect[3]) {
+ r[1] = rect[3];
+ r[3] = rect[1];
+ }
+ return r;
+ };
+
+ // Returns a rectangle [x1, y1, x2, y2] corresponding to the
+ // intersection of rect1 and rect2. If no intersection, returns 'false'
+ // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2]
+ Util.intersect = function Util_intersect(rect1, rect2) {
+ function compare(a, b) {
+ return a - b;
+ }
+
+ // Order points along the axes
+ var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
+ orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
+ result = [];
+
+ rect1 = Util.normalizeRect(rect1);
+ rect2 = Util.normalizeRect(rect2);
+
+ // X: first and second points belong to different rectangles?
+ if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) ||
+ (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) {
+ // Intersection must be between second and third points
+ result[0] = orderedX[1];
+ result[2] = orderedX[2];
+ } else {
+ return false;
+ }
+
+ // Y: first and second points belong to different rectangles?
+ if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) ||
+ (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) {
+ // Intersection must be between second and third points
+ result[1] = orderedY[1];
+ result[3] = orderedY[2];
+ } else {
+ return false;
+ }
+
+ return result;
+ };
+
+ Util.sign = function Util_sign(num) {
+ return num < 0 ? -1 : 1;
+ };
+
+ Util.appendToArray = function Util_appendToArray(arr1, arr2) {
+ Array.prototype.push.apply(arr1, arr2);
+ };
+
+ Util.prependToArray = function Util_prependToArray(arr1, arr2) {
+ Array.prototype.unshift.apply(arr1, arr2);
+ };
+
+ Util.extendObj = function extendObj(obj1, obj2) {
+ for (var key in obj2) {
+ obj1[key] = obj2[key];
+ }
+ };
+
+ Util.getInheritableProperty = function Util_getInheritableProperty(dict,
+ name) {
+ while (dict && !dict.has(name)) {
+ dict = dict.get('Parent');
+ }
+ if (!dict) {
+ return null;
+ }
+ return dict.get(name);
+ };
+
+ Util.inherit = function Util_inherit(sub, base, prototype) {
+ sub.prototype = Object.create(base.prototype);
+ sub.prototype.constructor = sub;
+ for (var prop in prototype) {
+ sub.prototype[prop] = prototype[prop];
+ }
+ };
+
+ Util.loadScript = function Util_loadScript(src, callback) {
+ var script = document.createElement('script');
+ var loaded = false;
+ script.setAttribute('src', src);
+ if (callback) {
+ script.onload = function() {
+ if (!loaded) {
+ callback();
+ }
+ loaded = true;
+ };
+ }
+ document.getElementsByTagName('head')[0].appendChild(script);
+ };
+
+ return Util;
+})();
+
+/**
+ * PDF page viewport created based on scale, rotation and offset.
+ * @class
+ * @alias PDFJS.PageViewport
+ */
+var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
+ /**
+ * @constructor
+ * @private
+ * @param viewBox {Array} xMin, yMin, xMax and yMax coordinates.
+ * @param scale {number} scale of the viewport.
+ * @param rotation {number} rotations of the viewport in degrees.
+ * @param offsetX {number} offset X
+ * @param offsetY {number} offset Y
+ * @param dontFlip {boolean} if true, axis Y will not be flipped.
+ */
+ function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) {
+ this.viewBox = viewBox;
+ this.scale = scale;
+ this.rotation = rotation;
+ this.offsetX = offsetX;
+ this.offsetY = offsetY;
+
+ // creating transform to convert pdf coordinate system to the normal
+ // canvas like coordinates taking in account scale and rotation
+ var centerX = (viewBox[2] + viewBox[0]) / 2;
+ var centerY = (viewBox[3] + viewBox[1]) / 2;
+ var rotateA, rotateB, rotateC, rotateD;
+ rotation = rotation % 360;
+ rotation = rotation < 0 ? rotation + 360 : rotation;
+ switch (rotation) {
+ case 180:
+ rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
+ break;
+ case 90:
+ rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
+ break;
+ case 270:
+ rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
+ break;
+ //case 0:
+ default:
+ rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
+ break;
+ }
+
+ if (dontFlip) {
+ rotateC = -rotateC; rotateD = -rotateD;
+ }
+
+ var offsetCanvasX, offsetCanvasY;
+ var width, height;
+ if (rotateA === 0) {
+ offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
+ offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
+ width = Math.abs(viewBox[3] - viewBox[1]) * scale;
+ height = Math.abs(viewBox[2] - viewBox[0]) * scale;
+ } else {
+ offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
+ offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
+ width = Math.abs(viewBox[2] - viewBox[0]) * scale;
+ height = Math.abs(viewBox[3] - viewBox[1]) * scale;
+ }
+ // creating transform for the following operations:
+ // translate(-centerX, -centerY), rotate and flip vertically,
+ // scale, and translate(offsetCanvasX, offsetCanvasY)
+ this.transform = [
+ rotateA * scale,
+ rotateB * scale,
+ rotateC * scale,
+ rotateD * scale,
+ offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
+ offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
+ ];
+
+ this.width = width;
+ this.height = height;
+ this.fontScale = scale;
+ }
+ PageViewport.prototype = /** @lends PDFJS.PageViewport.prototype */ {
+ /**
+ * Clones viewport with additional properties.
+ * @param args {Object} (optional) If specified, may contain the 'scale' or
+ * 'rotation' properties to override the corresponding properties in
+ * the cloned viewport.
+ * @returns {PDFJS.PageViewport} Cloned viewport.
+ */
+ clone: function PageViewPort_clone(args) {
+ args = args || {};
+ var scale = 'scale' in args ? args.scale : this.scale;
+ var rotation = 'rotation' in args ? args.rotation : this.rotation;
+ return new PageViewport(this.viewBox.slice(), scale, rotation,
+ this.offsetX, this.offsetY, args.dontFlip);
+ },
+ /**
+ * Converts PDF point to the viewport coordinates. For examples, useful for
+ * converting PDF location into canvas pixel coordinates.
+ * @param x {number} X coordinate.
+ * @param y {number} Y coordinate.
+ * @returns {Object} Object that contains 'x' and 'y' properties of the
+ * point in the viewport coordinate space.
+ * @see {@link convertToPdfPoint}
+ * @see {@link convertToViewportRectangle}
+ */
+ convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) {
+ return Util.applyTransform([x, y], this.transform);
+ },
+ /**
+ * Converts PDF rectangle to the viewport coordinates.
+ * @param rect {Array} xMin, yMin, xMax and yMax coordinates.
+ * @returns {Array} Contains corresponding coordinates of the rectangle
+ * in the viewport coordinate space.
+ * @see {@link convertToViewportPoint}
+ */
+ convertToViewportRectangle:
+ function PageViewport_convertToViewportRectangle(rect) {
+ var tl = Util.applyTransform([rect[0], rect[1]], this.transform);
+ var br = Util.applyTransform([rect[2], rect[3]], this.transform);
+ return [tl[0], tl[1], br[0], br[1]];
+ },
+ /**
+ * Converts viewport coordinates to the PDF location. For examples, useful
+ * for converting canvas pixel location into PDF one.
+ * @param x {number} X coordinate.
+ * @param y {number} Y coordinate.
+ * @returns {Object} Object that contains 'x' and 'y' properties of the
+ * point in the PDF coordinate space.
+ * @see {@link convertToViewportPoint}
+ */
+ convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) {
+ return Util.applyInverseTransform([x, y], this.transform);
+ }
+ };
+ return PageViewport;
+})();
+
+var PDFStringTranslateTable = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014,
+ 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C,
+ 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160,
+ 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC
+];
+
+function stringToPDFString(str) {
+ var i, n = str.length, strBuf = [];
+ if (str[0] === '\xFE' && str[1] === '\xFF') {
+ // UTF16BE BOM
+ for (i = 2; i < n; i += 2) {
+ strBuf.push(String.fromCharCode(
+ (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1)));
+ }
+ } else {
+ for (i = 0; i < n; ++i) {
+ var code = PDFStringTranslateTable[str.charCodeAt(i)];
+ strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
+ }
+ }
+ return strBuf.join('');
+}
+
+function stringToUTF8String(str) {
+ return decodeURIComponent(escape(str));
+}
+
+function isEmptyObj(obj) {
+ for (var key in obj) {
+ return false;
+ }
+ return true;
+}
+
+function isBool(v) {
+ return typeof v === 'boolean';
+}
+
+function isInt(v) {
+ return typeof v === 'number' && ((v | 0) === v);
+}
+
+function isNum(v) {
+ return typeof v === 'number';
+}
+
+function isString(v) {
+ return typeof v === 'string';
+}
+
+function isName(v) {
+ return v instanceof Name;
+}
+
+function isCmd(v, cmd) {
+ return v instanceof Cmd && (cmd === undefined || v.cmd === cmd);
+}
+
+function isDict(v, type) {
+ if (!(v instanceof Dict)) {
+ return false;
+ }
+ if (!type) {
+ return true;
+ }
+ var dictType = v.get('Type');
+ return isName(dictType) && dictType.name === type;
+}
+
+function isArray(v) {
+ return v instanceof Array;
+}
+
+function isStream(v) {
+ return typeof v === 'object' && v !== null && v.getBytes !== undefined;
+}
+
+function isArrayBuffer(v) {
+ return typeof v === 'object' && v !== null && v.byteLength !== undefined;
+}
+
+function isRef(v) {
+ return v instanceof Ref;
+}
+
+/**
+ * Promise Capability object.
+ *
+ * @typedef {Object} PromiseCapability
+ * @property {Promise} promise - A promise object.
+ * @property {function} resolve - Fullfills the promise.
+ * @property {function} reject - Rejects the promise.
+ */
+
+/**
+ * Creates a promise capability object.
+ * @alias PDFJS.createPromiseCapability
+ *
+ * @return {PromiseCapability} A capability object contains:
+ * - a Promise, resolve and reject methods.
+ */
+function createPromiseCapability() {
+ var capability = {};
+ capability.promise = new Promise(function (resolve, reject) {
+ capability.resolve = resolve;
+ capability.reject = reject;
+ });
+ return capability;
+}
+
+PDFJS.createPromiseCapability = createPromiseCapability;
+
+/**
+ * Polyfill for Promises:
+ * The following promise implementation tries to generally implement the
+ * Promise/A+ spec. Some notable differences from other promise libaries are:
+ * - There currently isn't a seperate deferred and promise object.
+ * - Unhandled rejections eventually show an error if they aren't handled.
+ *
+ * Based off of the work in:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=810490
+ */
+(function PromiseClosure() {
+ if (globalScope.Promise) {
+ // Promises existing in the DOM/Worker, checking presence of all/resolve
+ if (typeof globalScope.Promise.all !== 'function') {
+ globalScope.Promise.all = function (iterable) {
+ var count = 0, results = [], resolve, reject;
+ var promise = new globalScope.Promise(function (resolve_, reject_) {
+ resolve = resolve_;
+ reject = reject_;
+ });
+ iterable.forEach(function (p, i) {
+ count++;
+ p.then(function (result) {
+ results[i] = result;
+ count--;
+ if (count === 0) {
+ resolve(results);
+ }
+ }, reject);
+ });
+ if (count === 0) {
+ resolve(results);
+ }
+ return promise;
+ };
+ }
+ if (typeof globalScope.Promise.resolve !== 'function') {
+ globalScope.Promise.resolve = function (value) {
+ return new globalScope.Promise(function (resolve) { resolve(value); });
+ };
+ }
+ if (typeof globalScope.Promise.reject !== 'function') {
+ globalScope.Promise.reject = function (reason) {
+ return new globalScope.Promise(function (resolve, reject) {
+ reject(reason);
+ });
+ };
+ }
+ if (typeof globalScope.Promise.prototype.catch !== 'function') {
+ globalScope.Promise.prototype.catch = function (onReject) {
+ return globalScope.Promise.prototype.then(undefined, onReject);
+ };
+ }
+ return;
+ }
+//#if !MOZCENTRAL
+ var STATUS_PENDING = 0;
+ var STATUS_RESOLVED = 1;
+ var STATUS_REJECTED = 2;
+
+ // In an attempt to avoid silent exceptions, unhandled rejections are
+ // tracked and if they aren't handled in a certain amount of time an
+ // error is logged.
+ var REJECTION_TIMEOUT = 500;
+
+ var HandlerManager = {
+ handlers: [],
+ running: false,
+ unhandledRejections: [],
+ pendingRejectionCheck: false,
+
+ scheduleHandlers: function scheduleHandlers(promise) {
+ if (promise._status === STATUS_PENDING) {
+ return;
+ }
+
+ this.handlers = this.handlers.concat(promise._handlers);
+ promise._handlers = [];
+
+ if (this.running) {
+ return;
+ }
+ this.running = true;
+
+ setTimeout(this.runHandlers.bind(this), 0);
+ },
+
+ runHandlers: function runHandlers() {
+ var RUN_TIMEOUT = 1; // ms
+ var timeoutAt = Date.now() + RUN_TIMEOUT;
+ while (this.handlers.length > 0) {
+ var handler = this.handlers.shift();
+
+ var nextStatus = handler.thisPromise._status;
+ var nextValue = handler.thisPromise._value;
+
+ try {
+ if (nextStatus === STATUS_RESOLVED) {
+ if (typeof handler.onResolve === 'function') {
+ nextValue = handler.onResolve(nextValue);
+ }
+ } else if (typeof handler.onReject === 'function') {
+ nextValue = handler.onReject(nextValue);
+ nextStatus = STATUS_RESOLVED;
+
+ if (handler.thisPromise._unhandledRejection) {
+ this.removeUnhandeledRejection(handler.thisPromise);
+ }
+ }
+ } catch (ex) {
+ nextStatus = STATUS_REJECTED;
+ nextValue = ex;
+ }
+
+ handler.nextPromise._updateStatus(nextStatus, nextValue);
+ if (Date.now() >= timeoutAt) {
+ break;
+ }
+ }
+
+ if (this.handlers.length > 0) {
+ setTimeout(this.runHandlers.bind(this), 0);
+ return;
+ }
+
+ this.running = false;
+ },
+
+ addUnhandledRejection: function addUnhandledRejection(promise) {
+ this.unhandledRejections.push({
+ promise: promise,
+ time: Date.now()
+ });
+ this.scheduleRejectionCheck();
+ },
+
+ removeUnhandeledRejection: function removeUnhandeledRejection(promise) {
+ promise._unhandledRejection = false;
+ for (var i = 0; i < this.unhandledRejections.length; i++) {
+ if (this.unhandledRejections[i].promise === promise) {
+ this.unhandledRejections.splice(i);
+ i--;
+ }
+ }
+ },
+
+ scheduleRejectionCheck: function scheduleRejectionCheck() {
+ if (this.pendingRejectionCheck) {
+ return;
+ }
+ this.pendingRejectionCheck = true;
+ setTimeout(function rejectionCheck() {
+ this.pendingRejectionCheck = false;
+ var now = Date.now();
+ for (var i = 0; i < this.unhandledRejections.length; i++) {
+ if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) {
+ var unhandled = this.unhandledRejections[i].promise._value;
+ var msg = 'Unhandled rejection: ' + unhandled;
+ if (unhandled.stack) {
+ msg += '\n' + unhandled.stack;
+ }
+ warn(msg);
+ this.unhandledRejections.splice(i);
+ i--;
+ }
+ }
+ if (this.unhandledRejections.length) {
+ this.scheduleRejectionCheck();
+ }
+ }.bind(this), REJECTION_TIMEOUT);
+ }
+ };
+
+ function Promise(resolver) {
+ this._status = STATUS_PENDING;
+ this._handlers = [];
+ try {
+ resolver.call(this, this._resolve.bind(this), this._reject.bind(this));
+ } catch (e) {
+ this._reject(e);
+ }
+ }
+ /**
+ * Builds a promise that is resolved when all the passed in promises are
+ * resolved.
+ * @param {array} array of data and/or promises to wait for.
+ * @return {Promise} New dependant promise.
+ */
+ Promise.all = function Promise_all(promises) {
+ var resolveAll, rejectAll;
+ var deferred = new Promise(function (resolve, reject) {
+ resolveAll = resolve;
+ rejectAll = reject;
+ });
+ var unresolved = promises.length;
+ var results = [];
+ if (unresolved === 0) {
+ resolveAll(results);
+ return deferred;
+ }
+ function reject(reason) {
+ if (deferred._status === STATUS_REJECTED) {
+ return;
+ }
+ results = [];
+ rejectAll(reason);
+ }
+ for (var i = 0, ii = promises.length; i < ii; ++i) {
+ var promise = promises[i];
+ var resolve = (function(i) {
+ return function(value) {
+ if (deferred._status === STATUS_REJECTED) {
+ return;
+ }
+ results[i] = value;
+ unresolved--;
+ if (unresolved === 0) {
+ resolveAll(results);
+ }
+ };
+ })(i);
+ if (Promise.isPromise(promise)) {
+ promise.then(resolve, reject);
+ } else {
+ resolve(promise);
+ }
+ }
+ return deferred;
+ };
+
+ /**
+ * Checks if the value is likely a promise (has a 'then' function).
+ * @return {boolean} true if value is thenable
+ */
+ Promise.isPromise = function Promise_isPromise(value) {
+ return value && typeof value.then === 'function';
+ };
+
+ /**
+ * Creates resolved promise
+ * @param value resolve value
+ * @returns {Promise}
+ */
+ Promise.resolve = function Promise_resolve(value) {
+ return new Promise(function (resolve) { resolve(value); });
+ };
+
+ /**
+ * Creates rejected promise
+ * @param reason rejection value
+ * @returns {Promise}
+ */
+ Promise.reject = function Promise_reject(reason) {
+ return new Promise(function (resolve, reject) { reject(reason); });
+ };
+
+ Promise.prototype = {
+ _status: null,
+ _value: null,
+ _handlers: null,
+ _unhandledRejection: null,
+
+ _updateStatus: function Promise__updateStatus(status, value) {
+ if (this._status === STATUS_RESOLVED ||
+ this._status === STATUS_REJECTED) {
+ return;
+ }
+
+ if (status === STATUS_RESOLVED &&
+ Promise.isPromise(value)) {
+ value.then(this._updateStatus.bind(this, STATUS_RESOLVED),
+ this._updateStatus.bind(this, STATUS_REJECTED));
+ return;
+ }
+
+ this._status = status;
+ this._value = value;
+
+ if (status === STATUS_REJECTED && this._handlers.length === 0) {
+ this._unhandledRejection = true;
+ HandlerManager.addUnhandledRejection(this);
+ }
+
+ HandlerManager.scheduleHandlers(this);
+ },
+
+ _resolve: function Promise_resolve(value) {
+ this._updateStatus(STATUS_RESOLVED, value);
+ },
+
+ _reject: function Promise_reject(reason) {
+ this._updateStatus(STATUS_REJECTED, reason);
+ },
+
+ then: function Promise_then(onResolve, onReject) {
+ var nextPromise = new Promise(function (resolve, reject) {
+ this.resolve = resolve;
+ this.reject = reject;
+ });
+ this._handlers.push({
+ thisPromise: this,
+ onResolve: onResolve,
+ onReject: onReject,
+ nextPromise: nextPromise
+ });
+ HandlerManager.scheduleHandlers(this);
+ return nextPromise;
+ },
+
+ catch: function Promise_catch(onReject) {
+ return this.then(undefined, onReject);
+ }
+ };
+
+ globalScope.Promise = Promise;
+//#else
+//throw new Error('DOM Promise is not present');
+//#endif
+})();
+
+var StatTimer = (function StatTimerClosure() {
+ function rpad(str, pad, length) {
+ while (str.length < length) {
+ str += pad;
+ }
+ return str;
+ }
+ function StatTimer() {
+ this.started = {};
+ this.times = [];
+ this.enabled = true;
+ }
+ StatTimer.prototype = {
+ time: function StatTimer_time(name) {
+ if (!this.enabled) {
+ return;
+ }
+ if (name in this.started) {
+ warn('Timer is already running for ' + name);
+ }
+ this.started[name] = Date.now();
+ },
+ timeEnd: function StatTimer_timeEnd(name) {
+ if (!this.enabled) {
+ return;
+ }
+ if (!(name in this.started)) {
+ warn('Timer has not been started for ' + name);
+ }
+ this.times.push({
+ 'name': name,
+ 'start': this.started[name],
+ 'end': Date.now()
+ });
+ // Remove timer from started so it can be called again.
+ delete this.started[name];
+ },
+ toString: function StatTimer_toString() {
+ var i, ii;
+ var times = this.times;
+ var out = '';
+ // Find the longest name for padding purposes.
+ var longest = 0;
+ for (i = 0, ii = times.length; i < ii; ++i) {
+ var name = times[i]['name'];
+ if (name.length > longest) {
+ longest = name.length;
+ }
+ }
+ for (i = 0, ii = times.length; i < ii; ++i) {
+ var span = times[i];
+ var duration = span.end - span.start;
+ out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
+ }
+ return out;
+ }
+ };
+ return StatTimer;
+})();
+
+PDFJS.createBlob = function createBlob(data, contentType) {
+ if (typeof Blob !== 'undefined') {
+ return new Blob([data], { type: contentType });
+ }
+ // Blob builder is deprecated in FF14 and removed in FF18.
+ var bb = new MozBlobBuilder();
+ bb.append(data);
+ return bb.getBlob(contentType);
+};
+
+PDFJS.createObjectURL = (function createObjectURLClosure() {
+ // Blob/createObjectURL is not available, falling back to data schema.
+ var digits =
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+
+ return function createObjectURL(data, contentType) {
+ if (!PDFJS.disableCreateObjectURL &&
+ typeof URL !== 'undefined' && URL.createObjectURL) {
+ var blob = PDFJS.createBlob(data, contentType);
+ return URL.createObjectURL(blob);
+ }
+
+ var buffer = 'data:' + contentType + ';base64,';
+ for (var i = 0, ii = data.length; i < ii; i += 3) {
+ var b1 = data[i] & 0xFF;
+ var b2 = data[i + 1] & 0xFF;
+ var b3 = data[i + 2] & 0xFF;
+ var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
+ var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
+ var d4 = i + 2 < ii ? (b3 & 0x3F) : 64;
+ buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
+ }
+ return buffer;
+ };
+})();
+
+function MessageHandler(name, comObj) {
+ this.name = name;
+ this.comObj = comObj;
+ this.callbackIndex = 1;
+ this.postMessageTransfers = true;
+ var callbacksCapabilities = this.callbacksCapabilities = {};
+ var ah = this.actionHandler = {};
+
+ ah['console_log'] = [function ahConsoleLog(data) {
+ console.log.apply(console, data);
+ }];
+ ah['console_error'] = [function ahConsoleError(data) {
+ console.error.apply(console, data);
+ }];
+ ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) {
+ UnsupportedManager.notify(data);
+ }];
+
+ comObj.onmessage = function messageHandlerComObjOnMessage(event) {
+ var data = event.data;
+ if (data.isReply) {
+ var callbackId = data.callbackId;
+ if (data.callbackId in callbacksCapabilities) {
+ var callback = callbacksCapabilities[callbackId];
+ delete callbacksCapabilities[callbackId];
+ if ('error' in data) {
+ callback.reject(data.error);
+ } else {
+ callback.resolve(data.data);
+ }
+ } else {
+ error('Cannot resolve callback ' + callbackId);
+ }
+ } else if (data.action in ah) {
+ var action = ah[data.action];
+ if (data.callbackId) {
+ Promise.resolve().then(function () {
+ return action[0].call(action[1], data.data);
+ }).then(function (result) {
+ comObj.postMessage({
+ isReply: true,
+ callbackId: data.callbackId,
+ data: result
+ });
+ }, function (reason) {
+ comObj.postMessage({
+ isReply: true,
+ callbackId: data.callbackId,
+ error: reason
+ });
+ });
+ } else {
+ action[0].call(action[1], data.data);
+ }
+ } else {
+ error('Unknown action from worker: ' + data.action);
+ }
+ };
+}
+
+MessageHandler.prototype = {
+ on: function messageHandlerOn(actionName, handler, scope) {
+ var ah = this.actionHandler;
+ if (ah[actionName]) {
+ error('There is already an actionName called "' + actionName + '"');
+ }
+ ah[actionName] = [handler, scope];
+ },
+ /**
+ * Sends a message to the comObj to invoke the action with the supplied data.
+ * @param {String} actionName Action to call.
+ * @param {JSON} data JSON data to send.
+ * @param {Array} [transfers] Optional list of transfers/ArrayBuffers
+ */
+ send: function messageHandlerSend(actionName, data, transfers) {
+ var message = {
+ action: actionName,
+ data: data
+ };
+ this.postMessage(message, transfers);
+ },
+ /**
+ * Sends a message to the comObj to invoke the action with the supplied data.
+ * Expects that other side will callback with the response.
+ * @param {String} actionName Action to call.
+ * @param {JSON} data JSON data to send.
+ * @param {Array} [transfers] Optional list of transfers/ArrayBuffers.
+ * @returns {Promise} Promise to be resolved with response data.
+ */
+ sendWithPromise:
+ function messageHandlerSendWithPromise(actionName, data, transfers) {
+ var callbackId = this.callbackIndex++;
+ var message = {
+ action: actionName,
+ data: data,
+ callbackId: callbackId
+ };
+ var capability = createPromiseCapability();
+ this.callbacksCapabilities[callbackId] = capability;
+ try {
+ this.postMessage(message, transfers);
+ } catch (e) {
+ capability.reject(e);
+ }
+ return capability.promise;
+ },
+ /**
+ * Sends raw message to the comObj.
+ * @private
+ * @param message {Object} Raw message.
+ * @param transfers List of transfers/ArrayBuffers, or undefined.
+ */
+ postMessage: function (message, transfers) {
+ if (transfers && this.postMessageTransfers) {
+ this.comObj.postMessage(message, transfers);
+ } else {
+ this.comObj.postMessage(message);
+ }
+ }
+};
+
+function loadJpegStream(id, imageUrl, objs) {
+ var img = new Image();
+ img.onload = (function loadJpegStream_onloadClosure() {
+ objs.resolve(id, img);
+ });
+ img.onerror = (function loadJpegStream_onerrorClosure() {
+ objs.resolve(id, null);
+ warn('Error during JPEG image loading');
+ });
+ img.src = imageUrl;
+}
+
+
+/**
+ * The maximum allowed image size in total pixels e.g. width * height. Images
+ * above this value will not be drawn. Use -1 for no limit.
+ * @var {number}
+ */
+PDFJS.maxImageSize = (PDFJS.maxImageSize === undefined ?
+ -1 : PDFJS.maxImageSize);
+
+/**
+ * The url of where the predefined Adobe CMaps are located. Include trailing
+ * slash.
+ * @var {string}
+ */
+PDFJS.cMapUrl = (PDFJS.cMapUrl === undefined ? null : PDFJS.cMapUrl);
+
+/**
+ * Specifies if CMaps are binary packed.
+ * @var {boolean}
+ */
+PDFJS.cMapPacked = PDFJS.cMapPacked === undefined ? false : PDFJS.cMapPacked;
+
+/**
+ * By default fonts are converted to OpenType fonts and loaded via font face
+ * rules. If disabled, the font will be rendered using a built in font renderer
+ * that constructs the glyphs with primitive path commands.
+ * @var {boolean}
+ */
+PDFJS.disableFontFace = (PDFJS.disableFontFace === undefined ?
+ false : PDFJS.disableFontFace);
+
+/**
+ * Path for image resources, mainly for annotation icons. Include trailing
+ * slash.
+ * @var {string}
+ */
+PDFJS.imageResourcesPath = (PDFJS.imageResourcesPath === undefined ?
+ '' : PDFJS.imageResourcesPath);
+
+/**
+ * Disable the web worker and run all code on the main thread. This will happen
+ * automatically if the browser doesn't support workers or sending typed arrays
+ * to workers.
+ * @var {boolean}
+ */
+PDFJS.disableWorker = (PDFJS.disableWorker === undefined ?
+ false : PDFJS.disableWorker);
+
+/**
+ * Path and filename of the worker file. Required when the worker is enabled in
+ * development mode. If unspecified in the production build, the worker will be
+ * loaded based on the location of the pdf.js file.
+ * @var {string}
+ */
+PDFJS.workerSrc = (PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc);
+
+/**
+ * Disable range request loading of PDF files. When enabled and if the server
+ * supports partial content requests then the PDF will be fetched in chunks.
+ * Enabled (false) by default.
+ * @var {boolean}
+ */
+PDFJS.disableRange = (PDFJS.disableRange === undefined ?
+ false : PDFJS.disableRange);
+
+/**
+ * Disable streaming of PDF file data. By default PDF.js attempts to load PDF
+ * in chunks. This default behavior can be disabled.
+ * @var {boolean}
+ */
+PDFJS.disableStream = (PDFJS.disableStream === undefined ?
+ false : PDFJS.disableStream);
+
+/**
+ * Disable pre-fetching of PDF file data. When range requests are enabled PDF.js
+ * will automatically keep fetching more data even if it isn't needed to display
+ * the current page. This default behavior can be disabled.
+ *
+ * NOTE: It is also necessary to disable streaming, see above,
+ * in order for disabling of pre-fetching to work correctly.
+ * @var {boolean}
+ */
+PDFJS.disableAutoFetch = (PDFJS.disableAutoFetch === undefined ?
+ false : PDFJS.disableAutoFetch);
+
+/**
+ * Enables special hooks for debugging PDF.js.
+ * @var {boolean}
+ */
+PDFJS.pdfBug = (PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug);
+
+/**
+ * Enables transfer usage in postMessage for ArrayBuffers.
+ * @var {boolean}
+ */
+PDFJS.postMessageTransfers = (PDFJS.postMessageTransfers === undefined ?
+ true : PDFJS.postMessageTransfers);
+
+/**
+ * Disables URL.createObjectURL usage.
+ * @var {boolean}
+ */
+PDFJS.disableCreateObjectURL = (PDFJS.disableCreateObjectURL === undefined ?
+ false : PDFJS.disableCreateObjectURL);
+
+/**
+ * Disables WebGL usage.
+ * @var {boolean}
+ */
+PDFJS.disableWebGL = (PDFJS.disableWebGL === undefined ?
+ true : PDFJS.disableWebGL);
+
+/**
+ * Disables fullscreen support, and by extension Presentation Mode,
+ * in browsers which support the fullscreen API.
+ * @var {boolean}
+ */
+PDFJS.disableFullscreen = (PDFJS.disableFullscreen === undefined ?
+ false : PDFJS.disableFullscreen);
+
+/**
+ * Enables CSS only zooming.
+ * @var {boolean}
+ */
+PDFJS.useOnlyCssZoom = (PDFJS.useOnlyCssZoom === undefined ?
+ false : PDFJS.useOnlyCssZoom);
+
+/**
+ * Controls the logging level.
+ * The constants from PDFJS.VERBOSITY_LEVELS should be used:
+ * - errors
+ * - warnings [default]
+ * - infos
+ * @var {number}
+ */
+PDFJS.verbosity = (PDFJS.verbosity === undefined ?
+ PDFJS.VERBOSITY_LEVELS.warnings : PDFJS.verbosity);
+
+/**
+ * The maximum supported canvas size in total pixels e.g. width * height.
+ * The default value is 4096 * 4096. Use -1 for no limit.
+ * @var {number}
+ */
+PDFJS.maxCanvasPixels = (PDFJS.maxCanvasPixels === undefined ?
+ 16777216 : PDFJS.maxCanvasPixels);
+
+/**
+ * Opens external links in a new window if enabled. The default behavior opens
+ * external links in the PDF.js window.
+ * @var {boolean}
+ */
+PDFJS.openExternalLinksInNewWindow = (
+ PDFJS.openExternalLinksInNewWindow === undefined ?
+ false : PDFJS.openExternalLinksInNewWindow);
+
+/**
+ * Document initialization / loading parameters object.
+ *
+ * @typedef {Object} DocumentInitParameters
+ * @property {string} url - The URL of the PDF.
+ * @property {TypedArray|Array|string} data - Binary PDF data. Use typed arrays
+ * (Uint8Array) to improve the memory usage. If PDF data is BASE64-encoded,
+ * use atob() to convert it to a binary string first.
+ * @property {Object} httpHeaders - Basic authentication headers.
+ * @property {boolean} withCredentials - Indicates whether or not cross-site
+ * Access-Control requests should be made using credentials such as cookies
+ * or authorization headers. The default is false.
+ * @property {string} password - For decrypting password-protected PDFs.
+ * @property {TypedArray} initialData - A typed array with the first portion or
+ * all of the pdf data. Used by the extension since some data is already
+ * loaded before the switch to range requests.
+ * @property {number} length - The PDF file length. It's used for progress
+ * reports and range requests operations.
+ * @property {PDFDataRangeTransport} range
+ */
+
+/**
+ * @typedef {Object} PDFDocumentStats
+ * @property {Array} streamTypes - Used stream types in the document (an item
+ * is set to true if specific stream ID was used in the document).
+ * @property {Array} fontTypes - Used font type in the document (an item is set
+ * to true if specific font ID was used in the document).
+ */
+
+/**
+ * This is the main entry point for loading a PDF and interacting with it.
+ * NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR)
+ * is used, which means it must follow the same origin rules that any XHR does
+ * e.g. No cross domain requests without CORS.
+ *
+ * @param {string|TypedArray|DocumentInitParameters|PDFDataRangeTransport} src
+ * Can be a url to where a PDF is located, a typed array (Uint8Array)
+ * already populated with data or parameter object.
+ *
+ * @param {PDFDataRangeTransport} pdfDataRangeTransport (deprecated) It is used
+ * if you want to manually serve range requests for data in the PDF.
+ *
+ * @param {function} passwordCallback (deprecated) It is used to request a
+ * password if wrong or no password was provided. The callback receives two
+ * parameters: function that needs to be called with new password and reason
+ * (see {PasswordResponses}).
+ *
+ * @param {function} progressCallback (deprecated) It is used to be able to
+ * monitor the loading progress of the PDF file (necessary to implement e.g.
+ * a loading bar). The callback receives an {Object} with the properties:
+ * {number} loaded and {number} total.
+ *
+ * @return {PDFDocumentLoadingTask}
+ */
+PDFJS.getDocument = function getDocument(src,
+ pdfDataRangeTransport,
+ passwordCallback,
+ progressCallback) {
+ var task = new PDFDocumentLoadingTask();
+
+ // Support of the obsolete arguments (for compatibility with API v1.0)
+ if (pdfDataRangeTransport) {
+ if (!(pdfDataRangeTransport instanceof PDFDataRangeTransport)) {
+ // Not a PDFDataRangeTransport instance, trying to add missing properties.
+ pdfDataRangeTransport = Object.create(pdfDataRangeTransport);
+ pdfDataRangeTransport.length = src.length;
+ pdfDataRangeTransport.initialData = src.initialData;
+ }
+ src = Object.create(src);
+ src.range = pdfDataRangeTransport;
+ }
+ task.onPassword = passwordCallback || null;
+ task.onProgress = progressCallback || null;
+
+ var workerInitializedCapability, transport;
+ var source;
+ if (typeof src === 'string') {
+ source = { url: src };
+ } else if (isArrayBuffer(src)) {
+ source = { data: src };
+ } else if (src instanceof PDFDataRangeTransport) {
+ source = { range: src };
+ } else {
+ if (typeof src !== 'object') {
+ error('Invalid parameter in getDocument, need either Uint8Array, ' +
+ 'string or a parameter object');
+ }
+ if (!src.url && !src.data && !src.range) {
+ error('Invalid parameter object: need either .data, .range or .url');
+ }
+
+ source = src;
+ }
+
+ var params = {};
+ for (var key in source) {
+ if (key === 'url' && typeof window !== 'undefined') {
+ // The full path is required in the 'url' field.
+ params[key] = combineUrl(window.location.href, source[key]);
+ continue;
+ } else if (key === 'range') {
+ continue;
+ } else if (key === 'data' && !(source[key] instanceof Uint8Array)) {
+ // Converting string or array-like data to Uint8Array.
+ var pdfBytes = source[key];
+ if (typeof pdfBytes === 'string') {
+ params[key] = stringToBytes(pdfBytes);
+ } else if (typeof pdfBytes === 'object' && pdfBytes !== null &&
+ !isNaN(pdfBytes.length)) {
+ params[key] = new Uint8Array(pdfBytes);
+ } else {
+ error('Invalid PDF binary data: either typed array, string or ' +
+ 'array-like object is expected in the data property.');
+ }
+ continue;
+ }
+ params[key] = source[key];
+ }
+
+ workerInitializedCapability = createPromiseCapability();
+ transport = new WorkerTransport(workerInitializedCapability, source.range);
+ workerInitializedCapability.promise.then(function transportInitialized() {
+ transport.fetchDocument(task, params);
+ });
+
+ return task;
+};
+
+/**
+ * PDF document loading operation.
+ * @class
+ */
+var PDFDocumentLoadingTask = (function PDFDocumentLoadingTaskClosure() {
+ /** @constructs PDFDocumentLoadingTask */
+ function PDFDocumentLoadingTask() {
+ this._capability = createPromiseCapability();
+
+ /**
+ * Callback to request a password if wrong or no password was provided.
+ * The callback receives two parameters: function that needs to be called
+ * with new password and reason (see {PasswordResponses}).
+ */
+ this.onPassword = null;
+
+ /**
+ * Callback to be able to monitor the loading progress of the PDF file
+ * (necessary to implement e.g. a loading bar). The callback receives
+ * an {Object} with the properties: {number} loaded and {number} total.
+ */
+ this.onProgress = null;
+ }
+
+ PDFDocumentLoadingTask.prototype =
+ /** @lends PDFDocumentLoadingTask.prototype */ {
+ /**
+ * @return {Promise}
+ */
+ get promise() {
+ return this._capability.promise;
+ },
+
+ // TODO add cancel or abort method
+
+ /**
+ * Registers callbacks to indicate the document loading completion.
+ *
+ * @param {function} onFulfilled The callback for the loading completion.
+ * @param {function} onRejected The callback for the loading failure.
+ * @return {Promise} A promise that is resolved after the onFulfilled or
+ * onRejected callback.
+ */
+ then: function PDFDocumentLoadingTask_then(onFulfilled, onRejected) {
+ return this.promise.then.apply(this.promise, arguments);
+ }
+ };
+
+ return PDFDocumentLoadingTask;
+})();
+
+/**
+ * Abstract class to support range requests file loading.
+ * @class
+ */
+var PDFDataRangeTransport = (function pdfDataRangeTransportClosure() {
+ /**
+ * @constructs PDFDataRangeTransport
+ * @param {number} length
+ * @param {Uint8Array} initialData
+ */
+ function PDFDataRangeTransport(length, initialData) {
+ this.length = length;
+ this.initialData = initialData;
+
+ this._rangeListeners = [];
+ this._progressListeners = [];
+ this._progressiveReadListeners = [];
+ this._readyCapability = createPromiseCapability();
+ }
+ PDFDataRangeTransport.prototype =
+ /** @lends PDFDataRangeTransport.prototype */ {
+ addRangeListener:
+ function PDFDataRangeTransport_addRangeListener(listener) {
+ this._rangeListeners.push(listener);
+ },
+
+ addProgressListener:
+ function PDFDataRangeTransport_addProgressListener(listener) {
+ this._progressListeners.push(listener);
+ },
+
+ addProgressiveReadListener:
+ function PDFDataRangeTransport_addProgressiveReadListener(listener) {
+ this._progressiveReadListeners.push(listener);
+ },
+
+ onDataRange: function PDFDataRangeTransport_onDataRange(begin, chunk) {
+ var listeners = this._rangeListeners;
+ for (var i = 0, n = listeners.length; i < n; ++i) {
+ listeners[i](begin, chunk);
+ }
+ },
+
+ onDataProgress: function PDFDataRangeTransport_onDataProgress(loaded) {
+ this._readyCapability.promise.then(function () {
+ var listeners = this._progressListeners;
+ for (var i = 0, n = listeners.length; i < n; ++i) {
+ listeners[i](loaded);
+ }
+ }.bind(this));
+ },
+
+ onDataProgressiveRead:
+ function PDFDataRangeTransport_onDataProgress(chunk) {
+ this._readyCapability.promise.then(function () {
+ var listeners = this._progressiveReadListeners;
+ for (var i = 0, n = listeners.length; i < n; ++i) {
+ listeners[i](chunk);
+ }
+ }.bind(this));
+ },
+
+ transportReady: function PDFDataRangeTransport_transportReady() {
+ this._readyCapability.resolve();
+ },
+
+ requestDataRange:
+ function PDFDataRangeTransport_requestDataRange(begin, end) {
+ throw new Error('Abstract method PDFDataRangeTransport.requestDataRange');
+ }
+ };
+ return PDFDataRangeTransport;
+})();
+
+PDFJS.PDFDataRangeTransport = PDFDataRangeTransport;
+
+/**
+ * Proxy to a PDFDocument in the worker thread. Also, contains commonly used
+ * properties that can be read synchronously.
+ * @class
+ */
+var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
+ function PDFDocumentProxy(pdfInfo, transport) {
+ this.pdfInfo = pdfInfo;
+ this.transport = transport;
+ }
+ PDFDocumentProxy.prototype = /** @lends PDFDocumentProxy.prototype */ {
+ /**
+ * @return {number} Total number of pages the PDF contains.
+ */
+ get numPages() {
+ return this.pdfInfo.numPages;
+ },
+ /**
+ * @return {string} A unique ID to identify a PDF. Not guaranteed to be
+ * unique.
+ */
+ get fingerprint() {
+ return this.pdfInfo.fingerprint;
+ },
+ /**
+ * @param {number} pageNumber The page number to get. The first page is 1.
+ * @return {Promise} A promise that is resolved with a {@link PDFPageProxy}
+ * object.
+ */
+ getPage: function PDFDocumentProxy_getPage(pageNumber) {
+ return this.transport.getPage(pageNumber);
+ },
+ /**
+ * @param {{num: number, gen: number}} ref The page reference. Must have
+ * the 'num' and 'gen' properties.
+ * @return {Promise} A promise that is resolved with the page index that is
+ * associated with the reference.
+ */
+ getPageIndex: function PDFDocumentProxy_getPageIndex(ref) {
+ return this.transport.getPageIndex(ref);
+ },
+ /**
+ * @return {Promise} A promise that is resolved with a lookup table for
+ * mapping named destinations to reference numbers.
+ *
+ * This can be slow for large documents: use getDestination instead
+ */
+ getDestinations: function PDFDocumentProxy_getDestinations() {
+ return this.transport.getDestinations();
+ },
+ /**
+ * @param {string} id The named destination to get.
+ * @return {Promise} A promise that is resolved with all information
+ * of the given named destination.
+ */
+ getDestination: function PDFDocumentProxy_getDestination(id) {
+ return this.transport.getDestination(id);
+ },
+ /**
+ * @return {Promise} A promise that is resolved with a lookup table for
+ * mapping named attachments to their content.
+ */
+ getAttachments: function PDFDocumentProxy_getAttachments() {
+ return this.transport.getAttachments();
+ },
+ /**
+ * @return {Promise} A promise that is resolved with an array of all the
+ * JavaScript strings in the name tree.
+ */
+ getJavaScript: function PDFDocumentProxy_getJavaScript() {
+ return this.transport.getJavaScript();
+ },
+ /**
+ * @return {Promise} A promise that is resolved with an {Array} that is a
+ * tree outline (if it has one) of the PDF. The tree is in the format of:
+ * [
+ * {
+ * title: string,
+ * bold: boolean,
+ * italic: boolean,
+ * color: rgb array,
+ * dest: dest obj,
+ * items: array of more items like this
+ * },
+ * ...
+ * ].
+ */
+ getOutline: function PDFDocumentProxy_getOutline() {
+ return this.transport.getOutline();
+ },
+ /**
+ * @return {Promise} A promise that is resolved with an {Object} that has
+ * info and metadata properties. Info is an {Object} filled with anything
+ * available in the information dictionary and similarly metadata is a
+ * {Metadata} object with information from the metadata section of the PDF.
+ */
+ getMetadata: function PDFDocumentProxy_getMetadata() {
+ return this.transport.getMetadata();
+ },
+ /**
+ * @return {Promise} A promise that is resolved with a TypedArray that has
+ * the raw data from the PDF.
+ */
+ getData: function PDFDocumentProxy_getData() {
+ return this.transport.getData();
+ },
+ /**
+ * @return {Promise} A promise that is resolved when the document's data
+ * is loaded. It is resolved with an {Object} that contains the length
+ * property that indicates size of the PDF data in bytes.
+ */
+ getDownloadInfo: function PDFDocumentProxy_getDownloadInfo() {
+ return this.transport.downloadInfoCapability.promise;
+ },
+ /**
+ * @return {Promise} A promise this is resolved with current stats about
+ * document structures (see {@link PDFDocumentStats}).
+ */
+ getStats: function PDFDocumentProxy_getStats() {
+ return this.transport.getStats();
+ },
+ /**
+ * Cleans up resources allocated by the document, e.g. created @font-face.
+ */
+ cleanup: function PDFDocumentProxy_cleanup() {
+ this.transport.startCleanup();
+ },
+ /**
+ * Destroys current document instance and terminates worker.
+ */
+ destroy: function PDFDocumentProxy_destroy() {
+ this.transport.destroy();
+ }
+ };
+ return PDFDocumentProxy;
+})();
+
+/**
+ * Page text content.
+ *
+ * @typedef {Object} TextContent
+ * @property {array} items - array of {@link TextItem}
+ * @property {Object} styles - {@link TextStyles} objects, indexed by font
+ * name.
+ */
+
+/**
+ * Page text content part.
+ *
+ * @typedef {Object} TextItem
+ * @property {string} str - text content.
+ * @property {string} dir - text direction: 'ttb', 'ltr' or 'rtl'.
+ * @property {array} transform - transformation matrix.
+ * @property {number} width - width in device space.
+ * @property {number} height - height in device space.
+ * @property {string} fontName - font name used by pdf.js for converted font.
+ */
+
+/**
+ * Text style.
+ *
+ * @typedef {Object} TextStyle
+ * @property {number} ascent - font ascent.
+ * @property {number} descent - font descent.
+ * @property {boolean} vertical - text is in vertical mode.
+ * @property {string} fontFamily - possible font family
+ */
+
+/**
+ * Page render parameters.
+ *
+ * @typedef {Object} RenderParameters
+ * @property {Object} canvasContext - A 2D context of a DOM Canvas object.
+ * @property {PDFJS.PageViewport} viewport - Rendering viewport obtained by
+ * calling of PDFPage.getViewport method.
+ * @property {string} intent - Rendering intent, can be 'display' or 'print'
+ * (default value is 'display').
+ * @property {Object} imageLayer - (optional) An object that has beginLayout,
+ * endLayout and appendImage functions.
+ * @property {function} continueCallback - (deprecated) A function that will be
+ * called each time the rendering is paused. To continue
+ * rendering call the function that is the first argument
+ * to the callback.
+ */
+
+/**
+ * PDF page operator list.
+ *
+ * @typedef {Object} PDFOperatorList
+ * @property {Array} fnArray - Array containing the operator functions.
+ * @property {Array} argsArray - Array containing the arguments of the
+ * functions.
+ */
+
+/**
+ * Proxy to a PDFPage in the worker thread.
+ * @class
+ */
+var PDFPageProxy = (function PDFPageProxyClosure() {
+ function PDFPageProxy(pageIndex, pageInfo, transport) {
+ this.pageIndex = pageIndex;
+ this.pageInfo = pageInfo;
+ this.transport = transport;
+ this.stats = new StatTimer();
+ this.stats.enabled = !!globalScope.PDFJS.enableStats;
+ this.commonObjs = transport.commonObjs;
+ this.objs = new PDFObjects();
+ this.cleanupAfterRender = false;
+ this.pendingDestroy = false;
+ this.intentStates = {};
+ }
+ PDFPageProxy.prototype = /** @lends PDFPageProxy.prototype */ {
+ /**
+ * @return {number} Page number of the page. First page is 1.
+ */
+ get pageNumber() {
+ return this.pageIndex + 1;
+ },
+ /**
+ * @return {number} The number of degrees the page is rotated clockwise.
+ */
+ get rotate() {
+ return this.pageInfo.rotate;
+ },
+ /**
+ * @return {Object} The reference that points to this page. It has 'num' and
+ * 'gen' properties.
+ */
+ get ref() {
+ return this.pageInfo.ref;
+ },
+ /**
+ * @return {Array} An array of the visible portion of the PDF page in the
+ * user space units - [x1, y1, x2, y2].
+ */
+ get view() {
+ return this.pageInfo.view;
+ },
+ /**
+ * @param {number} scale The desired scale of the viewport.
+ * @param {number} rotate Degrees to rotate the viewport. If omitted this
+ * defaults to the page rotation.
+ * @return {PDFJS.PageViewport} Contains 'width' and 'height' properties
+ * along with transforms required for rendering.
+ */
+ getViewport: function PDFPageProxy_getViewport(scale, rotate) {
+ if (arguments.length < 2) {
+ rotate = this.rotate;
+ }
+ return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
+ },
+ /**
+ * @return {Promise} A promise that is resolved with an {Array} of the
+ * annotation objects.
+ */
+ getAnnotations: function PDFPageProxy_getAnnotations() {
+ if (this.annotationsPromise) {
+ return this.annotationsPromise;
+ }
+
+ var promise = this.transport.getAnnotations(this.pageIndex);
+ this.annotationsPromise = promise;
+ return promise;
+ },
+ /**
+ * Begins the process of rendering a page to the desired context.
+ * @param {RenderParameters} params Page render parameters.
+ * @return {RenderTask} An object that contains the promise, which
+ * is resolved when the page finishes rendering.
+ */
+ render: function PDFPageProxy_render(params) {
+ var stats = this.stats;
+ stats.time('Overall');
+
+ // If there was a pending destroy cancel it so no cleanup happens during
+ // this call to render.
+ this.pendingDestroy = false;
+
+ var renderingIntent = (params.intent === 'print' ? 'print' : 'display');
+
+ if (!this.intentStates[renderingIntent]) {
+ this.intentStates[renderingIntent] = {};
+ }
+ var intentState = this.intentStates[renderingIntent];
+
+ // If there's no displayReadyCapability yet, then the operatorList
+ // was never requested before. Make the request and create the promise.
+ if (!intentState.displayReadyCapability) {
+ intentState.receivingOperatorList = true;
+ intentState.displayReadyCapability = createPromiseCapability();
+ intentState.operatorList = {
+ fnArray: [],
+ argsArray: [],
+ lastChunk: false
+ };
+
+ this.stats.time('Page Request');
+ this.transport.messageHandler.send('RenderPageRequest', {
+ pageIndex: this.pageNumber - 1,
+ intent: renderingIntent
+ });
+ }
+
+ var internalRenderTask = new InternalRenderTask(complete, params,
+ this.objs,
+ this.commonObjs,
+ intentState.operatorList,
+ this.pageNumber);
+ if (!intentState.renderTasks) {
+ intentState.renderTasks = [];
+ }
+ intentState.renderTasks.push(internalRenderTask);
+ var renderTask = internalRenderTask.task;
+
+ // Obsolete parameter support
+ if (params.continueCallback) {
+ renderTask.onContinue = params.continueCallback;
+ }
+
+ var self = this;
+ intentState.displayReadyCapability.promise.then(
+ function pageDisplayReadyPromise(transparency) {
+ if (self.pendingDestroy) {
+ complete();
+ return;
+ }
+ stats.time('Rendering');
+ internalRenderTask.initalizeGraphics(transparency);
+ internalRenderTask.operatorListChanged();
+ },
+ function pageDisplayReadPromiseError(reason) {
+ complete(reason);
+ }
+ );
+
+ function complete(error) {
+ var i = intentState.renderTasks.indexOf(internalRenderTask);
+ if (i >= 0) {
+ intentState.renderTasks.splice(i, 1);
+ }
+
+ if (self.cleanupAfterRender) {
+ self.pendingDestroy = true;
+ }
+ self._tryDestroy();
+
+ if (error) {
+ internalRenderTask.capability.reject(error);
+ } else {
+ internalRenderTask.capability.resolve();
+ }
+ stats.timeEnd('Rendering');
+ stats.timeEnd('Overall');
+ }
+
+ return renderTask;
+ },
+
+ /**
+ * @return {Promise} A promise resolved with an {@link PDFOperatorList}
+ * object that represents page's operator list.
+ */
+ getOperatorList: function PDFPageProxy_getOperatorList() {
+ function operatorListChanged() {
+ if (intentState.operatorList.lastChunk) {
+ intentState.opListReadCapability.resolve(intentState.operatorList);
+ }
+ }
+
+ var renderingIntent = 'oplist';
+ if (!this.intentStates[renderingIntent]) {
+ this.intentStates[renderingIntent] = {};
+ }
+ var intentState = this.intentStates[renderingIntent];
+
+ if (!intentState.opListReadCapability) {
+ var opListTask = {};
+ opListTask.operatorListChanged = operatorListChanged;
+ intentState.receivingOperatorList = true;
+ intentState.opListReadCapability = createPromiseCapability();
+ intentState.renderTasks = [];
+ intentState.renderTasks.push(opListTask);
+ intentState.operatorList = {
+ fnArray: [],
+ argsArray: [],
+ lastChunk: false
+ };
+
+ this.transport.messageHandler.send('RenderPageRequest', {
+ pageIndex: this.pageIndex,
+ intent: renderingIntent
+ });
+ }
+ return intentState.opListReadCapability.promise;
+ },
+
+ /**
+ * @return {Promise} That is resolved a {@link TextContent}
+ * object that represent the page text content.
+ */
+ getTextContent: function PDFPageProxy_getTextContent() {
+ return this.transport.messageHandler.sendWithPromise('GetTextContent', {
+ pageIndex: this.pageNumber - 1
+ });
+ },
+ /**
+ * Destroys resources allocated by the page.
+ */
+ destroy: function PDFPageProxy_destroy() {
+ this.pendingDestroy = true;
+ this._tryDestroy();
+ },
+ /**
+ * For internal use only. Attempts to clean up if rendering is in a state
+ * where that's possible.
+ * @ignore
+ */
+ _tryDestroy: function PDFPageProxy__destroy() {
+ if (!this.pendingDestroy ||
+ Object.keys(this.intentStates).some(function(intent) {
+ var intentState = this.intentStates[intent];
+ return (intentState.renderTasks.length !== 0 ||
+ intentState.receivingOperatorList);
+ }, this)) {
+ return;
+ }
+
+ Object.keys(this.intentStates).forEach(function(intent) {
+ delete this.intentStates[intent];
+ }, this);
+ this.objs.clear();
+ this.annotationsPromise = null;
+ this.pendingDestroy = false;
+ },
+ /**
+ * For internal use only.
+ * @ignore
+ */
+ _startRenderPage: function PDFPageProxy_startRenderPage(transparency,
+ intent) {
+ var intentState = this.intentStates[intent];
+ // TODO Refactor RenderPageRequest to separate rendering
+ // and operator list logic
+ if (intentState.displayReadyCapability) {
+ intentState.displayReadyCapability.resolve(transparency);
+ }
+ },
+ /**
+ * For internal use only.
+ * @ignore
+ */
+ _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk,
+ intent) {
+ var intentState = this.intentStates[intent];
+ var i, ii;
+ // Add the new chunk to the current operator list.
+ for (i = 0, ii = operatorListChunk.length; i < ii; i++) {
+ intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
+ intentState.operatorList.argsArray.push(
+ operatorListChunk.argsArray[i]);
+ }
+ intentState.operatorList.lastChunk = operatorListChunk.lastChunk;
+
+ // Notify all the rendering tasks there are more operators to be consumed.
+ for (i = 0; i < intentState.renderTasks.length; i++) {
+ intentState.renderTasks[i].operatorListChanged();
+ }
+
+ if (operatorListChunk.lastChunk) {
+ intentState.receivingOperatorList = false;
+ this._tryDestroy();
+ }
+ }
+ };
+ return PDFPageProxy;
+})();
+
+/**
+ * For internal use only.
+ * @ignore
+ */
+var WorkerTransport = (function WorkerTransportClosure() {
+ function WorkerTransport(workerInitializedCapability, pdfDataRangeTransport) {
+ this.pdfDataRangeTransport = pdfDataRangeTransport;
+ this.workerInitializedCapability = workerInitializedCapability;
+ this.commonObjs = new PDFObjects();
+
+ this.loadingTask = null;
+
+ this.pageCache = [];
+ this.pagePromises = [];
+ this.downloadInfoCapability = createPromiseCapability();
+
+ // If worker support isn't disabled explicit and the browser has worker
+ // support, create a new web worker and test if it/the browser fullfills
+ // all requirements to run parts of pdf.js in a web worker.
+ // Right now, the requirement is, that an Uint8Array is still an Uint8Array
+ // as it arrives on the worker. Chrome added this with version 15.
+//#if !SINGLE_FILE
+ if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
+ var workerSrc = PDFJS.workerSrc;
+ if (!workerSrc) {
+ error('No PDFJS.workerSrc specified');
+ }
+
+ try {
+ // Some versions of FF can't create a worker on localhost, see:
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
+ var worker = new Worker(workerSrc);
+ var messageHandler = new MessageHandler('main', worker);
+ this.messageHandler = messageHandler;
+
+ messageHandler.on('test', function transportTest(data) {
+ var supportTypedArray = data && data.supportTypedArray;
+ if (supportTypedArray) {
+ this.worker = worker;
+ if (!data.supportTransfers) {
+ PDFJS.postMessageTransfers = false;
+ }
+ this.setupMessageHandler(messageHandler);
+ workerInitializedCapability.resolve();
+ } else {
+ this.setupFakeWorker();
+ }
+ }.bind(this));
+
+ var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]);
+ // Some versions of Opera throw a DATA_CLONE_ERR on serializing the
+ // typed array. Also, checking if we can use transfers.
+ try {
+ messageHandler.send('test', testObj, [testObj.buffer]);
+ } catch (ex) {
+ info('Cannot use postMessage transfers');
+ testObj[0] = 0;
+ messageHandler.send('test', testObj);
+ }
+ return;
+ } catch (e) {
+ info('The worker has been disabled.');
+ }
+ }
+//#endif
+ // Either workers are disabled, not supported or have thrown an exception.
+ // Thus, we fallback to a faked worker.
+ this.setupFakeWorker();
+ }
+ WorkerTransport.prototype = {
+ destroy: function WorkerTransport_destroy() {
+ this.pageCache = [];
+ this.pagePromises = [];
+ var self = this;
+ this.messageHandler.sendWithPromise('Terminate', null).then(function () {
+ FontLoader.clear();
+ if (self.worker) {
+ self.worker.terminate();
+ }
+ });
+ },
+
+ setupFakeWorker: function WorkerTransport_setupFakeWorker() {
+ globalScope.PDFJS.disableWorker = true;
+
+ if (!PDFJS.fakeWorkerFilesLoadedCapability) {
+ PDFJS.fakeWorkerFilesLoadedCapability = createPromiseCapability();
+ // In the developer build load worker_loader which in turn loads all the
+ // other files and resolves the promise. In production only the
+ // pdf.worker.js file is needed.
+//#if !PRODUCTION
+ Util.loadScript(PDFJS.workerSrc);
+//#endif
+//#if PRODUCTION && SINGLE_FILE
+// PDFJS.fakeWorkerFilesLoadedCapability.resolve();
+//#endif
+//#if PRODUCTION && !SINGLE_FILE
+// Util.loadScript(PDFJS.workerSrc, function() {
+// PDFJS.fakeWorkerFilesLoadedCapability.resolve();
+// });
+//#endif
+ }
+ PDFJS.fakeWorkerFilesLoadedCapability.promise.then(function () {
+ warn('Setting up fake worker.');
+ // If we don't use a worker, just post/sendMessage to the main thread.
+ var fakeWorker = {
+ postMessage: function WorkerTransport_postMessage(obj) {
+ fakeWorker.onmessage({data: obj});
+ },
+ terminate: function WorkerTransport_terminate() {}
+ };
+
+ var messageHandler = new MessageHandler('main', fakeWorker);
+ this.setupMessageHandler(messageHandler);
+
+ // If the main thread is our worker, setup the handling for the messages
+ // the main thread sends to it self.
+ PDFJS.WorkerMessageHandler.setup(messageHandler);
+
+ this.workerInitializedCapability.resolve();
+ }.bind(this));
+ },
+
+ setupMessageHandler:
+ function WorkerTransport_setupMessageHandler(messageHandler) {
+ this.messageHandler = messageHandler;
+
+ function updatePassword(password) {
+ messageHandler.send('UpdatePassword', password);
+ }
+
+ var pdfDataRangeTransport = this.pdfDataRangeTransport;
+ if (pdfDataRangeTransport) {
+ pdfDataRangeTransport.addRangeListener(function(begin, chunk) {
+ messageHandler.send('OnDataRange', {
+ begin: begin,
+ chunk: chunk
+ });
+ });
+
+ pdfDataRangeTransport.addProgressListener(function(loaded) {
+ messageHandler.send('OnDataProgress', {
+ loaded: loaded
+ });
+ });
+
+ pdfDataRangeTransport.addProgressiveReadListener(function(chunk) {
+ messageHandler.send('OnDataRange', {
+ chunk: chunk
+ });
+ });
+
+ messageHandler.on('RequestDataRange',
+ function transportDataRange(data) {
+ pdfDataRangeTransport.requestDataRange(data.begin, data.end);
+ }, this);
+ }
+
+ messageHandler.on('GetDoc', function transportDoc(data) {
+ var pdfInfo = data.pdfInfo;
+ this.numPages = data.pdfInfo.numPages;
+ var pdfDocument = new PDFDocumentProxy(pdfInfo, this);
+ this.pdfDocument = pdfDocument;
+ this.loadingTask._capability.resolve(pdfDocument);
+ }, this);
+
+ messageHandler.on('NeedPassword',
+ function transportNeedPassword(exception) {
+ var loadingTask = this.loadingTask;
+ if (loadingTask.onPassword) {
+ return loadingTask.onPassword(updatePassword,
+ PasswordResponses.NEED_PASSWORD);
+ }
+ loadingTask._capability.reject(
+ new PasswordException(exception.message, exception.code));
+ }, this);
+
+ messageHandler.on('IncorrectPassword',
+ function transportIncorrectPassword(exception) {
+ var loadingTask = this.loadingTask;
+ if (loadingTask.onPassword) {
+ return loadingTask.onPassword(updatePassword,
+ PasswordResponses.INCORRECT_PASSWORD);
+ }
+ loadingTask._capability.reject(
+ new PasswordException(exception.message, exception.code));
+ }, this);
+
+ messageHandler.on('InvalidPDF', function transportInvalidPDF(exception) {
+ this.loadingTask._capability.reject(
+ new InvalidPDFException(exception.message));
+ }, this);
+
+ messageHandler.on('MissingPDF', function transportMissingPDF(exception) {
+ this.loadingTask._capability.reject(
+ new MissingPDFException(exception.message));
+ }, this);
+
+ messageHandler.on('UnexpectedResponse',
+ function transportUnexpectedResponse(exception) {
+ this.loadingTask._capability.reject(
+ new UnexpectedResponseException(exception.message, exception.status));
+ }, this);
+
+ messageHandler.on('UnknownError',
+ function transportUnknownError(exception) {
+ this.loadingTask._capability.reject(
+ new UnknownErrorException(exception.message, exception.details));
+ }, this);
+
+ messageHandler.on('DataLoaded', function transportPage(data) {
+ this.downloadInfoCapability.resolve(data);
+ }, this);
+
+ messageHandler.on('PDFManagerReady', function transportPage(data) {
+ if (this.pdfDataRangeTransport) {
+ this.pdfDataRangeTransport.transportReady();
+ }
+ }, this);
+
+ messageHandler.on('StartRenderPage', function transportRender(data) {
+ var page = this.pageCache[data.pageIndex];
+
+ page.stats.timeEnd('Page Request');
+ page._startRenderPage(data.transparency, data.intent);
+ }, this);
+
+ messageHandler.on('RenderPageChunk', function transportRender(data) {
+ var page = this.pageCache[data.pageIndex];
+
+ page._renderPageChunk(data.operatorList, data.intent);
+ }, this);
+
+ messageHandler.on('commonobj', function transportObj(data) {
+ var id = data[0];
+ var type = data[1];
+ if (this.commonObjs.hasData(id)) {
+ return;
+ }
+
+ switch (type) {
+ case 'Font':
+ var exportedData = data[2];
+
+ var font;
+ if ('error' in exportedData) {
+ var error = exportedData.error;
+ warn('Error during font loading: ' + error);
+ this.commonObjs.resolve(id, error);
+ break;
+ } else {
+ font = new FontFaceObject(exportedData);
+ }
+
+ FontLoader.bind(
+ [font],
+ function fontReady(fontObjs) {
+ this.commonObjs.resolve(id, font);
+ }.bind(this)
+ );
+ break;
+ case 'FontPath':
+ this.commonObjs.resolve(id, data[2]);
+ break;
+ default:
+ error('Got unknown common object type ' + type);
+ }
+ }, this);
+
+ messageHandler.on('obj', function transportObj(data) {
+ var id = data[0];
+ var pageIndex = data[1];
+ var type = data[2];
+ var pageProxy = this.pageCache[pageIndex];
+ var imageData;
+ if (pageProxy.objs.hasData(id)) {
+ return;
+ }
+
+ switch (type) {
+ case 'JpegStream':
+ imageData = data[3];
+ loadJpegStream(id, imageData, pageProxy.objs);
+ break;
+ case 'Image':
+ imageData = data[3];
+ pageProxy.objs.resolve(id, imageData);
+
+ // heuristics that will allow not to store large data
+ var MAX_IMAGE_SIZE_TO_STORE = 8000000;
+ if (imageData && 'data' in imageData &&
+ imageData.data.length > MAX_IMAGE_SIZE_TO_STORE) {
+ pageProxy.cleanupAfterRender = true;
+ }
+ break;
+ default:
+ error('Got unknown object type ' + type);
+ }
+ }, this);
+
+ messageHandler.on('DocProgress', function transportDocProgress(data) {
+ var loadingTask = this.loadingTask;
+ if (loadingTask.onProgress) {
+ loadingTask.onProgress({
+ loaded: data.loaded,
+ total: data.total
+ });
+ }
+ }, this);
+
+ messageHandler.on('PageError', function transportError(data) {
+ var page = this.pageCache[data.pageNum - 1];
+ var intentState = page.intentStates[data.intent];
+ if (intentState.displayReadyCapability) {
+ intentState.displayReadyCapability.reject(data.error);
+ } else {
+ error(data.error);
+ }
+ }, this);
+
+ messageHandler.on('JpegDecode', function(data) {
+ var imageUrl = data[0];
+ var components = data[1];
+ if (components !== 3 && components !== 1) {
+ return Promise.reject(
+ new Error('Only 3 components or 1 component can be returned'));
+ }
+
+ return new Promise(function (resolve, reject) {
+ var img = new Image();
+ img.onload = function () {
+ var width = img.width;
+ var height = img.height;
+ var size = width * height;
+ var rgbaLength = size * 4;
+ var buf = new Uint8Array(size * components);
+ var tmpCanvas = createScratchCanvas(width, height);
+ var tmpCtx = tmpCanvas.getContext('2d');
+ tmpCtx.drawImage(img, 0, 0);
+ var data = tmpCtx.getImageData(0, 0, width, height).data;
+ var i, j;
+
+ if (components === 3) {
+ for (i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
+ buf[j] = data[i];
+ buf[j + 1] = data[i + 1];
+ buf[j + 2] = data[i + 2];
+ }
+ } else if (components === 1) {
+ for (i = 0, j = 0; i < rgbaLength; i += 4, j++) {
+ buf[j] = data[i];
+ }
+ }
+ resolve({ data: buf, width: width, height: height});
+ };
+ img.onerror = function () {
+ reject(new Error('JpegDecode failed to load image'));
+ };
+ img.src = imageUrl;
+ });
+ });
+ },
+
+ fetchDocument: function WorkerTransport_fetchDocument(loadingTask, source) {
+ this.loadingTask = loadingTask;
+
+ source.disableAutoFetch = PDFJS.disableAutoFetch;
+ source.disableStream = PDFJS.disableStream;
+ source.chunkedViewerLoading = !!this.pdfDataRangeTransport;
+ if (this.pdfDataRangeTransport) {
+ source.length = this.pdfDataRangeTransport.length;
+ source.initialData = this.pdfDataRangeTransport.initialData;
+ }
+ this.messageHandler.send('GetDocRequest', {
+ source: source,
+ disableRange: PDFJS.disableRange,
+ maxImageSize: PDFJS.maxImageSize,
+ cMapUrl: PDFJS.cMapUrl,
+ cMapPacked: PDFJS.cMapPacked,
+ disableFontFace: PDFJS.disableFontFace,
+ disableCreateObjectURL: PDFJS.disableCreateObjectURL,
+ verbosity: PDFJS.verbosity
+ });
+ },
+
+ getData: function WorkerTransport_getData() {
+ return this.messageHandler.sendWithPromise('GetData', null);
+ },
+
+ getPage: function WorkerTransport_getPage(pageNumber, capability) {
+ if (pageNumber <= 0 || pageNumber > this.numPages ||
+ (pageNumber|0) !== pageNumber) {
+ return Promise.reject(new Error('Invalid page request'));
+ }
+
+ var pageIndex = pageNumber - 1;
+ if (pageIndex in this.pagePromises) {
+ return this.pagePromises[pageIndex];
+ }
+ var promise = this.messageHandler.sendWithPromise('GetPage', {
+ pageIndex: pageIndex
+ }).then(function (pageInfo) {
+ var page = new PDFPageProxy(pageIndex, pageInfo, this);
+ this.pageCache[pageIndex] = page;
+ return page;
+ }.bind(this));
+ this.pagePromises[pageIndex] = promise;
+ return promise;
+ },
+
+ getPageIndex: function WorkerTransport_getPageIndexByRef(ref) {
+ return this.messageHandler.sendWithPromise('GetPageIndex', { ref: ref });
+ },
+
+ getAnnotations: function WorkerTransport_getAnnotations(pageIndex) {
+ return this.messageHandler.sendWithPromise('GetAnnotations',
+ { pageIndex: pageIndex });
+ },
+
+ getDestinations: function WorkerTransport_getDestinations() {
+ return this.messageHandler.sendWithPromise('GetDestinations', null);
+ },
+
+ getDestination: function WorkerTransport_getDestination(id) {
+ return this.messageHandler.sendWithPromise('GetDestination', { id: id } );
+ },
+
+ getAttachments: function WorkerTransport_getAttachments() {
+ return this.messageHandler.sendWithPromise('GetAttachments', null);
+ },
+
+ getJavaScript: function WorkerTransport_getJavaScript() {
+ return this.messageHandler.sendWithPromise('GetJavaScript', null);
+ },
+
+ getOutline: function WorkerTransport_getOutline() {
+ return this.messageHandler.sendWithPromise('GetOutline', null);
+ },
+
+ getMetadata: function WorkerTransport_getMetadata() {
+ return this.messageHandler.sendWithPromise('GetMetadata', null).
+ then(function transportMetadata(results) {
+ return {
+ info: results[0],
+ metadata: (results[1] ? new PDFJS.Metadata(results[1]) : null)
+ };
+ });
+ },
+
+ getStats: function WorkerTransport_getStats() {
+ return this.messageHandler.sendWithPromise('GetStats', null);
+ },
+
+ startCleanup: function WorkerTransport_startCleanup() {
+ this.messageHandler.sendWithPromise('Cleanup', null).
+ then(function endCleanup() {
+ for (var i = 0, ii = this.pageCache.length; i < ii; i++) {
+ var page = this.pageCache[i];
+ if (page) {
+ page.destroy();
+ }
+ }
+ this.commonObjs.clear();
+ FontLoader.clear();
+ }.bind(this));
+ }
+ };
+ return WorkerTransport;
+
+})();
+
+/**
+ * A PDF document and page is built of many objects. E.g. there are objects
+ * for fonts, images, rendering code and such. These objects might get processed
+ * inside of a worker. The `PDFObjects` implements some basic functions to
+ * manage these objects.
+ * @ignore
+ */
+var PDFObjects = (function PDFObjectsClosure() {
+ function PDFObjects() {
+ this.objs = {};
+ }
+
+ PDFObjects.prototype = {
+ /**
+ * Internal function.
+ * Ensures there is an object defined for `objId`.
+ */
+ ensureObj: function PDFObjects_ensureObj(objId) {
+ if (this.objs[objId]) {
+ return this.objs[objId];
+ }
+
+ var obj = {
+ capability: createPromiseCapability(),
+ data: null,
+ resolved: false
+ };
+ this.objs[objId] = obj;
+
+ return obj;
+ },
+
+ /**
+ * If called *without* callback, this returns the data of `objId` but the
+ * object needs to be resolved. If it isn't, this function throws.
+ *
+ * If called *with* a callback, the callback is called with the data of the
+ * object once the object is resolved. That means, if you call this
+ * function and the object is already resolved, the callback gets called
+ * right away.
+ */
+ get: function PDFObjects_get(objId, callback) {
+ // If there is a callback, then the get can be async and the object is
+ // not required to be resolved right now
+ if (callback) {
+ this.ensureObj(objId).capability.promise.then(callback);
+ return null;
+ }
+
+ // If there isn't a callback, the user expects to get the resolved data
+ // directly.
+ var obj = this.objs[objId];
+
+ // If there isn't an object yet or the object isn't resolved, then the
+ // data isn't ready yet!
+ if (!obj || !obj.resolved) {
+ error('Requesting object that isn\'t resolved yet ' + objId);
+ }
+
+ return obj.data;
+ },
+
+ /**
+ * Resolves the object `objId` with optional `data`.
+ */
+ resolve: function PDFObjects_resolve(objId, data) {
+ var obj = this.ensureObj(objId);
+
+ obj.resolved = true;
+ obj.data = data;
+ obj.capability.resolve(data);
+ },
+
+ isResolved: function PDFObjects_isResolved(objId) {
+ var objs = this.objs;
+
+ if (!objs[objId]) {
+ return false;
+ } else {
+ return objs[objId].resolved;
+ }
+ },
+
+ hasData: function PDFObjects_hasData(objId) {
+ return this.isResolved(objId);
+ },
+
+ /**
+ * Returns the data of `objId` if object exists, null otherwise.
+ */
+ getData: function PDFObjects_getData(objId) {
+ var objs = this.objs;
+ if (!objs[objId] || !objs[objId].resolved) {
+ return null;
+ } else {
+ return objs[objId].data;
+ }
+ },
+
+ clear: function PDFObjects_clear() {
+ this.objs = {};
+ }
+ };
+ return PDFObjects;
+})();
+
+/**
+ * Allows controlling of the rendering tasks.
+ * @class
+ */
+var RenderTask = (function RenderTaskClosure() {
+ function RenderTask(internalRenderTask) {
+ this._internalRenderTask = internalRenderTask;
+
+ /**
+ * Callback for incremental rendering -- a function that will be called
+ * each time the rendering is paused. To continue rendering call the
+ * function that is the first argument to the callback.
+ * @type {function}
+ */
+ this.onContinue = null;
+ }
+
+ RenderTask.prototype = /** @lends RenderTask.prototype */ {
+ /**
+ * Promise for rendering task completion.
+ * @return {Promise}
+ */
+ get promise() {
+ return this._internalRenderTask.capability.promise;
+ },
+
+ /**
+ * Cancels the rendering task. If the task is currently rendering it will
+ * not be cancelled until graphics pauses with a timeout. The promise that
+ * this object extends will resolved when cancelled.
+ */
+ cancel: function RenderTask_cancel() {
+ this._internalRenderTask.cancel();
+ },
+
+ /**
+ * Registers callbacks to indicate the rendering task completion.
+ *
+ * @param {function} onFulfilled The callback for the rendering completion.
+ * @param {function} onRejected The callback for the rendering failure.
+ * @return {Promise} A promise that is resolved after the onFulfilled or
+ * onRejected callback.
+ */
+ then: function RenderTask_then(onFulfilled, onRejected) {
+ return this.promise.then.apply(this.promise, arguments);
+ }
+ };
+
+ return RenderTask;
+})();
+
+/**
+ * For internal use only.
+ * @ignore
+ */
+var InternalRenderTask = (function InternalRenderTaskClosure() {
+
+ function InternalRenderTask(callback, params, objs, commonObjs, operatorList,
+ pageNumber) {
+ this.callback = callback;
+ this.params = params;
+ this.objs = objs;
+ this.commonObjs = commonObjs;
+ this.operatorListIdx = null;
+ this.operatorList = operatorList;
+ this.pageNumber = pageNumber;
+ this.running = false;
+ this.graphicsReadyCallback = null;
+ this.graphicsReady = false;
+ this.cancelled = false;
+ this.capability = createPromiseCapability();
+ this.task = new RenderTask(this);
+ // caching this-bound methods
+ this._continueBound = this._continue.bind(this);
+ this._scheduleNextBound = this._scheduleNext.bind(this);
+ this._nextBound = this._next.bind(this);
+ }
+
+ InternalRenderTask.prototype = {
+
+ initalizeGraphics:
+ function InternalRenderTask_initalizeGraphics(transparency) {
+
+ if (this.cancelled) {
+ return;
+ }
+ if (PDFJS.pdfBug && 'StepperManager' in globalScope &&
+ globalScope.StepperManager.enabled) {
+ this.stepper = globalScope.StepperManager.create(this.pageNumber - 1);
+ this.stepper.init(this.operatorList);
+ this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
+ }
+
+ var params = this.params;
+ this.gfx = new CanvasGraphics(params.canvasContext, this.commonObjs,
+ this.objs, params.imageLayer);
+
+ this.gfx.beginDrawing(params.viewport, transparency);
+ this.operatorListIdx = 0;
+ this.graphicsReady = true;
+ if (this.graphicsReadyCallback) {
+ this.graphicsReadyCallback();
+ }
+ },
+
+ cancel: function InternalRenderTask_cancel() {
+ this.running = false;
+ this.cancelled = true;
+ this.callback('cancelled');
+ },
+
+ operatorListChanged: function InternalRenderTask_operatorListChanged() {
+ if (!this.graphicsReady) {
+ if (!this.graphicsReadyCallback) {
+ this.graphicsReadyCallback = this._continueBound;
+ }
+ return;
+ }
+
+ if (this.stepper) {
+ this.stepper.updateOperatorList(this.operatorList);
+ }
+
+ if (this.running) {
+ return;
+ }
+ this._continue();
+ },
+
+ _continue: function InternalRenderTask__continue() {
+ this.running = true;
+ if (this.cancelled) {
+ return;
+ }
+ if (this.task.onContinue) {
+ this.task.onContinue.call(this.task, this._scheduleNextBound);
+ } else {
+ this._scheduleNext();
+ }
+ },
+
+ _scheduleNext: function InternalRenderTask__scheduleNext() {
+ window.requestAnimationFrame(this._nextBound);
+ },
+
+ _next: function InternalRenderTask__next() {
+ if (this.cancelled) {
+ return;
+ }
+ this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList,
+ this.operatorListIdx,
+ this._continueBound,
+ this.stepper);
+ if (this.operatorListIdx === this.operatorList.argsArray.length) {
+ this.running = false;
+ if (this.operatorList.lastChunk) {
+ this.gfx.endDrawing();
+ this.callback();
+ }
+ }
+ }
+
+ };
+
+ return InternalRenderTask;
+})();
+
+
+var Metadata = PDFJS.Metadata = (function MetadataClosure() {
+ function fixMetadata(meta) {
+ return meta.replace(/>\\376\\377([^<]+)/g, function(all, codes) {
+ var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g,
+ function(code, d1, d2, d3) {
+ return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
+ });
+ var chars = '';
+ for (var i = 0; i < bytes.length; i += 2) {
+ var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
+ chars += code >= 32 && code < 127 && code !== 60 && code !== 62 &&
+ code !== 38 && false ? String.fromCharCode(code) :
+ '' + (0x10000 + code).toString(16).substring(1) + ';';
+ }
+ return '>' + chars;
+ });
+ }
+
+ function Metadata(meta) {
+ if (typeof meta === 'string') {
+ // Ghostscript produces invalid metadata
+ meta = fixMetadata(meta);
+
+ var parser = new DOMParser();
+ meta = parser.parseFromString(meta, 'application/xml');
+ } else if (!(meta instanceof Document)) {
+ error('Metadata: Invalid metadata object');
+ }
+
+ this.metaDocument = meta;
+ this.metadata = {};
+ this.parse();
+ }
+
+ Metadata.prototype = {
+ parse: function Metadata_parse() {
+ var doc = this.metaDocument;
+ var rdf = doc.documentElement;
+
+ if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in
+ rdf = rdf.firstChild;
+ while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
+ rdf = rdf.nextSibling;
+ }
+ }
+
+ var nodeName = (rdf) ? rdf.nodeName.toLowerCase() : null;
+ if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes()) {
+ return;
+ }
+
+ var children = rdf.childNodes, desc, entry, name, i, ii, length, iLength;
+ for (i = 0, length = children.length; i < length; i++) {
+ desc = children[i];
+ if (desc.nodeName.toLowerCase() !== 'rdf:description') {
+ continue;
+ }
+
+ for (ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) {
+ if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text') {
+ entry = desc.childNodes[ii];
+ name = entry.nodeName.toLowerCase();
+ this.metadata[name] = entry.textContent.trim();
+ }
+ }
+ }
+ },
+
+ get: function Metadata_get(name) {
+ return this.metadata[name] || null;
+ },
+
+ has: function Metadata_has(name) {
+ return typeof this.metadata[name] !== 'undefined';
+ }
+ };
+
+ return Metadata;
+})();
+
+
+//
-
-
- {{--