开发者

How to print ExtJS component?

How do I pop up t开发者_Go百科he Print dialog that will print out a component when OK-ed?


                    var targetElement = Ext.getCmp('PrintablePanelId');
                    var myWindow = window.open('', '', 'width=200,height=100');
                    myWindow.document.write('<html><head>');
                    myWindow.document.write('<title>' + 'Title' + '</title>');
                    myWindow.document.write('<link rel="Stylesheet" type="text/css" href="http://dev.sencha.com/deploy/ext-4.0.1/resources/css/ext-all.css" />');
                    myWindow.document.write('<script type="text/javascript" src="http://dev.sencha.com/deploy/ext-4.0.1/bootstrap.js"></script>');
                    myWindow.document.write('</head><body>');
                    myWindow.document.write(targetElement.body.dom.innerHTML);
                    myWindow.document.write('</body></html>');
                    myWindow.print();

write your extjs printable component into document.


I like Gopal Saini's answer! I took his approach and wrote a function for one of my apps. Here's the code. Tested on FF and Safari. Haven't tried it on IE but it should work.

print: function(el){

    var win = window.open('', '', 'width='+el.getWidth()+',height='+el.getHeight());
    if (win==null){
        alert("Pop-up is blocked!");
        return;
    }


    Ext.Ajax.request({

        url: window.location.href,
        method: "GET",
        scope: this,
        success: function(response){

            var html = response.responseText;
            var xmlDoc;
            if (window.DOMParser){
                xmlDoc = new DOMParser().parseFromString(html,"text/xml");
            }
            else{
                xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
                xmlDoc.async = false;
                xmlDoc.loadXML(html);
            }


            win.document.write('<html><head>');
            win.document.write('<title>' + document.title + '</title>');


            var xml2string = function(node) {
               if (typeof(XMLSerializer) !== 'undefined') {
                  var serializer = new XMLSerializer();
                  return serializer.serializeToString(node);
               } else if (node.xml) { 
                  return node.xml;
               }
            }


            var links = xmlDoc.getElementsByTagName("link");
            for (var i=0; i<links.length; i++){
                win.document.write(xml2string(links[i]));
            }

            win.document.write('</head><body>');
            win.document.write(el.dom.innerHTML);
            win.document.write('</body></html>');
            win.print();
        },
        failure: function(response){
            win.close();
        }
    });
}


ExtJS 4.1: https://github.com/loiane/extjs4-ux-gridprinter


Printing in ExtJS is not paticularly easy. The best resource I've found on making components printable can be found on a Sencha architect's blog. The post describes how to set up custom print renderers for components, and other details about printing. However, this information is for ExtJS 3.x; it's possible that ExtJS 4 has made printing easier.


You can also add a component to be printed to the Ext.window.Window with a modal property set to true and just open a standard print dialog which will only print the desired component.

var view = this.getView();
var extWindow = Ext.create('Ext.window.Window', { modal: true });
extWindow.add(component); // move component from the original panel to the popup window
extWindow.show();

window.print(); // prints only the content of a modal window

// push events to the event queue to be fired on the print dialog close
setTimeout(function() {
    view.add(component); // add component back to the original panel
    extWindow.close();
}, 0);


Another option to consider is to render the component to an image or pdf. While the pop-up window/print option is nice, some browsers don't print correctly. They tend to ignore background images, certain css properties, etc. To get the component to print exactly the way it appears in the pop-up window, I ended up writing some server side code to transform the html into an image.

Here's what the client code looks like:

print: function(el){

    var waitMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
    waitMask.show();


  //Parse current url to set up the host and path variables. These will be
  //used to construct absolute urls to any stylesheets.
    var currURL = window.location.href.toString();
    var arr = currURL.split("/");
    var len = 0;
    for (var i=0; i<arr.length; i++){
        if (i<3) len+=(arr[i].length+1);
    }
    var host = currURL.substring(0, len);
    if (host.substring(host.length-1)=="/") host = host.substring(0, host.length-1);

    var path = window.location.pathname;
    if (path.lastIndexOf("/")!=path.length-1){
        var filename = path.substring(path.lastIndexOf("/")+1);
        if (filename.indexOf(".")!=-1){
            path = path.substring(0, path.lastIndexOf("/")+1);
        }
        else{
            path += "/";
        }
    }


  //Start constructing an html document that we will send to the server
    var html = ('<html><head>');
    html += ('<title>' + document.title + '</title>');


  //Insert stylesheets found in the current page. Update href attributes
  //to absolute URLs as needed.
    var links = document.getElementsByTagName("link");
    for (var i=0; i<links.length; i++){
        var attr = links[i].attributes;
        if (attr.getNamedItem("rel")!=null){

            var rel = attr.getNamedItem("rel").value;
            var type = attr.getNamedItem("type").value;
            var href = attr.getNamedItem("href").value;

            if (href.toLowerCase().indexOf("http")!=0){
                if (href.toString().substring(0, 1)=="/"){
                    href = host + href;
                }
                else{
                    href = host + path + href;
                }
            }

            html += ('<link type="' + type + '" rel="' + rel+ '" href="' + href + '"/>');
        }
    }

    html += ('</head><body id="print">');
    html += (el.dom.innerHTML);
    html += ('</body></html>');


  //Execute AJAX request to convert the html into an image or pdf -
  //something that will preserve styles, background images, etc.
  //This, of course, requires some server-side code. In our case,
  //our server is generating a png that we return to the client.
    Ext.Ajax.request({

        url: "/WebServices/Print?action=submit",
        method: "POST",
        rawData: html,
        scope: this,
        success: function(response){
            var url = "/WebServices/Print?action=pickup&id="+response.responseText;
            window.location.href = url;
            waitMask.hide();
        },
        failure: function(response){
            win.close();
            waitMask.hide();
            var msg = (response.responseText.length>0 ? response.responseText : response.statusText);
            alert(msg);
        }
    });
}

Again, this requires some server-side magic to transform the html into an image. In my case, I implemented a "Print" service. Clients submit job requests via the "submit" action and retrieve output products via the "pickup" action.

To convert html to images, I ended up using a free command line app called Web Screen Capture. It only works on windows and I don't know how scalable it is so use at your risk.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜