almost finished
@ -0,0 +1,577 @@
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
/* Copyright 2012 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/* globals VBArray, PDFJS */
|
||||
|
||||
'use strict';
|
||||
|
||||
// Initializing PDFJS global object here, it case if we need to change/disable
|
||||
// some PDF.js features, e.g. range requests
|
||||
if (typeof PDFJS === 'undefined') {
|
||||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
// Checking if the typed arrays are supported
|
||||
// Support: iOS<6.0 (subarray), IE<10, Android<4.0
|
||||
(function checkTypedArrayCompatibility() {
|
||||
if (typeof Uint8Array !== 'undefined') {
|
||||
// Support: iOS<6.0
|
||||
if (typeof Uint8Array.prototype.subarray === 'undefined') {
|
||||
Uint8Array.prototype.subarray = function subarray(start, end) {
|
||||
return new Uint8Array(this.slice(start, end));
|
||||
};
|
||||
Float32Array.prototype.subarray = function subarray(start, end) {
|
||||
return new Float32Array(this.slice(start, end));
|
||||
};
|
||||
}
|
||||
|
||||
// Support: Android<4.1
|
||||
if (typeof Float64Array === 'undefined') {
|
||||
window.Float64Array = Float32Array;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function subarray(start, end) {
|
||||
return new TypedArray(this.slice(start, end));
|
||||
}
|
||||
|
||||
function setArrayOffset(array, offset) {
|
||||
if (arguments.length < 2) {
|
||||
offset = 0;
|
||||
}
|
||||
for (var i = 0, n = array.length; i < n; ++i, ++offset) {
|
||||
this[offset] = array[i] & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
function TypedArray(arg1) {
|
||||
var result, i, n;
|
||||
if (typeof arg1 === 'number') {
|
||||
result = [];
|
||||
for (i = 0; i < arg1; ++i) {
|
||||
result[i] = 0;
|
||||
}
|
||||
} else if ('slice' in arg1) {
|
||||
result = arg1.slice(0);
|
||||
} else {
|
||||
result = [];
|
||||
for (i = 0, n = arg1.length; i < n; ++i) {
|
||||
result[i] = arg1[i];
|
||||
}
|
||||
}
|
||||
|
||||
result.subarray = subarray;
|
||||
result.buffer = result;
|
||||
result.byteLength = result.length;
|
||||
result.set = setArrayOffset;
|
||||
|
||||
if (typeof arg1 === 'object' && arg1.buffer) {
|
||||
result.buffer = arg1.buffer;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
window.Uint8Array = TypedArray;
|
||||
window.Int8Array = TypedArray;
|
||||
|
||||
// we don't need support for set, byteLength for 32-bit array
|
||||
// so we can use the TypedArray as well
|
||||
window.Uint32Array = TypedArray;
|
||||
window.Int32Array = TypedArray;
|
||||
window.Uint16Array = TypedArray;
|
||||
window.Float32Array = TypedArray;
|
||||
window.Float64Array = TypedArray;
|
||||
})();
|
||||
|
||||
// URL = URL || webkitURL
|
||||
// Support: Safari<7, Android 4.2+
|
||||
(function normalizeURLObject() {
|
||||
if (!window.URL) {
|
||||
window.URL = window.webkitURL;
|
||||
}
|
||||
})();
|
||||
|
||||
// Object.defineProperty()?
|
||||
// Support: Android<4.0, Safari<5.1
|
||||
(function checkObjectDefinePropertyCompatibility() {
|
||||
if (typeof Object.defineProperty !== 'undefined') {
|
||||
var definePropertyPossible = true;
|
||||
try {
|
||||
// some browsers (e.g. safari) cannot use defineProperty() on DOM objects
|
||||
// and thus the native version is not sufficient
|
||||
Object.defineProperty(new Image(), 'id', { value: 'test' });
|
||||
// ... another test for android gb browser for non-DOM objects
|
||||
var Test = function Test() {};
|
||||
Test.prototype = { get id() { } };
|
||||
Object.defineProperty(new Test(), 'id',
|
||||
{ value: '', configurable: true, enumerable: true, writable: false });
|
||||
} catch (e) {
|
||||
definePropertyPossible = false;
|
||||
}
|
||||
if (definePropertyPossible) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty = function objectDefineProperty(obj, name, def) {
|
||||
delete obj[name];
|
||||
if ('get' in def) {
|
||||
obj.__defineGetter__(name, def['get']);
|
||||
}
|
||||
if ('set' in def) {
|
||||
obj.__defineSetter__(name, def['set']);
|
||||
}
|
||||
if ('value' in def) {
|
||||
obj.__defineSetter__(name, function objectDefinePropertySetter(value) {
|
||||
this.__defineGetter__(name, function objectDefinePropertyGetter() {
|
||||
return value;
|
||||
});
|
||||
return value;
|
||||
});
|
||||
obj[name] = def.value;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
// No XMLHttpRequest#response?
|
||||
// Support: IE<11, Android <4.0
|
||||
(function checkXMLHttpRequestResponseCompatibility() {
|
||||
var xhrPrototype = XMLHttpRequest.prototype;
|
||||
var xhr = new XMLHttpRequest();
|
||||
if (!('overrideMimeType' in xhr)) {
|
||||
// IE10 might have response, but not overrideMimeType
|
||||
// Support: IE10
|
||||
Object.defineProperty(xhrPrototype, 'overrideMimeType', {
|
||||
value: function xmlHttpRequestOverrideMimeType(mimeType) {}
|
||||
});
|
||||
}
|
||||
if ('responseType' in xhr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The worker will be using XHR, so we can save time and disable worker.
|
||||
PDFJS.disableWorker = true;
|
||||
|
||||
Object.defineProperty(xhrPrototype, 'responseType', {
|
||||
get: function xmlHttpRequestGetResponseType() {
|
||||
return this._responseType || 'text';
|
||||
},
|
||||
set: function xmlHttpRequestSetResponseType(value) {
|
||||
if (value === 'text' || value === 'arraybuffer') {
|
||||
this._responseType = value;
|
||||
if (value === 'arraybuffer' &&
|
||||
typeof this.overrideMimeType === 'function') {
|
||||
this.overrideMimeType('text/plain; charset=x-user-defined');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Support: IE9
|
||||
if (typeof VBArray !== 'undefined') {
|
||||
Object.defineProperty(xhrPrototype, 'response', {
|
||||
get: function xmlHttpRequestResponseGet() {
|
||||
if (this.responseType === 'arraybuffer') {
|
||||
return new Uint8Array(new VBArray(this.responseBody).toArray());
|
||||
} else {
|
||||
return this.responseText;
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
Object.defineProperty(xhrPrototype, 'response', {
|
||||
get: function xmlHttpRequestResponseGet() {
|
||||
if (this.responseType !== 'arraybuffer') {
|
||||
return this.responseText;
|
||||
}
|
||||
var text = this.responseText;
|
||||
var i, n = text.length;
|
||||
var result = new Uint8Array(n);
|
||||
for (i = 0; i < n; ++i) {
|
||||
result[i] = text.charCodeAt(i) & 0xFF;
|
||||
}
|
||||
return result.buffer;
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
// window.btoa (base64 encode function) ?
|
||||
// Support: IE<10
|
||||
(function checkWindowBtoaCompatibility() {
|
||||
if ('btoa' in window) {
|
||||
return;
|
||||
}
|
||||
|
||||
var digits =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
|
||||
window.btoa = function windowBtoa(chars) {
|
||||
var buffer = '';
|
||||
var i, n;
|
||||
for (i = 0, n = chars.length; i < n; i += 3) {
|
||||
var b1 = chars.charCodeAt(i) & 0xFF;
|
||||
var b2 = chars.charCodeAt(i + 1) & 0xFF;
|
||||
var b3 = chars.charCodeAt(i + 2) & 0xFF;
|
||||
var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
|
||||
var d3 = i + 1 < n ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
|
||||
var d4 = i + 2 < n ? (b3 & 0x3F) : 64;
|
||||
buffer += (digits.charAt(d1) + digits.charAt(d2) +
|
||||
digits.charAt(d3) + digits.charAt(d4));
|
||||
}
|
||||
return buffer;
|
||||
};
|
||||
})();
|
||||
|
||||
// window.atob (base64 encode function)?
|
||||
// Support: IE<10
|
||||
(function checkWindowAtobCompatibility() {
|
||||
if ('atob' in window) {
|
||||
return;
|
||||
}
|
||||
|
||||
// https://github.com/davidchambers/Base64.js
|
||||
var digits =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
window.atob = function (input) {
|
||||
input = input.replace(/=+$/, '');
|
||||
if (input.length % 4 === 1) {
|
||||
throw new Error('bad atob input');
|
||||
}
|
||||
for (
|
||||
// initialize result and counters
|
||||
var bc = 0, bs, buffer, idx = 0, output = '';
|
||||
// get next character
|
||||
buffer = input.charAt(idx++);
|
||||
// character found in table?
|
||||
// initialize bit storage and add its ascii value
|
||||
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
|
||||
// and if not first of each 4 characters,
|
||||
// convert the first 8 bits to one ascii character
|
||||
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
|
||||
) {
|
||||
// try to find character in table (0-63, not found => -1)
|
||||
buffer = digits.indexOf(buffer);
|
||||
}
|
||||
return output;
|
||||
};
|
||||
})();
|
||||
|
||||
// Function.prototype.bind?
|
||||
// Support: Android<4.0, iOS<6.0
|
||||
(function checkFunctionPrototypeBindCompatibility() {
|
||||
if (typeof Function.prototype.bind !== 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
Function.prototype.bind = function functionPrototypeBind(obj) {
|
||||
var fn = this, headArgs = Array.prototype.slice.call(arguments, 1);
|
||||
var bound = function functionPrototypeBindBound() {
|
||||
var args = headArgs.concat(Array.prototype.slice.call(arguments));
|
||||
return fn.apply(obj, args);
|
||||
};
|
||||
return bound;
|
||||
};
|
||||
})();
|
||||
|
||||
// HTMLElement dataset property
|
||||
// Support: IE<11, Safari<5.1, Android<4.0
|
||||
(function checkDatasetProperty() {
|
||||
var div = document.createElement('div');
|
||||
if ('dataset' in div) {
|
||||
return; // dataset property exists
|
||||
}
|
||||
|
||||
Object.defineProperty(HTMLElement.prototype, 'dataset', {
|
||||
get: function() {
|
||||
if (this._dataset) {
|
||||
return this._dataset;
|
||||
}
|
||||
|
||||
var dataset = {};
|
||||
for (var j = 0, jj = this.attributes.length; j < jj; j++) {
|
||||
var attribute = this.attributes[j];
|
||||
if (attribute.name.substring(0, 5) !== 'data-') {
|
||||
continue;
|
||||
}
|
||||
var key = attribute.name.substring(5).replace(/\-([a-z])/g,
|
||||
function(all, ch) {
|
||||
return ch.toUpperCase();
|
||||
});
|
||||
dataset[key] = attribute.value;
|
||||
}
|
||||
|
||||
Object.defineProperty(this, '_dataset', {
|
||||
value: dataset,
|
||||
writable: false,
|
||||
enumerable: false
|
||||
});
|
||||
return dataset;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
})();
|
||||
|
||||
// HTMLElement classList property
|
||||
// Support: IE<10, Android<4.0, iOS<5.0
|
||||
(function checkClassListProperty() {
|
||||
var div = document.createElement('div');
|
||||
if ('classList' in div) {
|
||||
return; // classList property exists
|
||||
}
|
||||
|
||||
function changeList(element, itemName, add, remove) {
|
||||
var s = element.className || '';
|
||||
var list = s.split(/\s+/g);
|
||||
if (list[0] === '') {
|
||||
list.shift();
|
||||
}
|
||||
var index = list.indexOf(itemName);
|
||||
if (index < 0 && add) {
|
||||
list.push(itemName);
|
||||
}
|
||||
if (index >= 0 && remove) {
|
||||
list.splice(index, 1);
|
||||
}
|
||||
element.className = list.join(' ');
|
||||
return (index >= 0);
|
||||
}
|
||||
|
||||
var classListPrototype = {
|
||||
add: function(name) {
|
||||
changeList(this.element, name, true, false);
|
||||
},
|
||||
contains: function(name) {
|
||||
return changeList(this.element, name, false, false);
|
||||
},
|
||||
remove: function(name) {
|
||||
changeList(this.element, name, false, true);
|
||||
},
|
||||
toggle: function(name) {
|
||||
changeList(this.element, name, true, true);
|
||||
}
|
||||
};
|
||||
|
||||
Object.defineProperty(HTMLElement.prototype, 'classList', {
|
||||
get: function() {
|
||||
if (this._classList) {
|
||||
return this._classList;
|
||||
}
|
||||
|
||||
var classList = Object.create(classListPrototype, {
|
||||
element: {
|
||||
value: this,
|
||||
writable: false,
|
||||
enumerable: true
|
||||
}
|
||||
});
|
||||
Object.defineProperty(this, '_classList', {
|
||||
value: classList,
|
||||
writable: false,
|
||||
enumerable: false
|
||||
});
|
||||
return classList;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
})();
|
||||
|
||||
// Check console compatibility
|
||||
// In older IE versions the console object is not available
|
||||
// unless console is open.
|
||||
// Support: IE<10
|
||||
(function checkConsoleCompatibility() {
|
||||
if (!('console' in window)) {
|
||||
window.console = {
|
||||
log: function() {},
|
||||
error: function() {},
|
||||
warn: function() {}
|
||||
};
|
||||
} else if (!('bind' in console.log)) {
|
||||
// native functions in IE9 might not have bind
|
||||
console.log = (function(fn) {
|
||||
return function(msg) { return fn(msg); };
|
||||
})(console.log);
|
||||
console.error = (function(fn) {
|
||||
return function(msg) { return fn(msg); };
|
||||
})(console.error);
|
||||
console.warn = (function(fn) {
|
||||
return function(msg) { return fn(msg); };
|
||||
})(console.warn);
|
||||
}
|
||||
})();
|
||||
|
||||
// Check onclick compatibility in Opera
|
||||
// Support: Opera<15
|
||||
(function checkOnClickCompatibility() {
|
||||
// workaround for reported Opera bug DSK-354448:
|
||||
// onclick fires on disabled buttons with opaque content
|
||||
function ignoreIfTargetDisabled(event) {
|
||||
if (isDisabled(event.target)) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
function isDisabled(node) {
|
||||
return node.disabled || (node.parentNode && isDisabled(node.parentNode));
|
||||
}
|
||||
if (navigator.userAgent.indexOf('Opera') !== -1) {
|
||||
// use browser detection since we cannot feature-check this bug
|
||||
document.addEventListener('click', ignoreIfTargetDisabled, true);
|
||||
}
|
||||
})();
|
||||
|
||||
// Checks if possible to use URL.createObjectURL()
|
||||
// Support: IE
|
||||
(function checkOnBlobSupport() {
|
||||
// sometimes IE loosing the data created with createObjectURL(), see #3977
|
||||
if (navigator.userAgent.indexOf('Trident') >= 0) {
|
||||
PDFJS.disableCreateObjectURL = true;
|
||||
}
|
||||
})();
|
||||
|
||||
// Checks if navigator.language is supported
|
||||
(function checkNavigatorLanguage() {
|
||||
if ('language' in navigator) {
|
||||
return;
|
||||
}
|
||||
PDFJS.locale = navigator.userLanguage || 'en-US';
|
||||
})();
|
||||
|
||||
(function checkRangeRequests() {
|
||||
// Safari has issues with cached range requests see:
|
||||
// https://github.com/mozilla/pdf.js/issues/3260
|
||||
// Last tested with version 6.0.4.
|
||||
// Support: Safari 6.0+
|
||||
var isSafari = Object.prototype.toString.call(
|
||||
window.HTMLElement).indexOf('Constructor') > 0;
|
||||
|
||||
// Older versions of Android (pre 3.0) has issues with range requests, see:
|
||||
// https://github.com/mozilla/pdf.js/issues/3381.
|
||||
// Make sure that we only match webkit-based Android browsers,
|
||||
// since Firefox/Fennec works as expected.
|
||||
// Support: Android<3.0
|
||||
var regex = /Android\s[0-2][^\d]/;
|
||||
var isOldAndroid = regex.test(navigator.userAgent);
|
||||
|
||||
// Range requests are broken in Chrome 39 and 40, https://crbug.com/442318
|
||||
var isChromeWithRangeBug = /Chrome\/(39|40)\./.test(navigator.userAgent);
|
||||
|
||||
if (isSafari || isOldAndroid || isChromeWithRangeBug) {
|
||||
PDFJS.disableRange = true;
|
||||
PDFJS.disableStream = true;
|
||||
}
|
||||
})();
|
||||
|
||||
// Check if the browser supports manipulation of the history.
|
||||
// Support: IE<10, Android<4.2
|
||||
(function checkHistoryManipulation() {
|
||||
// Android 2.x has so buggy pushState support that it was removed in
|
||||
// Android 3.0 and restored as late as in Android 4.2.
|
||||
// Support: Android 2.x
|
||||
if (!history.pushState || navigator.userAgent.indexOf('Android 2.') >= 0) {
|
||||
PDFJS.disableHistory = true;
|
||||
}
|
||||
})();
|
||||
|
||||
// Support: IE<11, Chrome<21, Android<4.4, Safari<6
|
||||
(function checkSetPresenceInImageData() {
|
||||
// IE < 11 will use window.CanvasPixelArray which lacks set function.
|
||||
if (window.CanvasPixelArray) {
|
||||
if (typeof window.CanvasPixelArray.prototype.set !== 'function') {
|
||||
window.CanvasPixelArray.prototype.set = function(arr) {
|
||||
for (var i = 0, ii = this.length; i < ii; i++) {
|
||||
this[i] = arr[i];
|
||||
}
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// Old Chrome and Android use an inaccessible CanvasPixelArray prototype.
|
||||
// Because we cannot feature detect it, we rely on user agent parsing.
|
||||
var polyfill = false, versionMatch;
|
||||
if (navigator.userAgent.indexOf('Chrom') >= 0) {
|
||||
versionMatch = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
|
||||
// Chrome < 21 lacks the set function.
|
||||
polyfill = versionMatch && parseInt(versionMatch[2]) < 21;
|
||||
} else if (navigator.userAgent.indexOf('Android') >= 0) {
|
||||
// Android < 4.4 lacks the set function.
|
||||
// Android >= 4.4 will contain Chrome in the user agent,
|
||||
// thus pass the Chrome check above and not reach this block.
|
||||
polyfill = /Android\s[0-4][^\d]/g.test(navigator.userAgent);
|
||||
} else if (navigator.userAgent.indexOf('Safari') >= 0) {
|
||||
versionMatch = navigator.userAgent.
|
||||
match(/Version\/([0-9]+)\.([0-9]+)\.([0-9]+) Safari\//);
|
||||
// Safari < 6 lacks the set function.
|
||||
polyfill = versionMatch && parseInt(versionMatch[1]) < 6;
|
||||
}
|
||||
|
||||
if (polyfill) {
|
||||
var contextPrototype = window.CanvasRenderingContext2D.prototype;
|
||||
contextPrototype._createImageData = contextPrototype.createImageData;
|
||||
contextPrototype.createImageData = function(w, h) {
|
||||
var imageData = this._createImageData(w, h);
|
||||
imageData.data.set = function(arr) {
|
||||
for (var i = 0, ii = this.length; i < ii; i++) {
|
||||
this[i] = arr[i];
|
||||
}
|
||||
};
|
||||
return imageData;
|
||||
};
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
// Support: IE<10, Android<4.0, iOS
|
||||
(function checkRequestAnimationFrame() {
|
||||
function fakeRequestAnimationFrame(callback) {
|
||||
window.setTimeout(callback, 20);
|
||||
}
|
||||
|
||||
var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
|
||||
if (isIOS) {
|
||||
// requestAnimationFrame on iOS is broken, replacing with fake one.
|
||||
window.requestAnimationFrame = fakeRequestAnimationFrame;
|
||||
return;
|
||||
}
|
||||
if ('requestAnimationFrame' in window) {
|
||||
return;
|
||||
}
|
||||
window.requestAnimationFrame =
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
fakeRequestAnimationFrame;
|
||||
})();
|
||||
|
||||
(function checkCanvasSizeLimitation() {
|
||||
var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent);
|
||||
var isAndroid = /Android/g.test(navigator.userAgent);
|
||||
if (isIOS || isAndroid) {
|
||||
// 5MP
|
||||
PDFJS.maxCanvasPixels = 5242880;
|
||||
}
|
||||
})();
|
||||
|
||||
// Disable fullscreen support for certain problematic configurations.
|
||||
// Support: IE11+ (when embedded).
|
||||
(function checkFullscreenSupport() {
|
||||
var isEmbeddedIE = (navigator.userAgent.indexOf('Trident') >= 0 &&
|
||||
window.parent !== window);
|
||||
if (isEmbeddedIE) {
|
||||
PDFJS.disableFullscreen = true;
|
||||
}
|
||||
})();
|
@ -0,0 +1,27 @@
|
||||
/* This is just a sample file with CSS rules. You should write your own @font-face declarations
|
||||
* to add support for your desired fonts.
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Novecentowide Book';
|
||||
src: url("/ViewerJS/fonts/Novecentowide-Bold-webfont.eot");
|
||||
src: url("/ViewerJS/fonts/Novecentowide-Bold-webfont.eot?#iefix") format("embedded-opentype"),
|
||||
url("/ViewerJS/fonts/Novecentowide-Bold-webfont.woff") format("woff"),
|
||||
url("/fonts/Novecentowide-Bold-webfont.ttf") format("truetype"),
|
||||
url("/fonts/Novecentowide-Bold-webfont.svg#NovecentowideBookBold") format("svg");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'exotica';
|
||||
src: url('/ViewerJS/fonts/Exotica-webfont.eot');
|
||||
src: url('/ViewerJS/fonts/Exotica-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('/ViewerJS/fonts/Exotica-webfont.woff') format('woff'),
|
||||
url('/ViewerJS/fonts/Exotica-webfont.ttf') format('truetype'),
|
||||
url('/ViewerJS/fonts/Exotica-webfont.svg#exoticamedium') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 512 B |
After Width: | Height: | Size: 491 B |
After Width: | Height: | Size: 237 B |
After Width: | Height: | Size: 353 B |
After Width: | Height: | Size: 344 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 228 B |
After Width: | Height: | Size: 143 B |
@ -0,0 +1 @@
|
||||
var /**@const{!string}*/pdfjs_version = "v1.1.114";
|
@ -0,0 +1,419 @@
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* Copyright 2012 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/* globals CustomStyle, PDFJS */
|
||||
|
||||
'use strict';
|
||||
|
||||
var MAX_TEXT_DIVS_TO_RENDER = 100000;
|
||||
|
||||
var NonWhitespaceRegexp = /\S/;
|
||||
|
||||
function isAllWhitespace(str) {
|
||||
return !NonWhitespaceRegexp.test(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} TextLayerBuilderOptions
|
||||
* @property {HTMLDivElement} textLayerDiv - The text layer container.
|
||||
* @property {number} pageIndex - The page index.
|
||||
* @property {PageViewport} viewport - The viewport of the text layer.
|
||||
* @property {PDFFindController} findController
|
||||
*/
|
||||
|
||||
/**
|
||||
* TextLayerBuilder provides text-selection functionality for the PDF.
|
||||
* It does this by creating overlay divs over the PDF text. These divs
|
||||
* contain text that matches the PDF text they are overlaying. This object
|
||||
* also provides a way to highlight text that is being searched for.
|
||||
* @class
|
||||
*/
|
||||
var TextLayerBuilder = (function TextLayerBuilderClosure() {
|
||||
function TextLayerBuilder(options) {
|
||||
this.textLayerDiv = options.textLayerDiv;
|
||||
this.renderingDone = false;
|
||||
this.divContentDone = false;
|
||||
this.pageIdx = options.pageIndex;
|
||||
this.pageNumber = this.pageIdx + 1;
|
||||
this.matches = [];
|
||||
this.viewport = options.viewport;
|
||||
this.textDivs = [];
|
||||
this.findController = options.findController || null;
|
||||
}
|
||||
|
||||
TextLayerBuilder.prototype = {
|
||||
_finishRendering: function TextLayerBuilder_finishRendering() {
|
||||
this.renderingDone = true;
|
||||
|
||||
var event = document.createEvent('CustomEvent');
|
||||
event.initCustomEvent('textlayerrendered', true, true, {
|
||||
pageNumber: this.pageNumber
|
||||
});
|
||||
this.textLayerDiv.dispatchEvent(event);
|
||||
},
|
||||
|
||||
renderLayer: function TextLayerBuilder_renderLayer() {
|
||||
var textLayerFrag = document.createDocumentFragment();
|
||||
var textDivs = this.textDivs;
|
||||
var textDivsLength = textDivs.length;
|
||||
var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
// No point in rendering many divs as it would make the browser
|
||||
// unusable even after the divs are rendered.
|
||||
if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) {
|
||||
this._finishRendering();
|
||||
return;
|
||||
}
|
||||
|
||||
var lastFontSize;
|
||||
var lastFontFamily;
|
||||
for (var i = 0; i < textDivsLength; i++) {
|
||||
var textDiv = textDivs[i];
|
||||
if (textDiv.dataset.isWhitespace !== undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var fontSize = textDiv.style.fontSize;
|
||||
var fontFamily = textDiv.style.fontFamily;
|
||||
|
||||
// Only build font string and set to context if different from last.
|
||||
if (fontSize !== lastFontSize || fontFamily !== lastFontFamily) {
|
||||
ctx.font = fontSize + ' ' + fontFamily;
|
||||
lastFontSize = fontSize;
|
||||
lastFontFamily = fontFamily;
|
||||
}
|
||||
|
||||
var width = ctx.measureText(textDiv.textContent).width;
|
||||
if (width > 0) {
|
||||
textLayerFrag.appendChild(textDiv);
|
||||
var transform;
|
||||
if (textDiv.dataset.canvasWidth !== undefined) {
|
||||
// Dataset values come of type string.
|
||||
var textScale = textDiv.dataset.canvasWidth / width;
|
||||
transform = 'scaleX(' + textScale + ')';
|
||||
} else {
|
||||
transform = '';
|
||||
}
|
||||
var rotation = textDiv.dataset.angle;
|
||||
if (rotation) {
|
||||
transform = 'rotate(' + rotation + 'deg) ' + transform;
|
||||
}
|
||||
if (transform) {
|
||||
CustomStyle.setProp('transform' , textDiv, transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.textLayerDiv.appendChild(textLayerFrag);
|
||||
this._finishRendering();
|
||||
this.updateMatches();
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders the text layer.
|
||||
* @param {number} timeout (optional) if specified, the rendering waits
|
||||
* for specified amount of ms.
|
||||
*/
|
||||
render: function TextLayerBuilder_render(timeout) {
|
||||
if (!this.divContentDone || this.renderingDone) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.renderTimer) {
|
||||
clearTimeout(this.renderTimer);
|
||||
this.renderTimer = null;
|
||||
}
|
||||
|
||||
if (!timeout) { // Render right away
|
||||
this.renderLayer();
|
||||
} else { // Schedule
|
||||
var self = this;
|
||||
this.renderTimer = setTimeout(function() {
|
||||
self.renderLayer();
|
||||
self.renderTimer = null;
|
||||
}, timeout);
|
||||
}
|
||||
},
|
||||
|
||||
appendText: function TextLayerBuilder_appendText(geom, styles) {
|
||||
var style = styles[geom.fontName];
|
||||
var textDiv = document.createElement('div');
|
||||
this.textDivs.push(textDiv);
|
||||
if (isAllWhitespace(geom.str)) {
|
||||
textDiv.dataset.isWhitespace = true;
|
||||
return;
|
||||
}
|
||||
var tx = PDFJS.Util.transform(this.viewport.transform, geom.transform);
|
||||
var angle = Math.atan2(tx[1], tx[0]);
|
||||
if (style.vertical) {
|
||||
angle += Math.PI / 2;
|
||||
}
|
||||
var fontHeight = Math.sqrt((tx[2] * tx[2]) + (tx[3] * tx[3]));
|
||||
var fontAscent = fontHeight;
|
||||
if (style.ascent) {
|
||||
fontAscent = style.ascent * fontAscent;
|
||||
} else if (style.descent) {
|
||||
fontAscent = (1 + style.descent) * fontAscent;
|
||||
}
|
||||
|
||||
var left;
|
||||
var top;
|
||||
if (angle === 0) {
|
||||
left = tx[4];
|
||||
top = tx[5] - fontAscent;
|
||||
} else {
|
||||
left = tx[4] + (fontAscent * Math.sin(angle));
|
||||
top = tx[5] - (fontAscent * Math.cos(angle));
|
||||
}
|
||||
textDiv.style.left = left + 'px';
|
||||
textDiv.style.top = top + 'px';
|
||||
textDiv.style.fontSize = fontHeight + 'px';
|
||||
textDiv.style.fontFamily = style.fontFamily;
|
||||
|
||||
textDiv.textContent = geom.str;
|
||||
// |fontName| is only used by the Font Inspector. This test will succeed
|
||||
// when e.g. the Font Inspector is off but the Stepper is on, but it's
|
||||
// not worth the effort to do a more accurate test.
|
||||
if (PDFJS.pdfBug) {
|
||||
textDiv.dataset.fontName = geom.fontName;
|
||||
}
|
||||
// Storing into dataset will convert number into string.
|
||||
if (angle !== 0) {
|
||||
textDiv.dataset.angle = angle * (180 / Math.PI);
|
||||
}
|
||||
// We don't bother scaling single-char text divs, because it has very
|
||||
// little effect on text highlighting. This makes scrolling on docs with
|
||||
// lots of such divs a lot faster.
|
||||
if (textDiv.textContent.length > 1) {
|
||||
if (style.vertical) {
|
||||
textDiv.dataset.canvasWidth = geom.height * this.viewport.scale;
|
||||
} else {
|
||||
textDiv.dataset.canvasWidth = geom.width * this.viewport.scale;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setTextContent: function TextLayerBuilder_setTextContent(textContent) {
|
||||
this.textContent = textContent;
|
||||
|
||||
var textItems = textContent.items;
|
||||
for (var i = 0, len = textItems.length; i < len; i++) {
|
||||
this.appendText(textItems[i], textContent.styles);
|
||||
}
|
||||
this.divContentDone = true;
|
||||
},
|
||||
|
||||
convertMatches: function TextLayerBuilder_convertMatches(matches) {
|
||||
var i = 0;
|
||||
var iIndex = 0;
|
||||
var bidiTexts = this.textContent.items;
|
||||
var end = bidiTexts.length - 1;
|
||||
var queryLen = (this.findController === null ?
|
||||
0 : this.findController.state.query.length);
|
||||
var ret = [];
|
||||
|
||||
for (var m = 0, len = matches.length; m < len; m++) {
|
||||
// Calculate the start position.
|
||||
var matchIdx = matches[m];
|
||||
|
||||
// Loop over the divIdxs.
|
||||
while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) {
|
||||
iIndex += bidiTexts[i].str.length;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i === bidiTexts.length) {
|
||||
console.error('Could not find a matching mapping');
|
||||
}
|
||||
|
||||
var match = {
|
||||
begin: {
|
||||
divIdx: i,
|
||||
offset: matchIdx - iIndex
|
||||
}
|
||||
};
|
||||
|
||||
// Calculate the end position.
|
||||
matchIdx += queryLen;
|
||||
|
||||
// Somewhat the same array as above, but use > instead of >= to get
|
||||
// the end position right.
|
||||
while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) {
|
||||
iIndex += bidiTexts[i].str.length;
|
||||
i++;
|
||||
}
|
||||
|
||||
match.end = {
|
||||
divIdx: i,
|
||||
offset: matchIdx - iIndex
|
||||
};
|
||||
ret.push(match);
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
|
||||
renderMatches: function TextLayerBuilder_renderMatches(matches) {
|
||||
// Early exit if there is nothing to render.
|
||||
if (matches.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var bidiTexts = this.textContent.items;
|
||||
var textDivs = this.textDivs;
|
||||
var prevEnd = null;
|
||||
var pageIdx = this.pageIdx;
|
||||
var isSelectedPage = (this.findController === null ?
|
||||
false : (pageIdx === this.findController.selected.pageIdx));
|
||||
var selectedMatchIdx = (this.findController === null ?
|
||||
-1 : this.findController.selected.matchIdx);
|
||||
var highlightAll = (this.findController === null ?
|
||||
false : this.findController.state.highlightAll);
|
||||
var infinity = {
|
||||
divIdx: -1,
|
||||
offset: undefined
|
||||
};
|
||||
|
||||
function beginText(begin, className) {
|
||||
var divIdx = begin.divIdx;
|
||||
textDivs[divIdx].textContent = '';
|
||||
appendTextToDiv(divIdx, 0, begin.offset, className);
|
||||
}
|
||||
|
||||
function appendTextToDiv(divIdx, fromOffset, toOffset, className) {
|
||||
var div = textDivs[divIdx];
|
||||
var content = bidiTexts[divIdx].str.substring(fromOffset, toOffset);
|
||||
var node = document.createTextNode(content);
|
||||
if (className) {
|
||||
var span = document.createElement('span');
|
||||
span.className = className;
|
||||
span.appendChild(node);
|
||||
div.appendChild(span);
|
||||
return;
|
||||
}
|
||||
div.appendChild(node);
|
||||
}
|
||||
|
||||
var i0 = selectedMatchIdx, i1 = i0 + 1;
|
||||
if (highlightAll) {
|
||||
i0 = 0;
|
||||
i1 = matches.length;
|
||||
} else if (!isSelectedPage) {
|
||||
// Not highlighting all and this isn't the selected page, so do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = i0; i < i1; i++) {
|
||||
var match = matches[i];
|
||||
var begin = match.begin;
|
||||
var end = match.end;
|
||||
var isSelected = (isSelectedPage && i === selectedMatchIdx);
|
||||
var highlightSuffix = (isSelected ? ' selected' : '');
|
||||
|
||||
if (this.findController) {
|
||||
this.findController.updateMatchPosition(pageIdx, i, textDivs,
|
||||
begin.divIdx, end.divIdx);
|
||||
}
|
||||
|
||||
// Match inside new div.
|
||||
if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
|
||||
// If there was a previous div, then add the text at the end.
|
||||
if (prevEnd !== null) {
|
||||
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
|
||||
}
|
||||
// Clear the divs and set the content until the starting point.
|
||||
beginText(begin);
|
||||
} else {
|
||||
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset);
|
||||
}
|
||||
|
||||
if (begin.divIdx === end.divIdx) {
|
||||
appendTextToDiv(begin.divIdx, begin.offset, end.offset,
|
||||
'highlight' + highlightSuffix);
|
||||
} else {
|
||||
appendTextToDiv(begin.divIdx, begin.offset, infinity.offset,
|
||||
'highlight begin' + highlightSuffix);
|
||||
for (var n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) {
|
||||
textDivs[n0].className = 'highlight middle' + highlightSuffix;
|
||||
}
|
||||
beginText(end, 'highlight end' + highlightSuffix);
|
||||
}
|
||||
prevEnd = end;
|
||||
}
|
||||
|
||||
if (prevEnd) {
|
||||
appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
|
||||
}
|
||||
},
|
||||
|
||||
updateMatches: function TextLayerBuilder_updateMatches() {
|
||||
// Only show matches when all rendering is done.
|
||||
if (!this.renderingDone) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear all matches.
|
||||
var matches = this.matches;
|
||||
var textDivs = this.textDivs;
|
||||
var bidiTexts = this.textContent.items;
|
||||
var clearedUntilDivIdx = -1;
|
||||
|
||||
// Clear all current matches.
|
||||
for (var i = 0, len = matches.length; i < len; i++) {
|
||||
var match = matches[i];
|
||||
var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
|
||||
for (var n = begin, end = match.end.divIdx; n <= end; n++) {
|
||||
var div = textDivs[n];
|
||||
div.textContent = bidiTexts[n].str;
|
||||
div.className = '';
|
||||
}
|
||||
clearedUntilDivIdx = match.end.divIdx + 1;
|
||||
}
|
||||
|
||||
if (this.findController === null || !this.findController.active) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert the matches on the page controller into the match format
|
||||
// used for the textLayer.
|
||||
this.matches = this.convertMatches(this.findController === null ?
|
||||
[] : (this.findController.pageMatches[this.pageIdx] || []));
|
||||
this.renderMatches(this.matches);
|
||||
}
|
||||
};
|
||||
return TextLayerBuilder;
|
||||
})();
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements IPDFTextLayerFactory
|
||||
*/
|
||||
function DefaultTextLayerFactory() {}
|
||||
DefaultTextLayerFactory.prototype = {
|
||||
/**
|
||||
* @param {HTMLDivElement} textLayerDiv
|
||||
* @param {number} pageIndex
|
||||
* @param {PageViewport} viewport
|
||||
* @returns {TextLayerBuilder}
|
||||
*/
|
||||
createTextLayerBuilder: function (textLayerDiv, pageIndex, viewport) {
|
||||
return new TextLayerBuilder({
|
||||
textLayerDiv: textLayerDiv,
|
||||
pageIndex: pageIndex,
|
||||
viewport: viewport
|
||||
});
|
||||
}
|
||||
};
|
@ -0,0 +1,394 @@
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* Copyright 2012 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var CSS_UNITS = 96.0 / 72.0;
|
||||
var DEFAULT_SCALE = 'auto';
|
||||
var UNKNOWN_SCALE = 0;
|
||||
var MAX_AUTO_SCALE = 1.25;
|
||||
var SCROLLBAR_PADDING = 40;
|
||||
var VERTICAL_PADDING = 5;
|
||||
|
||||
// optimised CSS custom property getter/setter
|
||||
var CustomStyle = (function CustomStyleClosure() {
|
||||
|
||||
// As noted on: http://www.zachstronaut.com/posts/2009/02/17/
|
||||
// animate-css-transforms-firefox-webkit.html
|
||||
// in some versions of IE9 it is critical that ms appear in this list
|
||||
// before Moz
|
||||
var prefixes = ['ms', 'Moz', 'Webkit', 'O'];
|
||||
var _cache = {};
|
||||
|
||||
function CustomStyle() {}
|
||||
|
||||
CustomStyle.getProp = function get(propName, element) {
|
||||
// check cache only when no element is given
|
||||
if (arguments.length === 1 && typeof _cache[propName] === 'string') {
|
||||
return _cache[propName];
|
||||
}
|
||||
|
||||
element = element || document.documentElement;
|
||||
var style = element.style, prefixed, uPropName;
|
||||
|
||||
// test standard property first
|
||||
if (typeof style[propName] === 'string') {
|
||||
return (_cache[propName] = propName);
|
||||
}
|
||||
|
||||
// capitalize
|
||||
uPropName = propName.charAt(0).toUpperCase() + propName.slice(1);
|
||||
|
||||
// test vendor specific properties
|
||||
for (var i = 0, l = prefixes.length; i < l; i++) {
|
||||
prefixed = prefixes[i] + uPropName;
|
||||
if (typeof style[prefixed] === 'string') {
|
||||
return (_cache[propName] = prefixed);
|
||||
}
|
||||
}
|
||||
|
||||
//if all fails then set to undefined
|
||||
return (_cache[propName] = 'undefined');
|
||||
};
|
||||
|
||||
CustomStyle.setProp = function set(propName, element, str) {
|
||||
var prop = this.getProp(propName);
|
||||
if (prop !== 'undefined') {
|
||||
element.style[prop] = str;
|
||||
}
|
||||
};
|
||||
|
||||
return CustomStyle;
|
||||
})();
|
||||
|
||||
function getFileName(url) {
|
||||
var anchor = url.indexOf('#');
|
||||
var query = url.indexOf('?');
|
||||
var end = Math.min(
|
||||
anchor > 0 ? anchor : url.length,
|
||||
query > 0 ? query : url.length);
|
||||
return url.substring(url.lastIndexOf('/', end) + 1, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns scale factor for the canvas. It makes sense for the HiDPI displays.
|
||||
* @return {Object} The object with horizontal (sx) and vertical (sy)
|
||||
scales. The scaled property is set to false if scaling is
|
||||
not required, true otherwise.
|
||||
*/
|
||||
function getOutputScale(ctx) {
|
||||
var devicePixelRatio = window.devicePixelRatio || 1;
|
||||
var backingStoreRatio = ctx.webkitBackingStorePixelRatio ||
|
||||
ctx.mozBackingStorePixelRatio ||
|
||||
ctx.msBackingStorePixelRatio ||
|
||||
ctx.oBackingStorePixelRatio ||
|
||||
ctx.backingStorePixelRatio || 1;
|
||||
var pixelRatio = devicePixelRatio / backingStoreRatio;
|
||||
return {
|
||||
sx: pixelRatio,
|
||||
sy: pixelRatio,
|
||||
scaled: pixelRatio !== 1
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls specified element into view of its parent.
|
||||
* element {Object} The element to be visible.
|
||||
* spot {Object} An object with optional top and left properties,
|
||||
* specifying the offset from the top left edge.
|
||||
*/
|
||||
function scrollIntoView(element, spot) {
|
||||
// Assuming offsetParent is available (it's not available when viewer is in
|
||||
// hidden iframe or object). We have to scroll: if the offsetParent is not set
|
||||
// producing the error. See also animationStartedClosure.
|
||||
var parent = element.offsetParent;
|
||||
var offsetY = element.offsetTop + element.clientTop;
|
||||
var offsetX = element.offsetLeft + element.clientLeft;
|
||||
if (!parent) {
|
||||
console.error('offsetParent is not set -- cannot scroll');
|
||||
return;
|
||||
}
|
||||
while (parent.clientHeight === parent.scrollHeight) {
|
||||
if (parent.dataset._scaleY) {
|
||||
offsetY /= parent.dataset._scaleY;
|
||||
offsetX /= parent.dataset._scaleX;
|
||||
}
|
||||
offsetY += parent.offsetTop;
|
||||
offsetX += parent.offsetLeft;
|
||||
parent = parent.offsetParent;
|
||||
if (!parent) {
|
||||
return; // no need to scroll
|
||||
}
|
||||
}
|
||||
if (spot) {
|
||||
if (spot.top !== undefined) {
|
||||
offsetY += spot.top;
|
||||
}
|
||||
if (spot.left !== undefined) {
|
||||
offsetX += spot.left;
|
||||
parent.scrollLeft = offsetX;
|
||||
}
|
||||
}
|
||||
parent.scrollTop = offsetY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to start monitoring the scroll event and converting them into
|
||||
* PDF.js friendly one: with scroll debounce and scroll direction.
|
||||
*/
|
||||
function watchScroll(viewAreaElement, callback) {
|
||||
var debounceScroll = function debounceScroll(evt) {
|
||||
if (rAF) {
|
||||
return;
|
||||
}
|
||||
// schedule an invocation of scroll for next animation frame.
|
||||
rAF = window.requestAnimationFrame(function viewAreaElementScrolled() {
|
||||
rAF = null;
|
||||
|
||||
var currentY = viewAreaElement.scrollTop;
|
||||
var lastY = state.lastY;
|
||||
if (currentY !== lastY) {
|
||||
state.down = currentY > lastY;
|
||||
}
|
||||
state.lastY = currentY;
|
||||
callback(state);
|
||||
});
|
||||
};
|
||||
|
||||
var state = {
|
||||
down: true,
|
||||
lastY: viewAreaElement.scrollTop,
|
||||
_eventHandler: debounceScroll
|
||||
};
|
||||
|
||||
var rAF = null;
|
||||
viewAreaElement.addEventListener('scroll', debounceScroll, true);
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use binary search to find the index of the first item in a given array which
|
||||
* passes a given condition. The items are expected to be sorted in the sense
|
||||
* that if the condition is true for one item in the array, then it is also true
|
||||
* for all following items.
|
||||
*
|
||||
* @returns {Number} Index of the first array element to pass the test,
|
||||
* or |items.length| if no such element exists.
|
||||
*/
|
||||
function binarySearchFirstItem(items, condition) {
|
||||
var minIndex = 0;
|
||||
var maxIndex = items.length - 1;
|
||||
|
||||
if (items.length === 0 || !condition(items[maxIndex])) {
|
||||
return items.length;
|
||||
}
|
||||
if (condition(items[minIndex])) {
|
||||
return minIndex;
|
||||
}
|
||||
|
||||
while (minIndex < maxIndex) {
|
||||
var currentIndex = (minIndex + maxIndex) >> 1;
|
||||
var currentItem = items[currentIndex];
|
||||
if (condition(currentItem)) {
|
||||
maxIndex = currentIndex;
|
||||
} else {
|
||||
minIndex = currentIndex + 1;
|
||||
}
|
||||
}
|
||||
return minIndex; /* === maxIndex */
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic helper to find out what elements are visible within a scroll pane.
|
||||
*/
|
||||
function getVisibleElements(scrollEl, views, sortByVisibility) {
|
||||
var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight;
|
||||
var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth;
|
||||
|
||||
function isElementBottomBelowViewTop(view) {
|
||||
var element = view.div;
|
||||
var elementBottom =
|
||||
element.offsetTop + element.clientTop + element.clientHeight;
|
||||
return elementBottom > top;
|
||||
}
|
||||
|
||||
var visible = [], view, element;
|
||||
var currentHeight, viewHeight, hiddenHeight, percentHeight;
|
||||
var currentWidth, viewWidth;
|
||||
var firstVisibleElementInd = (views.length === 0) ? 0 :
|
||||
binarySearchFirstItem(views, isElementBottomBelowViewTop);
|
||||
|
||||
for (var i = firstVisibleElementInd, ii = views.length; i < ii; i++) {
|
||||
view = views[i];
|
||||
element = view.div;
|
||||
currentHeight = element.offsetTop + element.clientTop;
|
||||
viewHeight = element.clientHeight;
|
||||
|
||||
if (currentHeight > bottom) {
|
||||
break;
|
||||
}
|
||||
|
||||
currentWidth = element.offsetLeft + element.clientLeft;
|
||||
viewWidth = element.clientWidth;
|
||||
if (currentWidth + viewWidth < left || currentWidth > right) {
|
||||
continue;
|
||||
}
|
||||
hiddenHeight = Math.max(0, top - currentHeight) +
|
||||
Math.max(0, currentHeight + viewHeight - bottom);
|
||||
percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0;
|
||||
|
||||
visible.push({
|
||||
id: view.id,
|
||||
x: currentWidth,
|
||||
y: currentHeight,
|
||||
view: view,
|
||||
percent: percentHeight
|
||||
});
|
||||
}
|
||||
|
||||
var first = visible[0];
|
||||
var last = visible[visible.length - 1];
|
||||
|
||||
if (sortByVisibility) {
|
||||
visible.sort(function(a, b) {
|
||||
var pc = a.percent - b.percent;
|
||||
if (Math.abs(pc) > 0.001) {
|
||||
return -pc;
|
||||
}
|
||||
return a.id - b.id; // ensure stability
|
||||
});
|
||||
}
|
||||
return {first: first, last: last, views: visible};
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler to suppress context menu.
|
||||
*/
|
||||
function noContextMenuHandler(e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filename or guessed filename from the url (see issue 3455).
|
||||
* url {String} The original PDF location.
|
||||
* @return {String} Guessed PDF file name.
|
||||
*/
|
||||
function getPDFFileNameFromURL(url) {
|
||||
var reURI = /^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/;
|
||||
// SCHEME HOST 1.PATH 2.QUERY 3.REF
|
||||
// Pattern to get last matching NAME.pdf
|
||||
var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i;
|
||||
var splitURI = reURI.exec(url);
|
||||
var suggestedFilename = reFilename.exec(splitURI[1]) ||
|
||||
reFilename.exec(splitURI[2]) ||
|
||||
reFilename.exec(splitURI[3]);
|
||||
if (suggestedFilename) {
|
||||
suggestedFilename = suggestedFilename[0];
|
||||
if (suggestedFilename.indexOf('%') !== -1) {
|
||||
// URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf
|
||||
try {
|
||||
suggestedFilename =
|
||||
reFilename.exec(decodeURIComponent(suggestedFilename))[0];
|
||||
} catch(e) { // Possible (extremely rare) errors:
|
||||
// URIError "Malformed URI", e.g. for "%AA.pdf"
|
||||
// TypeError "null has no properties", e.g. for "%2F.pdf"
|
||||
}
|
||||
}
|
||||
}
|
||||
return suggestedFilename || 'document.pdf';
|
||||
}
|
||||
|
||||
var ProgressBar = (function ProgressBarClosure() {
|
||||
|
||||
function clamp(v, min, max) {
|
||||
return Math.min(Math.max(v, min), max);
|
||||
}
|
||||
|
||||
function ProgressBar(id, opts) {
|
||||
this.visible = true;
|
||||
|
||||
// Fetch the sub-elements for later.
|
||||
this.div = document.querySelector(id + ' .progress');
|
||||
|
||||
// Get the loading bar element, so it can be resized to fit the viewer.
|
||||
this.bar = this.div.parentNode;
|
||||
|
||||
// Get options, with sensible defaults.
|
||||
this.height = opts.height || 100;
|
||||
this.width = opts.width || 100;
|
||||
this.units = opts.units || '%';
|
||||
|
||||
// Initialize heights.
|
||||
this.div.style.height = this.height + this.units;
|
||||
this.percent = 0;
|
||||
}
|
||||
|
||||
ProgressBar.prototype = {
|
||||
|
||||
updateBar: function ProgressBar_updateBar() {
|
||||
if (this._indeterminate) {
|
||||
this.div.classList.add('indeterminate');
|
||||
this.div.style.width = this.width + this.units;
|
||||
return;
|
||||
}
|
||||
|
||||
this.div.classList.remove('indeterminate');
|
||||
var progressSize = this.width * this._percent / 100;
|
||||
this.div.style.width = progressSize + this.units;
|
||||
},
|
||||
|
||||
get percent() {
|
||||
return this._percent;
|
||||
},
|
||||
|
||||
set percent(val) {
|
||||
this._indeterminate = isNaN(val);
|
||||
this._percent = clamp(val, 0, 100);
|
||||
this.updateBar();
|
||||
},
|
||||
|
||||
setWidth: function ProgressBar_setWidth(viewer) {
|
||||
if (viewer) {
|
||||
var container = viewer.parentNode;
|
||||
var scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
|
||||
if (scrollbarWidth > 0) {
|
||||
this.bar.setAttribute('style', 'width: calc(100% - ' +
|
||||
scrollbarWidth + 'px);');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
hide: function ProgressBar_hide() {
|
||||
if (!this.visible) {
|
||||
return;
|
||||
}
|
||||
this.visible = false;
|
||||
this.bar.classList.add('hidden');
|
||||
document.body.classList.remove('loadingInProgress');
|
||||
},
|
||||
|
||||
show: function ProgressBar_show() {
|
||||
if (this.visible) {
|
||||
return;
|
||||
}
|
||||
this.visible = true;
|
||||
document.body.classList.add('loadingInProgress');
|
||||
this.bar.classList.remove('hidden');
|
||||
}
|
||||
};
|
||||
|
||||
return ProgressBar;
|
||||
})();
|
@ -0,0 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<meta name=viewport content=width=device-width, initial-scale=1>
|
||||
<title>The Library Is Open - Special Issue 9</title>
|
||||
<!--
|
||||
<meta name=Keywords content= >
|
||||
<meta name=Description content= >
|
||||
<link rel=icon href= type=image/x-icon>
|
||||
-->
|
||||
<link rel=stylesheet type=text/css href=./style.css>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
|
||||
<header>
|
||||
<h1><a id="title" href="./index.html">The Library Is Open</a></h1>
|
||||
<h2>Special Issue 09</h2>
|
||||
<h3>Piet Zwart Institute</h3>
|
||||
<hr><hr><br>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="./video.html">Video</a></li>
|
||||
<li><a href="./poster.html">Poster</a></li>
|
||||
<li><a href="./publication.html">Publication</a></li>
|
||||
<li><a href="./bb.html">Blurry Boudaries</a></li>
|
||||
<li><a href="./mc.html">Marginal Conversation</a></li>
|
||||
<li><a href="./ka.html">Knowledge In Action</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<br>
|
||||
</header>
|
||||
<br>
|
||||
|
||||
<article>
|
||||
<div id="right" >
|
||||
<section id="description">
|
||||
<p id="firstLine">Dear readers,<br><br>
|
||||
The Library Is Open invites you to an afternoon of workshops that make the operations within libraries visible. Join us in exploring the actions and roles of legal and extra-legal libraries (municipal, pirate, academic, +++), their custodians, and the public that form a community around collections of texts.</p>
|
||||
|
||||
<p><b>Marginal Conversation</b><br>
|
||||
We read texts, and write notes in the margins; usually in private, isolated from other readers. We come across texts with others' notes on them; the author unknown, their thoughts obscure. What happens when we share our notes, vocalise and perform them?</p>
|
||||
<p>In this workshop...we'll read, annotate and discuss an open letter which asks for pirate library practices to come out from the shadows. We'll read aloud and perform parts of the text, enriched by our doubts, sympathies, tensions and diverse understandings. We'll personalise the text, opening it up for collective conversations. Our voices will occupy the space and leave traces on the text and in the library.</p>
|
||||
|
||||
<p><b>Knowledge In Action</b><br>
|
||||
Through role play you will perform the activities crucial to the sustenance of libraries. You will interpret and reimagine the actors that take part in knowledge production and distribution, such as the librarian, the researcher, the pirate, the publisher, the reader, the writer, the student, the copyist, the printer.</p>
|
||||
<p>The workshop consists of three activities where different scenarios shift your accustomed perspective to start common dialogues. Put yourselves in the shoes of the librarian, imagine together a reading space, and contest the morality of knowledge proprietization.</p>
|
||||
|
||||
|
||||
<p><b>Blurry boundaries</b><br>
|
||||
Select, annotate, analyze, scan, correct, digitize, print, read, transfer, erase, encode, curate, hack, interface, work, copy...<br>
|
||||
How do we reveal the hidden labour involved in these processes? What libraries become possible when you transform physical books into digital files, and vice versa? </p>
|
||||
<p>In this workshop you will be a librarian converting books into machine readable files, a process involving tools, time and choices.</p><br>
|
||||
|
||||
<p class="extras">Contributors:<br>
|
||||
Simon Browne, Tancredi Di Giovanni, Paloma García, Rita Graça, Artemis Gryllaki, Pedro Sá Couto, Femke Snelting, Biyi Wen, Bohye Woo</p>
|
||||
|
||||
<p class="extras">Special thanks to:<br>
|
||||
Bodó Balázs, Dušan Barok, Anita Burato, André Castro, Aymeric Mansoux, Michael Murtaugh, Martino Morandi, Leslie Robbins, Steve Rushton, Amy Suo Wu, Eva Weinmayr</p>
|
||||
</section>
|
||||
</div>
|
||||
<div class="vl"></div>
|
||||
<div id="left">
|
||||
<section id="pdf">
|
||||
<iframe src="./ViewerJS/?zoom=page-width#../media/pdfs/bb_reader.pdf" alt="pdf" width="100%" height="100%">
|
||||
</section>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,12 +1,64 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The Library Is Open</title>
|
||||
<meta charset="utf-8">
|
||||
<meta charset=utf-8>
|
||||
<meta name=viewport content=width=device-width, initial-scale=1>
|
||||
<meta http-equiv="refresh" content="0; url=./video.html">
|
||||
<title>The Library Is Open - Special Issue 9</title>
|
||||
<!--
|
||||
<meta name=Keywords content= >
|
||||
<meta name=Description content= >
|
||||
<link rel=icon href= type=image/x-icon>
|
||||
-->
|
||||
<link rel=stylesheet type=text/css href=./style.css>
|
||||
</head>
|
||||
<body>
|
||||
<embed src="https://issue.xpub.nl/09/posterSI9.pdf" alt="pdf"
|
||||
pluginspage="https://www.adobe.com/products/acrobat/readstep2.html"
|
||||
width="100%" height="1000px">
|
||||
|
||||
<div id="wrapper">
|
||||
|
||||
<header>
|
||||
<h1><a id="title" href="#">The Library Is Open</a></h1>
|
||||
<h2>Special Issue 09</h2>
|
||||
<h3>Piet Zwart Institute</h3>
|
||||
|
||||
<hr><hr><br>
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="./video.html">Video</a></li>
|
||||
<li><a href="./poster.html">Poster</a></li>
|
||||
<li><a href="./publication.html">Publication</a></li>
|
||||
<li><a href="./bb.html">Blurry Boudaries</a></li>
|
||||
<li><a href="./mc.html">Marginal Conversation</a></li>
|
||||
<li><a href="./ka.html">Knowledge In Action</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<br><br>
|
||||
|
||||
</header>
|
||||
|
||||
<section>
|
||||
|
||||
<div id="left">
|
||||
<article id="description">
|
||||
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec blandit metus dapibus risus gravida malesuada. Duis vel mauris diam. Mauris sollicitudin tincidunt ipsum, in auctor quam egestas sit amet. Morbi leo nibh, tempus ullamcorper velit ut, pretium molestie magna. Morbi diam felis, pulvinar porta ipsum in, convallis tincidunt leo. Morbi viverra orci id mi viverra elementum. Fusce id convallis erat, in vestibulum nisi. Mauris malesuada ullamcorper lobortis. Mauris egestas porttitor neque, at condimentum eros efficitur eu. Curabitur vel massa vel velit ornare maximus. Aenean cursus leo mi, eget venenatis velit varius quis.</p>
|
||||
<p>Nullam nisl lorem, finibus eget dictum non, suscipit sed erat. Aliquam auctor ornare nibh, nec sollicitudin tortor tempus eget. Sed in ullamcorper nisi. Curabitur in accumsan erat. Aenean luctus, diam vitae lobortis viverra, tellus tellus tempus quam, eu sodales tellus eros et libero. Sed euismod velit mollis quam rutrum finibus. Sed egestas ullamcorper tristique. Nam accumsan mollis nunc, quis elementum ex laoreet in. Quisque eleifend interdum sapien. Donec quis vestibulum nunc.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
<div class="vl"></div>
|
||||
<div id="right" >
|
||||
<article id="description">
|
||||
<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec blandit metus dapibus risus gravida malesuada. Duis vel mauris diam. Mauris sollicitudin tincidunt ipsum, in auctor quam egestas sit amet. Morbi leo nibh, tempus ullamcorper velit ut, pretium molestie magna. Morbi diam felis, pulvinar porta ipsum in, convallis tincidunt leo. Morbi viverra orci id mi viverra elementum. Fusce id convallis erat, in vestibulum nisi. Mauris malesuada ullamcorper lobortis. Mauris egestas porttitor neque, at condimentum eros efficitur eu. Curabitur vel massa vel velit ornare maximus. Aenean cursus leo mi, eget venenatis velit varius quis.</p>
|
||||
<p>Nullam nisl lorem, finibus eget dictum non, suscipit sed erat. Aliquam auctor ornare nibh, nec sollicitudin tortor tempus eget. Sed in ullamcorper nisi. Curabitur in accumsan erat. Aenean luctus, diam vitae lobortis viverra, tellus tellus tempus quam, eu sodales tellus eros et libero. Sed euismod velit mollis quam rutrum finibus. Sed egestas ullamcorper tristique. Nam accumsan mollis nunc, quis elementum ex laoreet in. Quisque eleifend interdum sapien. Donec quis vestibulum nunc.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<meta name=viewport content=width=device-width, initial-scale=1>
|
||||
<title>The Library Is Open - Special Issue 9</title>
|
||||
<!--
|
||||
<meta name=Keywords content= >
|
||||
<meta name=Description content= >
|
||||
<link rel=icon href= type=image/x-icon>
|
||||
-->
|
||||
<link rel=stylesheet type=text/css href=./style.css>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
|
||||
<header>
|
||||
<h1><a id="title" href="./index.html">The Library Is Open</a></h1>
|
||||
<h2>Special Issue 09</h2>
|
||||
<h3>Piet Zwart Institute</h3>
|
||||
<hr><hr><br>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="./video.html">Video</a></li>
|
||||
<li><a href="./poster.html">Poster</a></li>
|
||||
<li><a href="./publication.html">Publication</a></li>
|
||||
<li><a href="./bb.html">Blurry Boudaries</a></li>
|
||||
<li><a href="./mc.html">Marginal Conversation</a></li>
|
||||
<li><a href="./ka.html">Knowledge In Action</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<br>
|
||||
</header>
|
||||
<br>
|
||||
|
||||
<article>
|
||||
<div id="right" >
|
||||
<section id="description">
|
||||
<p id="firstLine">Dear readers,<br><br>
|
||||
The Library Is Open invites you to an afternoon of workshops that make the operations within libraries visible. Join us in exploring the actions and roles of legal and extra-legal libraries (municipal, pirate, academic, +++), their custodians, and the public that form a community around collections of texts.</p>
|
||||
|
||||
<p><b>Marginal Conversation</b><br>
|
||||
We read texts, and write notes in the margins; usually in private, isolated from other readers. We come across texts with others' notes on them; the author unknown, their thoughts obscure. What happens when we share our notes, vocalise and perform them?</p>
|
||||
<p>In this workshop...we'll read, annotate and discuss an open letter which asks for pirate library practices to come out from the shadows. We'll read aloud and perform parts of the text, enriched by our doubts, sympathies, tensions and diverse understandings. We'll personalise the text, opening it up for collective conversations. Our voices will occupy the space and leave traces on the text and in the library.</p>
|
||||
|
||||
<p><b>Knowledge In Action</b><br>
|
||||
Through role play you will perform the activities crucial to the sustenance of libraries. You will interpret and reimagine the actors that take part in knowledge production and distribution, such as the librarian, the researcher, the pirate, the publisher, the reader, the writer, the student, the copyist, the printer.</p>
|
||||
<p>The workshop consists of three activities where different scenarios shift your accustomed perspective to start common dialogues. Put yourselves in the shoes of the librarian, imagine together a reading space, and contest the morality of knowledge proprietization.</p>
|
||||
|
||||
|
||||
<p><b>Blurry boundaries</b><br>
|
||||
Select, annotate, analyze, scan, correct, digitize, print, read, transfer, erase, encode, curate, hack, interface, work, copy...<br>
|
||||
How do we reveal the hidden labour involved in these processes? What libraries become possible when you transform physical books into digital files, and vice versa? </p>
|
||||
<p>In this workshop you will be a librarian converting books into machine readable files, a process involving tools, time and choices.</p><br>
|
||||
|
||||
<p class="extras">Contributors:<br>
|
||||
Simon Browne, Tancredi Di Giovanni, Paloma García, Rita Graça, Artemis Gryllaki, Pedro Sá Couto, Femke Snelting, Biyi Wen, Bohye Woo</p>
|
||||
|
||||
<p class="extras">Special thanks to:<br>
|
||||
Bodó Balázs, Dušan Barok, Anita Burato, André Castro, Aymeric Mansoux, Michael Murtaugh, Martino Morandi, Leslie Robbins, Steve Rushton, Amy Suo Wu, Eva Weinmayr</p>
|
||||
</section>
|
||||
</div>
|
||||
<div class="vl"></div>
|
||||
<div id="left">
|
||||
<section id="pdf">
|
||||
<iframe src="./ViewerJS/?zoom=page-width#../media/pdfs/mc_reader.pdf" alt="pdf" width="100%" height="100%">
|
||||
</section>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>The Library Is Open</title>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<embed src="https://issue.xpub.nl/09/posterSI9.pdf" alt="pdf"
|
||||
pluginspage="https://www.adobe.com/products/acrobat/readstep2.html"
|
||||
width="100%" height="1000px">
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,75 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<meta name=viewport content=width=device-width, initial-scale=1>
|
||||
<title>The Library Is Open - Special Issue 9</title>
|
||||
<!--
|
||||
<meta name=Keywords content= >
|
||||
<meta name=Description content= >
|
||||
<link rel=icon href= type=image/x-icon>
|
||||
-->
|
||||
<link rel=stylesheet type=text/css href=./style.css>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<main>
|
||||
|
||||
<header>
|
||||
<h1><a id="title" href="./index.html">The Library Is Open</a></h1>
|
||||
<h2>Special Issue 09</h2>
|
||||
<h3>Piet Zwart Institute</h3>
|
||||
<hr><hr><br>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="./video.html">Video</a></li>
|
||||
<li><a href="./poster.html">Poster</a></li>
|
||||
<li><a href="./publication.html">Publication</a></li>
|
||||
<li><a href="./bb.html">Blurry Boudaries</a></li>
|
||||
<li><a href="./mc.html">Marginal Conversation</a></li>
|
||||
<li><a href="./ka.html">Knowledge In Action</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<br>
|
||||
</header>
|
||||
<br>
|
||||
|
||||
<article>
|
||||
<div id="right" >
|
||||
<section id="description">
|
||||
<p id="firstLine">Dear readers,<br><br>
|
||||
The Library Is Open invites you to an afternoon of workshops that make the operations within libraries visible. Join us in exploring the actions and roles of legal and extra-legal libraries (municipal, pirate, academic, +++), their custodians, and the public that form a community around collections of texts.</p>
|
||||
|
||||
<p><b>Marginal Conversation</b><br>
|
||||
We read texts, and write notes in the margins; usually in private, isolated from other readers. We come across texts with others' notes on them; the author unknown, their thoughts obscure. What happens when we share our notes, vocalise and perform them?</p>
|
||||
<p>In this workshop...we'll read, annotate and discuss an open letter which asks for pirate library practices to come out from the shadows. We'll read aloud and perform parts of the text, enriched by our doubts, sympathies, tensions and diverse understandings. We'll personalise the text, opening it up for collective conversations. Our voices will occupy the space and leave traces on the text and in the library.</p>
|
||||
|
||||
<p><b>Knowledge In Action</b><br>
|
||||
Through role play you will perform the activities crucial to the sustenance of libraries. You will interpret and reimagine the actors that take part in knowledge production and distribution, such as the librarian, the researcher, the pirate, the publisher, the reader, the writer, the student, the copyist, the printer.</p>
|
||||
<p>The workshop consists of three activities where different scenarios shift your accustomed perspective to start common dialogues. Put yourselves in the shoes of the librarian, imagine together a reading space, and contest the morality of knowledge proprietization.</p>
|
||||
|
||||
|
||||
<p><b>Blurry boundaries</b><br>
|
||||
Select, annotate, analyze, scan, correct, digitize, print, read, transfer, erase, encode, curate, hack, interface, work, copy...<br>
|
||||
How do we reveal the hidden labour involved in these processes? What libraries become possible when you transform physical books into digital files, and vice versa? </p>
|
||||
<p>In this workshop you will be a librarian converting books into machine readable files, a process involving tools, time and choices.</p><br>
|
||||
|
||||
<p class="extras">Contributors:<br>
|
||||
Simon Browne, Tancredi Di Giovanni, Paloma García, Rita Graça, Artemis Gryllaki, Pedro Sá Couto, Femke Snelting, Biyi Wen, Bohye Woo</p>
|
||||
|
||||
<p class="extras">Special thanks to:<br>
|
||||
Bodó Balázs, Dušan Barok, Anita Burato, André Castro, Aymeric Mansoux, Michael Murtaugh, Martino Morandi, Leslie Robbins, Steve Rushton, Amy Suo Wu, Eva Weinmayr</p>
|
||||
</section>
|
||||
</div>
|
||||
<div class="vl"></div>
|
||||
<div id="left">
|
||||
<section id="pdf">
|
||||
<iframe src="./ViewerJS/?zoom=page-width#../media/pdfs/poster.pdf" alt="pdf" width="100%" height="100%">
|
||||
</section>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<meta name=viewport content=width=device-width, initial-scale=1>
|
||||
<title>The Library Is Open - Special Issue 9</title>
|
||||
<!--
|
||||
<meta name=Keywords content= >
|
||||
<meta name=Description content= >
|
||||
<link rel=icon href= type=image/x-icon>
|
||||
-->
|
||||
<link rel=stylesheet type=text/css href=./style.css>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="wrapper">
|
||||
|
||||
<header>
|
||||
<h1><a id="title" href="#">The Library Is Open</a></h1>
|
||||
<h2>Special Issue 09</h2>
|
||||
<h3>Piet Zwart Institute</h3>
|
||||
|
||||
<hr><hr><br>
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="./video.html">Video</a></li>
|
||||
<li><a href="./poster.html">Poster</a></li>
|
||||
<li><a href="./publication.html">Publication</a></li>
|
||||
<li><a href="./bb.html">Blurry Boudaries</a></li>
|
||||
<li><a href="./mc.html">Marginal Conversation</a></li>
|
||||
<li><a href="./ka.html">Knowledge In Action</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<br><br>
|
||||
|
||||
</header>
|
||||
|
||||
<section id="poster">
|
||||
|
||||
<article class="pdfs">
|
||||
<iframe src="./ViewerJS/?zoom=page-width#../media/pdfs/poster.pdf" alt="pdf" width="100%" height="100%">
|
||||
</article>
|
||||
|
||||
</section>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,125 @@
|
||||
@font-face {
|
||||
font-family: "Book";
|
||||
src: url("./media/fonts/standard-book-webfont.woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Book";
|
||||
src: url("./media/fonts/standard-book-italic-webfont.woff");
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: Book ;
|
||||
}
|
||||
|
||||
main {
|
||||
width: 90%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
header {
|
||||
z-index: 101;
|
||||
background-color: white;
|
||||
padding-top: 10px;
|
||||
line-height: .9em;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
article {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
nav {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
ul {
|
||||
width: 80%;
|
||||
margin: auto;
|
||||
list-style: none;
|
||||
font-size: 15px;
|
||||
padding: 0px;
|
||||
line-height: 19px;
|
||||
}
|
||||
|
||||
#left {
|
||||
float: left;
|
||||
width: 50%;
|
||||
margin: auto;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.vl {
|
||||
z-index: -1;
|
||||
border-left: 2px solid black;
|
||||
height: 500px;
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
margin-left: -1px;
|
||||
bottom: 19px;
|
||||
}
|
||||
|
||||
#right {
|
||||
float: right;
|
||||
width: 50%;
|
||||
margin: auto;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
section {
|
||||
width: 96%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
#pdf {
|
||||
width: 94%;
|
||||
height: 55vh;
|
||||
}
|
||||
|
||||
#description {
|
||||
height: 55vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#firstLine {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.extras {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
|
||||
header {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
#left { width: 96%; }
|
||||
|
||||
.vl { visibility: hidden; }
|
||||
|
||||
#right {
|
||||
width: 96%;
|
||||
float: left
|
||||
}
|
||||
|
||||
#pdf { width: 96%; }
|
||||
|
||||
}
|
||||
|
||||
@media only screen and (max-height: 805px) {
|
||||
|
||||
.vl { height: : 700px; }
|
||||
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<meta name=viewport content=width=device-width, initial-scale=1>
|
||||
<title>The Library Is Open - Special Issue 9</title>
|
||||
<!--
|
||||
<meta name=Keywords content= >
|
||||
<meta name=Description content= >
|
||||
<link rel=icon href= type=image/x-icon>
|
||||
-->
|
||||
<link rel=stylesheet type=text/css href=./style.css>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<main>
|
||||
|
||||
<header>
|
||||
<h1><a id="title" href="./index.html">The Library Is Open</a></h1>
|
||||
<h2>Special Issue 09</h2>
|
||||
<h3>Piet Zwart Institute</h3>
|
||||
<hr><hr><br>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="./video.html">Video</a></li>
|
||||
<li><a href="./poster.html">Poster</a></li>
|
||||
<li><a href="./publication.html">Publication</a></li>
|
||||
<li><a href="./bb.html">Blurry Boudaries</a></li>
|
||||
<li><a href="./mc.html">Marginal Conversation</a></li>
|
||||
<li><a href="./ka.html">Knowledge In Action</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<br>
|
||||
</header>
|
||||
<br>
|
||||
|
||||
<article>
|
||||
<div id="left">
|
||||
<section id="video">
|
||||
<video controls="" width="100%">
|
||||
<source src="https://media.xpub.nl/special_issue_06-web.mp4" poster="preview.png" type="video/mp4">
|
||||
Your browser does not support the video tag :(
|
||||
Try a recent version of Firefox or Chromium!
|
||||
</video>
|
||||
</section>
|
||||
</div>
|
||||
<div class="vl"></div>
|
||||
<div id="right" >
|
||||
<section id="description">
|
||||
<p id="firstLine">Dear readers,<br><br>
|
||||
The Library Is Open invites you to an afternoon of workshops that make the operations within libraries visible. Join us in exploring the actions and roles of legal and extra-legal libraries (municipal, pirate, academic, +++), their custodians, and the public that form a community around collections of texts.</p>
|
||||
|
||||
<p><b>Marginal Conversation</b><br>
|
||||
We read texts, and write notes in the margins; usually in private, isolated from other readers. We come across texts with others' notes on them; the author unknown, their thoughts obscure. What happens when we share our notes, vocalise and perform them?</p>
|
||||
<p>In this workshop...we'll read, annotate and discuss an open letter which asks for pirate library practices to come out from the shadows. We'll read aloud and perform parts of the text, enriched by our doubts, sympathies, tensions and diverse understandings. We'll personalise the text, opening it up for collective conversations. Our voices will occupy the space and leave traces on the text and in the library.</p>
|
||||
|
||||
<p><b>Knowledge In Action</b><br>
|
||||
Through role play you will perform the activities crucial to the sustenance of libraries. You will interpret and reimagine the actors that take part in knowledge production and distribution, such as the librarian, the researcher, the pirate, the publisher, the reader, the writer, the student, the copyist, the printer.</p>
|
||||
<p>The workshop consists of three activities where different scenarios shift your accustomed perspective to start common dialogues. Put yourselves in the shoes of the librarian, imagine together a reading space, and contest the morality of knowledge proprietization.</p>
|
||||
|
||||
|
||||
<p><b>Blurry boundaries</b><br>
|
||||
Select, annotate, analyze, scan, correct, digitize, print, read, transfer, erase, encode, curate, hack, interface, work, copy...<br>
|
||||
How do we reveal the hidden labour involved in these processes? What libraries become possible when you transform physical books into digital files, and vice versa? </p>
|
||||
<p>In this workshop you will be a librarian converting books into machine readable files, a process involving tools, time and choices.</p><br>
|
||||
|
||||
<p class="extras">Contributors:<br>
|
||||
Simon Browne, Tancredi Di Giovanni, Paloma García, Rita Graça, Artemis Gryllaki, Pedro Sá Couto, Femke Snelting, Biyi Wen, Bohye Woo</p>
|
||||
|
||||
<p class="extras">Special thanks to:<br>
|
||||
Bodó Balázs, Dušan Barok, Anita Burato, André Castro, Aymeric Mansoux, Michael Murtaugh, Martino Morandi, Leslie Robbins, Steve Rushton, Amy Suo Wu, Eva Weinmayr</p>
|
||||
</section>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|