3

I am using a jquery plugin called printElement:

http://projects.erikzaadi.com/jQueryPlugins/jQuery.printElement/

It's working on the first click just as it should but upon further clicks (after closing the pop up window) it continues to pop up windows. On the second click it pops up four times, on the third click I'm lucky enough to get 36 pop ups. Each show after I've closed the previous pop up window. I've tried bind() and unbind() and event.stopPropagation() without any change.

Here is where I call it:

$('a[href="#print"]').click(function(){$("body").printElement();});

and here is the plugin code:

/// <reference path="http://code.jquery.com/jquery-1.4.1-vsdoc.js" />
/*
* Print Element Plugin 1.2
*
* Copyright (c) 2010 Erik Zaadi
*
* Inspired by PrintArea (http://plugins.jquery.com/project/PrintArea) and
* http://stackoverflow.com/questions/472951/how-do-i-print-an-iframe-from-javascript-     in-safari-chrome
*
*  Home Page : http://projects.erikzaadi/jQueryPlugins/jQuery.printElement 
*  Issues (bug reporting) :      http://github.com/erikzaadi/jQueryPlugins/issues/labels/printElement
*  jQuery plugin page : http://plugins.jquery.com/project/printElement 
*  
*  Thanks to David B (http://github.com/ungenio) and icgJohn  (http://www.blogger.com/profile/11881116857076484100)
*  For their great contributions!
* 
* Dual licensed under the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
*   
*   Note, Iframe Printing is not supported in Opera and Chrome 3.0, a popup window will be shown instead
*/
; (function (window, undefined) {
var document = window["document"];
var $ = window["jQuery"];
$.fn["printElement"] = function (options) {
    var mainOptions = $.extend({}, $.fn["printElement"]["defaults"], options);
    //iframe mode is not supported for opera and chrome 3.0 (it prints the entire page).
    //http://www.google.com/support/forum/p/Webmasters/thread?tid=2cb0f08dce8821c3&hl=en
    if (mainOptions["printMode"] == 'iframe') {
        if ($.browser.opera || (/chrome/.test(navigator.userAgent.toLowerCase())))
            mainOptions["printMode"] = 'popup';
    }
    //Remove previously printed iframe if exists
    $("[id^='printElement_']").remove();

    return this.each(function () {
        //Support Metadata Plug-in if available
        var opts = $.meta ? $.extend({}, mainOptions, $(this).data()) : mainOptions;
        _printElement($(this), opts);
    });
};
$.fn["printElement"]["defaults"] = {
    "printMode": 'iframe', //Usage : iframe / popup
    "pageTitle": '', //Print Page Title
    "overrideElementCSS": null,
    /* Can be one of the following 3 options:
    * 1 : boolean (pass true for stripping all css linked)
    * 2 : array of $.fn.printElement.cssElement (s)
    * 3 : array of strings with paths to alternate css files (optimized for print)
    */
    "printBodyOptions": {
        "styleToAdd": 'padding:10px;margin:10px;', //style attributes to add to the body of print document
        "classNameToAdd": '' //css class to add to the body of print document
    },
    "leaveOpen": false, // in case of popup, leave the print page open or not
    "iframeElementOptions": {
        "styleToAdd": 'border:none;position:absolute;width:0px;height:0px;bottom:0px;left:0px;', //style attributes to add to the iframe element
        "classNameToAdd": '' //css class to add to the iframe element
    }
};
$.fn["printElement"]["cssElement"] = {
    "href": '',
    "media": ''
};
function _printElement(element, opts) {
    //Create markup to be printed
    var html = _getMarkup(element, opts);

    var popupOrIframe = null;
    var documentToWriteTo = null;
    if (opts["printMode"].toLowerCase() == 'popup') {
        popupOrIframe = window.open('about:blank', 'printElementWindow', 'width=650,height=440,scrollbars=yes');
        documentToWriteTo = popupOrIframe.document;
    }
    else {
        //The random ID is to overcome a safari bug http://www.cjboco.com.sharedcopy.com/post.cfm/442dc92cd1c0ca10a5c35210b8166882.html
        var printElementID = "printElement_" + (Math.round(Math.random() * 99999)).toString();
        //Native creation of the element is faster..
        var iframe = document.createElement('IFRAME');
        $(iframe).attr({
            style: opts["iframeElementOptions"]["styleToAdd"],
            id: printElementID,
            className: opts["iframeElementOptions"]["classNameToAdd"],
            frameBorder: 0,
            scrolling: 'no',
            src: 'about:blank'
        });
        document.body.appendChild(iframe);
        documentToWriteTo = (iframe.contentWindow || iframe.contentDocument);
        if (documentToWriteTo.document)
            documentToWriteTo = documentToWriteTo.document;
        iframe = document.frames ? document.frames[printElementID] : document.getElementById(printElementID);
        popupOrIframe = iframe.contentWindow || iframe;
    }
    focus();
    documentToWriteTo.open();
    documentToWriteTo.write(html);
    documentToWriteTo.close();
    _callPrint(popupOrIframe);
};

function _callPrint(element) {
    if (element && element["printPage"])
        element["printPage"]();
    else
        setTimeout(function () {
            _callPrint(element);
        }, 50);
}

function _getElementHTMLIncludingFormElements(element) {
    var $element = $(element);
    //Radiobuttons and checkboxes
    $(":checked", $element).each(function () {
        this.setAttribute('checked', 'checked');
    });
    //simple text inputs
    $("input[type='text']", $element).each(function () {
        this.setAttribute('value', $(this).val());
    });
    $("select", $element).each(function () {
        var $select = $(this);
        $("option", $select).each(function () {
            if ($select.val() == $(this).val())
                this.setAttribute('selected', 'selected');
        });
    });
    $("textarea", $element).each(function () {
        //Thanks http://blog.ekini.net/2009/02/24/jquery-getting-the-latest-textvalue-inside-a-textarea/
        var value = $(this).attr('value');
        //fix for issue 7 (http://plugins.jquery.com/node/13503 and http://github.com/erikzaadi/jQueryPlugins/issues#issue/7)
        if ($.browser.mozilla && this.firstChild)
            this.firstChild.textContent = value;
        else
            this.innerHTML = value;
    });
    //http://dbj.org/dbj/?p=91
    var elementHtml = $('<div></div>').append($element.clone()).html();
    return elementHtml;
}

function _getBaseHref() {
    var port = (window.location.port) ? ':' + window.location.port : '';
    return window.location.protocol + '//' + window.location.hostname + port + window.location.pathname;
}

function _getMarkup(element, opts) {
    var $element = $(element);
    var elementHtml = _getElementHTMLIncludingFormElements(element);

    var html = new Array();
    html.push('<html><head><title>' + opts["pageTitle"] + '</title>');
    if (opts["overrideElementCSS"]) {
        if (opts["overrideElementCSS"].length > 0) {
            for (var x = 0; x < opts["overrideElementCSS"].length; x++) {
                var current = opts["overrideElementCSS"][x];
                if (typeof (current) == 'string')
                    html.push('<link type="text/css" rel="stylesheet" href="' + current + '" >');
                else
                    html.push('<link type="text/css" rel="stylesheet" href="' + current["href"] + '" media="' + current["media"] + '" >');
            }
        }
    }
    else {
        $("link", document).filter(function () {
            return $(this).attr("rel").toLowerCase() == "stylesheet";
        }).each(function () {
            html.push('<link type="text/css" rel="stylesheet" href="' + $(this).attr("href") + '" media="' + $(this).attr('media') + '" >');
        });
    }
    //Ensure that relative links work
    html.push('<base href="' + _getBaseHref() + '" />');
    html.push('</head><body style="' + opts["printBodyOptions"]["styleToAdd"] + '" class="' + opts["printBodyOptions"]["classNameToAdd"] + '">');
    html.push('<div class="' + $element.attr('class') + '">' + elementHtml + '</div>');
    html.push('<script type="text/javascript">function printPage(){focus();print();' + ((!$.browser.opera && !opts["leaveOpen"] && opts["printMode"].toLowerCase() == 'popup') ? 'close();' : '') + '}</script>');
    html.push('</body></html>');

    return html.join('');
};
})(window);

I've tried this bit of code:

$('a[href="#print"]').bind( "click", function() {
$("body").printElement();
});

this:

$('a[href="#print"]').unbind().bind( "click", function() {
$("body").printElement();
});

this:

 $('a[href="#print"]').unbind("click").bind( "click", function() {
$("body").printElement();
});

this:

  $('a[href="#print"]').click(function(e){
      e.stopPropagation();
      $("body").printElement();
   });

this:

  $('a[href="#print"]').click(function(e){
      e.stopImmediatePropagation();
      $("body").printElement();
   });

this:

$('a[href="#print"]').on( "click", function() {
$("body").printElement();
});

and I've thrown in the stopPropgation method in with the bind methods in various combinations. They all continue to work the first time and fire multiple times afterwards.

Fletchling
  • 177
  • 10
  • Are you initializing plugin inside a handler or a function? Are you sure you are not calling it more than once? – A. Wolff Sep 24 '13 at 17:51
  • 3
    This sounds like it's not a problem with the plugin, but with your code binding click handlers multiple times – Jason P Sep 24 '13 at 17:54
  • @ A. Wolff - It's called inside a document.ready function. And I have not seen any evidence of it being called more than once. – Fletchling Sep 24 '13 at 17:57
  • @JasonP - If this was the case wouldn't this fix it? $('a[href="#print"]').unbind().click(function(){$("body").printElement();}); – Fletchling Sep 24 '13 at 17:58
  • @Fletchling If you changed that to `.unbind('click')`, maybe. Try the code in this fiddle and see how many times the statement gets logged: http://jsfiddle.net/EBDSA/ – Jason P Sep 24 '13 at 18:00
  • @JasonP - Sorry, yes I meant `unbind()`. Oddly enough that didn't write "printing" in my console at all. Tried Chrome and FF just in case one was being shady. – Fletchling Sep 24 '13 at 18:14
  • 1
    In [jsfiddle](http://jsfiddle.net/fw4wW/) everything works fine. It doesn't render HTML properly in popup but that's the jsfiddle problem I couldn't resolve. It treats html tags generated in JS as they were outside `'` and gives a warning, though popup opens exactly once on every click. – matewka Sep 24 '13 at 21:34
  • [Here's jsfiddle](http://jsfiddle.net/fw4wW/1/) with correctly rendered popup window. Everything works fine. I guess your problem is somewhere beyond the code you provided. – matewka Sep 24 '13 at 21:40

2 Answers2

0

This is a complete guess but is probably worth trying: Is this code inside body?

$('a[href="#print"]').click(function(){$("body").printElement();});

The plugin copies all the content from body (in your case) and reproduces in an iframe, which might be evaluating the event binding every time the plugin runs, creating a loop. Try moving the code above outside the area you are printing (body).

Hugo Silva
  • 6,748
  • 3
  • 25
  • 42
  • That's an interesting thought as it is in a js file at the bottom of the body. But, that didn't fix it. I still appreciate the help though. – Fletchling Sep 25 '13 at 15:29
0

This solved it:

$('a[href="#print"]').one( "click", function() {
    $("body").printElement();
});

When I read the documentation here, I took it as, it would fire when I clicked the link the first time and if I clicked it again nothing would happen. But, desperation forced me to try and it's working now. Thank you all for trying to help me out.

Fletchling
  • 177
  • 10