browser/extensions/pdfjs/content/web/debugger.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
michael@0 3 /* Copyright 2012 Mozilla Foundation
michael@0 4 *
michael@0 5 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 6 * you may not use this file except in compliance with the License.
michael@0 7 * You may obtain a copy of the License at
michael@0 8 *
michael@0 9 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 10 *
michael@0 11 * Unless required by applicable law or agreed to in writing, software
michael@0 12 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 14 * See the License for the specific language governing permissions and
michael@0 15 * limitations under the License.
michael@0 16 */
michael@0 17 /* globals PDFJS */
michael@0 18
michael@0 19 'use strict';
michael@0 20
michael@0 21 var FontInspector = (function FontInspectorClosure() {
michael@0 22 var fonts;
michael@0 23 var active = false;
michael@0 24 var fontAttribute = 'data-font-name';
michael@0 25 function removeSelection() {
michael@0 26 var divs = document.querySelectorAll('div[' + fontAttribute + ']');
michael@0 27 for (var i = 0, ii = divs.length; i < ii; ++i) {
michael@0 28 var div = divs[i];
michael@0 29 div.className = '';
michael@0 30 }
michael@0 31 }
michael@0 32 function resetSelection() {
michael@0 33 var divs = document.querySelectorAll('div[' + fontAttribute + ']');
michael@0 34 for (var i = 0, ii = divs.length; i < ii; ++i) {
michael@0 35 var div = divs[i];
michael@0 36 div.className = 'debuggerHideText';
michael@0 37 }
michael@0 38 }
michael@0 39 function selectFont(fontName, show) {
michael@0 40 var divs = document.querySelectorAll('div[' + fontAttribute + '=' +
michael@0 41 fontName + ']');
michael@0 42 for (var i = 0, ii = divs.length; i < ii; ++i) {
michael@0 43 var div = divs[i];
michael@0 44 div.className = show ? 'debuggerShowText' : 'debuggerHideText';
michael@0 45 }
michael@0 46 }
michael@0 47 function textLayerClick(e) {
michael@0 48 if (!e.target.dataset.fontName ||
michael@0 49 e.target.tagName.toUpperCase() !== 'DIV') {
michael@0 50 return;
michael@0 51 }
michael@0 52 var fontName = e.target.dataset.fontName;
michael@0 53 var selects = document.getElementsByTagName('input');
michael@0 54 for (var i = 0; i < selects.length; ++i) {
michael@0 55 var select = selects[i];
michael@0 56 if (select.dataset.fontName != fontName) {
michael@0 57 continue;
michael@0 58 }
michael@0 59 select.checked = !select.checked;
michael@0 60 selectFont(fontName, select.checked);
michael@0 61 select.scrollIntoView();
michael@0 62 }
michael@0 63 }
michael@0 64 return {
michael@0 65 // Properties/functions needed by PDFBug.
michael@0 66 id: 'FontInspector',
michael@0 67 name: 'Font Inspector',
michael@0 68 panel: null,
michael@0 69 manager: null,
michael@0 70 init: function init() {
michael@0 71 var panel = this.panel;
michael@0 72 panel.setAttribute('style', 'padding: 5px;');
michael@0 73 var tmp = document.createElement('button');
michael@0 74 tmp.addEventListener('click', resetSelection);
michael@0 75 tmp.textContent = 'Refresh';
michael@0 76 panel.appendChild(tmp);
michael@0 77
michael@0 78 fonts = document.createElement('div');
michael@0 79 panel.appendChild(fonts);
michael@0 80 },
michael@0 81 cleanup: function cleanup() {
michael@0 82 fonts.textContent = '';
michael@0 83 },
michael@0 84 enabled: false,
michael@0 85 get active() {
michael@0 86 return active;
michael@0 87 },
michael@0 88 set active(value) {
michael@0 89 active = value;
michael@0 90 if (active) {
michael@0 91 document.body.addEventListener('click', textLayerClick, true);
michael@0 92 resetSelection();
michael@0 93 } else {
michael@0 94 document.body.removeEventListener('click', textLayerClick, true);
michael@0 95 removeSelection();
michael@0 96 }
michael@0 97 },
michael@0 98 // FontInspector specific functions.
michael@0 99 fontAdded: function fontAdded(fontObj, url) {
michael@0 100 function properties(obj, list) {
michael@0 101 var moreInfo = document.createElement('table');
michael@0 102 for (var i = 0; i < list.length; i++) {
michael@0 103 var tr = document.createElement('tr');
michael@0 104 var td1 = document.createElement('td');
michael@0 105 td1.textContent = list[i];
michael@0 106 tr.appendChild(td1);
michael@0 107 var td2 = document.createElement('td');
michael@0 108 td2.textContent = obj[list[i]].toString();
michael@0 109 tr.appendChild(td2);
michael@0 110 moreInfo.appendChild(tr);
michael@0 111 }
michael@0 112 return moreInfo;
michael@0 113 }
michael@0 114 var moreInfo = properties(fontObj, ['name', 'type']);
michael@0 115 var m = /url\(['"]?([^\)"']+)/.exec(url);
michael@0 116 var fontName = fontObj.loadedName;
michael@0 117 var font = document.createElement('div');
michael@0 118 var name = document.createElement('span');
michael@0 119 name.textContent = fontName;
michael@0 120 var download = document.createElement('a');
michael@0 121 download.href = m[1];
michael@0 122 download.textContent = 'Download';
michael@0 123 var logIt = document.createElement('a');
michael@0 124 logIt.href = '';
michael@0 125 logIt.textContent = 'Log';
michael@0 126 logIt.addEventListener('click', function(event) {
michael@0 127 event.preventDefault();
michael@0 128 console.log(fontObj);
michael@0 129 });
michael@0 130 var select = document.createElement('input');
michael@0 131 select.setAttribute('type', 'checkbox');
michael@0 132 select.dataset.fontName = fontName;
michael@0 133 select.addEventListener('click', (function(select, fontName) {
michael@0 134 return (function() {
michael@0 135 selectFont(fontName, select.checked);
michael@0 136 });
michael@0 137 })(select, fontName));
michael@0 138 font.appendChild(select);
michael@0 139 font.appendChild(name);
michael@0 140 font.appendChild(document.createTextNode(' '));
michael@0 141 font.appendChild(download);
michael@0 142 font.appendChild(document.createTextNode(' '));
michael@0 143 font.appendChild(logIt);
michael@0 144 font.appendChild(moreInfo);
michael@0 145 fonts.appendChild(font);
michael@0 146 // Somewhat of a hack, should probably add a hook for when the text layer
michael@0 147 // is done rendering.
michael@0 148 setTimeout(function() {
michael@0 149 if (this.active) {
michael@0 150 resetSelection();
michael@0 151 }
michael@0 152 }.bind(this), 2000);
michael@0 153 }
michael@0 154 };
michael@0 155 })();
michael@0 156
michael@0 157 // Manages all the page steppers.
michael@0 158 var StepperManager = (function StepperManagerClosure() {
michael@0 159 var steppers = [];
michael@0 160 var stepperDiv = null;
michael@0 161 var stepperControls = null;
michael@0 162 var stepperChooser = null;
michael@0 163 var breakPoints = {};
michael@0 164 return {
michael@0 165 // Properties/functions needed by PDFBug.
michael@0 166 id: 'Stepper',
michael@0 167 name: 'Stepper',
michael@0 168 panel: null,
michael@0 169 manager: null,
michael@0 170 init: function init() {
michael@0 171 var self = this;
michael@0 172 this.panel.setAttribute('style', 'padding: 5px;');
michael@0 173 stepperControls = document.createElement('div');
michael@0 174 stepperChooser = document.createElement('select');
michael@0 175 stepperChooser.addEventListener('change', function(event) {
michael@0 176 self.selectStepper(this.value);
michael@0 177 });
michael@0 178 stepperControls.appendChild(stepperChooser);
michael@0 179 stepperDiv = document.createElement('div');
michael@0 180 this.panel.appendChild(stepperControls);
michael@0 181 this.panel.appendChild(stepperDiv);
michael@0 182 if (sessionStorage.getItem('pdfjsBreakPoints')) {
michael@0 183 breakPoints = JSON.parse(sessionStorage.getItem('pdfjsBreakPoints'));
michael@0 184 }
michael@0 185 },
michael@0 186 cleanup: function cleanup() {
michael@0 187 stepperChooser.textContent = '';
michael@0 188 stepperDiv.textContent = '';
michael@0 189 steppers = [];
michael@0 190 },
michael@0 191 enabled: false,
michael@0 192 active: false,
michael@0 193 // Stepper specific functions.
michael@0 194 create: function create(pageIndex) {
michael@0 195 var debug = document.createElement('div');
michael@0 196 debug.id = 'stepper' + pageIndex;
michael@0 197 debug.setAttribute('hidden', true);
michael@0 198 debug.className = 'stepper';
michael@0 199 stepperDiv.appendChild(debug);
michael@0 200 var b = document.createElement('option');
michael@0 201 b.textContent = 'Page ' + (pageIndex + 1);
michael@0 202 b.value = pageIndex;
michael@0 203 stepperChooser.appendChild(b);
michael@0 204 var initBreakPoints = breakPoints[pageIndex] || [];
michael@0 205 var stepper = new Stepper(debug, pageIndex, initBreakPoints);
michael@0 206 steppers.push(stepper);
michael@0 207 if (steppers.length === 1) {
michael@0 208 this.selectStepper(pageIndex, false);
michael@0 209 }
michael@0 210 return stepper;
michael@0 211 },
michael@0 212 selectStepper: function selectStepper(pageIndex, selectPanel) {
michael@0 213 var i;
michael@0 214 if (selectPanel) {
michael@0 215 this.manager.selectPanel(this);
michael@0 216 }
michael@0 217 for (i = 0; i < steppers.length; ++i) {
michael@0 218 var stepper = steppers[i];
michael@0 219 if (stepper.pageIndex == pageIndex) {
michael@0 220 stepper.panel.removeAttribute('hidden');
michael@0 221 } else {
michael@0 222 stepper.panel.setAttribute('hidden', true);
michael@0 223 }
michael@0 224 }
michael@0 225 var options = stepperChooser.options;
michael@0 226 for (i = 0; i < options.length; ++i) {
michael@0 227 var option = options[i];
michael@0 228 option.selected = option.value == pageIndex;
michael@0 229 }
michael@0 230 },
michael@0 231 saveBreakPoints: function saveBreakPoints(pageIndex, bps) {
michael@0 232 breakPoints[pageIndex] = bps;
michael@0 233 sessionStorage.setItem('pdfjsBreakPoints', JSON.stringify(breakPoints));
michael@0 234 }
michael@0 235 };
michael@0 236 })();
michael@0 237
michael@0 238 // The stepper for each page's IRQueue.
michael@0 239 var Stepper = (function StepperClosure() {
michael@0 240 // Shorter way to create element and optionally set textContent.
michael@0 241 function c(tag, textContent) {
michael@0 242 var d = document.createElement(tag);
michael@0 243 if (textContent) {
michael@0 244 d.textContent = textContent;
michael@0 245 }
michael@0 246 return d;
michael@0 247 }
michael@0 248
michael@0 249 function glyphsToString(glyphs) {
michael@0 250 var out = '';
michael@0 251 for (var i = 0; i < glyphs.length; i++) {
michael@0 252 if (glyphs[i] === null) {
michael@0 253 out += ' ';
michael@0 254 } else {
michael@0 255 out += glyphs[i].fontChar;
michael@0 256 }
michael@0 257 }
michael@0 258 return out;
michael@0 259 }
michael@0 260
michael@0 261 var opMap = null;
michael@0 262
michael@0 263 var glyphCommands = {
michael@0 264 'showText': 0,
michael@0 265 'showSpacedText': 0,
michael@0 266 'nextLineShowText': 0,
michael@0 267 'nextLineSetSpacingShowText': 2
michael@0 268 };
michael@0 269
michael@0 270 function simplifyArgs(args) {
michael@0 271 if (typeof args === 'string') {
michael@0 272 var MAX_STRING_LENGTH = 75;
michael@0 273 return args.length <= MAX_STRING_LENGTH ? args :
michael@0 274 args.substr(0, MAX_STRING_LENGTH) + '...';
michael@0 275 }
michael@0 276 if (typeof args !== 'object' || args === null) {
michael@0 277 return args;
michael@0 278 }
michael@0 279 if ('length' in args) { // array
michael@0 280 var simpleArgs = [], i, ii;
michael@0 281 var MAX_ITEMS = 10;
michael@0 282 for (i = 0, ii = Math.min(MAX_ITEMS, args.length); i < ii; i++) {
michael@0 283 simpleArgs.push(simplifyArgs(args[i]));
michael@0 284 }
michael@0 285 if (i < args.length) {
michael@0 286 simpleArgs.push('...');
michael@0 287 }
michael@0 288 return simpleArgs;
michael@0 289 }
michael@0 290 var simpleObj = {};
michael@0 291 for (var key in args) {
michael@0 292 simpleObj[key] = simplifyArgs(args[key]);
michael@0 293 }
michael@0 294 return simpleObj;
michael@0 295 }
michael@0 296
michael@0 297 function Stepper(panel, pageIndex, initialBreakPoints) {
michael@0 298 this.panel = panel;
michael@0 299 this.breakPoint = 0;
michael@0 300 this.nextBreakPoint = null;
michael@0 301 this.pageIndex = pageIndex;
michael@0 302 this.breakPoints = initialBreakPoints;
michael@0 303 this.currentIdx = -1;
michael@0 304 this.operatorListIdx = 0;
michael@0 305 }
michael@0 306 Stepper.prototype = {
michael@0 307 init: function init() {
michael@0 308 var panel = this.panel;
michael@0 309 var content = c('div', 'c=continue, s=step');
michael@0 310 var table = c('table');
michael@0 311 content.appendChild(table);
michael@0 312 table.cellSpacing = 0;
michael@0 313 var headerRow = c('tr');
michael@0 314 table.appendChild(headerRow);
michael@0 315 headerRow.appendChild(c('th', 'Break'));
michael@0 316 headerRow.appendChild(c('th', 'Idx'));
michael@0 317 headerRow.appendChild(c('th', 'fn'));
michael@0 318 headerRow.appendChild(c('th', 'args'));
michael@0 319 panel.appendChild(content);
michael@0 320 this.table = table;
michael@0 321 if (!opMap) {
michael@0 322 opMap = Object.create(null);
michael@0 323 for (var key in PDFJS.OPS) {
michael@0 324 opMap[PDFJS.OPS[key]] = key;
michael@0 325 }
michael@0 326 }
michael@0 327 },
michael@0 328 updateOperatorList: function updateOperatorList(operatorList) {
michael@0 329 var self = this;
michael@0 330
michael@0 331 function cboxOnClick() {
michael@0 332 var x = +this.dataset.idx;
michael@0 333 if (this.checked) {
michael@0 334 self.breakPoints.push(x);
michael@0 335 } else {
michael@0 336 self.breakPoints.splice(self.breakPoints.indexOf(x), 1);
michael@0 337 }
michael@0 338 StepperManager.saveBreakPoints(self.pageIndex, self.breakPoints);
michael@0 339 }
michael@0 340
michael@0 341 var MAX_OPERATORS_COUNT = 15000;
michael@0 342 if (this.operatorListIdx > MAX_OPERATORS_COUNT) {
michael@0 343 return;
michael@0 344 }
michael@0 345
michael@0 346 var chunk = document.createDocumentFragment();
michael@0 347 var operatorsToDisplay = Math.min(MAX_OPERATORS_COUNT,
michael@0 348 operatorList.fnArray.length);
michael@0 349 for (var i = this.operatorListIdx; i < operatorsToDisplay; i++) {
michael@0 350 var line = c('tr');
michael@0 351 line.className = 'line';
michael@0 352 line.dataset.idx = i;
michael@0 353 chunk.appendChild(line);
michael@0 354 var checked = this.breakPoints.indexOf(i) != -1;
michael@0 355 var args = operatorList.argsArray[i] || [];
michael@0 356
michael@0 357 var breakCell = c('td');
michael@0 358 var cbox = c('input');
michael@0 359 cbox.type = 'checkbox';
michael@0 360 cbox.className = 'points';
michael@0 361 cbox.checked = checked;
michael@0 362 cbox.dataset.idx = i;
michael@0 363 cbox.onclick = cboxOnClick;
michael@0 364
michael@0 365 breakCell.appendChild(cbox);
michael@0 366 line.appendChild(breakCell);
michael@0 367 line.appendChild(c('td', i.toString()));
michael@0 368 var fn = opMap[operatorList.fnArray[i]];
michael@0 369 var decArgs = args;
michael@0 370 if (fn in glyphCommands) {
michael@0 371 var glyphIndex = glyphCommands[fn];
michael@0 372 var glyphs = args[glyphIndex];
michael@0 373 decArgs = args.slice();
michael@0 374 var newArg;
michael@0 375 if (fn === 'showSpacedText') {
michael@0 376 newArg = [];
michael@0 377 for (var j = 0; j < glyphs.length; j++) {
michael@0 378 if (typeof glyphs[j] === 'number') {
michael@0 379 newArg.push(glyphs[j]);
michael@0 380 } else {
michael@0 381 newArg.push(glyphsToString(glyphs[j]));
michael@0 382 }
michael@0 383 }
michael@0 384 } else {
michael@0 385 newArg = glyphsToString(glyphs);
michael@0 386 }
michael@0 387 decArgs[glyphIndex] = newArg;
michael@0 388 }
michael@0 389 line.appendChild(c('td', fn));
michael@0 390 line.appendChild(c('td', JSON.stringify(simplifyArgs(decArgs))));
michael@0 391 }
michael@0 392 if (operatorsToDisplay < operatorList.fnArray.length) {
michael@0 393 line = c('tr');
michael@0 394 var lastCell = c('td', '...');
michael@0 395 lastCell.colspan = 4;
michael@0 396 chunk.appendChild(lastCell);
michael@0 397 }
michael@0 398 this.operatorListIdx = operatorList.fnArray.length;
michael@0 399 this.table.appendChild(chunk);
michael@0 400 },
michael@0 401 getNextBreakPoint: function getNextBreakPoint() {
michael@0 402 this.breakPoints.sort(function(a, b) { return a - b; });
michael@0 403 for (var i = 0; i < this.breakPoints.length; i++) {
michael@0 404 if (this.breakPoints[i] > this.currentIdx) {
michael@0 405 return this.breakPoints[i];
michael@0 406 }
michael@0 407 }
michael@0 408 return null;
michael@0 409 },
michael@0 410 breakIt: function breakIt(idx, callback) {
michael@0 411 StepperManager.selectStepper(this.pageIndex, true);
michael@0 412 var self = this;
michael@0 413 var dom = document;
michael@0 414 self.currentIdx = idx;
michael@0 415 var listener = function(e) {
michael@0 416 switch (e.keyCode) {
michael@0 417 case 83: // step
michael@0 418 dom.removeEventListener('keydown', listener, false);
michael@0 419 self.nextBreakPoint = self.currentIdx + 1;
michael@0 420 self.goTo(-1);
michael@0 421 callback();
michael@0 422 break;
michael@0 423 case 67: // continue
michael@0 424 dom.removeEventListener('keydown', listener, false);
michael@0 425 var breakPoint = self.getNextBreakPoint();
michael@0 426 self.nextBreakPoint = breakPoint;
michael@0 427 self.goTo(-1);
michael@0 428 callback();
michael@0 429 break;
michael@0 430 }
michael@0 431 };
michael@0 432 dom.addEventListener('keydown', listener, false);
michael@0 433 self.goTo(idx);
michael@0 434 },
michael@0 435 goTo: function goTo(idx) {
michael@0 436 var allRows = this.panel.getElementsByClassName('line');
michael@0 437 for (var x = 0, xx = allRows.length; x < xx; ++x) {
michael@0 438 var row = allRows[x];
michael@0 439 if (row.dataset.idx == idx) {
michael@0 440 row.style.backgroundColor = 'rgb(251,250,207)';
michael@0 441 row.scrollIntoView();
michael@0 442 } else {
michael@0 443 row.style.backgroundColor = null;
michael@0 444 }
michael@0 445 }
michael@0 446 }
michael@0 447 };
michael@0 448 return Stepper;
michael@0 449 })();
michael@0 450
michael@0 451 var Stats = (function Stats() {
michael@0 452 var stats = [];
michael@0 453 function clear(node) {
michael@0 454 while (node.hasChildNodes()) {
michael@0 455 node.removeChild(node.lastChild);
michael@0 456 }
michael@0 457 }
michael@0 458 function getStatIndex(pageNumber) {
michael@0 459 for (var i = 0, ii = stats.length; i < ii; ++i) {
michael@0 460 if (stats[i].pageNumber === pageNumber) {
michael@0 461 return i;
michael@0 462 }
michael@0 463 }
michael@0 464 return false;
michael@0 465 }
michael@0 466 return {
michael@0 467 // Properties/functions needed by PDFBug.
michael@0 468 id: 'Stats',
michael@0 469 name: 'Stats',
michael@0 470 panel: null,
michael@0 471 manager: null,
michael@0 472 init: function init() {
michael@0 473 this.panel.setAttribute('style', 'padding: 5px;');
michael@0 474 PDFJS.enableStats = true;
michael@0 475 },
michael@0 476 enabled: false,
michael@0 477 active: false,
michael@0 478 // Stats specific functions.
michael@0 479 add: function(pageNumber, stat) {
michael@0 480 if (!stat) {
michael@0 481 return;
michael@0 482 }
michael@0 483 var statsIndex = getStatIndex(pageNumber);
michael@0 484 if (statsIndex !== false) {
michael@0 485 var b = stats[statsIndex];
michael@0 486 this.panel.removeChild(b.div);
michael@0 487 stats.splice(statsIndex, 1);
michael@0 488 }
michael@0 489 var wrapper = document.createElement('div');
michael@0 490 wrapper.className = 'stats';
michael@0 491 var title = document.createElement('div');
michael@0 492 title.className = 'title';
michael@0 493 title.textContent = 'Page: ' + pageNumber;
michael@0 494 var statsDiv = document.createElement('div');
michael@0 495 statsDiv.textContent = stat.toString();
michael@0 496 wrapper.appendChild(title);
michael@0 497 wrapper.appendChild(statsDiv);
michael@0 498 stats.push({ pageNumber: pageNumber, div: wrapper });
michael@0 499 stats.sort(function(a, b) { return a.pageNumber - b.pageNumber; });
michael@0 500 clear(this.panel);
michael@0 501 for (var i = 0, ii = stats.length; i < ii; ++i) {
michael@0 502 this.panel.appendChild(stats[i].div);
michael@0 503 }
michael@0 504 },
michael@0 505 cleanup: function () {
michael@0 506 stats = [];
michael@0 507 clear(this.panel);
michael@0 508 }
michael@0 509 };
michael@0 510 })();
michael@0 511
michael@0 512 // Manages all the debugging tools.
michael@0 513 var PDFBug = (function PDFBugClosure() {
michael@0 514 var panelWidth = 300;
michael@0 515 var buttons = [];
michael@0 516 var activePanel = null;
michael@0 517
michael@0 518 return {
michael@0 519 tools: [
michael@0 520 FontInspector,
michael@0 521 StepperManager,
michael@0 522 Stats
michael@0 523 ],
michael@0 524 enable: function(ids) {
michael@0 525 var all = false, tools = this.tools;
michael@0 526 if (ids.length === 1 && ids[0] === 'all') {
michael@0 527 all = true;
michael@0 528 }
michael@0 529 for (var i = 0; i < tools.length; ++i) {
michael@0 530 var tool = tools[i];
michael@0 531 if (all || ids.indexOf(tool.id) !== -1) {
michael@0 532 tool.enabled = true;
michael@0 533 }
michael@0 534 }
michael@0 535 if (!all) {
michael@0 536 // Sort the tools by the order they are enabled.
michael@0 537 tools.sort(function(a, b) {
michael@0 538 var indexA = ids.indexOf(a.id);
michael@0 539 indexA = indexA < 0 ? tools.length : indexA;
michael@0 540 var indexB = ids.indexOf(b.id);
michael@0 541 indexB = indexB < 0 ? tools.length : indexB;
michael@0 542 return indexA - indexB;
michael@0 543 });
michael@0 544 }
michael@0 545 },
michael@0 546 init: function init() {
michael@0 547 /*
michael@0 548 * Basic Layout:
michael@0 549 * PDFBug
michael@0 550 * Controls
michael@0 551 * Panels
michael@0 552 * Panel
michael@0 553 * Panel
michael@0 554 * ...
michael@0 555 */
michael@0 556 var ui = document.createElement('div');
michael@0 557 ui.id = 'PDFBug';
michael@0 558
michael@0 559 var controls = document.createElement('div');
michael@0 560 controls.setAttribute('class', 'controls');
michael@0 561 ui.appendChild(controls);
michael@0 562
michael@0 563 var panels = document.createElement('div');
michael@0 564 panels.setAttribute('class', 'panels');
michael@0 565 ui.appendChild(panels);
michael@0 566
michael@0 567 var container = document.getElementById('viewerContainer');
michael@0 568 container.appendChild(ui);
michael@0 569 container.style.right = panelWidth + 'px';
michael@0 570
michael@0 571 // Initialize all the debugging tools.
michael@0 572 var tools = this.tools;
michael@0 573 var self = this;
michael@0 574 for (var i = 0; i < tools.length; ++i) {
michael@0 575 var tool = tools[i];
michael@0 576 var panel = document.createElement('div');
michael@0 577 var panelButton = document.createElement('button');
michael@0 578 panelButton.textContent = tool.name;
michael@0 579 panelButton.addEventListener('click', (function(selected) {
michael@0 580 return function(event) {
michael@0 581 event.preventDefault();
michael@0 582 self.selectPanel(selected);
michael@0 583 };
michael@0 584 })(i));
michael@0 585 controls.appendChild(panelButton);
michael@0 586 panels.appendChild(panel);
michael@0 587 tool.panel = panel;
michael@0 588 tool.manager = this;
michael@0 589 if (tool.enabled) {
michael@0 590 tool.init();
michael@0 591 } else {
michael@0 592 panel.textContent = tool.name + ' is disabled. To enable add ' +
michael@0 593 ' "' + tool.id + '" to the pdfBug parameter ' +
michael@0 594 'and refresh (seperate multiple by commas).';
michael@0 595 }
michael@0 596 buttons.push(panelButton);
michael@0 597 }
michael@0 598 this.selectPanel(0);
michael@0 599 },
michael@0 600 cleanup: function cleanup() {
michael@0 601 for (var i = 0, ii = this.tools.length; i < ii; i++) {
michael@0 602 if (this.tools[i].enabled) {
michael@0 603 this.tools[i].cleanup();
michael@0 604 }
michael@0 605 }
michael@0 606 },
michael@0 607 selectPanel: function selectPanel(index) {
michael@0 608 if (typeof index !== 'number') {
michael@0 609 index = this.tools.indexOf(index);
michael@0 610 }
michael@0 611 if (index === activePanel) {
michael@0 612 return;
michael@0 613 }
michael@0 614 activePanel = index;
michael@0 615 var tools = this.tools;
michael@0 616 for (var j = 0; j < tools.length; ++j) {
michael@0 617 if (j == index) {
michael@0 618 buttons[j].setAttribute('class', 'active');
michael@0 619 tools[j].active = true;
michael@0 620 tools[j].panel.removeAttribute('hidden');
michael@0 621 } else {
michael@0 622 buttons[j].setAttribute('class', '');
michael@0 623 tools[j].active = false;
michael@0 624 tools[j].panel.setAttribute('hidden', 'true');
michael@0 625 }
michael@0 626 }
michael@0 627 }
michael@0 628 };
michael@0 629 })();

mercurial