Browsers bug on document.write - javascript

I have multiple widgets like this
var c2409 = "<div class="products">PRODUCT1 PRODUCT2 PRODUCT4 ...</div>";
document.write(c2409)
And I call this
<script src="website/getjswidget.aspx?cid=xxxx-xxxx-xxx-xxxx"></script>
Now looks like sometime after I clear the cache, this replace everything in my html and I get a blank page only with this div from my widget.
Any other solutions to replace document.write?

This is by design.
The write() method is mostly used for testing: If it is used after an HTML document is fully loaded, it will delete all existing HTML.
Source
If you want to append data to your webpage, use this:
document.body.innerHTML += 'your HTML code to add'
Edit: If you want to show this in a particular element, you can do something like this:
<!-- HTML element -->
<div id="myData"></div>
<!- Javascript code -->
document.getElementById('myData').innerHTML += 'your HTML'
Edit 2 (After some searching): You can get the current script element by using document.currentScript and then perhaps use Node.insertBefore to create a div right before that script tag, to put your data in.
Edit 3: Apparently document.currentScript doesn't work in IE. But this answer may help.

Related

Is it possible to do some client-side DOM manipulation before document ready?

I am trying to find a way (if possible) to use javascript to add some attributes to an element at render time and before the DOM is fully loaded. I know, that sounds counterproductive, but let me give you some background:
I'm working in an extremely limited templating platform that gives me access to some page variables, but they need some minor string manipulation. I can't leverage any of the ASP preprocessing so it has to happen on the client-side.
Specifically, I am trying to add Schema.org Microdata markup to an element before Googlebot scans through the document contents.
Essentially I need to modify an attribute value from $5.99 to 5.99.
Here's my most recent attempt, which makes the DOM modifications correctly, but not before Google's rich snippet validator processes the page:
<div class="pitinfo"><div class="padleft padright"><%Product.BasePrice%></div></div>
<!-- at page bottom -->
<script type="text/javascript">
(function() {
var pricesting = "<%Product.BasePrice%>";
var price = pricesting.slice(1);
$('.pitinfo').attr('itemprop', 'price');
$('.pitinfo').attr('content', price);
})();
</script>
After load I get this <div class="pitinfo" itemprop="price" content="9.99">$9.99</div>, however the Rich Snippet Testing tool tells me price is not set.
I have already tried using ASP in my template code but the hosting provider does not allow it.
Is it possible to make the DOM modifications sometime in the middle of the document rendering flow?
It is possible to insert a <script> tag inside of the <body>. JavaScript inside of the tag is loaded before the HTML after it, so you would be able to edit the element's value before the rest of the HTML/JS is loaded.
For example:
<div>
<div id="element" value="$5.99"></div>
<script>
var element = document.getElementById("element")
element.value = 5.99;
</script>
</div>
You can check it out here

How to append to just the main body tag, in a page with iframes?

I am developing a Greasemonkey script to append a div right after the body tag, here is the jQuery:
$("body:first").append (
'<div id="btn" style="width:50px;display:block">SHOW</div> <div id="gmPopupContainer" style="display:none">my text here</div>'
);
It works fine as long as there is only one body tag on the page, but a problem arises when there are iframes on the webpage. It appends to all the body nested in the iframes.
I've tried many jQuery selectors without success. What is the correct way to do this?
In general, use #noframesDoc in your metadata block to stop the script from running in iframes.
Or, in this case you can also use something like:
var topmostFramesMainBody = $(top.document.body).first ();
If that doesn't work, provide the details specified in My very simple Greasemonkey script is not running?.
(Note that you should ALWAYS provide those details.)
You can do $("<div id="btn" ...>SHOW</div>").insertAfter('body');

about script tags inside form tags

i have added a script tag in side a select tag which creates options dynamically. The function works fine but the W3C validator gives me 4 errors regarding this syntax. It will be helpful if you guys could find me a solution for this problem.
These are the 2 errors that repeat 2 times.
1. document type does not allow element "script" here
2. year_option(); end tag for "select" which is not finished
1) the only tags that <select> can have are <option> and <optgroup> tags
the validator is complaining because <script> is not one of those things -- the browser is doing its best to take your invalid markup and turn it into something valid, so despite the fact that it works, that's why you get the error, if you're actually putting <script> tags inside of a <select>
2) your script tags should be at the bottom of your page, and instead of using document.write to put option tags there, use DOM methods to add options to the select element after the fact
<select name="select-box"></select>
<!-- ...rest of page... -->
<script src="external-script.js"></script>
/* contents of external-script.js */
var select_box = document.querySelector("select[name=select-box]"),
bob_opt = document.createElement("option"),
doug_opt = document.createElement("option");
bob_opt.value = "Bob";
doug_opt.value = "Doug";
bob_opt.appendChild(document.createTextNode("Bob"));
doug_opt.appendChild(document.createTextNode("Doug"));
select_box.appendChild(bob_opt);
select_box.appendChild(doug_opt);
There are faster and neater, or more-elaborate or more flexible ways of doing this, but this is closer to the "right way" than something like:
<select>
<script>document.write("<option value=\"" + i + "\">one</option>");</script>
</select>
Or whatever you might currently have there.
JS is not meant to be templated like that, without using/writing a templating library for that purpose.
1) Script tags should be located in head, or perhaps elsewhere in the document, but not inside select tags
2) Looks like you are missing a tag, or perhaps its having problems finding it because of the first error.
You can put your JavaScript out side the select tag, and you can append option tags later, when select tag is rendered on the page, after page load using $(document).ready.
You can standardize your code by placing JavaScript in separate file, there you can do like
$(document).ready(function(){
//Your code to init all things,
//e.g. load options in select box etc..
//so It will be easy later to maintain the code, all init code will go here
});
Or if you are not using jquery, you can use below code
function your_function(){
//your init code will go here
}
document.getElementsByTagName("body")[0].onLoad = your_function;
that's it, place your code in your_function()

Perform the flickr badge code after page loads

I'm using the flikr badge code (http://www.flickr.com/badge_code_v2.gne) like so
<!-- Start of Flickr Badge -->
<div id="flickr_badge_uber_wrapper">
<script type="text/javascript" src="http://www.flickr.com/badge_code_v2.gne?..."></script>
<p class="clear">see more...</p>
</div>
<!-- End of Flickr Badge -->
This works great, apart from it's near the top of the page and the flikr api will occasionally hang the rest of the site. To stop this I figure I could either move the html to the bottom of the page and use some extra css to stylise where I want it to go, or use some javascript to make it load later. The former sounds like it involves a bit too much absolute positioning, while I'm a little confused how to go about the latter.
Normally this would be easy, for example:
document.onload = function() {
// Do something
}
But how do I do it with the flickr badge code, it's a link to dynamically produced javascript?
EDIT
The source from the link is i.e. the js pulled in:
var b_txt = '';
// write the badge
b_txt+= // some html, b_txt+= called for each image.
b_txt += '<span style="position:absolute;left:-999em;top:-999em;visibility:hidden" class="flickr_badge_beacon"><img src="http://geo.yahoo.com/p?s=792600102&t=53dd558c54466a104f77d195043a008d&r=http%3A%2F%2Flocalhost%3A8000%2F&fl_ev=0&lang=en&intl=uk" width="0" height="0" alt="" /></span>';
document.write(b_txt);
Use a placeholder <div> where you want it to finally appear. Then use jquery $(document).ready and set the innerHTML of your placeholder div to the span/img/script tag. place the script tag near then end of the body, and it will load last. When everything is finished loading, document.ready will be fired
Something like this
$(document).ready(
function(){
$("#placeholder").innerHTML("<script/span/img>");
});
A simple solution would be to pull the script tag out of the wrapper. Position the flickr_badge_uber_wrapper wherever you'd like it, and then place the javascript src call at the end of the body. I don't see a reason why the javascript couldn't be pulled from the wrapper and loaded later on page load. That should be the easiest way to keep your page from hanging.

How can I create a javascript badge or widget?

I want to create a javascript badge that displays a list of links. We host the javascript on our domain. Other sites can put an empty div tag on their page and at the bottom a reference to our javascript that would render the content in the div tag. How do you implement something like this?
I would give the SCRIPT tag an ID and replace the script tag itself with the DIV + contents, making it so they only have to include one line of code. Something along the lines of the following:
<script id="my-script" src="http://example.com/my-script.js"></script>
In your script, you can swap out the SCRIPT tag for your DIV in one fell swoop, like so:
var scriptTag, myDiv;
scriptTag = document.getElementById('my-script');
myDiv = document.createElement('DIV');
myDiv.innerHTML = '<p>Wow, cool!</p>';
scriptTag.parentNode.replaceChild(myDiv, scriptTag);
just as you say, have them put a div at the bottom of their page:
<div id="mywidget"></div>
then have them link to your javascript:
<script type="text/javascript" src="http://yourdomain.com/mywidget.js"></script>
then have them alter their body tag, or onload to call your script
<script type="text/javascript">
document.body.onload = loadYourWidget();
</script>
You do not necessary need an initial div to fill with you link list.
Simply create the div using document.write at the place where the script is placed.
<script type="text/javascript" src="http://domain.com/badge.js"></script>
... and in your script:
var links = [
'One',
'Two',
'Three'
];
document.write("<div>" + links.join(", ") + "</div>");
Another benefit is that you do not have to wait for the page to be fully loaded.
Like #Owen said, except why not craft your javascript so that
<script type="text/javascript" src="http://yourdomain.com/mywidget.js"></script>
does the work of populating <div id="mywidget"></div> on its own, thus negating the need for them to call loadYourWidget() from their DOM load if you include the script tag right after the mywidget div in the html source. This isn't really a best practice, but I think it'll work.
Example for your mywidget.js code:
document.getElementById('mywidget').innerHTML = "<a href=''>LinkOne</a> <a href=''>LinkTwo</a>";
It took me some time to find this answer on Stackexchange because I was using different search terms. I believe that the link suggested there is a more complete answer than the ones already given here:
How to build a web widget (using jQuery)
It covers:
ensure the widget’s code doesn’t accidentally mess up with the rest of the page,
dynamically load external CSS and JavaScript files,
bypass browsers’ single-origin policy using JSONP.

Categories