/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ /* Copyright 2013 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 HTMLCanvasElement */ 'use strict'; (function mozPrintCallbackPolyfillClosure() { if ('mozPrintCallback' in document.createElement('canvas')) { return; } // Cause positive result on feature-detection: HTMLCanvasElement.prototype.mozPrintCallback = undefined; var canvases; // During print task: non-live NodeList of elements var index; // Index of element that is being processed var print = window.print; window.print = function print() { if (canvases) { console.warn('Ignored window.print() because of a pending print job.'); return; } try { dispatchEvent('beforeprint'); } finally { canvases = document.querySelectorAll('canvas'); index = -1; next(); } }; function dispatchEvent(eventType) { var event = document.createEvent('CustomEvent'); event.initCustomEvent(eventType, false, false, 'custom'); window.dispatchEvent(event); } function next() { if (!canvases) { return; // Print task cancelled by user (state reset in abort()) } renderProgress(); if (++index < canvases.length) { var canvas = canvases[index]; if (typeof canvas.mozPrintCallback === 'function') { canvas.mozPrintCallback({ context: canvas.getContext('2d'), abort: abort, done: next }); } else { next(); } } else { renderProgress(); print.call(window); setTimeout(abort, 20); // Tidy-up } } function abort() { if (canvases) { canvases = null; renderProgress(); dispatchEvent('afterprint'); } } function renderProgress() { var progressContainer = document.getElementById('mozPrintCallback-shim'); if (canvases) { var progress = Math.round(100 * index / canvases.length); var progressBar = progressContainer.querySelector('progress'); var progressPerc = progressContainer.querySelector('.relative-progress'); progressBar.value = progress; progressPerc.textContent = progress + '%'; progressContainer.removeAttribute('hidden'); progressContainer.onclick = abort; } else { progressContainer.setAttribute('hidden', ''); } } var hasAttachEvent = !!document.attachEvent; window.addEventListener('keydown', function(event) { // Intercept Cmd/Ctrl + P in all browsers. // Also intercept Cmd/Ctrl + Shift + P in Chrome and Opera if (event.keyCode === 80/*P*/ && (event.ctrlKey || event.metaKey) && !event.altKey && (!event.shiftKey || window.chrome || window.opera)) { window.print(); if (hasAttachEvent) { // Only attachEvent can cancel Ctrl + P dialog in IE <=10 // attachEvent is gone in IE11, so the dialog will re-appear in IE11. return; } event.preventDefault(); if (event.stopImmediatePropagation) { event.stopImmediatePropagation(); } else { event.stopPropagation(); } return; } if (event.keyCode === 27 && canvases) { // Esc abort(); } }, true); if (hasAttachEvent) { document.attachEvent('onkeydown', function(event) { event = event || window.event; if (event.keyCode === 80/*P*/ && event.ctrlKey) { event.keyCode = 0; return false; } }); } if ('onbeforeprint' in window) { // Do not propagate before/afterprint events when they are not triggered // from within this polyfill. (FF/IE). var stopPropagationIfNeeded = function(event) { if (event.detail !== 'custom' && event.stopImmediatePropagation) { event.stopImmediatePropagation(); } }; window.addEventListener('beforeprint', stopPropagationIfNeeded, false); window.addEventListener('afterprint', stopPropagationIfNeeded, false); } })();