diff --git a/Gruntfile.js b/Gruntfile.js
index 55ab68f..ad9641f 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -16,6 +16,7 @@ module.exports = function (grunt) {
csvreader_assets = src_dir + '/csvreader_assets',
tsvreader_assets = src_dir + '/tsvreader_assets',
pdfreader_assets = src_dir + '/pdfreader_assets',
+ tablereader_assets = src_dir + '/tablereader_assets',
reader_assets_src_dir = src_dir + '/reader_assets',
admin_assets_src_dir = src_dir + '/admin_assets',
webviews_assets_src_dir = src_dir + '/webviews_assets';
@@ -189,6 +190,15 @@ module.exports = function (grunt) {
{expand: true, cwd: 'src/templates/pages', src: ['*.hbs'], dest: admin_dist_dir}
]
},
+ pages_frame: {
+ // Target-level options
+ options: {
+ layout: 'default_frame.hbs'
+ },
+ files: [
+ {expand: true, cwd: 'src/templates/pages', src: ['*.hbs'], dest: admin_dist_dir+'/frames/'}
+ ]
+ },
login: {
options: {
layout: 'login.hbs'
@@ -241,14 +251,38 @@ module.exports = function (grunt) {
/* copy pdfreader assets to reader & admin */
{
expand: true,
- cwd: pdfreader_assets, src: ['lib/**','js/**'],
+ cwd: pdfreader_assets, src: ['js/**'],
dest: reader_assets_dist_dir + '/'
},
{
expand: true,
- cwd: pdfreader_assets, src: ['lib/**','js/**'],
+ cwd: pdfreader_assets, src: ['js/**'],
dest: admin_assets_dist_dir + '/'
},
+ {
+ expand: true,
+ cwd: 'bower_components/pdfjs-dist/build/',
+ src: [ 'pdf.js', 'pdf.worker.js' ],
+ dest: reader_assets_dist_dir + '/lib/pdf.js/'
+ },
+ {
+ expand: true,
+ cwd: 'bower_components/pdfjs-dist/build/',
+ src: [ 'pdf.js', 'pdf.worker.js' ],
+ dest: admin_assets_dist_dir + '/lib/pdf.js/'
+ },
+ {
+ expand: true,
+ cwd: 'bower_components/pdfjs-dist/web/',
+ src: [ 'compatibility.js' ],
+ dest: reader_assets_dist_dir + '/lib/pdf.js/'
+ },
+ {
+ expand: true,
+ cwd: 'bower_components/pdfjs-dist/web/',
+ src: [ 'compatibility.js' ],
+ dest: admin_assets_dist_dir + '/lib/pdf.js/'
+ },
{
expand: true,
cwd: 'bower_components/canvasloader/js/',
@@ -400,7 +434,8 @@ module.exports = function (grunt) {
'./js/bootstrap-timepicker.min.js'],
dest: admin_assets_dist_dir + '/lib/bootstrap-timepicker/'
},
- // formbuilder
+
+ /* copy jquery-ui */
{ expand:true, cwd:'bower_components/jquery-ui/ui/minified',
src: [ "jquery.ui.core.min.js", "jquery.ui.widget.min.js",
"jquery.ui.mouse.min.js",
@@ -408,6 +443,15 @@ module.exports = function (grunt) {
"jquery.ui.droppable.min.js",
"jquery.ui.sortable.min.js" ],
dest: admin_assets_dist_dir + '/lib/' },
+ { expand:true, cwd:'bower_components/jquery-ui/ui/minified',
+ src: [ "jquery.ui.core.min.js", "jquery.ui.widget.min.js",
+ "jquery.ui.mouse.min.js",
+ "jquery.ui.draggable.min.js",
+ "jquery.ui.droppable.min.js",
+ "jquery.ui.sortable.min.js" ],
+ dest: reader_assets_dist_dir + '/lib/' },
+
+ // formbuilder
{ src: 'bower_components/backbone-deep-model/distribution/deep-model.min.js',
dest: admin_assets_dist_dir + '/lib/backbone/deep-model.min.js' },
{ src: 'bower_components/backbone/backbone.js',
@@ -764,7 +808,31 @@ module.exports = function (grunt) {
cwd: 'bower_components/taffydb/',
src: ['taffy-min.js'],
dest: webviews_assets_dist_dir + '/lib'
- }
+ },
+ /* copy pivottable.js dist */
+ {
+ expand: true,
+ cwd: 'bower_components/pivottable/dist/',
+ src: ['./**'],
+ dest: admin_assets_dist_dir + '/lib/pivottable/'
+ },
+ {
+ expand: true,
+ cwd: 'bower_components/pivottable/dist/',
+ src: ['./**'],
+ dest: reader_assets_dist_dir + '/lib/pivottable/'
+ },
+ /* copy tablereader assets to reader & admin */
+ {
+ expand: true,
+ cwd: tablereader_assets, src: ['js/**'],
+ dest: reader_assets_dist_dir + '/'
+ },
+ {
+ expand: true,
+ cwd: tablereader_assets, src: ['js/**'],
+ dest: admin_assets_dist_dir + '/'
+ },
]
}
},
diff --git a/bower.json b/bower.json
index b483e43..9da3f82 100644
--- a/bower.json
+++ b/bower.json
@@ -30,7 +30,7 @@
"path": "~3.24.10",
"querystring": "~3.24.10",
"tweenjs": "*",
- "videojs": "~4.6.3",
+ "videojs": ">=4.6.3",
"js-url": "~1.8.6",
"flexslider": "*",
"screenfull": "~1.2.1",
@@ -42,7 +42,9 @@
"jssor-slider": "*",
"bootstrap-datepicker": "~1.3.0",
"canvasloader": "~0.9.1",
- "bootstrap-timepicker": "~0.2.6"
+ "bootstrap-timepicker": "~0.2.6",
+ "pdfjs-dist": "~1.0.1135",
+ "pivottable": "*"
},
"resolutions": {
"font-awesome": ">=4.2.0",
diff --git a/src/admin_assets/js/initS3Auth.js b/src/admin_assets/js/initS3Auth.js
index e9618ba..e2571c1 100644
--- a/src/admin_assets/js/initS3Auth.js
+++ b/src/admin_assets/js/initS3Auth.js
@@ -95,8 +95,7 @@ else
else
{
AWS.config.update({
- accessKeyId: s3AuthObj.accessKeyId,
- secretAccessKey: s3AuthObj.secretAccessKey
+ credentials: new AWS.Credentials(s3AuthObj.credentials)
});
initAWSS3();
}
diff --git a/src/admin_assets/js/login.js b/src/admin_assets/js/login.js
index 7151209..f4c5714 100644
--- a/src/admin_assets/js/login.js
+++ b/src/admin_assets/js/login.js
@@ -1,4 +1,68 @@
-$(function(){
+var docQuery = path.parseQuery(document.location.search.slice(1));
+// automatic login
+if(docQuery.autologin)
+{
+ (function(){
+ var credentials;
+ if(docQuery.credentials)
+ {
+ credentials = JSON.parse(docQuery.credentials);
+ var conv = {
+ "AccessKeyId": "accessKeyId",
+ "SecretAccessKey": "secretAccessKey",
+ "SessionToken": "sessionToken"
+ };
+ for(var key in conv)
+ {
+ if(credentials[key])
+ {
+ credentials[conv[key]] = credentials[key];
+ delete credentials[key];
+ }
+ }
+ }
+ else
+ {
+ credentials = {
+ accessKeyId: docQuery.accessKeyId,
+ secretAccessKey: docQuery.secretAccessKey
+ };
+ }
+ if(!credentials)
+ return;
+ try {
+ var auth_obj = JSON.parse(storage.getItem(config.storageAuthKey));
+ if(auth_obj &&
+ (auth_obj.method == 'main' &&
+ compareCredentials(auth_obj.credentials, credentials)) &&
+ docQuery.rootDirectory == auth_obj.rootDirectory &&
+ (!docQuery.selectedApp ||
+ docQuery.selectedApp == auth_obj.selectedApp))
+ {
+ redirectLoggedInUser();
+ return;
+ }
+ } catch(e) { }
+ var hideit = true;
+ $(function(){ if(hideit) $('body').hide() });
+ loginWithCredentials(credentials,
+ docQuery.rootDirectory, docQuery.selectedApp,
+ function(err)
+ {
+ if(err)
+ {
+ alert(err);
+ hideit = false;
+ $('body').show();
+ return;
+ }
+ redirectLoggedInUser();
+ });
+ })()
+}
+else
+{
+ $(function(){
$('.form-signin').bind('submit', function(e)
{
e.preventDefault();
@@ -23,90 +87,23 @@ $(function(){
selectedApp = rootDirectory.substr(rds_idx + 1);
rootDirectory = rootDirectory.substring(0, rds_idx);
}
- AWS.config.update({
- accessKeyId: accessKeyId,
- secretAccessKey: secretAccessKey
- });
- AWS.config.region = config.s3BucketRegion;
- var s3 = new AWS.S3({ region: config.s3BucketRegion, maxRetries: 1 }),
- bucket = config.s3Bucket;
$('button', form).prop('disabled', true);
- s3.listObjects({
- Bucket: bucket,
- Prefix: rootDirectory + "/" +
- (selectedApp ? selectedApp + '/' : ''),
- MaxKeys: 1
- }, function(err, data)
- {
- function continue_job()
- {
- if(selectedApp)
- storage.setItem(config.storageAppNameKey,
- selectedApp);
- $submitBtn.ladda( 'stop' );
- redirectLoggedInUser();
- }
- if(err)
- {
- $submitBtn.ladda( 'stop' );
- alert(_("Couldn't connect to aws s3") + ": " + err);
- }
- else if(!data || !data.Contents ||
- data.Contents.length <= 0)
- {
- $submitBtn.ladda( 'stop' );
- alert(_("Invalid directory!"));
- }
- else
- {
- if(!storage)
- alert(_("This app does not support your browser"));
- else
- {
- var auth_obj = {
- method: 'main',
- accessKeyId: accessKeyId,
- secretAccessKey: secretAccessKey,
- rootDirectory: rootDirectory
- };
- storage.type = 'local';
- var storage_t = $('#remember-me').prop('checked') ?
- 'local' : 'session';
- storage.setItem('storage-type', storage_t);
-
- storage.type = storage_t;
- var prevObj = storage.getItem(config.storageAuthKey);
- if(!prevObj || prevObj.accessKeyId != accessKeyId)
- clearUserStorage(); // clear user info
- storage.setItem(config.storageAuthKey, JSON.stringify(auth_obj));
- if(selectedApp)
- {
- storage.setItem(config.singleAppModeKey, "1");
- continue_job();
- }
- else
- {
- /* select default app before redirect! */
- s3ListDirectories(s3, {
- Bucket: config.s3Bucket,
- Prefix: auth_obj.rootDirectory + '/'
- }, function(err, apps)
- {
- if(err)
- {
- alert(err);
- return;
- }
- if(apps.length > 0)
- selectedApp = apps[0];
- continue_job();
- })
- }
- }
- }
-
- $('button', form).prop('disabled', false);
- });
+ var credentials = {
+ accessKeyId: accessKeyId,
+ secretAccessKey: secretAccessKey
+ };
+ loginWithCredentials(credentials, rootDirectory, selectedApp,
+ function(err)
+ {
+ $submitBtn.ladda( 'stop' );
+ $('button', form).prop('disabled', false);
+ if(err)
+ {
+ alert(err);
+ return;
+ }
+ redirectLoggedInUser();
+ });
return false;
});
// social network authentication starts
@@ -140,7 +137,8 @@ $(function(){
}
return false;
});
-});
+ });
+}
function idFedLogin(opts, cb)
{
/* opts_ex = {
@@ -280,3 +278,90 @@ function clearUserStorage()
storage.setItem(config.storageAppNameKey, '');
storage.setItem(config.singleAppModeKey, '');
}
+function loginWithCredentials(credentials, rootDirectory, selectedApp, callback)
+{
+ AWS.config.credentials = new AWS.Credentials(credentials);
+ AWS.config.region = config.s3BucketRegion;
+ var s3 = new AWS.S3({ region: config.s3BucketRegion, maxRetries: 1 }),
+ bucket = config.s3Bucket;
+ s3.listObjects({
+ Bucket: bucket,
+ Prefix: rootDirectory + "/" +
+ (selectedApp ? selectedApp + '/' : ''),
+ MaxKeys: 1
+ }, function(err, data)
+ {
+ function continue_job()
+ {
+ if(selectedApp)
+ storage.setItem(config.storageAppNameKey,
+ selectedApp);
+ callback();
+ }
+ if(err)
+ {
+ callback(_("Couldn't connect to aws s3") + ": " + err);
+ }
+ else if(!data || !data.Contents ||
+ data.Contents.length <= 0)
+ {
+ callback(_("Invalid directory!"));
+ }
+ else
+ {
+ if(!storage)
+ callback(_("This app does not support your browser"));
+ else
+ {
+ var auth_obj = {
+ method: 'main',
+ credentials: credentials,
+ rootDirectory: rootDirectory
+ };
+ storage.type = 'local';
+ var storage_t = $('#remember-me').prop('checked') ?
+ 'local' : 'session';
+ storage.setItem('storage-type', storage_t);
+
+ storage.type = storage_t;
+ var prevObj = storage.getItem(config.storageAuthKey);
+ prevObj = prevObj ? JSON.parse(prevObj) : null;
+ if(!prevObj ||
+ !(prevObj.method == 'main' &&
+ compareCredentials(prevObj, credentials)))
+ clearUserStorage(); // clear user info
+ storage.setItem(config.storageAuthKey, JSON.stringify(auth_obj));
+ if(selectedApp)
+ {
+ storage.setItem(config.singleAppModeKey, "1");
+ continue_job();
+ }
+ else
+ {
+ /* select default app before redirect! */
+ s3ListDirectories(s3, {
+ Bucket: config.s3Bucket,
+ Prefix: auth_obj.rootDirectory + '/'
+ }, function(err, apps)
+ {
+ if(err)
+ {
+ callback(err);
+ return;
+ }
+ if(apps.length > 0)
+ selectedApp = apps[0];
+ continue_job();
+ })
+ }
+ }
+ }
+ });
+}
+function compareCredentials(c1, c2)
+{
+ return c1.accessKeyId == c2.accessKeyId &&
+ c1.secretAccessKey == c2.secretAccessKey &&
+ ((!c1.sessionToken && !c2.sessionToken) ||
+ (c1.sessionToken == c2.sessionToken));
+}
diff --git a/src/admin_assets/js/pages/analytics.js b/src/admin_assets/js/pages/analytics.js
index 326f05a..740ea62 100644
--- a/src/admin_assets/js/pages/analytics.js
+++ b/src/admin_assets/js/pages/analytics.js
@@ -1,3 +1,4 @@
+
var app_name = storage.getItem(config.storageAppNameKey),
app_dir = get_app_dir(app_name);
@@ -10,6 +11,9 @@ app_dir = get_app_dir(app_name);
gapi.analytics.ready(function()
{
+
+
+
awsS3Ready(function()
{
awsS3.getObject({
@@ -99,42 +103,79 @@ gapi.analytics.ready(function()
}
function setup_ga_data()
{
- var countryDataChart = new gapi.analytics.googleCharts.DataChart({
- query: {
- ids: 'ga:' + ga_profile.id,
- metrics: 'ga:sessions',
- dimensions: 'ga:country',
- //'start-date': '30daysAgo',
- //'end-date': 'yesterday'
- },
- chart: {
- container: 'country-chart',
- type: 'GEO',
- options: {
- width: '100%'
- }
- }
- });
- countryDataChart.execute();
-
- var deviceDataChart = new gapi.analytics.googleCharts.DataChart({
- query: {
- ids: 'ga:' + ga_profile.id,
- metrics: 'ga:sessions',
- dimensions: 'ga:mobileDeviceModel',
- sort: '-ga:sessions',
- 'max-results': 6
- },
- chart: {
- container: 'device-chart',
- type: 'PIE',
- options: {
- width: '100%'
- }
- }
- });
- deviceDataChart.execute();
+
+
+
+ var report = new gapi.analytics.report.Data({
+ query: {
+ ids: 'ga:' + ga_profile.id,
+ metrics: 'ga:totalEvents',
+ 'start-date':'2005-01-01',
+ dimensions: 'ga:eventLabel,ga:yearMonth,ga:operatingSystem',
+ filters: 'ga:eventAction=@ucceeded',
+ 'max-results':10000
+ }
+ });
+ report.on('success', function(response) {
+ console.log(response);
+ var data = response.rows;
+ var publications = [];
+ data.forEach(function(d, i) {
+ parts = d[0].split('?')
+ d.filePath= parts[0]; //Remove args
+ console.log(d.filePath);
+ parts2 = (d.filePath).split('/');
+ if (parts2.length>1){
+
+ d.folderName = parts2[parts2.length-2];
+ d.fileNameAndExtension = parts2[parts2.length-1];
+ parts3 = (d.fileNameAndExtension).split('.');
+ d.fileName = parts3[0];
+ d.fileExtension = parts3[1];
+ //Publications are inside directories have the pdf extension
+ if (d.fileExtension=='pdf'){
+ var obj = {};
+ obj.Publication= d.folderName;
+ obj.YearMonth = d[1]
+ obj.OS = d[2]
+ obj.Qty = +d[3];
+ if (d.fileName.lastIndexOf('_') == d.fileName.length - 1) obj.Type='Paid';//Paid publications have a file name ending with _
+ else obj.Type='Free';
+ publications.push(obj);
+ }
+ }
+ });
+
+
+
+ //console.log(publications);
+
+ var sum = $.pivotUtilities.aggregatorTemplates.sum;
+ var numberFormat = $.pivotUtilities.numberFormat;
+ var intFormat = numberFormat({digitsAfterDecimal: 0});
+
+ $("#pivotstable").pivotUI(
+ publications,
+ {
+ rows: ["Publication"],
+ cols: ["Type"],
+ aggregators: {"Quantity":function() { return sum(intFormat)(["Qty"]) }},
+ hiddenAttributes: ["Qty"]
+ }
+
+
+ );
+
+
+
+
+ });
+
+
+ report.execute();
+
+
}
});
});
@@ -197,3 +238,5 @@ function responseCompleteProcessGetItems(cb, noerror)
}
};
}
+
+;
diff --git a/src/admin_assets/js/pages/authorizations.js b/src/admin_assets/js/pages/authorizations.js
new file mode 100644
index 0000000..142b360
--- /dev/null
+++ b/src/admin_assets/js/pages/authorizations.js
@@ -0,0 +1,158 @@
+$(function()
+{
+ var app_name = storage.getItem(config.storageAppNameKey),
+ app_dir = get_app_dir(app_name),
+ auth_key = app_dir + '/APP_/Uploads/authorizations_.plist',
+ oauth_origin = 'http://localhost/',
+ oauth_url = oauth_origin+'/php/admin/oauth.php';
+ if(!app_name)
+ return;
+
+ awsS3Ready(start);
+ function start()
+ {
+ start_request_for_auth_status();
+ $('#auth-gen').click(function()
+ {
+ $('#auth-status').text('Generating refresh token');
+ generate_refresh_token(function(err, refreshToken)
+ {
+ if(err)
+ return notifyUserError(err);
+ if(!refreshToken)
+ {
+ $('#auth-status').text('No refresh token available!');
+ return;
+ }
+ $('#auth-status').text('Storing refresh token');
+ request_auth_save({
+ refresh_token: refreshToken
+ }, function(err)
+ {
+ if(err)
+ {
+ notifyUserError(err);
+ $('#auth-status').text('');
+ return;
+ }
+ $('#auth-status').text('Refresh token is available!');
+ });
+ });
+ return false;
+ });
+ }
+
+ function start_request_for_auth_status()
+ {
+ $('#auth-status').text('Checking authorization status');
+ request_auth(function(err, obj)
+ {
+ if(err)
+ {
+ handleAWSS3Error(err);
+ $('#auth-status').text('');
+ return;
+ }
+ if(obj.refresh_token)
+ {
+ $('#auth-status').text('Refresh token is available!');
+ }
+ else
+ {
+ $('#auth-status').text('Refresh token does not exists!');
+ }
+ });
+ }
+ function request_auth(callback)
+ {
+ awsS3.getObject({
+ Bucket: config.s3Bucket,
+ Key: auth_key
+ }, function(err, res)
+ {
+ if(err && err.code != 'NoSuchKey')
+ {
+ callback(err);
+ return;
+ }
+ try {
+ var obj = res ? $.plist($.parseXML(res.Body.toString())) : {};
+ callback(undefined, obj);
+ } catch(err2) {
+ callback('Error parsing: ' + err2);
+ }
+ });
+ }
+
+ function request_auth_save(obj, callback)
+ {
+ var body = $.plist('toString', obj);
+ awsS3.putObject({
+ Bucket: config.s3Bucket,
+ Key: auth_key,
+ Body: body,
+ CacheControl: 'must-revalidate, max-age=0'
+ }, function(err)
+ {
+ callback && callback(err);
+ });
+ }
+
+ var authWin, authInterval, authCallback;
+
+ if(window.addEventListener)
+ window.addEventListener('message', window_on_message, false);
+ else if(window.attachEvent)
+ window.attachEvent('onmessage', window_on_message);
+
+ function generate_refresh_token(callback)
+ {
+ authWin = window.open(oauth_url, oauth_url,
+ 'resizable=yes,scrollbars=yes,' +
+ 'width=640,height=480');
+ if(authInterval !== undefined)
+ clearInterval(authInterval);
+ authInterval = setInterval(ask_win_authorized, 100);
+ authCallback = function()
+ {
+ $.ajax({
+ url: oauth_url + '?' + querystring.stringify({
+ action: 'get',
+ key: 'refresh_token'
+ }),
+ xhrFields: {
+ withCredentials: true
+ },
+ success: function(value)
+ {
+ callback(undefined, value);
+ },
+ error: function(xhr, a2, err_text)
+ {
+ callback(sprintf(_("Couldn't generate access token: %s"),
+ err_text))
+ }
+ });
+ }
+ }
+
+ function ask_win_authorized()
+ {
+ if(authWin)
+ authWin.postMessage('isAuthorized', oauth_origin);
+ }
+ function window_on_message(event)
+ {
+ if(event.data == 'authorized')
+ {
+ authWin.close();
+ authCallback();
+ if(authInterval !== undefined)
+ {
+ clearInterval(authInterval);
+ authInterval = undefined;
+ }
+ }
+ }
+
+});
diff --git a/src/admin_assets/js/pages/issues.js b/src/admin_assets/js/pages/issues.js
new file mode 100644
index 0000000..4438814
--- /dev/null
+++ b/src/admin_assets/js/pages/issues.js
@@ -0,0 +1,945 @@
+var appName = storage.getItem(config.storageAppNameKey),
+appDir = get_app_dir(appName),
+doc_query = querystring.parse(get_url_query(document.location+'')),
+pubName = doc_query.wapublication || '',
+pubDir = pubName ? appDir + '/' + pubName : appDir,
+magazinesFn = pubName ? pubName + '.plist' : 'Magazines.plist';
+$(function() {
+ function workOnAwsS3()
+ {
+ formDisplay();
+ $issDlg.find('.fileinput').each(initUploadEl);
+ updateIssTable(function()
+ {
+ $('#page-loading-indicator2').fadeOut();
+ });
+ }
+ var $issTable = $(".issueDataTable"),
+ issuesTable = $issTable.dataTable({
+ "aaSorting": [[ 0, "desc" ]]
+ }),
+ $issDlg = $('#issModal');
+
+ activeInactiveEvents($issTable);
+ if(!appName)
+ return;
+
+ awsS3Ready(workOnAwsS3);
+
+
+ $issDlg.find('.svgedit-btn').bind('click', function()
+ {
+ var iss = $issDlg.find('input[name=FolderName]').val(),
+ filename = issDlgEvalAttr($(this).data('filename'));
+ if(filename)
+ {
+ window.open('svgedit.html?' + path.stringifyQuery({
+ app: appName,
+ filename: iss + '/' + filename
+ }), '_blank');
+ return false;
+ }
+ });
+ $issDlg.find('.pdfannotedit-btn').bind('click', function()
+ {
+ var iss = $issDlg.find('input[name=FolderName]').val(),
+ filename = issDlgEvalAttr($(this).data('filename'));
+ if(filename)
+ {
+ window.open('pdf-annotation-editor.html?' +
+ path.stringifyQuery({
+ waurl: pubDir + '/' + iss + '/' + filename
+ }), '_blank');
+ return false;
+ }
+ });
+
+ $("#asset-uploader").pluploadQueue({
+ // General settings
+ runtimes: 'html5',
+ url: 'https://' + config.s3Bucket + '.s3.amazonaws.com',
+ // Rename files by clicking on their titles
+ rename: true,
+
+ // Sort files
+ sortable: true,
+
+ // Enable ability to drag'n'drop files onto the widget (currently only HTML5 supports that)
+ dragdrop: true,
+
+ // Views to activate
+ views: {
+ list: true,
+ thumbs: true, // Show thumbs
+ active: 'thumbs'
+ },
+
+ multiple_queues: true
+ });
+ var asset_uploader = $("#asset-uploader").pluploadQueue();
+
+ if(s3AuthObj.type == 'idFed')
+ {
+ asset_uploader.unbind('UploadFile');
+ asset_uploader.bind('UploadFile', function(up, file)
+ {
+ var filename = file.target_name || file.name;
+ function onCancelUpload()
+ {
+ if(xhr)
+ xhr.abort();
+ }
+ function unbindEvents()
+ {
+ up.unbind('CancelUpload', onCancelUpload)
+ }
+ up.bind('CancelUpload', onCancelUpload);
+ var iss = $issDlg.find('input[name=FolderName]').val(),
+ asset_dir = $("#asset-uploader").data('dir'),
+ dir = pubDir + '/' + iss + (asset_dir ? '/' + asset_dir : ''),
+ xhr,
+ request = awsS3.putObject({
+ Bucket: config.s3Bucket,
+ Key: dir + '/' + filename,
+ Body: file.getNative()
+ }, function(err, res)
+ {
+ unbindEvents();
+ if(err)
+ {
+ console.error(err);
+ up.trigger('Error', {
+ code : plupload.HTTP_ERROR,
+ message : plupload.translate('HTTP Error.'),
+ file : file,
+ response: err+'',
+ status: xhr ? xhr.status : _('Unknown'),
+ responseHeaders:
+ xhr ? xhr.getAllResponseHeaders() : {}
+ });
+ return;
+ }
+ file.loaded = file.size;
+ up.trigger('UploadProgress', file);
+
+ file.status = plupload.DONE;
+ up.trigger('FileUploaded', file, {
+ response: 'success',
+ status: 200,
+ responseHeaders: {}
+ });
+ });
+ xhr = request.httpRequest.stream;
+ if(xhr && xhr.upload)
+ $(xhr.upload).on('progress', function(ev)
+ {
+ ev = ev.originalEvent;
+ file.loaded = ev.loaded;
+ up.trigger('UploadProgress', file);
+ });
+ });
+ }
+ else
+ {
+ asset_uploader.bind("BeforeUpload", function(up, file) {
+ var params = asset_uploader.settings.multipart_params;
+ params.key = $("#asset-uploader").data('current_dir') + file.name;
+ params.Filename = file.name;
+ });
+ }
+ function setPLUploadInfoForIss(iss)
+ {
+ var d = new Date(new Date().getTime() + (60 * 60 * 1000)),
+ asset_dir = $("#asset-uploader").data('dir'),
+ dir = pubDir + '/' + iss + '/' + (asset_dir ? asset_dir + '/' : ''),
+ policy = {
+ "expiration": d.toISOString(),
+ "conditions": [
+ {"bucket": config.s3Bucket},
+ ["starts-with", "$key", dir],
+ {"acl": "private"},
+ ["starts-with", "$Content-Type", ""],
+ ["starts-with", "$name", ""],
+ ["starts-with", "$Filename", ""],
+ ["starts-with", "$success_action_status", ""]
+ ]
+ },
+ policy_str = CryptoJS.enc.Base64.stringify(
+ CryptoJS.enc.Utf8.parse(JSON.stringify(policy))),
+ signature = CryptoJS.HmacSHA1(policy_str,
+ s3AuthObj.credentials.secretAccessKey)
+ .toString(CryptoJS.enc.Base64);
+ var post = {
+ acl: 'private',
+ AWSAccessKeyId: s3AuthObj.credentials.accessKeyId,
+ policy: policy_str,
+ signature: signature,
+ 'Content-Type': '$Content-Type',
+ success_action_status: '201'
+ };
+ $("#asset-uploader").data('current_dir', dir);
+ asset_uploader.setOption('multipart_params', post);
+ asset_uploader.splice(0, asset_uploader.files.length);
+ }
+ function uploadElEvalFilename(el, action)
+ {
+ var iss = $issDlg.data('issObj'),
+ $this = $(el),
+ ext = el.files && el.files.length > 0 ?
+ path.fileExtension(el.files[0].name) : '';
+ if(iss)
+ {
+ // use existing extension
+ // if it's there
+ if($this.hasClass('paidfileupload'))
+ ext = (action == 'delete') ? iss.paid_ext || ext :
+ ext || iss.paid_ext;
+ else if($this.hasClass('freefileupload'))
+ ext = (action == 'delete') ? iss.free_ext || ext :
+ ext || iss.free_ext;
+ }
+ return issDlgEvalAttr($this.attr('name'), { fileext: ext });
+ }
+ function uploadFileUpdate($upload)
+ {
+ $upload.find('input[type=file]').each(function()
+ {
+ var file = uploadElEvalFilename(this),
+ extensions = [ 'pdf', 'svg' ];
+ for(var i = 0, l = extensions.length; i < l; ++i)
+ {
+ var ext = extensions[i];
+ $upload.toggleClass('fileinput-' + ext,
+ (path.fileExtension(file) == '.' + ext));
+ }
+ });
+ }
+ function uploadFileUpdateExtension(inp)
+ {
+ var iss = $issDlg.data('issObj') || {},
+ $inp = $(inp),
+ ext = inp.files && inp.files.length > 0 ?
+ path.fileExtension(inp.files[0].name) : '';
+ if($inp.hasClass('paidfileupload'))
+ iss.paid_ext = ext;
+ else if($inp.hasClass('freefileupload'))
+ iss.free_ext = ext;
+ $issDlg.data('issObj', iss);
+ }
+ function initUploadEl()
+ {
+ var $upload = $(this),
+ $file = $upload.find('input[type=file]');
+ this._s3Upload = s3UploadInit($upload, {
+ s3: awsS3,
+ type: $file.data('type') || 'file',
+ Bucket: config.s3Bucket,
+ removeBeforeChange: issDlgAttrHasVar($file.attr('name'), 'fileext'),
+ Key: function(action)
+ {
+ var title = $issDlg.find('input[name=FolderName]').val(),
+ file = uploadElEvalFilename(this, action);
+ return pubDir + '/' + title + '/' + file;
+ },
+ signExpires: function()
+ {
+ return awsExpireReverse(config.awsExpireReverseInHours);
+ },
+ onUploadSuccess: function()
+ {
+ issDlgUpdated = true;
+ uploadFileUpdateExtension(this);
+ // this method should update file ui
+ uploadFileUpdate($upload)
+ },
+ onRemoveSuccess: function()
+ {
+ issDlgUpdated = true;
+ uploadFileUpdateExtension(this);
+ // this method should update file ui
+ uploadFileUpdate($upload)
+ },
+ onFileExistCheck: function(exists)
+ {
+ if($(this).hasClass('paidfileupload'))
+ {
+ $issDlg.find('input[name=Type]').each(function()
+ {
+ if(exists)
+ this.checked = (this.value == 'Paid');
+ else
+ this.checked = (this.value != 'Paid');
+ });
+ issDlgUpdateType();
+ }
+ },
+ checkBeforeUpload: function(inp_el, file, cb)
+ {
+ if($(inp_el).data('type') == 'Image')
+ {
+ makeImageFromFile(file, function(err, image)
+ {
+ if(err)
+ return notifyUserError(err);
+ var m = validateImageSizeByElementAttrs(inp_el, image);
+ cb(!m);
+ if(m)
+ notifyUserError(m);
+ });
+ }
+ else
+ {
+ cb(true);
+ }
+ },
+ onerror: handleAWSS3Error,
+ loadnow: false
+ });
+ }
+ var issDlgUpdated;
+ $issDlg.on('hidden.bs.modal', function()
+ {
+ var iss = $issDlg.data('issObj');
+ if(issDlgUpdated)
+ {
+ location.reload();
+ return;
+ }
+ // remove update info
+ $issDlg.data('issObj', null)
+ .removeClass('update-iss-dlg')
+ .toggleClass('new-iss-dlg', true);
+ $issDlg.find('input[type=text]').each(function()
+ {
+ $(this).val('');
+ });
+ $issDlg.find('.fileinput').each(function()
+ {
+ var $this = $(this);
+ $this.find('input[type=file]').val('');
+ $this.toggleClass('fileinput-new', true)
+ .removeClass('fileinput-exists');
+ $this.find('.fileinput-preview img').prop('src', '')
+ .remove();
+ });
+
+ asset_uploader.stop();
+ });
+ var illegalIsss = [ "AAD", "APP__", "APP_", "APP_", "APW_" ];
+ $issDlg.find('.set-title-btn').click(function()
+ {
+ var $this = $(this);
+ if($this.data('isLoading') || !awsS3)
+ return false;
+ var $title_inp = $issDlg.find('input[name=FolderName]'),
+ title_val = $title_inp.val();
+ if(!title_val)
+ return false;
+ var allowed_pattrn = /^[a-z0-9\-_]+$/;
+ if(illegalIsss.indexOf(title_val) >= 0 ||
+ !allowed_pattrn.test(title_val))
+ {
+ notifyUserError(_('Invalid issue name!'));
+ return false;
+ }
+ $this.ladda({}).ladda('start').data('isLoading', true);
+ $title_inp.prop('disabled', true);
+ s3ObjectExists(awsS3, {
+ Bucket: config.s3Bucket,
+ Prefix: pubDir + '/' + title_val + '/'
+ }, function(err, exists)
+ {
+ $this.ladda('stop').data('isLoading', false);
+ if(err)
+ {
+ handleAWSS3Error(err);
+ return;
+ }
+ if(!exists)
+ {
+ $(this).parent().hide();
+ $issDlg.find('.iss-body-form').show();
+ if(s3AuthObj.type != 'idFed')
+ setPLUploadInfoForIss(title_val);
+ }
+ else
+ {
+ $title_inp.prop('disabled', false);
+ notifyUserError(_('Folder exists!'));
+ }
+ });
+ return false;
+ });
+ $issDlg.on('show.bs.modal', function()
+ {
+ issDlgUpdated = false;
+ var iss = $issDlg.data('issObj'),
+ type = 'Free';
+ $issDlg.find('.uufile').remove();
+ $issDlg.find('input[type=file]').prop('disabled', false);
+ $issDlg.find('.fileinput').each(function()
+ {
+ uploadFileUpdate($(this))
+ });
+ if(iss)
+ {
+ type = '';
+ var iss_name = iss.FileName;
+ $issDlg.find('.set-title-btn').parent().hide();
+ $issDlg.find('input[name=FolderName]').prop('disabled', true);
+ $issDlg.find('.iss-body-form').show();
+ $issDlg.find('.fileinput').each(function()
+ {
+ var $upload = $(this),
+ inp = $upload.find('input[type=file]')[0];
+ if(this._s3Upload)
+ this._s3Upload.reload();
+ if(inp)
+ {
+ // fileinput download-btn ready
+ $upload.find('.download-btn').each(function()
+ {
+ var title =
+ $issDlg.find('input[name=FolderName]').val(),
+ file = uploadElEvalFilename(inp),
+ a_tag = this;
+ awsS3.getSignedUrl('getObject', {
+ Bucket: config.s3Bucket,
+ Key: pubDir + '/' + title + '/' + file,
+ Expires: awsExpireReverse(config.awsExpireReverseInHours)
+ }, function(err, url)
+ {
+ a_tag.href = !err && url ? url : '';
+ })
+ });
+ }
+ });
+ if(s3AuthObj.type != 'idFed')
+ setPLUploadInfoForIss(iss_name);
+
+ // list uploaded elements and add them to list
+ var issDir = pubDir + '/' + iss_name + '/',
+ excluded_files = [
+ iss_name + (iss.free_ext || ''),
+ iss_name + '_' + (iss.paid_ext || ''),
+ iss_name + '.png',
+ iss_name + '_newsstand.png'
+ ];
+ s3ListAllObjects(awsS3, {
+ Bucket: config.s3Bucket,
+ Prefix: issDir
+ }, function(err, res)
+ {
+ if(err)
+ {
+ handleAWSS3Error(err);
+ return;
+ }
+ var contents = res.Contents;
+ for(var i = 0, l = contents.length; i < l; ++i)
+ {
+ var key = contents[i].Key,
+ fn = key.substr(issDir.length).replace('*', '\\*');
+ if(fn && excluded_files.indexOf(fn) == -1)
+ insertUploadItem(fn, { class_name: 'uufile' });
+ }
+ });
+ }
+ else
+ {
+ $issDlg.find('input[name=FolderName]').prop('disabled', false);
+ $issDlg.find('.set-title-btn').parent().show();
+ $issDlg.find('.iss-body-form').hide();
+ }
+ $issDlg.find('input[name=Type]').each(function()
+ {
+ if(this.value == type)
+ this.checked = true;
+ else
+ this.checked = false;
+ });
+ issDlgUpdateType();
+ });
+ function issDlgEvalAttr(s, vars)
+ {
+ s = s+'';
+ vars = $.extend(false, getObjectOfForm($issDlg), vars);
+ for(var i in vars)
+ {
+ var name = '*'+i+'*',
+ val = vars[i];
+ for(var n = 0, idx; (idx = s.indexOf(name, n)) >= 0;
+ n = idx + name.length)
+ {
+ if(idx == 0 || s[idx-1] != '\\')
+ s = s.substr(0, idx) + val + s.substr(idx + name.length);
+ }
+ }
+ return s.replace('\\*', '*');
+ }
+ function issDlgAttrHasVar(s, vr)
+ {
+ var idx = s.indexOf('*'+vr+'*');
+ return idx == 0 || (idx > 0 && s[idx-1] != '\\');
+ }
+ $issDlg.find('input[name=Type]').on('change', issDlgUpdateType);
+ function issDlgUpdateType()
+ {
+ var paid_elem = $issDlg.find('.paid-elem'),
+ paid_radio = $issDlg.find('input[name=Type]').filter('[value=Paid]');
+ if(paid_radio.prop('checked'))
+ paid_elem.show();
+ else
+ paid_elem.hide();
+ }
+ var img_check_pttrn = /\.(jpe?g|png|gif)$/i;
+ function insertUploadItem(key, opts)
+ {
+ opts = opts || {};
+ var class_name = opts.class_name ? ' ' + opts.class_name : '',
+ isImg = img_check_pttrn.test(key),
+ uploadLI = $('
\
+ \
+ ').appendTo($issDlg.find('.upload-list'));
+ var el = uploadLI.find('.fileinput')[0];
+ initUploadEl.call(el);
+ if(el._s3Upload)
+ el._s3Upload.reload();
+ }
+
+
+ function updateIssTable(callback)
+ {
+ s3ListAllObjects(awsS3, {
+ Bucket: config.s3Bucket,
+ Prefix: pubDir + '/',
+ Delimiter: '/'
+ },
+ function(error, apps) {
+
+ awsS3.getObject({
+ Bucket: config.s3Bucket,
+ Key: pubDir+'/'+magazinesFn
+ }, function(err, activated) {
+ var appsList = apps.CommonPrefixes,
+ activeList;
+ try {
+ activeList = $.plist($.parseXML(activated.Body.toString()));
+ }catch(e) {
+ activeList = [];
+ }
+ var activeListLength = activeList.length;
+
+ var rowsList = [];
+ var temp = {};
+ var count = 0;
+
+ for(var i = 0; i < appsList.length; ++i) {
+
+ //---------------------------------------------------
+ // We have 3 unwanted folders...
+ // ignore them and don't show them on the list
+ //---------------------------------------------------
+
+ if (isolateFolderName(appsList[i].Prefix) == "AAD" ||
+ isolateFolderName(appsList[i].Prefix) == "APP__" ||
+ isolateFolderName(appsList[i].Prefix) == "APP_" ||
+ isolateFolderName(appsList[i].Prefix) == "APP_" ||
+ isolateFolderName(appsList[i].Prefix) == "APW_") {
+ continue;
+ }
+
+ //---------------------------------------------------
+ // Prepear a single row object with default value
+ //---------------------------------------------------
+
+ temp[count] = {
+ FileName: isolateFolderName(appsList[i].Prefix),
+ FolderName: isolateFolderName(appsList[i].Prefix),
+ Title: "",
+ Subtitle: "",
+ status: "inactive",
+ statusBtn: ""+_("Inactive")+"",
+ id: 0
+ }
+ for(var j = 0; j < activeListLength; ++j) {
+
+ //---------------------------------------------------
+ // There sometimes undefined keys is the object...
+ // it cause because of inactive publications...
+ // it's shouldn't happen, but we do taking
+ // care of it, so the front end user wont have any
+ // errors... jus in case...
+ //---------------------------------------------------
+
+ /*if (activeList[j] == undefined) {
+ continue;
+ }*/
+
+ //---------------------------------------------------
+ // Does the folder name fit each other?
+ // if so update this publication title, subtitle
+ // and status
+ //---------------------------------------------------
+
+ if (isolateFolderName2(activeList[j].FileName) == temp[count].FileName ||
+ isolateFolderName3(activeList[j].FileName) == temp[count].FileName) {
+ temp[count].Title = activeList[j].Title;
+ temp[count].Subtitle = activeList[j].Subtitle;
+ temp[count].status = "active";
+ temp[count].statusBtn = ""+_("Active")+"";
+ temp[count].id = j;
+ added = true;
+ break;
+ }
+ }
+
+ rowsList.push(temp[count]);
+ count++;
+ }
+ function getIssByRowId(id)
+ {
+ var pttrn = /row_([0-9]+)/,
+ match = pttrn.exec(id);
+ if(match)
+ {
+ var index = parseInt(match[1])
+ if(index >= 0)
+ return rowsList[index];
+ }
+ }
+ function issTRClick()
+ {
+ var $this = $(this),
+ item = getIssByRowId(this.id);
+ if(!item)
+ return;
+ awsS3.listObjects({
+ Bucket: config.s3Bucket,
+ Prefix: pubDir + '/' + item.FolderName + '/' +
+ item.FolderName
+ }, function(err, res)
+ {
+ if(err)
+ {
+ handleAWSS3Error(err);
+ return;
+ }
+ function getKeySub(item)
+ {
+ return item.Key.substr(prefLen);
+ }
+ var prefLen = res.Prefix.length,
+ free = startsWith(res.Contents, '.', getKeySub),
+ paid = startsWith(res.Contents, '_.', getKeySub);
+ item = $.extend(false, {}, item);
+
+ item.free_ext = free.length > 0 ?
+ free[0].Key.substr(prefLen) : null;
+ item.paid_ext = paid.length > 0 ?
+ paid[0].Key.substr(prefLen + 1) : null;
+
+ $issDlg.find('input[type=text]')
+ .each(function()
+ {
+ var $this = $(this),
+ name = $this.attr('name');
+ for(var key in item)
+ if(name == key)
+ {
+ $this.val(item[key]);
+ break;
+ }
+ });
+ $issDlg.data('issObj', item)
+ .removeClass('new-iss-dlg')
+ .toggleClass('update-iss-dlg', true)
+ .modal('show');
+ });
+ return false;
+ }
+ //---------------------------------------------------
+ // Add the rows to the table
+ //---------------------------------------------------
+
+ for(var i = 0; i < rowsList.length; ++i) {
+ addRowToTable(i, rowsList[i], issuesTable);
+ }
+
+ //---------------------------------------------------
+ // Apply events for the active/inactive buttons
+ //---------------------------------------------------
+
+
+ $issTable.on('click', 'tbody > tr', issTRClick)
+
+ callback && callback();
+ });
+ });
+ }
+ function isolateFolderName(name) {
+ return name.replace(pubDir + '/', "").replace("/", "");
+ }
+
+ function isolateFolderName2(name) {
+ return name.substring( name.indexOf("/")+1, name.length-5);
+ }
+
+ function isolateFolderName3(name) {
+ return name.substring( name.indexOf("/")+1, name.length-4);
+ }
+
+});
+
+function formDisplay() {
+ $("input[name='folderName']").bind("keyup", function() {
+ $(".hiddenFields").show();
+ });
+}
+
+function activeInactiveEvents(issuesTable) {
+
+ issuesTable.on("click", "a.btnActive", {}, function(e) {
+ e.preventDefault();
+ var obj = $(this);
+ activeIssue(obj, issuesTable);
+ return false;
+ });
+
+ issuesTable.on("click", "a.btnInactive", {}, function(e) {
+ e.preventDefault();
+ var obj = $(this);
+ inactiveIssue(obj, issuesTable);
+ return false;
+ });
+}
+
+function activeIssue(obj, issuesTable) {
+ var some_html = '';
+
+ bootbox.dialog({
+ message: some_html,
+ title: "Confirmation",
+ className: "littleModal",
+ buttons: {
+ success: {
+ label: "Confirm",
+ className: "btn-success",
+ callback: function() {
+ activeServerRequest(obj, issuesTable);
+ }
+ },
+ danger: {
+ label: "Cancel",
+ className: "btn-danger",
+ callback: function() {}
+ }
+ }
+ });
+}
+
+function inactiveIssue(obj, issuesTable) {
+ bootbox.dialog({
+ message: "Are you sure you want to inactive this issue?",
+ title: "Confirmation",
+ className: "littleModal",
+ buttons: {
+ success: {
+ label: "Confirm",
+ className: "btn-success",
+ callback: function() {
+ inactiveServerRequest(obj, issuesTable);
+ }
+ },
+ danger: {
+ label: "Cancel",
+ className: "btn-danger",
+ callback: function() {}
+ }
+ }
+ });
+}
+function is_paid_iss(filename, cb)
+{
+ s3ObjectExists(awsS3, {
+ Bucket: config.s3Bucket,
+ Key: pubDir + '/' + filename + '/' + filename + '_.pdf'
+ }, cb);
+}
+function activeServerRequest(obj, issuesTable) {
+
+ var pTitle = $("input[name='issTitleInput']").val();
+ var pSubtitle = $("input[name='issSubtitleInput']").val();
+
+ awsS3.getObject({
+ Bucket: window.config.s3Bucket,
+ Key: pubDir+'/' + magazinesFn
+ }, function(err, activated) {
+ //var activeList = PlistParser.parse($.parseXML(activated.Body.toString()));
+ var activeList;
+ try {
+ activeList = $.plist($.parseXML(activated.Body.toString())) || [];
+ }catch(e) {
+ activeList = [];
+ }
+ is_paid_iss(obj.data('filename'), function(err, is_paid)
+ {
+ if(err)
+ return handleAWSS3Error(err);
+ var iss = {
+ FileName: obj.data("filename") + "/" + obj.data("filename") +
+ (is_paid ? '_' : '') + ".pdf",
+ Title: pTitle,
+ Subtitle: pSubtitle
+ };
+ insertIssInList(iss, activeList);
+
+ var body = $.plist('toString', activeList);
+
+
+ var params = {
+ Bucket: config.s3Bucket, // required
+ Key: pubDir+'/' + magazinesFn,
+ //Body: PlistParser.toPlist(activeList)
+ Body: body
+ };
+ awsS3.putObject(params, function(err, data) {
+ if (err) {
+ return handleAWSS3Error(err);
+ } else {
+ //obj.addClass("btnInactive").addClass("btn-danger").removeClass("btnActive").removeClass("btn-success").html("Inactive").data("id", activeListLength);
+ //issuesTable.fnGetPosition( obj.parents('tr').closest('.ttitle')[0]).html(pTitle);
+ //issuesTable.fnGetPosition( obj.parents('tr').closest('.tsubtitle')[0]).html(pSubtitle);
+ location.reload();
+ }
+ });
+ });
+ });
+}
+
+function inactiveServerRequest(obj, issuesTable) {
+
+ awsS3.getObject({
+ Bucket: window.config.s3Bucket,
+ Key: pubDir+'/' + magazinesFn
+ }, function(err, activated) {
+
+ var tmp = obj.data('filename'),
+ activeList;
+ try {
+ activeList = $.plist($.parseXML(activated.Body.toString()));
+ }catch(e) {
+ activeList = [];
+ }
+ var filenames = [
+ tmp + '/' + tmp + '_.pdf',
+ tmp + '/' + tmp + '.pdf'
+ ];
+
+ for(var i = 0; i < activeList.length; )
+ if(filenames.indexOf(activeList[i].FileName) != -1)
+ activeList.splice(i, 1);
+ else
+ i++;
+ var body = $.plist('toString', activeList);
+
+ //var rowIndex = issuesTable.fnGetPosition( obj.closest('tr')[0] );
+ //issuesTable.fnDeleteRow(rowIndex);
+
+ var params = {
+ Bucket: window.config.s3Bucket, // required
+ Key: pubDir+'/' + magazinesFn,
+ //Body: PlistParser.toPlist(activeList)
+ Body: cleanKeys($.plist('toString', activeList))
+ };
+ window.awsS3.putObject(params, function(err, data) {
+ if (err) {
+ alert();
+ } else {
+ //obj.removeClass("btnInactive").removeClass("btn-danger").addClass("btnActive").addClass("btn-success").html("Active").data("id", 0);
+ //issuesTable.fnGetPosition( obj.parents('tr').closest('.ttitle')[0]).html("");
+ //issuesTable.fnGetPosition( obj.parents('tr').closest('.tsubtitle')[0]).html("");
+ location.reload();
+ }
+ });
+ });
+}
+
+function addRowToTable(index, data, issuesTable) {
+ issuesTable.fnAddData( {
+ 'DT_RowId': 'row_' + index,
+ '0': data.FileName,
+ '1': "" + data.Title + "",
+ '2': "" + data.Subtitle + "",
+ '3': data.statusBtn
+ });
+}
+
+
+function deleteFromObject(obj, deleteValue) {
+ var objToArray = $.map(obj, function(value, index) {
+ return [value];
+ });
+
+ for (var i = 0; i < objToArray.length; ++i) {
+ if (objToArray[i] == deleteValue) {
+ objToArray.splice(i, 1);
+ i--;
+ }
+ }
+
+ return ArrayToObject(objToArray);
+}
+
+function ArrayToObject(arr) {
+ var rv = {};
+ for (var i = 0; i < arr.length; ++i)
+ rv[i] = arr[i];
+ return rv;
+}
+
+function cleanKeys(obj) {
+ //return obj.replace("\\d+\<\/key\>\n\", "");
+ return obj.replace(/\n\\d+\<\/key\>\n\/g, "\n");
+}
+
+function insertIssInList(iss, list)
+{
+ var issfn = iss.FileName;
+ // replace issues or add it
+ for(var i = 0, l = list.length; i < l; )
+ {
+ var item = list[i];
+ if(item && item.FileName == issfn)
+ list.splice(i, 1);
+ else
+ i += 1;
+ }
+ list.unshift(iss);
+}
diff --git a/src/admin_assets/js/pages/pdf-annotation-editor.js b/src/admin_assets/js/pages/pdf-annotation-editor.js
index c6b8704..554a661 100644
--- a/src/admin_assets/js/pages/pdf-annotation-editor.js
+++ b/src/admin_assets/js/pages/pdf-annotation-editor.js
@@ -4,7 +4,7 @@ app_dir = get_app_dir(app_name),
doc_query = querystring.parse(get_url_query(document.location+'')),
pdf_url = doc_query ? doc_query.waurl : null, s3_key,
external_b = doc_query ? typeof doc_query.external != 'undefined' : null,
-pdf_url_dir, annots_key, update_header_fn;
+pdf_url_dir, annots_key, annots_fn, update_header_fn;
$(function(){
@@ -23,8 +23,8 @@ $(function(){
{
setTimeout(function()
{
- annots_key = path.dirname(pdf_url) + '/' +
- path.basename(pdf_url, path.extname(pdf_url)) + '_updates.plist';
+ annots_fn = path.basename(pdf_url, path.extname(pdf_url)) + '_updates.plist';
+ annots_key = path.dirname(pdf_url) + '/' + annots_fn;
var saved_data = localStorage.getItem(annots_key);
if(saved_data)
{
@@ -196,7 +196,7 @@ $(function(){
Bucket: config.s3Bucket,
Key: s3_key,
Metadata: {
- update: annots_key
+ update: annots_fn
}
}, function(err, res)
{
@@ -307,8 +307,10 @@ $(function(){
if(!hasChanged(annot))
continue;
var annot_data = {
- Action: annot.remove ? 'Remove' : 'Add'
+ Action: annot.remove ? 'Remove' : (annot.add ? 'Add' : 'Edit')
};
+ if(annot_data.Action != 'Add')
+ annot_data.IndexAtPage = annot.IndexAtPage;
if(annot.id)
annot_data.ID = annot.id;
pres.push(annot_data);
@@ -522,8 +524,14 @@ $(function(){
{
var cdata = $.extend(true, {}, data);
cdata.pdf_data = data;
+ cdata.IndexAtPage = i;
add_annot(cdata);
}
+ else
+ {
+ annot.pdf_data = data;
+ annot.IndexAtPage = i;
+ }
}
}
});
@@ -603,6 +611,7 @@ $(function(){
var annots = annotations['p' + page.index];
el = annot_editor_link_create(data, page);
data.id = genRandId();
+ data.add = true;
annots.push(data);
$links_div.append(el);
data.element = el;
diff --git a/src/admin_assets/js/pages/pivots.js b/src/admin_assets/js/pages/pivots.js
new file mode 100644
index 0000000..f663002
--- /dev/null
+++ b/src/admin_assets/js/pages/pivots.js
@@ -0,0 +1,28 @@
+$(function(){
+
+ var app_name = storage.getItem(config.storageAppNameKey),
+ app_dir = get_app_dir(app_name);
+
+ awsS3Ready(start);
+
+ function start()
+ {
+ awsS3.getSignedUrl('getObject', {
+ Bucket: config.s3Bucket,
+ Key: app_dir + '/APP_/REPORTS/publications_.csv',
+ Expires: awsExpireReverse(config.awsExpireReverseInHours)
+ }, function(err, table_url)
+ {
+ if(err)
+ return notifyUserError(err);
+ var tableReader = new TableReader({
+ element: document.getElementById('pivotstable')
+ });
+ tableReader.load(table_url, function(err)
+ {
+
+ });
+ });
+ }
+
+});
diff --git a/src/admin_assets/js/pages/preview.js b/src/admin_assets/js/pages/preview.js
index b570566..336332a 100644
--- a/src/admin_assets/js/pages/preview.js
+++ b/src/admin_assets/js/pages/preview.js
@@ -17,7 +17,17 @@ $(function()
if(err)
return notifyUserError("You should setup app first! Click Here!");
$('#preview-content').show();
- var setup_obj = res ? $.plist($.parseXML(res.Body.toString())) : {};
+ var setup_obj = res ? $.plist($.parseXML(res.Body.toString())) : {},
+ base_url = '//reader.librelio.com',
+ frame_src = base_url + '?' + querystring.stringify({
+ wapublisher: s3AuthObj.rootDirectory,
+ waapp: app_name
+ }),
+ frame_src_html5 = base_url + '?' + querystring.stringify({
+ wapublisher: s3AuthObj.rootDirectory,
+ waapp: app_name,
+ waversion: 'html5'
+ });
// set app active state
function set_toggle_name()
{
@@ -48,25 +58,25 @@ $(function()
$this.prop('disabled', false);
set_toggle_name.call($this);
if(!err)
- reader.prop('src', reader.prop('src'));
+ {
+ if(setup_obj.Active)
+ {
+ reader.show();
+ reader.prop('src', frame_src_html5);
+ }
+ else
+ reader.hide();
+ }
});
});
- var base_url = '//reader.librelio.com';
- $('#reader-link').attr('href', base_url + '?' +
- querystring.stringify({
- wapublisher:
- s3AuthObj.rootDirectory,
- waapp: app_name
- }));
+
+ $('#reader-link').attr('href', frame_src);
var reader = $('');
reader.prop('id', 'reader');
- reader.attr('src', base_url + '?' +
- querystring.stringify({
- wapublisher:
- s3AuthObj.rootDirectory,
- waapp: app_name,
- waversion: 'html5'
- }));
+ if(setup_obj.Active)
+ reader.attr('src', frame_src_html5);
+ else
+ reader.hide();
$('#reader-wrapper').append(reader);
});
});
diff --git a/src/admin_assets/js/pages/publications.js b/src/admin_assets/js/pages/publications.js
index a4ee729..216ff73 100644
--- a/src/admin_assets/js/pages/publications.js
+++ b/src/admin_assets/js/pages/publications.js
@@ -1,14 +1,33 @@
var appName = storage.getItem(config.storageAppNameKey),
-appDir = get_app_dir(appName);
+appDir = get_app_dir(appName),
+setup_obj;
$(function() {
function workOnAwsS3()
{
formDisplay();
$pubDlg.find('.fileinput').each(initUploadEl);
- updatePubTable(function()
- {
- $('#page-loading-indicator2').fadeOut();
- });
+ awsS3.getObject({
+ Bucket: config.s3Bucket,
+ Key: appDir + '/APP_/Uploads/setup.plist'
+ }, function(err, res)
+ {
+ if(err && err.code != 'NoSuchKey')
+ {
+ handleAWSS3Error(err)
+ return;
+ }
+ var obj = res ? $.plist($.parseXML(res.Body.toString())) : {};
+ setup_obj = obj;
+ if(setup_obj.PublicationType != 'multiple')
+ {
+ document.location = 'issues.html';
+ return;
+ }
+ updatePubTable(function()
+ {
+ $('#page-loading-indicator2').fadeOut();
+ });
+ });
}
var $pubTable = $(".publicationDataTable"),
publicationsTable = $pubTable.dataTable({
@@ -21,165 +40,8 @@ $(function() {
return;
awsS3Ready(workOnAwsS3);
-
- $('.new-pub-btn').click(function()
- {
- if(!awsS3)
- return false;
- });
- $pubDlg.find('.svgedit-btn').bind('click', function()
- {
- var pub = $pubDlg.find('input[name=FolderName]').val(),
- filename = pubDlgEvalAttr($(this).data('filename'));
- if(filename)
- {
- window.open('svgedit.html?' + path.stringifyQuery({
- app: appName,
- filename: pub + '/' + filename
- }), '_blank');
- return false;
- }
- });
- $pubDlg.find('.pdfannotedit-btn').bind('click', function()
- {
- var pub = $pubDlg.find('input[name=FolderName]').val(),
- filename = pubDlgEvalAttr($(this).data('filename'));
- if(filename)
- {
- window.open('pdf-annotation-editor.html?' +
- path.stringifyQuery({
- waurl: appDir + '/' + pub + '/' + filename
- }), '_blank');
- return false;
- }
- });
-
- $("#asset-uploader").pluploadQueue({
- // General settings
- runtimes: 'html5',
- url: 'https://' + config.s3Bucket + '.s3.amazonaws.com',
- // Rename files by clicking on their titles
- rename: true,
-
- // Sort files
- sortable: true,
-
- // Enable ability to drag'n'drop files onto the widget (currently only HTML5 supports that)
- dragdrop: true,
-
- // Views to activate
- views: {
- list: true,
- thumbs: true, // Show thumbs
- active: 'thumbs'
- },
-
- multiple_queues: true
- });
- var asset_uploader = $("#asset-uploader").pluploadQueue();
+
- if(s3AuthObj.type == 'idFed')
- {
- asset_uploader.unbind('UploadFile');
- asset_uploader.bind('UploadFile', function(up, file)
- {
- var filename = file.target_name || file.name;
- function onCancelUpload()
- {
- if(xhr)
- xhr.abort();
- }
- function unbindEvents()
- {
- up.unbind('CancelUpload', onCancelUpload)
- }
- up.bind('CancelUpload', onCancelUpload);
- var pub = $pubDlg.find('input[name=FolderName]').val(),
- asset_dir = $("#asset-uploader").data('dir'),
- dir = appDir + '/' + pub + (asset_dir ? '/' + asset_dir : ''),
- xhr,
- request = awsS3.putObject({
- Bucket: config.s3Bucket,
- Key: dir + '/' + filename,
- Body: file.getNative()
- }, function(err, res)
- {
- unbindEvents();
- if(err)
- {
- console.error(err);
- up.trigger('Error', {
- code : plupload.HTTP_ERROR,
- message : plupload.translate('HTTP Error.'),
- file : file,
- response: err+'',
- status: xhr ? xhr.status : _('Unknown'),
- responseHeaders:
- xhr ? xhr.getAllResponseHeaders() : {}
- });
- return;
- }
- file.loaded = file.size;
- up.trigger('UploadProgress', file);
-
- file.status = plupload.DONE;
- up.trigger('FileUploaded', file, {
- response: 'success',
- status: 200,
- responseHeaders: {}
- });
- });
- xhr = request.httpRequest.stream;
- if(xhr && xhr.upload)
- $(xhr.upload).on('progress', function(ev)
- {
- ev = ev.originalEvent;
- file.loaded = ev.loaded;
- up.trigger('UploadProgress', file);
- });
- });
- }
- else
- {
- asset_uploader.bind("BeforeUpload", function(up, file) {
- var params = asset_uploader.settings.multipart_params;
- params.key = $("#asset-uploader").data('current_dir') + file.name;
- params.Filename = file.name;
- });
- }
- function setPLUploadInfoForPub(pub)
- {
- var d = new Date(new Date().getTime() + (60 * 60 * 1000)),
- asset_dir = $("#asset-uploader").data('dir'),
- dir = appDir + '/' + pub + '/' + (asset_dir ? asset_dir + '/' : ''),
- policy = {
- "expiration": d.toISOString(),
- "conditions": [
- {"bucket": config.s3Bucket},
- ["starts-with", "$key", dir],
- {"acl": "private"},
- ["starts-with", "$Content-Type", ""],
- ["starts-with", "$name", ""],
- ["starts-with", "$Filename", ""],
- ["starts-with", "$success_action_status", ""]
- ]
- },
- policy_str = CryptoJS.enc.Base64.stringify(
- CryptoJS.enc.Utf8.parse(JSON.stringify(policy))),
- signature = CryptoJS.HmacSHA1(policy_str, s3AuthObj.secretAccessKey)
- .toString(CryptoJS.enc.Base64);
- var post = {
- acl: 'private',
- AWSAccessKeyId: s3AuthObj.accessKeyId,
- policy: policy_str,
- signature: signature,
- 'Content-Type': '$Content-Type',
- success_action_status: '201'
- };
- $("#asset-uploader").data('current_dir', dir);
- asset_uploader.setOption('multipart_params', post);
- asset_uploader.splice(0, asset_uploader.files.length);
- }
function uploadElEvalFilename(el, action)
{
var pub = $pubDlg.data('pubObj'),
@@ -199,32 +61,6 @@ $(function() {
}
return pubDlgEvalAttr($this.attr('name'), { fileext: ext });
}
- function uploadFileUpdate($upload)
- {
- $upload.find('input[type=file]').each(function()
- {
- var file = uploadElEvalFilename(this),
- extensions = [ 'pdf', 'svg' ];
- for(var i = 0, l = extensions.length; i < l; ++i)
- {
- var ext = extensions[i];
- $upload.toggleClass('fileinput-' + ext,
- (path.fileExtension(file) == '.' + ext));
- }
- });
- }
- function uploadFileUpdateExtension(inp)
- {
- var pub = $pubDlg.data('pubObj') || {},
- $inp = $(inp),
- ext = inp.files && inp.files.length > 0 ?
- path.fileExtension(inp.files[0].name) : '';
- if($inp.hasClass('paidfileupload'))
- pub.paid_ext = ext;
- else if($inp.hasClass('freefileupload'))
- pub.free_ext = ext;
- $pubDlg.data('pubObj', pub);
- }
function initUploadEl()
{
var $upload = $(this),
@@ -248,29 +84,15 @@ $(function() {
{
pubDlgUpdated = true;
uploadFileUpdateExtension(this);
- // this method should update file ui
- uploadFileUpdate($upload)
},
onRemoveSuccess: function()
{
pubDlgUpdated = true;
uploadFileUpdateExtension(this);
- // this method should update file ui
- uploadFileUpdate($upload)
},
onFileExistCheck: function(exists)
{
- if($(this).hasClass('paidfileupload'))
- {
- $pubDlg.find('input[name=Type]').each(function()
- {
- if(exists)
- this.checked = (this.value == 'Paid');
- else
- this.checked = (this.value != 'Paid');
- });
- pubDlgUpdateType();
- }
+
},
checkBeforeUpload: function(inp_el, file, cb)
{
@@ -322,7 +144,6 @@ $(function() {
.remove();
});
- asset_uploader.stop();
});
var illegalPubs = [ "AAD", "APP__", "APP_", "APP_", "APW_" ];
$pubDlg.find('.set-title-btn').click(function()
@@ -356,10 +177,23 @@ $(function() {
}
if(!exists)
{
- $(this).parent().hide();
- $pubDlg.find('.pub-body-form').show();
- if(s3AuthObj.type != 'idFed')
- setPLUploadInfoForPub(title_val);
+ awsS3.putObject({
+ Bucket: config.s3Bucket,
+ Key: appDir + '/' + title_val + '/' +
+ title_val + '.plist',
+ Body: $.plist('toString', [])
+ }, function(err, data) {
+
+ if(err)
+ {
+ $title_inp.prop('disabled', false);
+ return handleAWSS3Error(err);
+ }
+
+ pubDlgUpdated = true;
+ $(this).parent().hide();
+ $pubDlg.find('.pub-body-form').show();
+ });
}
else
{
@@ -372,76 +206,18 @@ $(function() {
$pubDlg.on('show.bs.modal', function()
{
pubDlgUpdated = false;
- var pub = $pubDlg.data('pubObj'),
- type = 'Free';
- $pubDlg.find('.uufile').remove();
+ var pub = $pubDlg.data('pubObj');
$pubDlg.find('input[type=file]').prop('disabled', false);
- $pubDlg.find('.fileinput').each(function()
- {
- uploadFileUpdate($(this))
- });
if(pub)
{
- type = '';
var pub_name = pub.FileName;
$pubDlg.find('.set-title-btn').parent().hide();
$pubDlg.find('input[name=FolderName]').prop('disabled', true);
$pubDlg.find('.pub-body-form').show();
$pubDlg.find('.fileinput').each(function()
{
- var $upload = $(this),
- inp = $upload.find('input[type=file]')[0];
if(this._s3Upload)
- this._s3Upload.reload();
- if(inp)
- {
- // fileinput download-btn ready
- $upload.find('.download-btn').each(function()
- {
- var title =
- $pubDlg.find('input[name=FolderName]').val(),
- file = uploadElEvalFilename(inp),
- a_tag = this;
- awsS3.getSignedUrl('getObject', {
- Bucket: config.s3Bucket,
- Key: appDir + '/' + title + '/' + file,
- Expires: awsExpireReverse(config.awsExpireReverseInHours)
- }, function(err, url)
- {
- a_tag.href = !err && url ? url : '';
- })
- });
- }
- });
- if(s3AuthObj.type != 'idFed')
- setPLUploadInfoForPub(pub_name);
-
- // list uploaded elements and add them to list
- var pubDir = appDir + '/' + pub_name + '/',
- excluded_files = [
- pub_name + (pub.free_ext || ''),
- pub_name + '_' + (pub.paid_ext || ''),
- pub_name + '.png',
- pub_name + '_newsstand.png'
- ];
- s3ListAllObjects(awsS3, {
- Bucket: config.s3Bucket,
- Prefix: pubDir
- }, function(err, res)
- {
- if(err)
- {
- handleAWSS3Error(err);
- return;
- }
- var contents = res.Contents;
- for(var i = 0, l = contents.length; i < l; ++i)
- {
- var key = contents[i].Key,
- fn = key.substr(pubDir.length).replace('*', '\\*');
- if(fn && excluded_files.indexOf(fn) == -1)
- insertUploadItem(fn, { class_name: 'uufile' });
- }
+ this._s3Upload.reload();
});
}
else
@@ -450,14 +226,6 @@ $(function() {
$pubDlg.find('.set-title-btn').parent().show();
$pubDlg.find('.pub-body-form').hide();
}
- $pubDlg.find('input[name=Type]').each(function()
- {
- if(this.value == type)
- this.checked = true;
- else
- this.checked = false;
- });
- pubDlgUpdateType();
});
function pubDlgEvalAttr(s, vars)
{
@@ -481,46 +249,6 @@ $(function() {
var idx = s.indexOf('*'+vr+'*');
return idx == 0 || (idx > 0 && s[idx-1] != '\\');
}
- $pubDlg.find('input[name=Type]').on('change', pubDlgUpdateType);
- function pubDlgUpdateType()
- {
- var paid_elem = $pubDlg.find('.paid-elem'),
- paid_radio = $pubDlg.find('input[name=Type]').filter('[value=Paid]');
- if(paid_radio.prop('checked'))
- paid_elem.show();
- else
- paid_elem.hide();
- }
- var img_check_pttrn = /\.(jpe?g|png|gif)$/i;
- function insertUploadItem(key, opts)
- {
- opts = opts || {};
- var class_name = opts.class_name ? ' ' + opts.class_name : '',
- isImg = img_check_pttrn.test(key),
- uploadLI = $('\
- \
- ').appendTo($pubDlg.find('.upload-list'));
- var el = uploadLI.find('.fileinput')[0];
- initUploadEl.call(el);
- if(el._s3Upload)
- el._s3Upload.reload();
- }
-
function updatePubTable(callback)
{
@@ -596,8 +324,7 @@ $(function() {
// and status
//---------------------------------------------------
- if (isolateFolderName2(activeList[j].FileName) == temp[count].FileName ||
- isolateFolderName3(activeList[j].FileName) == temp[count].FileName) {
+ if (activeList[j].FileName == temp[count].FileName) {
temp[count].Title = activeList[j].Title;
temp[count].Subtitle = activeList[j].Subtitle;
temp[count].status = "active";
@@ -622,10 +349,9 @@ $(function() {
return rowsList[index];
}
}
- function pubTRClick()
+ function pubEditClick()
{
- var $this = $(this),
- item = getPubByRowId(this.id);
+ var item = getPubByRowId(this.parentNode.parentNode.id);
if(!item)
return;
awsS3.listObjects({
@@ -672,6 +398,15 @@ $(function() {
});
return false;
}
+ function pubTRClick()
+ {
+ var item = getPubByRowId(this.id);
+ if(!item)
+ return;
+ document.location = 'issues.html?wapublication=' +
+ encodeURIComponent(item.FolderName);
+ return false;
+ }
//---------------------------------------------------
// Add the rows to the table
//---------------------------------------------------
@@ -685,7 +420,8 @@ $(function() {
//---------------------------------------------------
- $pubTable.on('click', 'tbody > tr', pubTRClick)
+ $pubTable.on('click', 'tbody > tr', pubTRClick);
+ $pubTable.on('click', '.edit-btn', pubEditClick);
callback && callback();
});
@@ -784,13 +520,6 @@ function inactivePublication(obj, publicationsTable) {
}
});
}
-function is_paid_pub(filename, cb)
-{
- s3ObjectExists(awsS3, {
- Bucket: config.s3Bucket,
- Key: appDir + '/' + filename + '/' + filename + '_.pdf'
- }, cb);
-}
function activeServerRequest(obj, publicationsTable) {
var pTitle = $("input[name='pubTitleInput']").val();
@@ -807,38 +536,32 @@ function activeServerRequest(obj, publicationsTable) {
}catch(e) {
activeList = [];
}
- is_paid_pub(obj.data('filename'), function(err, is_paid)
- {
- if(err)
- return handleAWSS3Error(err);
- var pub = {
- FileName: obj.data("filename") + "/" + obj.data("filename") +
- (is_paid ? '_' : '') + ".pdf",
- Title: pTitle,
- Subtitle: pSubtitle
- };
- insertPubInList(pub, activeList);
+ var pub = {
+ FileName: obj.data("filename"),
+ Title: pTitle,
+ Subtitle: pSubtitle
+ };
+ insertPubInList(pub, activeList);
- var body = $.plist('toString', activeList);
+ var body = $.plist('toString', activeList);
- var params = {
- Bucket: config.s3Bucket, // required
- Key: appDir+'/Magazines.plist',
- //Body: PlistParser.toPlist(activeList)
- Body: body
- };
- awsS3.putObject(params, function(err, data) {
- if (err) {
- return handleAWSS3Error(err);
- } else {
- //obj.addClass("btnInactive").addClass("btn-danger").removeClass("btnActive").removeClass("btn-success").html("Inactive").data("id", activeListLength);
- //publicationsTable.fnGetPosition( obj.parents('tr').closest('.ttitle')[0]).html(pTitle);
- //publicationsTable.fnGetPosition( obj.parents('tr').closest('.tsubtitle')[0]).html(pSubtitle);
- location.reload();
- }
- });
- });
+ var params = {
+ Bucket: config.s3Bucket, // required
+ Key: appDir+'/Magazines.plist',
+ //Body: PlistParser.toPlist(activeList)
+ Body: body
+ };
+ awsS3.putObject(params, function(err, data) {
+ if (err) {
+ return handleAWSS3Error(err);
+ } else {
+ //obj.addClass("btnInactive").addClass("btn-danger").removeClass("btnActive").removeClass("btn-success").html("Inactive").data("id", activeListLength);
+ //publicationsTable.fnGetPosition( obj.parents('tr').closest('.ttitle')[0]).html(pTitle);
+ //publicationsTable.fnGetPosition( obj.parents('tr').closest('.tsubtitle')[0]).html(pSubtitle);
+ location.reload();
+ }
+ });
});
}
@@ -896,7 +619,8 @@ function addRowToTable(index, data, publicationsTable) {
'0': data.FileName,
'1': "" + data.Title + "",
'2': "" + data.Subtitle + "",
- '3': data.statusBtn
+ '3': '',
+ '4': data.statusBtn
});
}
diff --git a/src/admin_assets/js/pages/setup.js b/src/admin_assets/js/pages/setup.js
index af36ae6..1ab6aee 100644
--- a/src/admin_assets/js/pages/setup.js
+++ b/src/admin_assets/js/pages/setup.js
@@ -15,22 +15,29 @@ $(function(){
loadSetupPage(app_dir, $page);
$page.find('.fileinput').each(function()
{
+ var $file = $(this).find('input[type=file]'),
+ ftype = $file.data('type') || 'Image';
s3UploadInit($(this), {
s3: awsS3,
- type: 'Image',
+ type: ftype,
Bucket: config.s3Bucket,
Prefix: app_dir + '/' + upload_dir,
checkBeforeUpload: function(inp_el, file, cb)
{
- makeImageFromFile(file, function(err, image)
- {
- if(err)
- return notifyUserError(err);
- var m = validateImageSizeByElementAttrs(inp_el, image);
- cb(!m);
- if(m)
- notifyUserError(m);
- });
+ if(ftype == 'Image')
+ {
+ makeImageFromFile(file, function(err, image)
+ {
+ if(err)
+ return notifyUserError(err);
+ var m = validateImageSizeByElementAttrs(inp_el, image);
+ cb(!m);
+ if(m)
+ notifyUserError(m);
+ });
+ }
+ else
+ cb(true);
},
signExpires: function()
{
diff --git a/src/admin_assets/less/main/layout/layout.less b/src/admin_assets/less/main/layout/layout.less
index 56c20f8..7890d31 100644
--- a/src/admin_assets/less/main/layout/layout.less
+++ b/src/admin_assets/less/main/layout/layout.less
@@ -103,3 +103,9 @@ body.padTop53 {
}
/* ================== END Template Layout ============== */
+
+
+#frame-wrp {
+ width: 100%;
+ overflow-x: hidden;
+}
\ No newline at end of file
diff --git a/src/admin_assets/less/pages/issues.less b/src/admin_assets/less/pages/issues.less
new file mode 100644
index 0000000..6217079
--- /dev/null
+++ b/src/admin_assets/less/pages/issues.less
@@ -0,0 +1,44 @@
+.new-iss-dlg {
+
+}
+.update-iss-dlg {
+
+}
+
+.new-iss-dlg .iss-dlg-new,
+.update-iss-dlg .iss-dlg-update,
+.fileinput-svg .fileinput-is-svg, .fileinput-pdf .fileinput-is-pdf {
+ display: inline-block;
+}
+
+.iss-dlg-new, .iss-dlg-update, .fileinput-is-svg, .fileinput-is-pdf {
+ display: none;
+}
+
+.iss-status-btn {
+ width: 65px;
+ margin: 0px auto;
+}
+
+#dataTable tbody tr {
+ cursor: pointer;
+}
+
+#dataTable .Name, #dataTable .Status {
+ padding-top: 8px;
+ padding-bottom: 8px;
+}
+
+#dataTable .Image {
+ max-height: 100px;
+ max-width: 300px;
+ display: block;
+ margin: 0px auto;
+}
+
+#issModal .modal-dialog {
+ width: 800px;
+}
+.plupload_filelist_footer {
+ height: 40px;
+}
diff --git a/src/admin_assets/less/pages/pivots.less b/src/admin_assets/less/pages/pivots.less
new file mode 100644
index 0000000..059ac15
--- /dev/null
+++ b/src/admin_assets/less/pages/pivots.less
@@ -0,0 +1,9 @@
+#pivotstable-wrp {
+ width: 100%;
+ min-height: 500px;
+ overflow-x: auto;
+ overflow-y: visible;
+}
+#pivotstable {
+ margin: 2px;
+}
\ No newline at end of file
diff --git a/src/admin_assets/less/theme.less b/src/admin_assets/less/theme.less
index 116ef7f..706849e 100644
--- a/src/admin_assets/less/theme.less
+++ b/src/admin_assets/less/theme.less
@@ -23,4 +23,4 @@
.vertical();
.mixin(@baseColor);
}
-}
\ No newline at end of file
+}
diff --git a/src/assets/js/dhtml.js b/src/assets/js/dhtml.js
index a0b9b74..18b2b47 100644
--- a/src/assets/js/dhtml.js
+++ b/src/assets/js/dhtml.js
@@ -213,7 +213,7 @@
parent = ctx;
ctx = ctx[_var[i]];
}
- if(ctx === undefined || ctx === null)
+ if(!parent && ctx === undefined || ctx === null)
return;
return {
parent: parent,
@@ -248,7 +248,7 @@
else
{
if(expr.call[2])
- return m_eval_expr([ expr.call[1] ], contexts, thisarg)[0];
+ return m_eval_expr([ expr.call[2] ], contexts, thisarg)[0];
}
}
};
@@ -355,6 +355,8 @@
return ret;
},
// logical functions
+ and: function(a, b) { return a && b; },
+ or: function(a, b) { return a || b; },
not: function(a) { return !a; },
eqci: function(a, b) { return (a+'').toLowerCase() == (b+'').toLowerCase(); },
eq: function(a, b) { return (a+'') == (b+''); },
diff --git a/src/assets/js/helper.js b/src/assets/js/helper.js
index 432abea..682afc8 100644
--- a/src/assets/js/helper.js
+++ b/src/assets/js/helper.js
@@ -1,3 +1,15 @@
+function url_origin(s)
+{
+ s = s || '';
+ var pttrn = /https?:\/\/[^\/]+/,
+ match = pttrn.exec(s);
+ if(match)
+ return match[0];
+ match = pttrn.exec(document.location+'');
+ if(match)
+ return match[0];
+ return '';
+}
function path_without_query(s)
{
s = s || '';
diff --git a/src/assets/js/localize.js b/src/assets/js/localize.js
index 2b74913..63ab0bb 100644
--- a/src/assets/js/localize.js
+++ b/src/assets/js/localize.js
@@ -57,10 +57,15 @@
});
}
localize.eval_all = localize_eval_all;
+ localize.aliases = {
+ 'fr': 'fr-FR'
+ };
localize.setLocale = function(locale, opts, cb)
{
if(typeof opts == 'function')
cb = opts;
+ if(localize.aliases[locale])
+ locale = localize.aliases[locale];
if(opts.icu === undefined || opts.icu)
{
var icu = document.createElement('script');
diff --git a/src/assets/lib/jquery.plist.js b/src/assets/lib/jquery.plist.js
index a02b81c..2952e71 100644
--- a/src/assets/lib/jquery.plist.js
+++ b/src/assets/lib/jquery.plist.js
@@ -130,7 +130,8 @@
{
var r = '';
for(var key in obj)
- if(typeof key != 'undefined')
+ if(typeof key != 'undefined' &&
+ typeof obj[key] != 'undefined')
r += indentStr(indentLen+1) +
elmToString('key', key) + newline() +
plistElementsToString(obj[key], opts,
diff --git a/src/data/conditions-generales.md b/src/data/conditions-generales.md
index dd8fd31..704f54b 100644
--- a/src/data/conditions-generales.md
+++ b/src/data/conditions-generales.md
@@ -1,6 +1,6 @@
-_ Dernière mise à jour: 17 novembre 2014_
+_ Dernière mise à jour: 13 août 2015_
-Les conditions générales qui suivent sont applicables pour l’ensemble de prestations de Librelio à des clients français, ayant fait l’objet préalable d’un devis approuvé par le Client, mentionnant ces conditions.
+Les conditions générales qui suivent sont applicables pour l’ensemble de prestations de Librelio, ayant fait l’objet préalable d’un devis ou d'une proposition approuvé par le Client, mentionnant ces conditions.
### 1- Propriété intellectuelle
@@ -28,7 +28,7 @@ Librelio informera, dans la mesure du possible le Client, dans un délai raison
### 3- Maintenance
Dans le cadre de prestations dont le devis mentionne la maintenance d'applications , Librelio s'engage :
-- • à maintenir en bon état de fonctionnement les applications couvertes par la prestation, sur les systèmes d'exploitation les plus récents, ainsi que les deux versions antérieures
+- • à maintenir en bon état de fonctionnement les applications couvertes par la prestation, sur les systèmes d'exploitation les plus récents, ainsi qu'une version antérieures
- • à publier sur internet les informations concernant évolutions apportées aux applications maintenues ou informer directement le Client
- • à effectuer la révision des application (modifications, adaptation, développement, etc.) s'imposant à la suite d'un changement dans la réglementation en vigueur à condition que le système installé chez l'utilisateur le permette.
diff --git a/src/data/config.json b/src/data/config.json
index fcdc29a..ed42880 100644
--- a/src/data/config.json
+++ b/src/data/config.json
@@ -12,5 +12,6 @@
"idFedFBUsersRoleArn": "arn:aws:iam::105216790221:role/RoleForFacebook",
"idFedGPUsersRoleArn": "arn:aws:iam::105216790221:role/RoleForGoogle",
"GoogleClientId": "1012641315687.apps.googleusercontent.com",
+ "backendUrl": "http://localhost/libreliodev-php",
"locale": "en-US"
}
diff --git a/src/language/en-US/admin.po b/src/language/en-US/admin.po
index 4342a59..d615440 100644
--- a/src/language/en-US/admin.po
+++ b/src/language/en-US/admin.po
@@ -672,3 +672,38 @@ msgstr ""
msgid "Start Upload"
msgstr ""
+#: templates/pages/setup-html5.hbs:55
+msgid "StyleSheets"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:62
+msgid "CSS For Covers Module"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:66 templates/pages/setup-html5.hbs:79
+msgid "Select css file"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:75
+msgid "CSS For PDFReader"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:93
+msgid "Subscriptions"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:100
+msgid "Subscription 1 title"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:108
+msgid "Subscription 1 link"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:116
+msgid "Subscription 2 title"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:124
+msgid "Subscription 2 link"
+msgstr ""
diff --git a/src/language/fr-FR/admin.po b/src/language/fr-FR/admin.po
index 1ab6ef5..142de3a 100644
--- a/src/language/fr-FR/admin.po
+++ b/src/language/fr-FR/admin.po
@@ -454,3 +454,39 @@ msgstr "Démarrer le chargement"
#: admin_assets/js/pages/tracking.js:65
msgid "Analytics data not yet available"
msgstr ""
+
+#: templates/pages/setup-html5.hbs:55
+msgid "StyleSheets"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:62
+msgid "CSS For Covers Module"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:66 templates/pages/setup-html5.hbs:79
+msgid "Select css file"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:75
+msgid "CSS For PDFReader"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:93
+msgid "Subscriptions"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:100
+msgid "Subscription 1 title"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:108
+msgid "Subscription 1 link"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:116
+msgid "Subscription 2 title"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:124
+msgid "Subscription 2 link"
+msgstr ""
diff --git a/src/language/pot/admin.pot b/src/language/pot/admin.pot
index dff45f0..c4db2ad 100644
--- a/src/language/pot/admin.pot
+++ b/src/language/pot/admin.pot
@@ -716,3 +716,39 @@ msgstr ""
#: templates/pages/triggers.hbs:316
msgid "Your subscription does not include triggers. Please contact Librelio for more details"
msgstr ""
+
+#: templates/pages/setup-html5.hbs:55
+msgid "StyleSheets"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:62
+msgid "CSS For Covers Module"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:66 templates/pages/setup-html5.hbs:79
+msgid "Select css file"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:75
+msgid "CSS For PDFReader"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:93
+msgid "Subscriptions"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:100
+msgid "Subscription 1 title"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:108
+msgid "Subscription 1 link"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:116
+msgid "Subscription 2 title"
+msgstr ""
+
+#: templates/pages/setup-html5.hbs:124
+msgid "Subscription 2 link"
+msgstr ""
diff --git a/src/pdfreader_assets/js/pdfreader-helper.js b/src/pdfreader_assets/js/pdfreader-helper.js
index 79c2e40..91313f9 100644
--- a/src/pdfreader_assets/js/pdfreader-helper.js
+++ b/src/pdfreader_assets/js/pdfreader-helper.js
@@ -7,7 +7,11 @@ $(function()
pdf_viewer.off('headersReceived', arguments.callee);
if(typeof update_fn == 'string' && update_fn.length > 0)
{
- $.ajax(s3bucket_file_url(http://github.com/update_fn), {
+ var pdf_url = pdf_viewer.pdfviewer('get', 'pdf_url');
+ if(!pdf_url)
+ return;
+ var pdf_url_dir = url_dir(pdf_url);
+ $.ajax(pdf_url_dir + '/' + update_fn, {
success: function(data)
{
try {
@@ -89,8 +93,11 @@ function pdfreader_parse_annotations_update(obj)
id: data.ID,
subtype: 'Link',
rect: (data.Rect||'').split(' ').map(parseFloat),
- remove: data.Action == 'Remove'
+ remove: data.Action == 'Remove',
+ add: data.Action == 'Add'
};
+ if(typeof data.IndexAtPage == 'number')
+ annot.IndexAtPage = data.IndexAtPage;
annots.push(annot);
switch(annot.subtype)
{
diff --git a/src/pdfreader_assets/js/pdfviewer.js b/src/pdfreader_assets/js/pdfviewer.js
index f756960..1c4297a 100644
--- a/src/pdfreader_assets/js/pdfviewer.js
+++ b/src/pdfreader_assets/js/pdfviewer.js
@@ -381,12 +381,12 @@
// set links
for (var i = 0; i < annotationsData.length; i++) {
var data = annotationsData[i];
- var annotation = PDFJS.Annotation.fromData(data);
- if (!annotation || !annotation.hasHtml()) {
+ //var annotation = PDFJS.Annotation.fromData(data);
+ if (!data || !data.hasHtml) {
continue;
}
//var element = annotation.getHtmlElement(docPage.commonObjs);
- data = annotation.getData();
+ //data = annotation.getData();
if(data.subtype !== 'Link')
continue;
if(page.extra_links)
@@ -820,6 +820,7 @@
{
var self = this,
o = self.data(pvobj_key);
+ o.pdf_url = pdf_url;
async.series([ function(next)
{
function xhrGetResponseHeaders(xhr)
@@ -868,7 +869,8 @@
{
filesize = filesize[0];
var rangeListeners = [],
- progressListeners = [];
+ progressListeners = [],
+ progressiveReadListeners = [];
function callListeners(listeners, thisArg, args)
{
for(var i = 0; i < listeners.length; ++i)
@@ -901,6 +903,14 @@
addProgressListener: function(listener)
{
progressListeners.push(listener);
+ },
+ addProgressiveReadListener: function(listener)
+ {
+ progressiveReadListeners.push(listener);
+ },
+ transportReady: function()
+ {
+
},
requestDataRange: function(begin, end)
{
@@ -915,8 +925,11 @@
{
if(this.status == 200 || this.status == 206)
{
+ var chunk = getArrayBuffer(xhr);
+ //callListeners(progressiveReadListeners, this,
+ // [ chunk ]);
callListeners(rangeListeners, this,
- [ begin, getArrayBuffer(xhr) ]);
+ [ begin, chunk ]);
}
};
xhr.onprogress = function(ev)
diff --git a/src/pdfreader_assets/less/pdfviewer.less b/src/pdfreader_assets/less/pdfviewer.less
index 6bf42de..a33187f 100644
--- a/src/pdfreader_assets/less/pdfviewer.less
+++ b/src/pdfreader_assets/less/pdfviewer.less
@@ -153,31 +153,29 @@
}
/* Themes */
-.dark-bkg {
- /* theme effect on pdfviewer */
- .pdfviewer {
+.pdfviewer {
+ color: white;
+ .page-selector {
+ background: black;
+ }
+ .pages-preview .active {
+ background-color: #333333;
+ }
+}
+.pdfviewer-controls {
+ a {
color: white;
- .page-selector {
- background: black;
- }
- .pages-preview .active {
- background-color: #333333;
- }
+ background: rgba(0, 0, 0, .5);
}
- .pdfviewer-controls {
- a {
- color: white;
- background: rgba(0, 0, 0, .5);
- }
- a:hover {
- background: rgba(0, 0, 0, 1);
- }
+ a:hover {
+ background: rgba(0, 0, 0, 1);
}
-
- .pdfviewer-loadingscreen {
- background: black;
- span {
- color: white;
- }
+}
+
+.pdfviewer-loadingscreen {
+ background: black;
+ span {
+ color: white;
}
}
+
diff --git a/src/pdfreader_assets/lib/pdf.js/compatibility.js b/src/pdfreader_assets/lib/pdf.js/compatibility.js
deleted file mode 100644
index 98dc839..0000000
--- a/src/pdfreader_assets/lib/pdf.js/compatibility.js
+++ /dev/null
@@ -1,577 +0,0 @@
-/* -*- 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
-(function checkTypedArrayCompatibility() {
- if (typeof Uint8Array !== 'undefined') {
- // some mobile versions do not support subarray (e.g. safari 5 / iOS)
- 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));
- };
- }
-
- // some mobile version might not support Float64Array
- 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
-(function normalizeURLObject() {
- if (!window.URL) {
- window.URL = window.webkitURL;
- }
-})();
-
-// Object.create() ?
-(function checkObjectCreateCompatibility() {
- if (typeof Object.create !== 'undefined') {
- return;
- }
-
- Object.create = function objectCreate(proto) {
- function Constructor() {}
- Constructor.prototype = proto;
- return new Constructor();
- };
-})();
-
-// Object.defineProperty() ?
-(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;
- }
- };
-})();
-
-// Object.keys() ?
-(function checkObjectKeysCompatibility() {
- if (typeof Object.keys !== 'undefined') {
- return;
- }
-
- Object.keys = function objectKeys(obj) {
- var result = [];
- for (var i in obj) {
- if (obj.hasOwnProperty(i)) {
- result.push(i);
- }
- }
- return result;
- };
-})();
-
-// No readAsArrayBuffer ?
-(function checkFileReaderReadAsArrayBuffer() {
- if (typeof FileReader === 'undefined') {
- return; // FileReader is not implemented
- }
- var frPrototype = FileReader.prototype;
- // Older versions of Firefox might not have readAsArrayBuffer
- if ('readAsArrayBuffer' in frPrototype) {
- return; // readAsArrayBuffer is implemented
- }
- Object.defineProperty(frPrototype, 'readAsArrayBuffer', {
- value: function fileReaderReadAsArrayBuffer(blob) {
- var fileReader = new FileReader();
- var originalReader = this;
- fileReader.onload = function fileReaderOnload(evt) {
- var data = evt.target.result;
- var buffer = new ArrayBuffer(data.length);
- var uint8Array = new Uint8Array(buffer);
-
- for (var i = 0, ii = data.length; i < ii; i++) {
- uint8Array[i] = data.charCodeAt(i);
- }
-
- Object.defineProperty(originalReader, 'result', {
- value: buffer,
- enumerable: true,
- writable: false,
- configurable: true
- });
-
- var event = document.createEvent('HTMLEvents');
- event.initEvent('load', false, false);
- originalReader.dispatchEvent(event);
- };
- fileReader.readAsBinaryString(blob);
- }
- });
-})();
-
-// No XMLHttpRequest.response ?
-(function checkXMLHttpRequestResponseCompatibility() {
- var xhrPrototype = XMLHttpRequest.prototype;
- if (!('overrideMimeType' in xhrPrototype)) {
- // IE10 might have response, but not overrideMimeType
- Object.defineProperty(xhrPrototype, 'overrideMimeType', {
- value: function xmlHttpRequestOverrideMimeType(mimeType) {}
- });
- }
- if ('response' in xhrPrototype ||
- 'mozResponseArrayBuffer' in xhrPrototype ||
- 'mozResponse' in xhrPrototype ||
- 'responseArrayBuffer' in xhrPrototype) {
- return;
- }
- // IE9 ?
- if (typeof VBArray !== 'undefined') {
- Object.defineProperty(xhrPrototype, 'response', {
- get: function xmlHttpRequestResponseGet() {
- return new Uint8Array(new VBArray(this.responseBody).toArray());
- }
- });
- return;
- }
-
- // other browsers
- function responseTypeSetter() {
- // will be only called to set "arraybuffer"
- this.overrideMimeType('text/plain; charset=x-user-defined');
- }
- if (typeof xhrPrototype.overrideMimeType === 'function') {
- Object.defineProperty(xhrPrototype, 'responseType',
- { set: responseTypeSetter });
- }
- function responseGetter() {
- 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;
- }
- Object.defineProperty(xhrPrototype, 'response', { get: responseGetter });
-})();
-
-// window.btoa (base64 encode function) ?
-(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) ?
-(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 ?
-(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
-(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
-(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
-(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
-(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()
-(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 &&
- /^[a-z]+(-[A-Z]+)?$/.test(navigator.language)) {
- return;
- }
- function formatLocale(locale) {
- var split = locale.split(/[-_]/);
- split[0] = split[0].toLowerCase();
- if (split.length > 1) {
- split[1] = split[1].toUpperCase();
- }
- return split.join('-');
- }
- var language = navigator.language || navigator.userLanguage || 'en-US';
- PDFJS.locale = formatLocale(language);
-})();
-
-(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.
- 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.
- var regex = /Android\s[0-2][^\d]/;
- var isOldAndroid = regex.test(navigator.userAgent);
-
- if (isSafari || isOldAndroid) {
- PDFJS.disableRange = true;
- }
-})();
-
-// Check if the browser supports manipulation of the history.
-(function checkHistoryManipulation() {
- if (!window.history.pushState) {
- PDFJS.disableHistory = true;
- }
-})();
-
-(function checkSetPresenceInImageData() {
- 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];
- }
- };
- }
- }
-})();
-
-(function checkStorages() {
- // Feature test as per http://diveintohtml5.info/storage.html
- // The additional localStorage call is to get around a FF quirk, see
- // bug #495747 in bugzilla
- try {
- if ('localStorage' in window && window['localStorage'] !== null) {
- return;
- }
- } catch (e) { }
- // When the generic viewer is used in Firefox the following code will fail
- // when the preference 'network.cookie.lifetimePolicy' is set to 1,
- // see Mozilla bug 365772.
- try {
- window.localStorage = {
- data: Object.create(null),
- getItem: function (key) {
- return this.data[key];
- },
- setItem: function (key, value) {
- this.data[key] = value;
- }
- };
- } catch (e) {
- console.log('Unable to create polyfill for localStorage');
- }
-})();
-
-(function checkRequestAnimationFrame() {
- if ('requestAnimationFrame' in window) {
- return;
- }
- window.requestAnimationFrame =
- window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
- (function fakeRequestAnimationFrame(callback) {
- window.setTimeout(callback, 20);
- });
-})();
diff --git a/src/pdfreader_assets/lib/pdf.js/pdf.js b/src/pdfreader_assets/lib/pdf.js/pdf.js
deleted file mode 100644
index f555669..0000000
--- a/src/pdfreader_assets/lib/pdf.js/pdf.js
+++ /dev/null
@@ -1,6967 +0,0 @@
-/* -*- 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 */
-
-// Initializing PDFJS global object (if still undefined)
-if (typeof PDFJS === 'undefined') {
- (typeof window !== 'undefined' ? window : this).PDFJS = {};
-}
-
-PDFJS.version = '1.0.1';
-PDFJS.build = '48b826b';
-
-(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
-};
-
-// 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 multiple arguments were passed, pass them all to the log function.
- if (arguments.length > 1) {
- var logArguments = ['Error:'];
- logArguments.push.apply(logArguments, arguments);
- console.log.apply(console, logArguments);
- // Join the arguments into a single string for the lines below.
- msg = [].join.call(arguments, ' ');
- } else {
- 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();
- // accept all protocols
- return true;
- /*
- switch (protocol) {
- case 'http':
- case 'https':
- case 'ftp':
- case 'mailto':
- 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;
-}
-
-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;
-})();
-
-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;
-})();
-
-var InvalidPDFException = (function InvalidPDFExceptionClosure() {
- function InvalidPDFException(msg) {
- this.name = 'InvalidPDFException';
- this.message = msg;
- }
-
- InvalidPDFException.prototype = new Error();
- InvalidPDFException.constructor = InvalidPDFException;
-
- return InvalidPDFException;
-})();
-
-var MissingPDFException = (function MissingPDFExceptionClosure() {
- function MissingPDFException(msg) {
- this.name = 'MissingPDFException';
- this.message = msg;
- }
-
- MissingPDFException.prototype = new Error();
- MissingPDFException.constructor = MissingPDFException;
-
- return MissingPDFException;
-})();
-
-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) {
- 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 stringToArray(str) {
- var length = str.length;
- var array = [];
- for (var i = 0; i < length; ++i) {
- array[i] = str.charCodeAt(i);
- }
- return array;
-}
-
-function stringToBytes(str) {
- 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());
- }
-});
-
- // 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;
-})();
-
-var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
-
-var Util = PDFJS.Util = (function UtilClosure() {
- function Util() {}
-
- Util.makeCssRgb = function Util_makeCssRgb(rgb) {
- return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
- };
-
- // 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;
- };
-
- // TODO(mack): Rename appendToArray
- Util.concatenateToArray = function concatenateToArray(arr1, arr2) {
- Array.prototype.push.apply(arr1, arr2);
- };
-
- Util.prependToArray = function concatenateToArray(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 isNull(v) {
- return v === null;
-}
-
-function isName(v) {
- return v instanceof Name;
-}
-
-function isCmd(v, cmd) {
- return v instanceof Cmd && (!cmd || 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 !== undefined &&
- ('getBytes' in v);
-}
-
-function isArrayBuffer(v) {
- return typeof v == 'object' && v !== null && v !== undefined &&
- ('byteLength' in v);
-}
-
-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;
- }
- 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 = reject;
- 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;
-})();
-
-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.src = imageUrl;
-}
-
-function xhrGetResponseHeaders(xhr)
-{
- var allHead = xhr.getAllResponseHeaders(),
- heads = allHead.split(/\r\n|\n|\r/g),
- ret = {};
- for(var i = 0; i < heads.length; ++i)
- {
- var head_name = heads[i].split(':')[0];
- if(head_name)
- ret[head_name] = xhr.getResponseHeader(head_name);
- }
- return ret;
-}
-
-
-var DEFAULT_ICON_SIZE = 22; // px
-var HIGHLIGHT_OFFSET = 4; // px
-var SUPPORTED_TYPES = ['Link', 'Text', 'Widget'];
-
-var Annotation = (function AnnotationClosure() {
- // 12.5.5: Algorithm: Appearance streams
- function getTransformMatrix(rect, bbox, matrix) {
- var bounds = Util.getAxialAlignedBoundingBox(bbox, matrix);
- var minX = bounds[0];
- var minY = bounds[1];
- var maxX = bounds[2];
- var maxY = bounds[3];
-
- if (minX === maxX || minY === maxY) {
- // From real-life file, bbox was [0, 0, 0, 0]. In this case,
- // just apply the transform for rect
- return [1, 0, 0, 1, rect[0], rect[1]];
- }
-
- var xRatio = (rect[2] - rect[0]) / (maxX - minX);
- var yRatio = (rect[3] - rect[1]) / (maxY - minY);
- return [
- xRatio,
- 0,
- 0,
- yRatio,
- rect[0] - minX * xRatio,
- rect[1] - minY * yRatio
- ];
- }
-
- function getDefaultAppearance(dict) {
- var appearanceState = dict.get('AP');
- if (!isDict(appearanceState)) {
- return;
- }
-
- var appearance;
- var appearances = appearanceState.get('N');
- if (isDict(appearances)) {
- var as = dict.get('AS');
- if (as && appearances.has(as.name)) {
- appearance = appearances.get(as.name);
- }
- } else {
- appearance = appearances;
- }
- return appearance;
- }
-
- function Annotation(params) {
- if (params.data) {
- this.data = params.data;
- return;
- }
-
- var dict = params.dict;
- var data = this.data = {};
-
- data.subtype = dict.get('Subtype').name;
- var rect = dict.get('Rect') || [0, 0, 0, 0];
- data.rect = Util.normalizeRect(rect);
- data.annotationFlags = dict.get('F');
-
- var color = dict.get('C');
- if (isArray(color) && color.length === 3) {
- // TODO(mack): currently only supporting rgb; need support different
- // colorspaces
- data.color = color;
- } else {
- data.color = [0, 0, 0];
- }
-
- // Some types of annotations have border style dict which has more
- // info than the border array
- if (dict.has('BS')) {
- var borderStyle = dict.get('BS');
- data.borderWidth = borderStyle.has('W') ? borderStyle.get('W') : 1;
- } else {
- var borderArray = dict.get('Border') || [0, 0, 1];
- data.borderWidth = borderArray[2] || 0;
-
- // TODO: implement proper support for annotations with line dash patterns.
- var dashArray = borderArray[3];
- if (data.borderWidth > 0 && dashArray) {
- if (!isArray(dashArray)) {
- // Ignore the border if dashArray is not actually an array,
- // this is consistent with the behaviour in Adobe Reader.
- data.borderWidth = 0;
- } else {
- var dashArrayLength = dashArray.length;
- if (dashArrayLength > 0) {
- // According to the PDF specification: the elements in a dashArray
- // shall be numbers that are nonnegative and not all equal to zero.
- var isInvalid = false;
- var numPositive = 0;
- for (var i = 0; i < dashArrayLength; i++) {
- var validNumber = (+dashArray[i] >= 0);
- if (!validNumber) {
- isInvalid = true;
- break;
- } else if (dashArray[i] > 0) {
- numPositive++;
- }
- }
- if (isInvalid || numPositive === 0) {
- data.borderWidth = 0;
- }
- }
- }
- }
- }
-
- this.appearance = getDefaultAppearance(dict);
- data.hasAppearance = !!this.appearance;
- data.id = params.ref.num;
- }
-
- Annotation.prototype = {
-
- getData: function Annotation_getData() {
- return this.data;
- },
-
- hasHtml: function Annotation_hasHtml() {
- return false;
- },
-
- getHtmlElement: function Annotation_getHtmlElement(commonObjs) {
- throw new NotImplementedException(
- 'getHtmlElement() should be implemented in subclass');
- },
-
- // TODO(mack): Remove this, it's not really that helpful.
- getEmptyContainer: function Annotation_getEmptyContainer(tagName, rect,
- borderWidth) {
- assert(!isWorker,
- 'getEmptyContainer() should be called from main thread');
-
- var bWidth = borderWidth || 0;
-
- rect = rect || this.data.rect;
- var element = document.createElement(tagName);
- element.style.borderWidth = bWidth + 'px';
- var width = rect[2] - rect[0] - 2 * bWidth;
- var height = rect[3] - rect[1] - 2 * bWidth;
- element.style.width = width + 'px';
- element.style.height = height + 'px';
- return element;
- },
-
- isInvisible: function Annotation_isInvisible() {
- var data = this.data;
- if (data && SUPPORTED_TYPES.indexOf(data.subtype) !== -1) {
- return false;
- } else {
- return !!(data &&
- data.annotationFlags && // Default: not invisible
- data.annotationFlags & 0x1); // Invisible
- }
- },
-
- isViewable: function Annotation_isViewable() {
- var data = this.data;
- return !!(!this.isInvisible() &&
- data &&
- (!data.annotationFlags ||
- !(data.annotationFlags & 0x22)) && // Hidden or NoView
- data.rect); // rectangle is nessessary
- },
-
- isPrintable: function Annotation_isPrintable() {
- var data = this.data;
- return !!(!this.isInvisible() &&
- data &&
- data.annotationFlags && // Default: not printable
- data.annotationFlags & 0x4 && // Print
- data.rect); // rectangle is nessessary
- },
-
- loadResources: function Annotation_loadResources(keys) {
- return new Promise(function (resolve, reject) {
- this.appearance.dict.getAsync('Resources').then(function (resources) {
- if (!resources) {
- resolve();
- return;
- }
- var objectLoader = new ObjectLoader(resources.map,
- keys,
- resources.xref);
- objectLoader.load().then(function() {
- resolve(resources);
- }, reject);
- }, reject);
- }.bind(this));
- },
-
- getOperatorList: function Annotation_getOperatorList(evaluator) {
-
- if (!this.appearance) {
- return Promise.resolve(new OperatorList());
- }
-
- var data = this.data;
-
- var appearanceDict = this.appearance.dict;
- var resourcesPromise = this.loadResources([
- 'ExtGState',
- 'ColorSpace',
- 'Pattern',
- 'Shading',
- 'XObject',
- 'Font'
- // ProcSet
- // Properties
- ]);
- var bbox = appearanceDict.get('BBox') || [0, 0, 1, 1];
- var matrix = appearanceDict.get('Matrix') || [1, 0, 0, 1, 0 ,0];
- var transform = getTransformMatrix(data.rect, bbox, matrix);
- var self = this;
-
- return resourcesPromise.then(function(resources) {
- var opList = new OperatorList();
- opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
- return evaluator.getOperatorList(self.appearance, resources, opList).
- then(function () {
- opList.addOp(OPS.endAnnotation, []);
- self.appearance.reset();
- return opList;
- });
- });
- }
- };
-
- Annotation.getConstructor =
- function Annotation_getConstructor(subtype, fieldType) {
-
- if (!subtype) {
- return;
- }
-
- // TODO(mack): Implement FreeText annotations
- if (subtype === 'Link') {
- return LinkAnnotation;
- } else if (subtype === 'Text') {
- return TextAnnotation;
- } else if (subtype === 'Widget') {
- if (!fieldType) {
- return;
- }
-
- if (fieldType === 'Tx') {
- return TextWidgetAnnotation;
- } else {
- return WidgetAnnotation;
- }
- } else {
- return Annotation;
- }
- };
-
- // TODO(mack): Support loading annotation from data
- Annotation.fromData = function Annotation_fromData(data) {
- var subtype = data.subtype;
- var fieldType = data.fieldType;
- var Constructor = Annotation.getConstructor(subtype, fieldType);
- if (Constructor) {
- return new Constructor({ data: data });
- }
- };
-
- Annotation.fromRef = function Annotation_fromRef(xref, ref) {
-
- var dict = xref.fetchIfRef(ref);
- if (!isDict(dict)) {
- return;
- }
-
- var subtype = dict.get('Subtype');
- subtype = isName(subtype) ? subtype.name : '';
- if (!subtype) {
- return;
- }
-
- var fieldType = Util.getInheritableProperty(dict, 'FT');
- fieldType = isName(fieldType) ? fieldType.name : '';
-
- var Constructor = Annotation.getConstructor(subtype, fieldType);
- if (!Constructor) {
- return;
- }
-
- var params = {
- dict: dict,
- ref: ref,
- };
-
- var annotation = new Constructor(params);
-
- if (annotation.isViewable() || annotation.isPrintable()) {
- return annotation;
- } else {
- warn('unimplemented annotation type: ' + subtype);
- }
- };
-
- Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
- annotations, opList, pdfManager, partialEvaluator, intent) {
-
- function reject(e) {
- annotationsReadyCapability.reject(e);
- }
-
- var annotationsReadyCapability = createPromiseCapability();
-
- var annotationPromises = [];
- for (var i = 0, n = annotations.length; i < n; ++i) {
- if (intent === 'display' && annotations[i].isViewable() ||
- intent === 'print' && annotations[i].isPrintable()) {
- annotationPromises.push(
- annotations[i].getOperatorList(partialEvaluator));
- }
- }
- Promise.all(annotationPromises).then(function(datas) {
- opList.addOp(OPS.beginAnnotations, []);
- for (var i = 0, n = datas.length; i < n; ++i) {
- var annotOpList = datas[i];
- opList.addOpList(annotOpList);
- }
- opList.addOp(OPS.endAnnotations, []);
- annotationsReadyCapability.resolve();
- }, reject);
-
- return annotationsReadyCapability.promise;
- };
-
- return Annotation;
-})();
-PDFJS.Annotation = Annotation;
-
-
-var WidgetAnnotation = (function WidgetAnnotationClosure() {
-
- function WidgetAnnotation(params) {
- Annotation.call(this, params);
-
- if (params.data) {
- return;
- }
-
- var dict = params.dict;
- var data = this.data;
-
- data.fieldValue = stringToPDFString(
- Util.getInheritableProperty(dict, 'V') || '');
- data.alternativeText = stringToPDFString(dict.get('TU') || '');
- data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || '';
- var fieldType = Util.getInheritableProperty(dict, 'FT');
- data.fieldType = isName(fieldType) ? fieldType.name : '';
- data.fieldFlags = Util.getInheritableProperty(dict, 'Ff') || 0;
- this.fieldResources = Util.getInheritableProperty(dict, 'DR') || Dict.empty;
-
- // Building the full field name by collecting the field and
- // its ancestors 'T' data and joining them using '.'.
- var fieldName = [];
- var namedItem = dict;
- var ref = params.ref;
- while (namedItem) {
- var parent = namedItem.get('Parent');
- var parentRef = namedItem.getRaw('Parent');
- var name = namedItem.get('T');
- if (name) {
- fieldName.unshift(stringToPDFString(name));
- } else {
- // The field name is absent, that means more than one field
- // with the same name may exist. Replacing the empty name
- // with the '`' plus index in the parent's 'Kids' array.
- // This is not in the PDF spec but necessary to id the
- // the input controls.
- var kids = parent.get('Kids');
- var j, jj;
- for (j = 0, jj = kids.length; j < jj; j++) {
- var kidRef = kids[j];
- if (kidRef.num == ref.num && kidRef.gen == ref.gen) {
- break;
- }
- }
- fieldName.unshift('`' + j);
- }
- namedItem = parent;
- ref = parentRef;
- }
- data.fullName = fieldName.join('.');
- }
-
- var parent = Annotation.prototype;
- Util.inherit(WidgetAnnotation, Annotation, {
- isViewable: function WidgetAnnotation_isViewable() {
- if (this.data.fieldType === 'Sig') {
- warn('unimplemented annotation type: Widget signature');
- return false;
- }
-
- return parent.isViewable.call(this);
- }
- });
-
- return WidgetAnnotation;
-})();
-
-var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
- function TextWidgetAnnotation(params) {
- WidgetAnnotation.call(this, params);
-
- if (params.data) {
- return;
- }
-
- this.data.textAlignment = Util.getInheritableProperty(params.dict, 'Q');
- }
-
- // TODO(mack): This dupes some of the logic in CanvasGraphics.setFont()
- function setTextStyles(element, item, fontObj) {
-
- var style = element.style;
- style.fontSize = item.fontSize + 'px';
- style.direction = item.fontDirection < 0 ? 'rtl': 'ltr';
-
- if (!fontObj) {
- return;
- }
-
- style.fontWeight = fontObj.black ?
- (fontObj.bold ? 'bolder' : 'bold') :
- (fontObj.bold ? 'bold' : 'normal');
- style.fontStyle = fontObj.italic ? 'italic' : 'normal';
-
- var fontName = fontObj.loadedName;
- var fontFamily = fontName ? '"' + fontName + '", ' : '';
- // Use a reasonable default font if the font doesn't specify a fallback
- var fallbackName = fontObj.fallbackName || 'Helvetica, sans-serif';
- style.fontFamily = fontFamily + fallbackName;
- }
-
-
- Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {
- hasHtml: function TextWidgetAnnotation_hasHtml() {
- return !this.data.hasAppearance && !!this.data.fieldValue;
- },
-
- getHtmlElement: function TextWidgetAnnotation_getHtmlElement(commonObjs) {
- assert(!isWorker, 'getHtmlElement() shall be called from main thread');
-
- var item = this.data;
-
- var element = this.getEmptyContainer('div');
- element.style.display = 'table';
-
- var content = document.createElement('div');
- content.textContent = item.fieldValue;
- var textAlignment = item.textAlignment;
- content.style.textAlign = ['left', 'center', 'right'][textAlignment];
- content.style.verticalAlign = 'middle';
- content.style.display = 'table-cell';
-
- var fontObj = item.fontRefName ?
- commonObjs.getData(item.fontRefName) : null;
- setTextStyles(content, item, fontObj);
-
- element.appendChild(content);
-
- return element;
- },
-
- getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) {
- if (this.appearance) {
- return Annotation.prototype.getOperatorList.call(this, evaluator);
- }
-
- var opList = new OperatorList();
- var data = this.data;
-
- // Even if there is an appearance stream, ignore it. This is the
- // behaviour used by Adobe Reader.
- if (!data.defaultAppearance) {
- return Promise.resolve(opList);
- }
-
- var stream = new Stream(stringToBytes(data.defaultAppearance));
- return evaluator.getOperatorList(stream, this.fieldResources, opList).
- then(function () {
- return opList;
- });
- }
- });
-
- return TextWidgetAnnotation;
-})();
-
-var InteractiveAnnotation = (function InteractiveAnnotationClosure() {
- function InteractiveAnnotation(params) {
- Annotation.call(this, params);
- }
-
- Util.inherit(InteractiveAnnotation, Annotation, {
- hasHtml: function InteractiveAnnotation_hasHtml() {
- return true;
- },
-
- highlight: function InteractiveAnnotation_highlight() {
- if (this.highlightElement &&
- this.highlightElement.hasAttribute('hidden')) {
- this.highlightElement.removeAttribute('hidden');
- }
- },
-
- unhighlight: function InteractiveAnnotation_unhighlight() {
- if (this.highlightElement &&
- !this.highlightElement.hasAttribute('hidden')) {
- this.highlightElement.setAttribute('hidden', true);
- }
- },
-
- initContainer: function InteractiveAnnotation_initContainer() {
-
- var item = this.data;
- var rect = item.rect;
-
- var container = this.getEmptyContainer('section', rect, item.borderWidth);
- container.style.backgroundColor = item.color;
-
- var color = item.color;
- var rgb = [];
- for (var i = 0; i < 3; ++i) {
- rgb[i] = Math.round(color[i] * 255);
- }
- item.colorCssRgb = Util.makeCssRgb(rgb);
-
- var highlight = document.createElement('div');
- highlight.className = 'annotationHighlight';
- highlight.style.left = highlight.style.top = -HIGHLIGHT_OFFSET + 'px';
- highlight.style.right = highlight.style.bottom = -HIGHLIGHT_OFFSET + 'px';
- highlight.setAttribute('hidden', true);
-
- this.highlightElement = highlight;
- container.appendChild(this.highlightElement);
-
- return container;
- }
- });
-
- return InteractiveAnnotation;
-})();
-
-var TextAnnotation = (function TextAnnotationClosure() {
- function TextAnnotation(params) {
- InteractiveAnnotation.call(this, params);
-
- if (params.data) {
- return;
- }
-
- var dict = params.dict;
- var data = this.data;
-
- var content = dict.get('Contents');
- var title = dict.get('T');
- data.content = stringToPDFString(content || '');
- data.title = stringToPDFString(title || '');
-
- if (data.hasAppearance) {
- data.name = 'NoIcon';
- } else {
- data.rect[1] = data.rect[3] - DEFAULT_ICON_SIZE;
- data.rect[2] = data.rect[0] + DEFAULT_ICON_SIZE;
- data.name = dict.has('Name') ? dict.get('Name').name : 'Note';
- }
-
- if (dict.has('C')) {
- data.hasBgColor = true;
- }
- }
-
- var ANNOT_MIN_SIZE = 10;
-
- Util.inherit(TextAnnotation, InteractiveAnnotation, {
-
- getHtmlElement: function TextAnnotation_getHtmlElement(commonObjs) {
- assert(!isWorker, 'getHtmlElement() shall be called from main thread');
-
- var item = this.data;
- var rect = item.rect;
-
- // sanity check because of OOo-generated PDFs
- if ((rect[3] - rect[1]) < ANNOT_MIN_SIZE) {
- rect[3] = rect[1] + ANNOT_MIN_SIZE;
- }
- if ((rect[2] - rect[0]) < ANNOT_MIN_SIZE) {
- rect[2] = rect[0] + (rect[3] - rect[1]); // make it square
- }
-
- var container = this.initContainer();
- container.className = 'annotText';
-
- var image = document.createElement('img');
- image.style.height = container.style.height;
- image.style.width = container.style.width;
- var iconName = item.name;
- image.src = PDFJS.imageResourcesPath + 'annotation-' +
- iconName.toLowerCase() + '.svg';
- image.alt = '[{{type}} Annotation]';
- image.dataset.l10nId = 'text_annotation_type';
- image.dataset.l10nArgs = JSON.stringify({type: iconName});
-
- var contentWrapper = document.createElement('div');
- contentWrapper.className = 'annotTextContentWrapper';
- contentWrapper.style.left = Math.floor(rect[2] - rect[0] + 5) + 'px';
- contentWrapper.style.top = '-10px';
-
- var content = document.createElement('div');
- content.className = 'annotTextContent';
- content.setAttribute('hidden', true);
-
- var i, ii;
- if (item.hasBgColor) {
- var color = item.color;
- var rgb = [];
- for (i = 0; i < 3; ++i) {
- // Enlighten the color (70%)
- var c = Math.round(color[i] * 255);
- rgb[i] = Math.round((255 - c) * 0.7) + c;
- }
- content.style.backgroundColor = Util.makeCssRgb(rgb);
- }
-
- var title = document.createElement('h1');
- var text = document.createElement('p');
- title.textContent = item.title;
-
- if (!item.content && !item.title) {
- content.setAttribute('hidden', true);
- } else {
- var e = document.createElement('span');
- var lines = item.content.split(/(?:\r\n?|\n)/);
- for (i = 0, ii = lines.length; i < ii; ++i) {
- var line = lines[i];
- e.appendChild(document.createTextNode(line));
- if (i < (ii - 1)) {
- e.appendChild(document.createElement('br'));
- }
- }
- text.appendChild(e);
-
- var pinned = false;
-
- var showAnnotation = function showAnnotation(pin) {
- if (pin) {
- pinned = true;
- }
- if (content.hasAttribute('hidden')) {
- container.style.zIndex += 1;
- content.removeAttribute('hidden');
- }
- };
-
- var hideAnnotation = function hideAnnotation(unpin) {
- if (unpin) {
- pinned = false;
- }
- if (!content.hasAttribute('hidden') && !pinned) {
- container.style.zIndex -= 1;
- content.setAttribute('hidden', true);
- }
- };
-
- var toggleAnnotation = function toggleAnnotation() {
- if (pinned) {
- hideAnnotation(true);
- } else {
- showAnnotation(true);
- }
- };
-
- image.addEventListener('click', function image_clickHandler() {
- toggleAnnotation();
- }, false);
- image.addEventListener('mouseover', function image_mouseOverHandler() {
- showAnnotation();
- }, false);
- image.addEventListener('mouseout', function image_mouseOutHandler() {
- hideAnnotation();
- }, false);
-
- content.addEventListener('click', function content_clickHandler() {
- hideAnnotation(true);
- }, false);
- }
-
- content.appendChild(title);
- content.appendChild(text);
- contentWrapper.appendChild(content);
- container.appendChild(image);
- container.appendChild(contentWrapper);
-
- return container;
- }
- });
-
- return TextAnnotation;
-})();
-
-var LinkAnnotation = (function LinkAnnotationClosure() {
- function LinkAnnotation(params) {
- InteractiveAnnotation.call(this, params);
-
- if (params.data) {
- return;
- }
-
- var dict = params.dict;
- var data = this.data;
-
- var action = dict.get('A');
- if (action) {
- var linkType = action.get('S').name;
- if (linkType === 'URI') {
- var url = action.get('URI');
- if (isName(url)) {
- // Some bad PDFs do not put parentheses around relative URLs.
- url = '/' + url.name;
- } else if (url) {
- url = addDefaultProtocolToUrl(url);
- }
- // TODO: pdf spec mentions urls can be relative to a Base
- // entry in the dictionary.
- if (!isValidUrl(url, false)) {
- url = '';
- }
- data.url = url;
- } else if (linkType === 'GoTo') {
- data.dest = action.get('D');
- } else if (linkType === 'GoToR') {
- var urlDict = action.get('F');
- if (isDict(urlDict)) {
- // We assume that the 'url' is a Filspec dictionary
- // and fetch the url without checking any further
- url = urlDict.get('F') || '';
- }
-
- // TODO: pdf reference says that GoToR
- // can also have 'NewWindow' attribute
- if (!isValidUrl(url, false)) {
- url = '';
- }
- data.url = url;
- data.dest = action.get('D');
- } else if (linkType === 'Named') {
- data.action = action.get('N').name;
- } else {
- warn('unrecognized link type: ' + linkType);
- }
- } else if (dict.has('Dest')) {
- // simple destination link
- var dest = dict.get('Dest');
- data.dest = isName(dest) ? dest.name : dest;
- }
- }
-
- // Lets URLs beginning with 'www.' default to using the 'http://' protocol.
- function addDefaultProtocolToUrl(url) {
- if (url && url.indexOf('www.') === 0) {
- return ('http://' + url);
- }
- return url;
- }
-
- Util.inherit(LinkAnnotation, InteractiveAnnotation, {
- hasOperatorList: function LinkAnnotation_hasOperatorList() {
- return false;
- },
-
- getHtmlElement: function LinkAnnotation_getHtmlElement(commonObjs) {
-
- var container = this.initContainer();
- container.className = 'annotLink';
-
- var item = this.data;
-
- container.style.borderColor = item.colorCssRgb;
- container.style.borderStyle = 'solid';
-
- var link = document.createElement('a');
- link.href = link.title = this.data.url || '';
-
- container.appendChild(link);
-
- return container;
- }
- });
-
- return LinkAnnotation;
-})();
-
-
-/**
- * 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);
-
-/**
- * Seting request method will change http requests of pdf file.
- * Possible values are ('GET','POST','PUT','HEAD','DELETE')
- * getDocument method will use this requet method
- */
-PDFJS.requestMethod = (PDFJS.requestMethod === undefined ?
- 'GET' : PDFJS.requestMethod);
-
-/**
- * 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.
- * @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);
-
-/**
- * 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);
-
-/**
- * Document initialization / loading parameters object.
- *
- * @typedef {Object} DocumentInitParameters
- * @property {string} url - The URL of the PDF.
- * @property {TypedArray} data - A typed array with PDF data.
- * @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.
- */
-
-/**
- * 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} source Can be a url to
- * where a PDF is located, a typed array (Uint8Array) already populated with
- * data or parameter object.
- *
- * @param {Object} pdfDataRangeTransport is optional. It is used if you want
- * to manually serve range requests for data in the PDF. See viewer.js for
- * an example of pdfDataRangeTransport's interface.
- *
- * @param {function} passwordCallback is optional. 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}).
- *
- * @return {Promise} A promise that is resolved with {@link PDFDocumentProxy}
- * object.
- */
-PDFJS.getDocument = function getDocument(source,
- pdfDataRangeTransport,
- passwordCallback,
- progressCallback, listeners) {
- var workerInitializedCapability, workerReadyCapability, transport;
-
- if (typeof source === 'string') {
- source = { url: source };
- } else if (isArrayBuffer(source)) {
- source = { data: source };
- } else if (typeof source !== 'object') {
- error('Invalid parameter in getDocument, need either Uint8Array, ' +
- 'string or a parameter object');
- }
-
- if (!source.url && !source.data) {
- error('Invalid parameter array, need either .data or .url');
- }
-
- // copy/use all keys as is except 'url' -- full path is required
- var params = {};
- for (var key in source) {
- if (key === 'url' && typeof window !== 'undefined') {
- params[key] = combineUrl(window.location.href, source[key]);
- continue;
- }
- params[key] = source[key];
- }
-
- workerInitializedCapability = createPromiseCapability();
- workerReadyCapability = createPromiseCapability();
- transport = new WorkerTransport(workerInitializedCapability,
- workerReadyCapability, pdfDataRangeTransport,
- progressCallback, listeners);
- workerInitializedCapability.promise.then(function transportInitialized() {
- transport.passwordCallback = passwordCallback;
- transport.fetchDocument(params);
- });
- return workerReadyCapability.promise;
-};
-
-/**
- * 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.
- */
- getDestinations: function PDFDocumentProxy_getDestinations() {
- return this.transport.getDestinations();
- },
- /**
- * @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;
- },
- /**
- * 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 - (optional) 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.
- */
-
-/**
- * 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 = ('intent' in params ?
- (params.intent == 'print' ? 'print' : 'display') : '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 = new RenderTask(internalRenderTask);
-
- 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} 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];
- 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, workerReadyCapability,
- pdfDataRangeTransport, progressCallback, listeners) {
- this.pdfDataRangeTransport = pdfDataRangeTransport;
-
- this.workerReadyCapability = workerReadyCapability;
- this.progressCallback = progressCallback;
- this.commonObjs = new PDFObjects();
-
- this.pageCache = [];
- this.pagePromises = [];
- this.downloadInfoCapability = createPromiseCapability();
- this.passwordCallback = null;
- this.listeners = listeners || {};
-
- // 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 (!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 {
- globalScope.PDFJS.disableWorker = true;
- this.loadFakeWorkerFiles().then(function() {
- this.setupFakeWorker();
- workerInitializedCapability.resolve();
- }.bind(this));
- }
- }.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.');
- }
- }
- // Either workers are disabled, not supported or have thrown an exception.
- // Thus, we fallback to a faked worker.
- globalScope.PDFJS.disableWorker = true;
- this.loadFakeWorkerFiles().then(function() {
- this.setupFakeWorker();
- workerInitializedCapability.resolve();
- }.bind(this));
- }
- 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();
- }
- });
- },
-
- loadFakeWorkerFiles: function WorkerTransport_loadFakeWorkerFiles() {
- 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.
- Util.loadScript(PDFJS.workerSrc, function() {
- PDFJS.fakeWorkerFilesLoadedCapability.resolve();
- });
- }
- return PDFJS.fakeWorkerFilesLoadedCapability.promise;
- },
-
- setupFakeWorker: function WorkerTransport_setupFakeWorker() {
- 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);
- },
-
- 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
- });
- });
-
- messageHandler.on('RequestDataRange',
- function transportDataRange(data) {
- pdfDataRangeTransport.requestDataRange(data.begin, data.end);
- }, this);
- }
-
- var listeners = this.listeners;
- messageHandler.on('headersReceived', function headersReceived(obj)
- {
- if(typeof listeners.onHeadersReceived == 'function')
- listeners.onHeadersReceived(obj);
- });
-
- 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.workerReadyCapability.resolve(pdfDocument);
- }, this);
-
- messageHandler.on('NeedPassword', function transportPassword(data) {
- if (this.passwordCallback) {
- return this.passwordCallback(updatePassword,
- PasswordResponses.NEED_PASSWORD);
- }
- this.workerReadyCapability.reject(data.exception.message,
- data.exception);
- }, this);
-
- messageHandler.on('IncorrectPassword', function transportBadPass(data) {
- if (this.passwordCallback) {
- return this.passwordCallback(updatePassword,
- PasswordResponses.INCORRECT_PASSWORD);
- }
- this.workerReadyCapability.reject(data.exception.message,
- data.exception);
- }, this);
-
- messageHandler.on('InvalidPDF', function transportInvalidPDF(data) {
- this.workerReadyCapability.reject(data.exception.name, data.exception);
- }, this);
-
- messageHandler.on('MissingPDF', function transportMissingPDF(data) {
- this.workerReadyCapability.reject(data.exception.message,
- data.exception);
- }, this);
-
- messageHandler.on('UnknownError', function transportUnknownError(data) {
- this.workerReadyCapability.reject(data.exception.message,
- data.exception);
- }, this);
-
- messageHandler.on('DataLoaded', function transportPage(data) {
- this.downloadInfoCapability.resolve(data);
- }, 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 FontFace(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) {
- if (this.progressCallback) {
- this.progressCallback({
- loaded: data.loaded,
- total: data.total
- });
- }
- }, this);
-
- messageHandler.on('DocError', function transportDocError(data) {
- this.workerReadyCapability.reject(data);
- }, this);
-
- messageHandler.on('PageError', function transportError(data) {
- var page = this.pageCache[data.pageNum - 1];
- var intentState = page.intentStates[data.intent];
- if (intentState.displayReadyCapability.promise) {
- 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(source) {
- source.disableAutoFetch = PDFJS.disableAutoFetch;
- source.chunkedViewerLoading = !!this.pdfDataRangeTransport;
- source.requestMethod = PDFJS.requestMethod;
- 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);
- },
-
- 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)
- };
- });
- },
-
- 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;
- /**
- * Promise for rendering task completion.
- * @type {Promise}
- */
- this.promise = this.internalRenderTask.capability.promise;
- }
-
- RenderTask.prototype = /** @lends RenderTask.prototype */ {
- /**
- * 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 callback 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(onFulfilled, onRejected);
- }
- };
-
- 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();
- // 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.params.continueCallback) {
- this.params.continueCallback(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;
-})();
-
-
-//