GithubHelp home page GithubHelp logo

postscribe's Introduction

THIS REPOSITORY IS NO LONGER MAINTAINED AND WILL BE ARCHIVED SHORTLY.

Overview

Version License Build Status Code Climate Coverage Dependencies Commitizen friendly semantic-release Gitter jsDelivr Hits

Remote scripts, especially ads, block the page from doing anything else while they load. They contribute a large % to load times which affects your bottom line. Asynchronous ads do not block the page and can be delivered after core content - Async FTW.

Why is it so hard to deliver ads asynchronously? Because they may contain calls to document.write, which expects to be handled synchronously. PostScribe lets you deliver a synchronous ad asynchronously without modifying the ad code.

Approach

Other tag writing libraries exist (see alternatives), but PostScribe is novel in its use of what we call DOM Proxies, a way to ensure that the content is written as close to the way the browser would natively write the content with document.write/innerHTML. Read: it behaves just like the browser would, without convoluted parsing or hacks.

For more information:

Getting Started

PostScribe overrides document.write. It is best and safest to use PostScribe after DOM is ready.

Installation

Browser

If you just want to use the script without installing anything, use the following to load the script from cdnjs:

<script src="https://cdnjs.cloudflare.com/ajax/libs/postscribe/2.0.8/postscribe.min.js"></script>

NPM

You can include postscribe using npm:

npm install --save postscribe

Postscribe runs in browsers, so this assumes you're using a module bundler like webpack, Browserify, JSPM or Rollup to consume CommonJS modules.

Bower

You can include postscribe using bower by installing from the CDN URL:

bower install --save https://cdnjs.cloudflare.com/ajax/libs/postscribe/2.0.8/postscribe.min.js

The library will exist at <components_folder>/postscribe/index.js.

Accessing

ES6/ES2015

import postscribe from 'postscribe';

AMD

define(['postscribe'], function(postscribe) {

});

CommonJS

var postscribe = require('postscribe');

Usage

To append html to #mydiv:

postscribe('#mydiv', '<h1>Hello PostScribe</h1>');

In general:

postscribe(element, html, options);
  • element: a DOM Element, jQuery object, or id selector (e.g. "#mydiv")
  • html: an html string or a function that takes a DOM Document and writes to it.
  • options: a hash of options
    • afterAsync: a callback called when an async script has loaded
    • afterDequeue: a callback called immediately before removing from the write queue
    • afterStreamStart: a callback called sync after a stream's first thread release
    • afterWrite: a callback called after writing buffered document.write calls
    • done: a callback that will be called when writing is finished
    • autoFix: a boolean that allows disabling the autoFix feature of prescribe
    • beforeEnqueue: a callback called immediately before adding to the write queue
    • beforeWriteToken: a callback called before writing a token
    • beforeWrite: a callback called before writing buffered document.write calls
    • error: a function that throws the error by default, but could be overwritten
    • releaseAsync: a boolean whether to let scripts w/ async attribute set fall out of the queue

If you just want to mess around, include the js files at the top of an html page that contains the following:

<div id="mydiv"></div>
<script type="text/javascript">
  postscribe('#mydiv', '<h1>Hello PostScribe</h1>');
</script>

How to use PostScribe to render an ad after load

Where normally you would have

<div id="ad"><h5>Advertisement</h5>
  <script type="text/javascript">
    // Build url params and make the ad call
    document.write('<script src=doubleclick_url_with_params><\/script>');
  </script>
</div>

Instead, remove the ad call and close the div

<div id="ad"><h5>Advertisement</h5></div>

<script type="text/javascript">
  // jQuery used as an example of delaying until load.
  $(function() {
    // Build url params and make the ad call
    postscribe('#ad', '<script src=doubleclick_url_with_params><\/script>');
  });
</script>

There are some hooks you may pass as the third argument. For example:

<script type="text/javascript">
  // jQuery used as an example of delaying until load.
  $(function() {
    postscribe('#ad', '<script src=doubleclick_url_with_params><\/script>', {
      done: function() {
        console.info('Dblclick script has been delivered.');
      }
    });
  });
</script>

See the beginning of postscribe.js for a complete list.

FAQ

Does it work with jQuery, Prototype, Backbone, Underscore, jQuery UI, YUI, mooTools, dojo, etc.?

Yep. It neither depends on nor conflicts with any of the existing popular javascript frameworks.

Does it work with another tag writing library on the page?

No. Only one tag writer at a time.

Who is using it

This project was originally developed at Krux as part of its SuperTag product. There it has been battle tested on high-profile sites like The New York Times, The Wall Street Journal, NBCU, and hundreds of others. It is actively maintained by Krux.

Browser Compatibility

PostScribe was designed to behave as closely to the native document.write/innerHTML does as possible, and we've taken great care to make sure that it works on every browser we can get our hands on. We expect it to work on every browser built after 2009. There are over 500 unit tests that run on every commit. PostScribe is thoroughly tested and known to work well in the following browsers:

  • Firefox 4+
  • Chrome 10+
  • Safari 5.0+
  • Opera 10.0+
  • Internet Explorer 8+
  • iPhone/iPad and other WebKit-based browsers

Note that we do not provide any support for Internet Explorer versions earlier than IE8.

Alternatives

We've stood on the shoulders of giants with our work, and there are other alternative approaches to solve this problem. Shout out to the best ones we found:

If you would like your project to be added to this list, file an issue and we'd be happy to.

Help/Bugs/Requests

We ♥ bug reports.

Have a problem? Need help? Would you like additional functionality added? We use GitHub's ticket system for keeping track of these requests.

Please check out the existing issues, and if you don't see that your problem is already being worked on, please file a new issue. The more information the better to describe your problem.

Contributing

We ♥ forks and pull requests.

Please see CONTRIBUTING.md for full details.

Environment

The project requires nodejs (>=5.6) and npm (>=3.6.0) for development. It has no runtime dependencies.

Developing

Check the code out and install the development dependencies using:

npm install

Building

To build the code, run

npm run build

Linting

We use ESLint and JSCS to do static analysis of the JavaScript and keep things smelling good. To run both, use:

npm run lint

Testing

Using travis-ci, the unit tests are run on every commit using PhantomJS to run the tests with a real browser.

To test the code locally, you can use:

npm test

To run tests in Test-Driven-Development mode, where the test will be run after every change, use:

npm run tdd

To run the cross-browser tests, use:

npm run test:cross-browser

Issue Guidelines

Please either add a failing unit test or include a jsfiddle that distills and reproduces the issue.

Try forking this jsfiddle. We've set everything up there for you so that you can reproduce your issue.

License

We aim for you to use this inside your application, so we picked the least restrictive license we could find.

See LICENSE.

postscribe's People

Contributors

andyogo avatar benjaminclot avatar bnkuhn avatar carambolage avatar dbrans avatar dbrekalo avatar dllopis-sfdc avatar elidickinson avatar greenkeeperio-bot avatar hpbuniat avatar jgreens avatar jnewman avatar jnewman-sfdc avatar kvakulo avatar lukasdrgon avatar rocco avatar sfdc-aaronkulick avatar svc-scm avatar technickai avatar tomat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

postscribe's Issues

postscribe problem with nested ul tags

ul tags are not properly nested using postscribe.js 1.3.2
postscribe("#info2"
, "<ul>"
+ "<li>1 - one"
+ "<li>2 - two"
+ "<ul><li>a - aaya<li>b - bee</ul>"
+ "<li>3 - three"
+ "</ul>"
);

RESULT:
<ul><li>1 - one<li>2 - two</ul>
<ul><li>a - aaya<li>b - bee</ul>
<li>3 - three

Problem with googletagservices scripts

Hi,

we are having some issue with scripts that some clients are serving us through googletagservices.

The script is processed by our adserver correctly but with postcribe it writes down this command but doesn't process it:

<script src="http://www.googletagservices.com/tag/js/gpt.js">
googletag.pubads()
.definePassback('CAMPAING_NAME', [160, 600])
.setClickUrl("http://adtechlink")
.display();
</script>

I've made two examples in jsfiddle with a live ad we recived (it might be pulled by the client next week):
Working with document.write
http://jsfiddle.net/Q73jh/2/
Not working with postscribe
http://jsfiddle.net/TZ6XA/2/

I think is a duplicated of the closed issue in #10

document.open()

We implemented postscribe to lazyload display ads and speed up the performance in the mobile view of our webpage.

1 ad was using the following code:

document.open();
document.writln('..... some code...');
document.writln('..... some code...');
document.close();

the ad caused the page to break and only display a white page, after it was loaded.
we made a temporary fix and overwrote document.open() to stop the ad breaking our code. did anyone face a similar issue?

Postscribe fails to see multiple script tags in a document.write

Given the following document.write call:

document.write("<"+"script>\n   var ut_imagearray = {\n     \'mobile\': [\n     \'http://images.undertone.com/ut/re/screenshift/creative/img/mobilewood.jpg\',\n        \'http://images.undertone.com/ut/re/screenshift/creative/img/undertone.svg\',\n     \'http://images.undertone.com/ut/re/screenshift/creative/img/laptop.png\',\n        \'http://images.undertone.com/ut/re/screenshift/creative/img/smbg1.jpg\'\n  ], \'alternate\': [\n       \'http://images.undertone.com/ut/re/screenshift/creative/img/wood.jpg\',\n      \'http://images.undertone.com/ut/re/screenshift/creative/img/undertone.svg\',\n     \'http://images.undertone.com/ut/re/screenshift/creative/img/laptop.png\',\n        \'http://images.undertone.com/ut/re/screenshift/creative/img/smbg1.jpg\'\n  ]},\n   ut_creativehtml        = \"http://images.undertone.com/ut/re/screenshift/creative/index.zepto.html\",\n ut_iecreativehtml      = \"http://images.undertone.com/ut/re/screenshift/creative/index.jquery.html\",\n    ut_clickBase           = \"http://ads.undertone.com/c?oaparams=2__bannerid=542886__campaignid=135304__zoneid=56853__UTLCA=1__ccat=7503,7547,12940__st=ourgraham.dev__cb=4cbcb02274e24d6c865cf0a26f9ecf04__bk=mv2hbr__id=ezcpcxnm7520nzdemk3d7j7su__oadest=\",\n ut_eventBase           = \"http://ads.undertone.com/l?bannerid=542886&campaignid=135304&zoneid=56853&UTLIA=1&ccat=7503,7547,12940&cb=0e20ca5b97ac4786b674347bd05272f3&bk=mv2hbr&id=ezcpcxnm7520nzdemk3d7j7su&st=http%3A%2F%2Fourgraham.dev%2Fbritains-got-talent&e=\",\n    ut_bannerid            = 542886,\n  ut_clickTags           = [\'http://undertone.com/screenshift\'];\n<"+"/script>\n<"+"script type=\"text/javascript\" src=\"http://images.undertone.com/ut/re/screenshift/creative/js/reveal.min.js\"><"+"/script><"+"script type=\"text/javascript\">new Image().src=\"http://ads.undertone.com/l?bannerid=542886&campaignid=135304&zoneid=56853&UTLIA=1&ccat=7503,7547,12940&cb=0e20ca5b97ac4786b674347bd05272f3&bk=mv2hbr&id=ezcpcxnm7520nzdemk3d7j7su&st=http%3A%2F%2Fourgraham.dev%2Fbritains-got-talent\"<"+"/script><"+"script src=\"http://segment-pixel.invitemedia.com/pixel?pixelID=156217&partnerID=515&clientID=12216&key=segment&returnType=js\"><"+"/script>\n<"+"noscript>\n<"+"img src=\"http://segment-pixel.invitemedia.com/pixel?pixelID=156217&partnerID=515&clientID=12216&key=segment\" width=\"1\" height=\"1\" />\n<"+"/noscript><"+"script type=\"text/javascript\">\ntry {\n    if(\'|42|43|44|45|46|47|48|49|52|53|54|55|61|62|63|\'.indexOf(\'|69|\')==-1) {\n        if(\'2434\'!=\'1962\') {\n            _qoptions={qacct:\"p-54JT4Ioyi-32M\",labels:\"Portals,Network.56853,Network2.2434.56853,Insights.1584.135304.542886,Insights2.32848.105633\" };\n            document.writeln(\'<"+"scr\'+\'ipt type=\"text/javascript\" src=\"http://edge.quantserve.com/quant.js\"><"+"/scr\'+\'ipt>\');\n\n            if(\'105633\'!=\'104291\') {\n              document.writeln(\'<"+"scr\'+\'ipt language=\"JavaScript1.3\" src=\"http://b.voicefive.com/c2/2113/rs.js#c1=3&c3=32848&c4=C:135304-Z:56853&c5=L:105633-C:135304&c6=&c11=&c13=&c14=14&c16=undertone\"><"+"/scr\'+\'ipt>\');\n            }\n            else {\n              document.writeln(\'<"+"scr\'+\'ipt language=\"JavaScript1.3\" src=\"http://b.voicefive.com/c2/2113/rs.js#c1=3&c3=32848&c4=C:135304-Z:56853&c5=L:105633-C:135304&c6=&c11=&c13=&c14=14&c16=undertone&ax_n=ut92052116197\"><"+"/scr\'+\'ipt>\');\n            }\n\n            if(\'\'.indexOf(\'link\')!=0 && \'\'!=\'OPTOUT\' && \'|1229|1287|1877|2233|2581|\'.indexOf(\'|2434|\')==-1) {\n              document.writeln(\'<"+"img src=\"http://pixel.quantserve.com/seg/r;a=p-54JT4Ioyi-32M;rand=1382439735;redirecturl2=http://ads.undertone.com/fc.php?dp=8&pid=!qcsegs\" alt=\"\" style=\"display:none;\" border=\"0\" height=\"1\" width=\"1\" /><"+"img src=\"http://tags.bluekai.com/site/450\" alt=\"\" style=\"display:none;\" border=\"0\" height=\"1\" width=\"1\" />\');\n              if(Math.random()<"+"0.45) {\n                document.writeln(\'<"+"img src=\"http://adadvisor.net/adscores/g.pixel?sid=9211197038&_cb=1382439735\" alt=\"\" style=\"display:none;\" border=\"0\" height=\"1\" width=\"1\" />\');\n              }\n              var ut_dps=[], ut_dps_changed=false;\n              for(var i=0,ck=document.cookie.split(\';\');i<"+"ck.length;i++) {\n                try {\n                  var c=ck[i].split(\'=\',2);\n                  if(c[0].replace(/^\\s+|\\s+$/g,\'\')==\'UTDP\') {\n                     ut_dps=unescape(c[1]).split(\',\');\n                     break;\n                  }\n                } catch(err) {}\n              }\n              if(ut_dps.indexOf(\'4\')==-1) {\n                ut_dps.push(\'4\');\n                document.writeln(\'<"+"img src=\"http://loadr.exelator.com/load/?p=104&g=330&j=0&cb=1382439735\" alt=\"\" style=\"display:none;\" border=\"0\" height=\"1\" width=\"1\" />\');\n                ut_dps_changed=true;\n              }\n              if(ut_dps.indexOf(\'12\')==-1) {\n                ut_dps.push(\'12\');\n                document.writeln(\'<"+"img src=\"http://r.nexac.com/e/getdata.xgi?pkey=ojjb86ufowd43&dt=br&edr=on&reppipe=,&ru=http%3A//ads.undertone.com/fc.php%3Fdp%3D12%26pid%3D%3Cna_da%3E\" alt=\"\" style=\"display:none;\" border=\"0\" height=\"1\" width=\"1\" />\');\n                ut_dps_changed=true;\n              }\n              if(ut_dps.indexOf(\'18\')==-1) {\n                ut_dps.push(\'18\');\n                document.writeln(\'<"+"iframe style=\"display:none\" src=\"http://images.undertone.com/append/1x1.html\" framespacing=\"0\" frameborder=\"no\" scrolling=\"no\" width=\"1\" height=\"1\"><"+"/iframe>\');\n                ut_dps_changed=true;\n              }\n              if(ut_dps_changed) {\n                var d=new Date();\n                d.setDate(d.getDate()+1);\n                document.cookie=\'UTDP=\'+escape(ut_dps.join(\',\'))+\'; expires=\'+d.toUTCString();\n              }\n            }\n        }\n    } else {\n        document.writeln(\'<"+"img src=\"http://pixel.quantserve.com/pixel/p-54JT4Ioyi-32M.gif?labels=Portals%2CNetwork%2e56853%2CNetwork2%2e2434%2e56853%2CInsights%2e1584%2e135304%2e542886%2CInsights2%2e32848%2e105633%2CMobile&media=ad\" alt=\"\" style=\"display:none;\" border=\"0\" height=\"1\" width=\"1\" />\');\n        document.writeln(\'<"+"img src=\"http://b.scorecardresearch.com/p?c1=3&amp;c2=2113&amp;c3=32848&amp;c4=C:135304-Z:56853&amp;c5=L:105633-C:135304&amp;c12=2672207c0829497cad2717c4c8828537&amp;c13=&amp;c14=14&amp;ns_ap_sc=&amp;ns_ap_pl=&amp;ns_ap_device=&amp;ns_ap_lat=&amp;ns_ap_lon=&amp;rn=fafc4fe456ce4be4901c32eefd1d76b7&amp;ax_fwd=1\" alt=\"\" />\');\n    }\n    if(542886>0) {\n        document.writeln(\'<"+"scr\'+\'ipt type=\"text/javascript\" src=\"http://pixel.adsafeprotected.com/jload?anId=14&campId=135304&pubId=56853&chanId=4832&placementId=105633&adsafe_par&uId=2672207c0829497cad2717c4c8828537&impId=ezcpcxnm7520nzdemk3d7j7su\"><"+"/scr\'+\'ipt>\');\n    }\n} catch(err) {}\n<"+"/script>");

Postscribe fails to render more than one script tag (the first one).

The only output I see is:

<script>
  var ut_imagearray = {
    'mobile': [
  'http://images.undertone.com/ut/re/screenshift/creative/img/mobilewood.jpg',
  'http://images.undertone.com/ut/re/screenshift/creative/img/undertone.svg',
  'http://images.undertone.com/ut/re/screenshift/creative/img/laptop.png',
  'http://images.undertone.com/ut/re/screenshift/creative/img/smbg1.jpg'
], 'alternate': [
  'http://images.undertone.com/ut/re/screenshift/creative/img/wood.jpg',
  'http://images.undertone.com/ut/re/screenshift/creative/img/undertone.svg',
  'http://images.undertone.com/ut/re/screenshift/creative/img/laptop.png',
  'http://images.undertone.com/ut/re/screenshift/creative/img/smbg1.jpg'
]},
  ut_creativehtml = "http://images.undertone.com/ut/re/screenshift/creative/index.zepto.html",
  ut_iecreativehtml = "http://images.undertone.com/ut/re/screenshift/creative/index.jquery.html",
  ut_clickBase  = "http://ads.undertone.com/c?oaparams=2__bannerid=542886__campaignid=135304__…d2fb746718c6fbea65b0379ce__bk=mv2kpf__id=h1zsshq457195j0ad13syi03__oadest=",
  ut_eventBase = "http://ads.undertone.com/l?bannerid=542886&campaignid=135304&zoneid=56853&U…hq457195j0ad13syi03&st=http%3A%2F%2Fourgraham.dev%2Fbritains-got-talent&e=",
  ut_bannerid = 542886,
  ut_clickTags = ['http://undertone.com/screenshift'];
</script>

It looks like handleScriptToken is clearing the stream each time it encounters a script tag (line 323).

var remainder = this.parser.clear();

I'm still investigating this issue and if I find a solution, I'll submit a pull request.

I was just wondering if the solution seemed any more obvious to someone more familiar with the code base?

Any help would be appreciated.

Thanks

Handing an external Script as second Parameter produces bad JS

This is what I do. Just using your plain Example

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="html_parser.js"></script>
<script type="text/javascript" src="postscribe.js"></script>

<div id="trackingStuff">Hidden Trackingstuff</div>
<script type="text/javascript">
$(function() {
    postscribe('#trackingStuff', '<script src=login_live_test.js></script>');
});
</script>

This produces JS Syntax Errors because he seems to use the '/script' Endtag
as end of the surrounding Script-Tag. And so he writes the following into the Body

'); }); 

Am I doing something wrong, or is there really something broken?

Full Example:
https://dl.dropbox.com/u/638360/ps/minimal_version.html

OpenX Unique Ads

I'm using OpenX to serve my ads and when you fetch the ads a 'block=1' is added so that the same ads aren't served to the same page. The problems is that when using (your wonderful plugin) postscribe, each request for an add is treated as if a different page is requesting it, which causes the same ad to be served to the same page more than once.

Possible race condition

Cheers,

as we are using Postscribe in our require.js Ad delivery, we discovered a problem in combination with our way of chaining adcalls in case the first one didn't serve any ad.
The situation:
We do have a JS engine from our partner that we include. We then print their function using Postscribe:

window.postscribe(element,
    '<scr' + 'ipt>script-tag here</scr' + 'ipt>',
    {
        done: function() {
            that.hasAdContent(element);
        }
    }
);

hasAdContent is our own method to detect if there is specific content in the element. The possible race condition now is, that the script tag inside the script Tags is written and then the options.done method is being executed and as far as I can see it is the latest option possible.

Is there some way to actually wait for the script-tag to be executed aswell (not just written) before the options.done function is used without using a selfmade timeout?

Oh, and the problem actually is, that due to that race condition, two ads are displayed at the same position. Forgot to mention that.

Best regards,
S.

Only first ad loads after console error

On the first ad I see the script written to the page and the ad appears. However, for each subsequent ad, I do not see the script written to the page (no ad) even though I see the postscribe function call.

I also see an error (TypeError: doc is undefined) in the console that points to postscribe.js (line 139)
postscribe error

Refresh ads quickly causes problems with postscribe.

@adrienbataille wrote:

Derek,
You can see here my jsfiddle with a snippet which looks like my code

http://jsfiddle.net/qXJ4j/3/

To reproduce the bug on jsfiddle, you have to quickly click many times on the link, and "done" is not called after.
But on my website, the error occurs both on loading the page and after requests to get content with all new advertising links (got with postscribe). On each page, postcribe is used at list 4 times at same time.
My browsers are Chrome and Safari on Mac OS.
Adrien

Catching error throw by postscribe doesn't work

I'm using postscribe on my web site to get doubleclick ads with an ajax navigation but sometimes an error occurred and after postscribe stop working.
So I try to catch but it changes nothing.
The error throws is from line 536.

<div id="banner" class="alignBanner">
    <noscript><a href="http://ad.doubleclick.net/jump/sri.canalvie/homepage;ss=canalviedemo;pos=top;tile=2;sz=300x250;ord=603946" target="pub"><img src="http://ad.doubleclick.net/ad/sri.canalvie/homepage;ss=canalviedemo;pos=top;tile=2;sz=300x250;ord=603946" width="300" height="250" alt="publicité"/></a></noscript>
</div>
<script type="text/javascript">
    try {
        postscribe('#banner', '<script type="text/javascript" src="http://ad.doubleclick.net/adj/sri.canalvie/homepage;ss=canalviedemo;pos=top;tile=2;sz=300x250;ord=603946"><\/script>'); 
    } catch (err) {
        alert("postscribe error ads");
    }
</script>

dfp success or hints?

I was able to use this with old google dart tags and now can't seem to get this to work with dfp. Anyone had success or share how they did this? The tags and javascript get written out to the div but the javascript doesn't appear to actually fire. My latest attempt is like this.

So I have the basic setup in the header with slot declarations.

        <script type='text/javascript'>
        (function(){
        var useSSL = 'https:' == document.location.protocol;
        var src = (useSSL ? 'https:' : 'http:') + '//www.googletagservices.com/tag/js/gpt.js';
        document.write('<scr' + 'ipt src="' + src + '"></scr' + 'ipt>');
        })();
        </script>

        <script type="text/javascript">

        //Adslot 1 declaration
        var slot1= googletag.defineSlot('/8000/somesite.com/tags/news', [[300,250]],'cube1').setTargeting('pos',['Cube1_RRail_ATF']).addService(googletag.pubads());

        googletag.pubads().setTargeting('kv',['news']);
        googletag.pubads().enableSyncRendering();
        googletag.enableServices();

        </script>
        <!-- End: GPT -->

Then my div on the page gets written into with the placement tag when my script is triggered.

<script type='text/javascript'> var mcAdTag = 'googletag.display(\'cube1\');<\/scr' + 'ipt>'; postscribe('#cube1', mcAdTag, {done: function() { loadTheAds(); }}); </script>

The markup and div targeted on the page..

        <div id='cube1'></div>

This results in no errors it just prints it out with no action.

<div id='cube1'>
<script type='text/javascript'>googletag.display('cube1');</script>
</div>

document.write(el.outerHTML)

I ran into an issue using postscribe with a third party ad tag. Here is a simplified version of the tag:

var el = document.createElement("script");
el.src = "//tags.thirdpartyadnetwork.com?key1=value1&key2=value2"
document.write(el.outerHTML);

postscribe writes the tag to the page as such:

<script src="//tags.thirdpartyadnetwork.com?key1=value1&amp;key2=value2"></script>

the & is being translated literally as an HTML entity by the browser resulting in the query string:

key1: value1
amp;key2: value2

now I assume this is happening because of the el.outerHTML being used in combination with document.write here.

simple test page showing the issue:

<!DOCTYPE html>
<html>
  <head lang="en">
    <meta charset="UTF-8">
    <title postscribe issue></title>

    <script src="postscribe.js"></script>

  </head>
  <body>

    <div id="ima-div"></div>
    <script>

      // script string
      var tag = '<script>var el = document.createElement("script");' +
                'el.src = "//tags.thirdpartyadnetwork.com?key1=value1&key2=value2";' +
                'document.write(el.outerHTML);<\/script>';

      postscribe('#ima-div', tag);
    </script>

  </body>
</html>

postscribe breaks with document.write and self closing div

postscribe("#mydiv","<script>document.write('<div id=\"hello\"/>');</scr"+"ipt>")

Seems to not work so hot for me. Live example here: http://dl.dropboxusercontent.com/u/325339/postscribe_test.html

In Chrome/Mac this gives me:

Uncaught TypeError: Cannot call method 'appendChild' of undefined

in Firefox/Mac:

uncaught exception: [object Object]
[Break On This Error]   

this.actuals[parentIsProxyOf].appendChild(node);

Looks like something goofy with how it's finding/setting the proxy parent ID.

document.writln Error

Some adcall responding scripts deliver document.writeln code.
I can't find any code within postscibe for handling these stuff.
I will try to fix this issue but probably you will be faster ;D

Thanks in advance!
Martin

Postscribe blocks the browser

Hi
If there is a start tag that is splitted in multiple document.write statements it triggers intensive computation in the browser and blocks the browser thread. Chrome and internet explorer blocks the others behave better.

Example:
document.write('line1');
document.write('line1');
document.write('line1');
document.write('<AA attribute1="value1" ');
document.write(' attribute2="value1" ');
document.write(' attribute3="value1" ');
document.write(' attribute4="value1" ');
document.write(' attribute5="value1" ');
document.write(' attribute6="value1" ');
document.write(' attribute6a="value1" ');
document.write(' attribute7="value1" >');
document.write('');
document.write('line1');
document.write('line1');

The issue is because the
var match = stream.match( startTag );\statement in the startTag method takes longer and longer when the stream increase and there is no match.
The time to perform that statement increases by 10 when the next text is added to the stream. I couldn't simulate the issue outside the postscribe.

The fix I added was this:
var endTagIndex = stream.indexOf('>');
if(endTagIndex === -1) {
return null; //avoid the match statement if there will be no match
}
var match = stream.match( startTag );

if I know there is no match then I avoid the match statement.

Can you confirm this?

Postscribe adds ad outside of target element

Hi,

I'm currently trying to implement a way to asynchronously load IM-Ads. Unfortunately this doesn't seem to work - the ad is always displayed outside of the destination container. This happens only for Ads from this specific Ad-service. I also tried other ad-tags, i.e. from "Adtech" which were displayed correctly via postscribe.
Any suggestions? I already tried to debug postscribe.js but I don't get the position where you append the loaded ad to the specified container?!

See my plunkr for more details:
http://plnkr.co/edit/lsbeWxHxh8UsUhlShbvX

Best regards,
Martin

Automate release

Should include:

  • Tagging
  • PR for new version on CDNs
  • Add release notes.
  • Push to CDNs

document.open is not overriden

A synchronous document.open call is completely ignored, while calling it asynchronously causes the page to go fully blank.

GhostWriter has safe-guards for document.open, and document.close, so if some ad calls them, they don't do any damage to the page.

The workaround is as simple as document.open = document.close = function () {} and in my opinion is worth introducing to postscribe.

Can't handle slightly corrupted HTML

Browsers can handle this:

document.write('<img src"abc.jpg"><div>WORKS</div>')

Well Firefox prints <img src"abc.jpg"="">, but the div is still there.

Postscribe can't handle this.

<html>
<style>img { display: none }</style>
<div id="js">
<script>document.write('<img src"abc.jpg"><div>OK</div>')</script>
</div>
<div id="ps1"></div>
<div id="ps2"></div>
<script src="https://raw.github.com/krux/postscribe/master/dist/postscribe.js"></script>
<script>
postscribe('#ps1', '<script>document.write(\'<div>OK</div>\')</sc' + 'ript>');
postscribe('#ps2', '<script>document.write(\'<img src"abc.jpg"><div>OK</div>\')</sc' + 'ript>');
</script>
</html>

Expected behavior: 3 times OK. Actual behavior: 2 times OK

retrieving dom node in done() handler

Hi,

In the done() handler, I'd like to know which dom node postscribe has just written to. There are however no arguments provided to this callback.

this change would do this (for me)

options.done(active.root.id);

or maybe there already is another way of retrieving this?

thanks

postscribe dies after caught error.

I get a ReferenceError with an empty object as thrown error.
Right after that error I get
{message: "Bad script nesting or script finished twice"}

All subsequent postscribe requests fail. I see postscribe.queue being full but stops processing.

Is there a way to tell postscribe to continue processing even after a (caught) error ?

I've not had success reproducing this bug.

Failed to display more than 1 Ads

Hi all,

I am trying to use postscribe to load 3 GoogleAds script - but unfortunatelly it only loads the first Ads. I can see that on the 2nd, and 3rd Ads, the elemen rendered by postscribe is not complete.

Code

Add placeholder 1
Add placeholder 2
<script> $(document).ready(function() { google_ad_client = "ca-pub-xxx"; /* V_120x240 */ google_ad_slot = "xxx"; google_ad_width = xxx; google_ad_height = xxx; setTimeout(postscribe('#ad_0','<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"><\/script>'),20); // This part is not working, iframe is not completely rendered. google_ad_client = "ca-pub-xxx"; /* V_120x240 */ google_ad_slot = "xxx"; google_ad_width = xxx; google_ad_height = xxx; setTimeout(postscribe('#ad_1','<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"><\/script>'),20000); }); </script>

Anybody has better insight?

Best regards,

Riwut L

Is a mistake ?

Hi bnkuhn , the body of function defaults:
if(options.hasOwnProperty(key) && val !== undefined) {}
From doc, it says " Set default options where some option was not specified.", so i think it is a mistake.
I suggest:

function defaults(options, _defaults) {
options = options || {};
eachKey(_defaults, function(key, val) {
if(options.hasOwnProperty(key)
&& options[ key ] === undefined // Make sure it is not specified
&& val !== undefined) {
options[key] = val;
}
});
return options;
}

Question About Refreshing Ads

Hello,

I saw this issue from a while back: #13

And I saw these to jsfiddles: http://jsfiddle.net/dbrans/46n7t/ and http://jsfiddle.net/qXJ4j/3/

What is the best current method to refresh ads w/ postscribe?

I want to refresh the ads say every 30 seconds. I did read this response from @dbrans:

Ultimately, we need a way to tell the postscribe WriteStream to "stop" before you blow it away. The usage might look like this:

// Stop postscribe before emptying the div
postscribe("#banner_7426").stop(function() {
$("#banner_7462").empty();
});

... My question is that I do not believe this is implemented yet, so can we use the "empty" or "hide" methods without a problem? I know @dbrans says the DOM will get heavy, but actually I am afraid I do not yet know what that means. I believe it means "bogged down".

I was going to try to use innerHTML but obviously that can't parse external scripts to refresh ads that way.

Just trying to find out any negatives to using "empty" and if it will result in lost impressions, because I see the person who created the issue #13 discovered in his ticket that actually the error was coming from a different type of error, and not relating to "empty" although it was not made clear if this was also a problem as @dbrans also said "I think that the problem in this fiddle is that the dom gets blown away but postscribe is still trying to use parts of it:"

Thank you!

DFP 6 broken in use with PostScribe

I just had to set up a campaign from GoldBach and faced various Issues in combination with PostScribe.

Firstly DFP supports two modes - synchronous and asynchronous Ad Loading:

Synchronous

This mode will throw a 404 HTTP Error trying to load gpt_impl_35.js.
"NetworkError: 404 Not Found - http://www.qa1-tutti.dev/http&#58;&#47;&#47;partner&#46;googleadservices&#46;com&#47;gpt&#47;pubads&#95;impl&#95;35&#46;js"
The reason for this is that DFP in sync mode correctly escapes HTML Entities for document.write. But Since we are using PostScribe here, this brakes the above URL.
Solution add an unescapeHTMLEntities function to HTMLParser.

Asynchronous

This mode does not suffer from the HTML Entities Issue but instead is not working in IE8 and below.
According to this StackOverflow post, the reason for this is the on site extension of Host Objects in combination with DFP JS using for in to loop over Array elements:
http://stackoverflow.com/questions/8751620/google-ads-not-showing-up-in-ie8
I removed all our EcmaScript 5 Pollyfills but still it was not working in IE8...


Unfortunately after HTML Entities fix, it still breaks in firefox - I only got async DFP working here. in lte IE8 sync work with that fix.

PostScribe closes another tag

I'm having an issue with postscribe. It was quite weird because it looked like It closed divs to quickly. I was able to simplify the code that postscribe breaks with to the following form:

postscribe('#someelement', '<div id="first" style="background: red; padding: 5px">' +
  '<embed></embed>' +
  '<div id="second" style="background: yellow">Should be yellow in red box, right?</div>' +
'</div>');

The expected result is the div#second should be created inside div#first. (This is what for example jQuery would do when inserting HTML with .html() method).

The actual result is that div#first and div#second are siblings.

The trick in here is that '' tags are not needed, because is always empty, but it should not be replaced with end tags of other type.

This works:

postscribe('#someelement', '<div id="first" style="background: red; padding: 5px">' +
  '<embed>' +
  '<div id="second" style="background: yellow">Should be yellow in red box, right?</div>' +
'</div>'}});

Postscribe fails to catch errors, prevents additional loading

When loading the ad, I can see the following error in the console:

  • Unsafe JavaScript attempt to access frame with URL

The issue looks similar to #15, but with the latest version the error persists. The ad seems to load properly in most browsers, but unfortunately in IE8, it seems to prevent further calls from running. I've created a plunker that recreates the issue, and I can see the error in the console using chrome.

http://plnkr.co/edit/w0swNcqnILCllSOLv4Mo?p=preview

param and embed are atomic tags too

html was breaking if i write code like

<div><object><param></param></object></div>

But works ok for code

<div><object><param /></object></div>

it looks like similar problem to #16
i've added "param" and "embed" to atomicTag variable and it works good.

Problem with nested Div containers?

Hey guys,

I am having an issue with an ad, where I simply don't understand the behaviour.
The code that is coming back from the server is like:

<div id="wallpaperPlatzhalter" style="width: 1px; height: 90px;"></div>
<div id="wallpaperBannerContainer" style="position: absolute; top: 0px; left: 102px; z-index: 100;">
   <div id="adp_container_856997" style="position:relative;display:block;"></div>
   <div style="position: relative;">
      <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" id="wallpaperFlashBanner_111576214_39769905214" width="728" height="90" >
         //param stuff here
      </object>
      <div style="z-index: 200; position: absolute; top: 0px; left: 0px;" class="flashAdBanner_111576214_39769905214"><a target="_blank" href="http://somewebsite"><img src="http://s0.2mdn.net/dot.gif" border="0" width="728" height="90" ></a></div>
   </div>
</div>
<div id="wallpaperSkyscraperContainer" style="position: absolute; top: 0px; left: 830px; z-index: 100;">
   <div style="position: relative;">
      <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" id="wallpaperFlashSky_111576214_39769905214" width="160" height="600" >
         //param stuff here
      </object>
      <div style="z-index: 200; position: absolute; top: 0px; left: 0px;" class="flashAdSky_111576214_39769905214"><a target="_blank" href="http://somewebsite"><img src="http://s0.2mdn.net/dot.gif" border="0" width="160" height="600" ></a></div>
   </div>
</div>
<div id="banner_ad_111576214_39769905214_tracking" style="position:absolute;top:0px;right:0px;width:1px;height:1px;visibility:hidden;border:none;">
    <img src="http://someimage" height="1" width="1" border="0" style="width:1px !important;height 1px !important" />
</div>

However, after it's rendered in the page both DIVs that are coming after the object tag (both ones with z-index: 200) are placed outside of their 2 parent DIVs. Result:

<div id="wallpaperPlatzhalter" style="width: 1px; height: 90px;"></div>
<div id="wallpaperBannerContainer" style="position: absolute; top: 0px; left: 102px; z-index: 100;">
   <div id="adp_container_856997" style="position:relative;display:block;"></div>
   <div style="position: relative;">
      <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" id="wallpaperFlashBanner_111576214_39769905214" width="728" height="90" >
         ...
      </object>
   </div>
</div>
<div style="z-index: 200; position: absolute; top: 0px; left: 0px;" class="flashAdBanner_111576214_39769905214"><a target="_blank" href="http://somewebsite"><img src="http://s0.2mdn.net/dot.gif" border="0" width="728" height="90" ></a></div>
<div id="wallpaperSkyscraperContainer" style="position: absolute; top: 0px; left: 830px; z-index: 100;">
   <div style="position: relative;">
      <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" id="wallpaperFlashSky_111576214_39769905214" width="160" height="600" >
         ...
      </object>
   </div>
</div>
<div style="z-index: 200; position: absolute; top: 0px; left: 0px;" class="flashAdSky_111576214_39769905214"><a target="_blank" href="http://somewebsite"><img src="http://s0.2mdn.net/dot.gif" border="0" width="160" height="600" ></a></div>
<div id="banner_ad_111576214_39769905214_tracking" style="position:absolute;top:0px;right:0px;width:1px;height:1px;visibility:hidden;border:none;">
    <img src="http://someimage" height="1" width="1" border="0" style="width:1px !important;height 1px !important" />
</div>

I totally don't get how that is happening - is it some wrong behaviour from postscribe regarding nested DIVs or problems with object/embed tags?

Any help would be appreciated!

Cheers,
Sascha

PostScribe vs Local Stored iFrames Question

Hi, I implemented postscribe but it doesn't seem to do much in comparison to using locally stored iframes (with doc.write tags in them).

Is there anyway to get postscribe to write to say 8 divs at the same time?

mini postscribe

Could you point out the drawbacks of this function?

function remarketing() {
    window.document.write = function (html) {
        var write = document.createElement('div');

        //write.style.display = 'none'; -> CSS .doc-write {display: none;}
        write.className = 'doc-write';
        write.innerHTML = html;
        document.body.appendChild(write);
    };

    window.google_conversion_id = WP.adwords.conversionID;
    window.google_custom_params = WP.adwords.tagParams;
    window.google_remarketing_only = true;
    // 1: shows a 1-line notification to visitors
    // 2: shows a 2-line notification to visitors
    // 3: no notification to visitors
    window.google_conversion_format = 3;

    curl(['domReady!', 'js!adwords']);
}

https://github.com/cujojs/curl
Google's conversion.js fires one (whole, from opening to closing script element) doc.write.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.