Piwik tracking script working on all browsers except IE8 and below - javascript

I have a tracking script on an E-commerce site receipt page. The script simply fetches the product information from the DOM and tracks it using the Piwik E-commerce tracking functions. This works fine in all browsers except Internet Explorer 8 and below. I've been trying to figure out what's wrong with the script for weeks. I've tested it locally on a dummy receipt page and it works fine in IE, but it's not tracking any sales for IE 5-8 on the live page.
The tracking script is inserted to the receipt page via an OpenTag tag and so is piwik.js, but I'm using the asynchronous tracker so that shouldn't be an issue, as all browsers except IE confirms.
Here is the code that is injected via OpenTag:
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script type="text/javascript">
// Closure that supports jQuery
(function($) {
// Function for removing everything from a string except numbers and
// returning that number as an integer
var num = function(text) {
return parseInt(text.replace(/[^0-9]/g, ''));
};
// Trims whitespace from before and after a string. " hello " => "hello"
var trim = function(text) {
return text.replace(/^\s+|\s+$/g, '');
};
// Run on document ready
$(function() {
// Ready a reference to Piwik async queue
_paq = _paq || [];
// Referansenummeret
var order_id = num(
$('span#ctl00_CPHCnt_McInPlaceEdYourRefNbr_McInPlaceEdYourRefNbr')
.closest('p').text()
);
// Hent verdien som ligger etter "Total:"
// var total = num(
// $('span#ctl00_CPHCnt_HandlevognProdukListe1_McInPlaceEdTotInclAVT2_McInPlaceEdTotInclAVT2')
// .closest('tr').children('td:last-child').text()
// );
var total = 0;
// Hent verdien som ligger etter "Sum:"
var sub_total = num(
$('span#ctl00_CPHCnt_HandlevognProdukListe1_McInPlaceEditorSum_McInPlaceEditorSum')
.closest('tr').children('td:last-child').text()
);
// Hent verdien som ligger etter "Herav mva:"
var mva = num(
$('table.CartSummaryTable .TotalValue').closest('tr').next()
.children('td:last-child').text()
);
// Hent verdien som ligger etter "Frakt inkl. evt. gebyr:"
var shipping = num(
$('span#ctl00_CPHCnt_HandlevognProdukListe1_McInPlaceEdFreightInclFee_McInPlaceEdFreightInclFee')
.closest('tr').children('td:last-child').text()
);
// Cheat solution - the total doesn't have a 100% hitrate so just
// add the sub_total and shipping together.
total = sub_total + shipping;
// Iterate over the product rows and extract the information
$('table#ProductList tr.VerticalText').each(function(index, row) {
var sku = trim($('td:first-child', row).text());
var prod_name = trim($('div.ProduktDesc span', row).text());
var categories = [];
var price = num($('td:nth-child(5)', row).text());
var quant = num($('td:nth-child(4)', row).text());
// Extrapolate categories from the product link URL
var path = $('.ProduktDesc a', row).attr('href').split('/');
for(var i = 2; i < path.length - 1; i++)
{
categories.push(path[i]);
}
// Track this product
_paq.push(['addEcommerceItem', sku, prod_name, categories, price, quant]);
});
// Track this order
_paq.push(['trackEcommerceOrder', order_id, total, sub_total, mva, shipping, false]);
});
}(window.jQuery.noConflict(true)));
</script>
Asking on StackOverflow is my last resort, I can't for the life of me figure out why this isn't tracking any sales for Internet Explorer 5-8.
I'll accept the first answer that leads me to solve this issue.

We figured it out. It turns out OpenTag was transforming the URL "//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" into "////ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" only in Internet Explorer. We solved it by figuring out the protocol using JavaScript instead.

Related

Use Script and XML Feed to pause Adgroups in Google Adwords

I'm trying to do a script which pauses an adgroup based in the field AVAILABILITY in a XML (a Google Merchant XML).
I have a merchant XML, and want to use the ID (the id is algo used in the adgroup name) and AVAILABILITY (In Stock, Out of Stock, Preorder) from the XML to pause Adgroups in my campaign.
I tried to modify an example, I had found here, using adgroups in place of campaigns, but I think the error is when the script try to read the XML.
In the lines bellow lines I receive the error: "TypeError: Cannot call method "getValue" of null. (line 16)"
var id = entries[i].getChild('g:id').getValue();
var availability = entries[i].getChild('g:availability').getValue();
My XML is like this:
<rss xmlns:g="http://base.google.com/ns/1.0" version="2.0">
<channel>
<item>
<title>
<![CDATA[ Far Cry 4: Overrun ]]>
</title>
<link>https://www.nuuvem.com/item/far-cry-4-overrun</link>
<description>
<![CDATA[
Neste novo conteúdo para Far Cry 4, enquanto a guerra sem trégua por Kyrat continua, os jogadores assumirão o papel dos Rakshasa e do Caminho Dourado para manter locais que dão pontos no mapa da batalha.
]]>
</description>
<g:availability>in stock</g:availability>
<g:price currency="BRL">8.99</g:price>
<g:image_link> http://dskhvldhwok3h.cloudfront.net/image/upload/t_boxshot_big/v1/products/557dbcb269702d0a9c490801/boxshots/ynhjodwlnmur0crkiaxp.jpg </g:image_link>
<g:product_type>
<![CDATA[ Ação ]]>
</g:product_type>
<g:google_product_category>Software > Video Game Software > Computer Games</g:google_product_category>
<g:condition>new</g:condition>
<g:identifier_exists>FALSE</g:identifier_exists>
<g:id>2668</g:id>
</item>
My script now looks like this:
function main() {
// Load an XML file:
var xmlURL = "XML URL HERE";
var xmlFile = UrlFetchApp.fetch(xmlURL);
// Parse the XML file:
var document = XmlService.parse(xmlFile);
var root = document.getRootElement();
// Go through all children of <deepdive_pages>:
var entries = document.getRootElement().getChildren();
for (var i = 0; i < entries.length; i++) {
//for (var i = 0; i < 10; i++) {
var id = entries[i].getChild('g:id').getValue();
var availability = entries[i].getChild('g:availability').getValue();
// If company_root_id has 0 jobs
if (availability == "out of stock") {
var adGroupIterator = AdWordsApp.adGroups().withCondition('Name CONTAINS "| ' + id + ' |"').get(); // Find all campaigns with the company name
while (adGroupIterator.hasNext()) { // Go over all campaings with company id in the name
var adgroup = adGroupIterator.next();
if (adgroup.isEnabled()) { // If campaign is enables, pause it
adgroup.pause();
Logger.log("adgroup " + adgroup.getName() + " was paused.");
}
}
}
// If company_root_id has MORE than 0 jobs
else {
var adGroupIterator = AdWordsApp.adGroups().withCondition('Name CONTAINS "| ' + id + ' |"').get(); // Find all campaigns with the company name
while (adGroupIterator.hasNext()) { // Go over all campaings with company id in the name
var adgroup = adGroupIterator.next();
if (adgroup.isPaused()) { // If campaign is paused, enable it
adgroup.enable();
Logger.log("adgroup " + adgroup.getName() + " was enabled.");
}
}
} // End If Else
}
}
Many thanks for any help!
With the help of Calin in this post: https://www.en.advertisercommunity.com/t5/Advanced-Features/Script-to-pause-Adggroups-based-in-information-from-a-Merchant/m-p/1024590#
I solved my problem.
To read the XML correctly, I used:
// Load an XML file:
var xmlURL = "XML_MERCHANT_URL_HERE";
var xmlFile = UrlFetchApp.fetch(xmlURL);
// Parse the XML file:
var document = XmlService.parse(xmlFile);
var ns = XmlService.getNamespace("http://base.google.com/ns/1.0");
var rss = document.getRootElement().getChildren(); //root element is <rss>; it's children are actually only one, <channel>
var entries = rss[0].getChildren('item'); //getting all 'item' children of the first rss element, <channel>
// Go through all children of <deepdive_pages>:
Logger.log(entries.length);
for (var i = 0; i < entries.length; i++) {
var id = entries[i].getChild('id',ns).getText();
var availability = entries[i].getChild('availability',ns).getText();
//Logger.log("ID: "+id+", Availability: "+availability);
Before I did'nt declared the XML namespace and I was using getchild, but in this case I need to use getChildren.

Javascript not adding variables from database up

Hi guys so basically i am trying to add data in a nutrtion label which i built. So the label it self has everything from fat, carbs , protein etc. Now i have set up a database with:
ingName: ...
fat: ...
Carbs: ....
etc etc
So right now i am just trying to get it to work for fat. Once i do this i can easily do the others. I can search through the database easily.When the user presses Add button it will add the ingredient below the search box and then change the content of fat. However if the user adds anther record the fat content wont add up together.
So for example i have Banana which has 4 fat and apple which has 1 fat. I add apple first and the fat content changes to 1 fat. When i add banana it should become 5 fat, however it will actually go to 4. So the records are not being added up correctly.
Js:
else{
var searchedValue = $('#search_term').val();
var temp2 = 0;
$.post( 'build.php', { 'search_term':searchedValue, 'current_fat':temp2 }, function(data) {
$('.result').html( data );
});
temp = $("#fat").text();
temp = parseInt(temp);
current_fat += temp2;
current_fat += temp;
console.log(temp + " " + temp2 + " " + current_fat);
$("#fat").text(current_fat);
The part which is causing the problem is in the else loop, i cant seem to figure out how to fix it,
If you need the php file i can get you that, but it seems to be in the else loop in the js file but i cant seem to figure out how to fix it. Been about a week i have been stuck on this mental problem :)
Thanks anyway for the help x
Try this:
$('#addButton').on('click', function( event ) {
//your other stuff
var searchedValue = $('#search_term').val();
//remove this : var temp2 = 0;
//add this:
temp = $("#fat").text();
temp = parseInt(temp);
//change your post reg to:
$.post( 'build.php', { 'search_term':searchedValue, 'current_fat':temp }, function(data) {
$('.result').html( data );
});
//rest of your code...

Javascript: Simple currency converter with previous conversions

what i aim to do is a very simple currency converter. Basically, you type in a number, and press a button, a text is displayed that says "x dollars is y euros". Press the button again, a new text is displayed where the old one was, and the old one is displayed under the new one.
I've come so far that when something is entered in the field, it pops up below, and if you press the button again (with the same or a different value) it becomes a list of text.
To clarify what it is i'm saying here, take a look at this jsfiddle: http://jsfiddle.net/w8KAS/5/
Now i want to make it so that only numbers work, and so that number(x) is converted when the button is pressed and displayed below next to some fitting text (like "x dollars is y euros")
This is my js code, check the jsfiddle full code (html, js, css)
Any suggestions?
var count = 0;
function validate() {
var amount = document.querySelector("#amount");
if(amount.value.length > 0) {
amount.className = 'correct';
}
else {
amount.className = 'empty';
}
if (document.querySelector('.empty')) {
alert('Något är fel');
}
else {
addconvert(amount.value);
}
}
function addconvert(amount) {
var table = document.querySelector('#tbody');
var tr = document.createElement('tr');
var amountTd = document.createElement('td');
var amountTextNode = document.createTextNode(amount);
amountTd.appendChild(amountTextNode)
tr.appendChild(amountTd);
table.insertBefore(tr, table.firstChild);
count++;
}
var button = document.querySelector(".button");
button.onclick = validate;
Your number validation is failing. Change the first part of your validation to this:
function validate() {
var amount = document.querySelector("#amount");
var amountNum = parseFloat(amount.value); //This is the numeric value, use it for calculations
if(amount.value.length > 0 && !isNaN(amountNum) ) {
amount.className = 'correct';
amount.value = amountNum;
}
...
Working here: http://jsfiddle.net/edgarinvillegas/w8KAS/6/
Cheers
You need a conversion rate (there are APIs for that), and then you can just add them together in a string
var convRate = 1.3;
var amountTextNode = document.createTextNode(amount + " dollars is " + amount*convRate + " euros");
Regarding the API, Yahoo will tell you what you need without even the need to sign-in
$.ajax({
url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(%22USDEUR%22)&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback="
}).done(function(data) {
convRate = data.query.results.rate.Rate
});
To make sure that only numbers work, you can test the variable amount.value using the isNaN function. This will return true if the user's input is Not-a-Number, so if it returns false, you can proceed with your conversion.
if (!isNaN(amount.value)){
addconvert(+amount.value) // the plus symbol converts to a number
} else {
// display error here
}
Inside your addconvert function, you can add code to will multiply your input amount by an exchange rate to get a rough conversion.
function addconvert(){
// ...
var euros = 0.74 * amount
var text = amount + ' dollars is ' + euros + ' euros'
var amountTextNode = document.createTextNode(text);

Firing the Facebook Conversion Pixel

I'm still pretty new to Javascript, but I was wondering what would be the best way to fire the Facebook conversion pixel (below) without actually loading a "confirmation"/"Thank You" page?
<script type="text/javascript">
var fb_param = {};
fb_param.pixel_id = 'XXXXXXXXXXX';
fb_param.value = '0.00';
fb_param.currency = 'USD';
(function(){
var fpw = document.createElement('script');
fpw.async = true;
fpw.src = '//connect.facebook.net/en_US/fp.js';
var ref = document.getElementsByTagName('script')[0];
ref.parentNode.insertBefore(fpw, ref);
})();
</script>
<noscript><img height="1" width="1" alt="" style="display:none"
src="https://www.facebook.com/offsite_event.php?id=XXXXXXXXXX&value=0&currency=USD" /></noscript>
Facebook says that we should plug this into our "Thank You pages" that visitors see after they convert (fill out a form, make a purchase, etc). However, some of our forms are popups or forms on sidebars next to content that we don't want readers to be directed away from by a confirmation page.
With Google Analytics, I can create an "invisible" pageview by firing _gaq.push(['_trackPageview']); code that can tell GA that it should count that invisible pageview as a goal completion.
Is there something similar to that that's general enough to tell my site to fire the FB pixel?
EDIT: I've updated my code as what I had mentioned previously did not work. Thanks to #Flambino to pointing out.
This is my revised answer using a pixel rather than a script to pass the conversion pixel. I reference the How to track a Google Adwords conversion onclick? SO post:
<head>
<script type="text/javascript">
function facebookConversionPixel(fb_pixel, fb_value){
var image = new Image(1,1);
image.src = "//www.facebook.com/offsite_event.php?id=" + fb_pixel + "&value=" + fb_value + "&currency=USD";
}
</script>
</head>
<body>
FBCONV
</body>
From the FB docs "How to track in-page events":
After the base code snippet is installed, you can track in-page actions, such as clicks on a button, by making a _fbq.push('track') call for the conversion pixel through registering different event handlers on an HTML DOM element. For example:
function trackConversionEvent(val, cny) {
var cd = {};
cd.value = val;
cd.currency = cny;
_fbq.push(['track', '<pixel_id>', cd]);
}
<button onClick="trackConversionEvent('10.00','USD');" />
Just move the entire original code into the event of your choice. Then just change 1 part of the code. The thing you will have to do is make the fb_param global instead of local.
See below at the comment
$('.button').click(function() {
window.fb_param = {}; // must be global by adding `window.`
fb_param.pixel_id = '123456789';
fb_param.value = '0.00';
fb_param.currency = 'USD';
(function(){
var fpw = document.createElement('script'); fpw.async = true; fpw.src = '//connect.facebook.net/en_US/fp.js';
var ref = document.getElementsByTagName('script')[0];
ref.parentNode.insertBefore(fpw, ref);
})();
});
I was having similar kind of issue and I would like to run multiple adds to track pixels codes and some reason I was not able to track. What I did is that, in the current page I have added pixel code in footer and javascript function
to call when my ajax button get submitted.
First refer to Facebook documentation page
https://developers.facebook.com/docs/ads-for-websites/conversion-pixel-code-migration#multi-conv-events
How to track Multiple Conversion Events
After the base code snippet is installed, you can track multiple conversions within the same web page by making multiple _fbq.push('track') calls for each conversion pixel ids. For example:
_fbq.push(['track','<pixel_id1>',{'value':'10.00','currency':'USD'}]);
_fbq.push(['track','<pixel_id2>']);
How to track In-Page Events
After the base code snippet is installed, you can track in-page actions, such as clicks on a button, by making a _fbq.push('track') call for the conversion pixel through registering different event handlers on an HTML DOM element. For example:
function trackConversionEvent(val, cny) {
var cd = {};
cd.value = val;
cd.currency = cny;
_fbq.push(['track', '<pixel_id>', cd]);
}
<button onClick="trackConversionEvent('10.00','USD');" />
Also, add the facebook pixel tracking code chrome addon and refer the facebook pixel helper page: https://developers.facebook.com/docs/ads-for-websites/pixel-troubleshooting
See my below solution/answer
Facebook tracking code in the current page
(function() {
var _fbq = window._fbq || (window._fbq = []);
if (!_fbq.loaded) {
var fbds = document.createElement('script');
fbds.async = true;
fbds.src = '//connect.facebook.net/en_US/fbds.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(fbds, s);
_fbq.loaded = true;
}
})();
window._fbq = window._fbq || [];
window._fbq.push(['track', 'yourid', {'value':'1.00','currency':'USD'}]);
<!-- Facebook Conversion -->
<script>(function() {
var _fbq = window._fbq || (window._fbq = []);
if (!_fbq.loaded) {
var fbds = document.createElement('script');
fbds.async = true;
fbds.src = '//connect.facebook.net/en_US/fbds.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(fbds, s);
_fbq.loaded = true;
}
})();
window._fbq = window._fbq || [];
window._fbq.push(['track', 'yourid', {'value':'1.00','currency':'USD'}]);
</script>
And the javascript code to call when ajax form submit or button click
<script>
function trackConversionEvent(val, cny) {
var cd = {};
cd.value = val;
cd.currency = cny;
_fbq.push(['track', 'yourid1', cd]);
_fbq.push(['track', 'yourid1', cd]);
}
</script>
and the call the function when ajax called
jQuery(form).ajaxSubmit({
type:"POST",
data: $(form).serialize(),
url:"process.php",
success: function() {
**trackConversionEvent**('1.00','USD');
}
......
Facebook has updated their pixels, so I created my own custom function to call that will dynamically put the parameters together to submit to Facebook.
Step 1. On every page, make sure you've initialised your pixel in the head element of the page.
Step 2. Add this custom function I created (it's a bit verbose as it is the first draft, so I'm sure there are ways to optimise it for your benefit).
triggerFacebookPixel: function(type, price, product_id, product_name, product_category, num_items) {
//See https://developers.facebook.com/docs/ads-for-websites/pixel-events/v2.8#events for documentation
//type = "ViewContent"|"AddToCart"|"Search"|"AddToWishlist"|"InitiateCheckout"|"AddPaymentInfo"|"Purchase"|"Lead"|"CompleteRegistration"
//product_id = Numeric Product ID. String or Integer accepted for single product events, or an array of integers for multiple products.
//price = Decimal/Float number of individual product's price or total price paid in conversion, or the user's status for 'CompleteRegistration'
//product_name = Optional. String of individual product's name or string of search query
//product_category = Optional. String of product category, hierarchy's accepted. E.g. "Clothing > Shirts > Men's > T-Shirts"
//num_items = Optional. Total number of products.
var data = {
value: typeof(price) == 'string' ? parseFloat(price) : price,
currency: 'USD'
}
switch (type) {
case 'Search':
data.content_ids = product_id;
data.search_string = product_name;
if (product_category !== undefined && product_category != '') {
data.content_category = product_category;
}
break;
case 'Lead':
data.content_name = product_name;
data.content_category = product_category;
break;
case 'CompleteRegistration':
data.status = product_id;
data.content_name = product_name;
break;
default:
//Product Specific Calls
//ViewContent|AddToCart|AddToWishlist|InitiateCheckout|AddPaymentInfo|Purchase
if (num_items == 1) {
data.content_ids = [typeof(product_id) == 'string' ? parseInt(product_id) : product_id];
data.content_category = product_category;
data.content_name = product_name;
} else {
data.content_ids = product_id;
}
//"num_items" is only a parameter used in these two types
if (type == 'InitiateCheckout' || type == 'Purchase') {
data.num_items = num_items
}
//"content_type" is only a parameter used in these three types
if (type == 'Purchase' || type == 'AddToCart' || type == 'ViewContent') {
data.content_type = 'product';
}
break;
}
fbq('track', type, data);
}
Step 3. Call that function with the appropriate parameters.
For your thank you pop-up after a purchase, the pixel is fired differently if the user purchases 1 item as opposed to multiple items. Basically, Facebook accepts parameters for product names and categories if it's just one product, but doesn't accept those parameters if it's multiple products.
For the following examples, here is some sample product data of a user purchasing 1 item:
Product Name: "My Super Awesome T-Shirt"
Product ID: 182
Product Category: "Clothing > Shirts > T-Shirts"
Total amount user paid (including shipping/handling & tax): $10.84
And here's the function you'd call on the confirmation:
triggerFacebookPixel('Purchase', 10.84, 182, 'My Super Awesome T-Shirt', 'Clothing > Shirts > T-Shirts', 1);
When a user purchases multiple items, the pixel handles it differently, excluding the product names and categories and only sending their ID's. So let's pretend our user purchased these two items:
Product ID's: 182 and 164 (the shirt and something else)
Total amount user paid (including shipping/handling & tax): $24.75
This is how you'd use the function:
triggerFacebookPixel('Purchase', 24.75, [182, 164], '', '', 2);
For other standard events as defined by Facebook regarding products, you can use this same function for "ViewContent", "AddToCart", "AddToWishlist", "InitiateCheckout", and "AddPaymentInfo". Just change "Purchase" to any of those key words in your call.
The other events aren't necessarily related to products: "Lead", "Search", and "Complete Registration". You can still use this function for those key words like this.
Example: user searched for "blue shirts":
triggerFacebookPixel('Search', 0, [], 'blue shirts');
If you want to pass a product category in the user search function, you can pass that as a string at the end. I can't think of a use-case scenario where you'd know what category the user is searching for. Unless you used this in the event that the product appears in the search results and the user clicked on it from the search page. That might be what this function is actually for but the documentation isn't quite clear on that. If that's the case for you, then simply change the 0 and empty array to the actual values (price and product ID, respectively) of the product that was clicked on from the search results page, and add its category as a string as the last parameter after the search string.
Example: user submitted a form that signed them up to your newsletter:
triggerFacebookPixel('CompleteRegistration', 0, 'Signed Up', 'Newsletter');
Facebook's documentation states that "CompleteRegistration" should be used when a registration form is completed, e.g. complete subscription/signup for a service. The "Signed Up" string is the "status" parameter and the "Newsletter" string is the "content_name" parameter.
Example: user submitted a form that signed them up for a free 30-day trial of some service you offer (so they are now a lead), where the name of the service is "Free 30-Day Trial Service" and it's in the sub-category "Free Trials" under the category "My Services":
triggerFacebookPixel('Lead', 0, 'Free 30-Day Trial Service', 'My Services > Free Trials');
Facebook's documentation states that "Lead" is when a sign up is completed, e.g. click on pricing, signup for trial. I assumed that the name of the service is the parameter "content_name" and the category of the service is the "content_category" parameter.

Fetch random excerpt from Wikipedia (Javascript, client-only)

I have a web page that asks the user for a paragraph of text, then performs some operation on it. To demo it to lazy users, I'd like to add an "I feel lucky" button that will grab some random text from Wikipedia and populate the inputs.
How can I use Javascript to fetch a sequence of text from a random Wikipedia article?
I found some examples of fetching and parsing articles using the Wikipedia API, but they tend to be server side. I'm looking for a solution that runs entirely from the client and doesn't get scuppered by same origin policy.
Note random gibberish is not sufficient; I need human-readable sentences that make sense.
My answer builds on the technique suggested here.
The tricky part is formulating the correct query string:
http://en.wikipedia.org/w/api.php?action=query&generator=random&prop=extracts&exchars=500&format=json&callback=onWikipedia
generator=random selects a random page
prop=extracts and exchars=500 retrieves a 500 character extract
format=json returns JSON-formatted data
callback= causes that data to be wrapped in a function call so it can be treated like any other <script> and injected into your page (see JSONP), thus bypassing cross-domain barriers.
requestid can optionally be added, with a new value each time, to avoid stale results from the browser cache (required in IE9)
The page served by the query is something that looks like this (I've added whitespace for readability):
onWikipedia(
{"query":
{"pages":
{"12362520":
{"pageid":12362520,
"ns":0,
"title":"Power Building",
"extract":"<p>The <b>Power Building<\/b> is a historic commercial building in
the downtown of Cincinnati, Ohio, United States. Built in 1903, it
was designed by Harry Hake. It was listed on the National Register
of Historic Places on March 5, 1999. One week later, a group of
buildings in the northeastern section of downtown was named a
historic district, the Cincinnati East Manufacturing and Warehouse
District; the Power Building is one of the district's contributing
properties.<\/p>\n<h2> Notes<\/h2>"
} } } }
)
Of course you'll get a different article each time.
Here's a full, working example which you can try out on JSBin.
<HTML><BODY>
<p><textarea id="textbox" style="width:350px; height:150px"></textarea></p>
<p><button type="button" id="button" onclick="startFetch(100, 500)">
Fetch random Wikipedia extract</button></p>
<script type="text/javascript">
var textbox = document.getElementById("textbox");
var button = document.getElementById("button");
var tempscript = null, minchars, maxchars, attempts;
function startFetch(minimumCharacters, maximumCharacters, isRetry) {
if (tempscript) return; // a fetch is already in progress
if (!isRetry) {
attempts = 0;
minchars = minimumCharacters; // save params in case retry needed
maxchars = maximumCharacters;
button.disabled = true;
button.style.cursor = "wait";
}
tempscript = document.createElement("script");
tempscript.type = "text/javascript";
tempscript.id = "tempscript";
tempscript.src = "http://en.wikipedia.org/w/api.php"
+ "?action=query&generator=random&prop=extracts"
+ "&exchars="+maxchars+"&format=json&callback=onFetchComplete&requestid="
+ Math.floor(Math.random()*999999).toString();
document.body.appendChild(tempscript);
// onFetchComplete invoked when finished
}
function onFetchComplete(data) {
document.body.removeChild(tempscript);
tempscript = null
var s = getFirstProp(data.query.pages).extract;
s = htmlDecode(stripTags(s));
if (s.length > minchars || attempts++ > 5) {
textbox.value = s;
button.disabled = false;
button.style.cursor = "auto";
} else {
startFetch(0, 0, true); // retry
}
}
function getFirstProp(obj) {
for (var i in obj) return obj[i];
}
// This next bit borrowed from Prototype / hacked together
// You may want to replace with something more robust
function stripTags(s) {
return s.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, "");
}
function htmlDecode(input){
var e = document.createElement("div");
e.innerHTML = input;
return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}
</script>
</BODY></HTML>
One downside of generator=random is you often get talk pages or generated content that are not actual articles. If anyone can improve the query string to limit it to quality articles, that would be great!

Categories