/*! * googoose 1.0.2 * https://github.com/aadel112/googoose/js/jquery.googoose.js * @license Apache 2.0 * * Copyright (C) 2016 - aadel112.com - A project by Aaron Adel */ (function ( $ ) { $.fn.googoose = function( options, callback ) { var GG = this; var now = new Date().getTime(); var proto = new RegExp(/^(http|https|file):/); var ab = new RegExp(/^\//); GG.finish = function() { if( options.debug ) GG.debug_fn('finish action'); if (callback) { var blob = new Blob([options.html], { type: 'application/msword' }); callback(null, blob); } else { GG.saveHtmlAsFile(options.filename, options.html); } } var options = $.extend({ // These are the defaults. area: 'div.googoose-wrapper', headerfooterid: 'googoose-hdrftrtbl', margins: '1.0in', zoom: '75', filename: 'Doc1_' + now + '.doc', size: '8.5in 11.0in', display: 'Print', lang: 'en-US', toc: 'div.googoose.toc', pagebreak: 'div.googoose.break', headerarea: 'div.googoose.headerr', footerarea: 'div.googoose.footerr', headerid: 'googoose-headerr', footerid: 'googoose-footerr', headermargin: '.5in', footermargin: '.5in', currentpage: 'span.googoose.currentpage', totalpage: 'span.googoose.totalpage', finishaction: GG.finish, html: null, initobj: document, debugtype: 'alert', debug: 0, maxWidth: 624 }, options ); GG.options = options; //http://requiremind.com/memoization-speed-up-your-javascript-performance/ GG.memoize = function(fn, resolver) { var memoized = function() { resolver = resolver || JSON.stringify; var cache = memoized.cache; var args = Array.prototype.slice.call(arguments); var key = resolver.apply(this, args); if(key in cache) { GG.debug_fn('hit cache'); return cache[key]; } var result = fn.apply(this, arguments); cache[key] = result; return result; }; memoized.cache = {}; return memoized; } GG.debug_fn = function( args ) { options.debugtype == 'console' ? console.log( args ) : alert( args ); } //http://stackoverflow.com/questions/18755750/saving-text-in-a-local-file-in-internet-explorer-10 GG.saveHtmlAsFile = function( fileNameToSaveAs, textToWrite ) { /* Saves a text string as a blob file*/ var ie = navigator.userAgent.match(/MSIE\s([\d.]+)/), ie11 = navigator.userAgent.match(/Trident\/7.0/) && navigator.userAgent.match(/rv:11/), ieEDGE = navigator.userAgent.match(/Edge/g), ieVer=(ie ? ie[1] : (ie11 ? 11 : (ieEDGE ? 12 : -1))); if (ie && ieVer<10) { console.log("No blobs on IE ver<10"); return; } var textFileAsBlob = new Blob([textToWrite], { type: 'application/msword' }); if (ieVer>-1) { window.navigator.msSaveBlob(textFileAsBlob, fileNameToSaveAs); } else { var downloadLink = document.createElement("a"); downloadLink.download = fileNameToSaveAs; downloadLink.href = window.URL.createObjectURL(textFileAsBlob); downloadLink.onclick = function(e) { document.body.removeChild(e.target); }; downloadLink.style.display = "none"; document.body.appendChild(downloadLink); downloadLink.click(); } } // http://stackoverflow.com/questions/7394748/whats-the-right-way-to-decode-a-string-that-has-special-html-entities-in-it GG.decodeHtmlEntity = function(str) { return str.replace(/&#(\d+);/g, function(match, dec) { return String.fromCharCode(dec); }); } GG.translate_mso_features = function( html ) { if( options.debug ) GG.debug_fn('GG.translate_mso_features'); html = GG.decodeHtmlEntity(html); html = GG.remove_bad_tags(html); html = GG.convert_pagebreaks(html); html = GG.convert_toc(html); html = GG.convert_hdrftr(html); html = GG.convert_imgs(html); return html; } GG.remove_bad_tags = function( html ) { if( options.debug ) GG.debug_fn('GG.remove_bad_tags'); var thtml = $(html); thtml.find('noscript').each(function() { $(this).replaceWith(''); }); thtml.each(function() { if($(this).is(':hidden')){ $(this).remove(); } }); html = thtml[0].outerHTML; return html; } GG.convert_pagebreaks = function( html ) { if( options.debug ) GG.debug_fn('GG.convert_pagebreaks'); //user decides in html what will be a page break in word, this converts to a page break if( options.pagebreak ) { var thtml = $(html); thtml.find(options.pagebreak).replaceWith(GG.get_pagebreak()); html = thtml[0].outerHTML; } return html; } GG.convert_toc = function( html ) { if( options.debug ) GG.debug_fn('GG.convert_toc'); //user determines in html what will be the toc in word if( options.toc && $(options.toc).length ) { var thtml = $(html); thtml.find(options.toc).replaceWith(GG.get_toc_contents()); html = thtml[0].outerHTML; } return html; } GG.convert_hdrftr = function (html) { if (options.debug) GG.debug_fn('GG.convert_hdrftr'); var hvis = options.headerarea && $(options.headerarea).length; var fvis = options.footerarea && $(options.footerarea).length; if (hvis || fvis) { var thtml = $('
' + html + '
'); var hdrftr = $('
'); hdrftr.append('
'); thtml.append(hdrftr); html = thtml[0].outerHTML; html = GG.convert_totalpage(html); html = GG.convert_currentpage(html); } var thtml = $(html); if (hvis) { var new_header = thtml.find(options.headerarea)[0].outerHTML; thtml.find(options.headerarea)[0].replaceWith(''); thtml.find('#' + options.headerfooterid + ' .h').append( GG.headerstart() + new_header + GG.headerend()); html = thtml[0].outerHTML; } if (fvis) { var new_footer = thtml.find(options.footerarea)[0].outerHTML; thtml.find(options.footerarea)[0].replaceWith(''); thtml.find('#' + options.headerfooterid + ' .f').append( GG.footerstart() + new_footer + GG.footerend()); html = thtml[0].outerHTML; } return html; } //ORIGINAL FUNCTION //GG.convert_imgs = function( html ) { // if( options.debug ) // GG.debug_fn('GG.convert_imgs'); // //make sure all standard images use absolute path // var thtml = $(html); // imgs = thtml.find('img'); // imgs.each(function() { // var src = $(this)[0].src; // var l = window.location; // var t = l.protocol + '//' + l.host + '/'; // if( proto.test( src ) ) { // } // else if (ab.test(src)) { // src = t + src; // } // else { // var p = l.path.replace('/\/[^\/.]+$/', '/' ); // src = t + p + src; // } // $(this).attr( 'src', src ); // }); // html = thtml[0].outerHTML; // return html; //} GG.convert_imgs = function( html ) { if( options.debug ) GG.debug_fn('GG.convert_imgs'); var thtml = $(html); // Embed all images using Data URLs var images = Array(); var img = thtml.find('img'); for (var i = 0; i < img.length; i++) { // Calculate dimensions of output image var w = Math.min(img[i].width, options.maxWidth); var h = img[i].height * (w / img[i].width); // Create canvas for converting image to data URL var canvas = document.createElement("CANVAS"); canvas.width = w; canvas.height = h; // Draw image to canvas var context = canvas.getContext('2d'); context.drawImage(img[i], 0, 0, w, h); // Get data URL encoding of image var uri = canvas.toDataURL("image/png"); $(img[i]).attr("src", img[i].src); img[i].width = w; img[i].height = h; // Save encoded image to array images[i] = { type: uri.substring(uri.indexOf(":") + 1, uri.indexOf(";")), encoding: uri.substring(uri.indexOf(";") + 1, uri.indexOf(",")), location: $(img[i]).attr("src"), data: uri.substring(uri.indexOf(",") + 1) }; } // Prepare bottom of mhtml file with image data var mhtmlBottom = "\n"; for (var i = 0; i < images.length; i++) { mhtmlBottom += "--NEXT.ITEM-BOUNDARY\n"; mhtmlBottom += "Content-Location: " + images[i].location + "\n"; mhtmlBottom += "Content-Type: " + images[i].type + "\n"; mhtmlBottom += "Content-Transfer-Encoding: " + images[i].encoding + "\n\n"; mhtmlBottom += images[i].data + "\n\n"; } mhtmlBottom += "--NEXT.ITEM-BOUNDARY--"; html = thtml[0].outerHTML; return html + mhtmlBottom; } GG.convert_totalpage = function(html) { if( options.debug ) GG.debug_fn('GG.convert_totalpage'); if( options.totalpage && $(options.totalpage).length ) { var thtml = $(html); thtml.find(options.totalpage).html(''); thtml.find(options.totalpage).append( GG.get_total_page_number() ); html = thtml[0].outerHTML; } return html; } GG.convert_currentpage = function(html) { if( options.debug ) GG.debug_fn('GG.convert_currentpage'); if( options.currentpage && $(options.currentpage).length ) { var thtml = $(html); thtml.find(options.currentpage).html(''); thtml.find(options.currentpage).append( GG.get_page_number() ); html = thtml[0].outerHTML; } return html; } GG.get_pagebreak = function() { if( options.debug ) GG.debug_fn('GG.get_pagebreak'); return '
'; } GG.headerstart = function() { var html = ''; html += '\n
\n'; html += '

\n'; return html; } GG.headerend = function() { if( options.debug ) GG.debug_fn('GG.headerend'); return '

\n'; } GG.footerstart = function() { if( options.debug ) GG.debug_fn('GG.footerstart'); var html = ''; html += '
'; return html; } GG.footerend = function() { if( options.debug ) GG.debug_fn('GG.footerend'); return '
\n'; } GG.get_page_number = function() { if( options.debug ) GG.debug_fn('GG.get_page_number'); var html = '1'; return html; } GG.get_total_page_number = function() { if( options.debug ) GG.debug_fn('GG.get_total_page_number'); var html = '1\n'; return html; } GG.get_toc_contents = function() { if( options.debug ) GG.debug_fn('GG.get_toc_contents'); var toc = '

\n'; toc += '\n'; toc += 'Table of content - Please right-click and choose "Update fields".\n'; toc += '\n'; toc += '

\n'; return toc; } //TODO - figure out a way to simulate a right mpuse click, update fields GG.include_css = function( html ) { if( options.debug ) GG.debug_fn('GG.include_css'); //adding any header information that may be pertinent in the copied html var tags = ['style', 'link']; for( i = 0; i < tags.length ; ++i ) { $(document).find(tags[i]).each( function( ) { if(tags[i] != 'link' || ($(this).attr('rel') == 'stylesheet' && proto.test($(this).attr('href')))) { html += ( '\n' + $(this)[0].outerHTML + '\n' ); } } ); } return html; } GG.html = function() { if( options.debug ) GG.debug_fn('GG.html'); if( !$(options.area).length ) { return null; } // // fixes IE pre tag handling // $('pre').each(function() { // $(this)[0].outerHTML = $(this)[0].outerHTML.replace(/\n/g, "
\n"); // }); // adding the standard mso header var html = '\n'; html += '\n'; html +=' ' html += '\n'; html += ''; html = GG.include_css( html ); //adding in mso style necessesities html += '\n'; //close head html += '\n'; //start body html += ('\n
'); //add area content if($(options.initobj).is(options.area)) { if(options.debug) GG.debug_fn('is'); html += GG.translate_mso_features($(options.initobj)[0].outerHTML); } else { if(options.debug) GG.debug_fn('no is'); $(options.initobj).find(options.area).each(function(){ html += GG.translate_mso_features($(this)[0].outerHTML); }); } //close body html += '
\n'; //close doc html += '\n'; return html; } //memoized fns // GG.pngname = GG.memoize(GG.get_png_name); //execution if( options.debug ) GG.debug_fn('googoose exec'); options.html = GG.html(); if( options.html && options.finishaction ) { options.finishaction(); } // return options; return GG; }; }( jQuery ));