Postpone the ads script execution - javascript

With the help of the following php function:
<?php
if (!function_exists('wrapAds')) {
function wrapAds($current_banner_name){
$STRING_EMPTY = "";
$openExprResult = array();
$closeExpreResult = array();
$openExpr = "/(<div[^>]*>)/";
$closeExpr = "/(<\/div>)/";
$banner = tsp_get_banner($current_banner_name);
$result = '<pre data-script-reference>'
.htmlspecialchars($banner)
.'</pre>';
return $result;
}
}
?>
I am rendering the following markup:
<pre data-script-reference="1"><!--- s: middle-box-sidebar -->
<div class="ads middle-box-sidebar"><script type="text/javascript">
var FW_type = "4w";
var FW_code = "18xxxx;95xxx;70xxx;0";
var FW_dimension = "300x250";
var FW_category = "gossip";
</script>
<script src="//optimized-by.4wnetwork.com/simply_loader.js?4wvideo=true" type="text/javascript"></script></div>
<!--- e: middle-box-sidebar --></pre>
Now I am tring to postpone the encoded script execution later with the following script:
<script type="text/javascript">
[].slice.call(document.querySelectorAll('pre[data-script-reference]'))
.forEach(function(item){
var txt = document.createElement("textarea");
txt.innerHTML = item.innerHTML;
var parentNode = item.parentNode;
var p0 = txt.innerText;
// parentNode.removeChild(item);
parentNode.innerHTML += p0;
</script>
seems that decoded script isn't executed at all, what I am doing wrong?

After a trillion of useless code executions, I just noted a curious statement inside a long list of warnings:
"Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.". I googled around this message and I found a nice question.
The only not accepted answer suggest postscribe.js
Asynchronously write javascript, even with document.write.
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.
So, since I have to manage both ads in the body and in the sidebar, I made a little refactoring, moving the php function in the functions.php:
/**
* redefine and get the legacy ads block from base library by name
* render as encoded plain text inside a *pre* wrapper
*/
function tsp_get_banner($current_banner_name){
$STRING_EMPTY = "";
// https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags
$openExpr = "/(<div[^>]*>)/";
$closeExpr = "/(<\/div>)/";
$openExprResult = $closeExpreResult = array();
$banner = original_tsp_get_banner($current_banner_name);
preg_match($openExpr, $banner, $openExprResult);
$banner = preg_replace($openExpr, $STRING_EMPTY, $banner);
preg_match($closeExpr, $banner, $closeExpreResult);
$banner = preg_replace($closeExpr, $STRING_EMPTY, $banner);
return wrapAdsSnippet($banner, $openExprResult[0], $closeExpreResult[0]);
}
function wrapAdsSnippet($source, $prefix, $postfix){
$result = '<pre data-script-reference style="display:none;">'
.htmlspecialchars($source)
.'</pre>';
if(isset($prefix) && isset($postfix)){
$result = $prefix.$result.$postfix;
}
return $result;
}
then I changed the inclusion of the block:
so that I don't need to change anything.
<?php
echo tsp_get_banner("middle-box-sidebar");
echo renderAds("middle-box-sidebar");
?>
I have just to change the final script to include in the footer.php:
var MyCompanyLab;
(function (MyCompanyLab) {
"use strict";
var Ads;
(function (Ads) {
var Optimization;
(function (Optimization) {
var PostProcessor = (function () {
function PostProcessor() {
}
PostProcessor.postponeAdsExecution = function () {
$("pre[data-script-reference]").each(function (idx, item) {
var parentNode = item.parentNode;
postscribe(parentNode, $('<textarea />').html(item.innerHTML).text(), {
done: function () { },
error: function () { },
releaseAsync: true,
});
parentNode.removeChild(item);
});
};
return PostProcessor;
}());
Optimization.PostProcessor = PostProcessor;
})(Optimization = Ads.Optimization || (Ads.Optimization = {}));
})(Ads = MyCompanyLab.Ads || (MyCompanyLab.Ads = {}));
})(MyCompanyLab|| (MyCompanyLab= {}));
<script type="text/javascript">
...
MyCompanyLab.Ads.Optimization.PostProcessor.postponeAdsExecution();
...
</script>

Related

Run A JavaScript Function Written In Called/Responce Data Of AJAX In Main Page

My problem is that I have a JavaScript function written in a PHP file and when I call it from AJAX request, I want to run that JavaScript function on the main page too after successful AJAX request. As an example, I have a main.html file where I have written an AJAXX function as below.
main.html
<script type="text/javascript">
/* AJAX Function
----------------------------------------------- */
function ajaxFunction() {
var FD = new FormData();
var ajx = new XMLHttpRequest();
ajx.onreadystatechange = function () {
if (ajx.readyState == 4 && ajx.status == 200) {
document.getElementById("mainContent").innerHTML = ajx.responseText;
hello(); //Uncaught ReferenceError: hello is not defined
}
};
ajx.open("POST", "/example.php", true);
ajx.send(FD);
document.getElementById("mainContent").innerHTML = 'Loading...';
return false;
}
</script>
And my example.php file contains a JavaScript function as
example.php
<?php
echo 'Some contents and functions';
echo '<script type="text/javascript">
function hello() {
alert("Hello");
}
</script>';
echo 'Some contents and functions';
?>
Now when I run index.html file, I get Uncaught ReferenceError: hello is not defined error in console rest I am seeing the function body is written on HTML page while inspecting elements on-page.
As I know that innerHTML does not run scripts. So what's the workaround to this problem. You can view the below-linked answer also that I think is related to my question but tried and not working with my problem.
Researched Questions/Answers:
https://stackoverflow.com/a/3250386/3170029
https://stackoverflow.com/a/47614491/3170029
As I shared and you know that innerHTML does not run scripts. so we have to look around it then I found a solution on StackOverflow and I am sharing here with this problem's answer.
main.html
<script type="text/javascript">
/* AJAX Function
----------------------------------------------- */
function ajaxFunction() {
var FD = new FormData();
var ajx = new XMLHttpRequest();
ajx.onreadystatechange = function () {
if (ajx.readyState == 4 && ajx.status == 200) {
setInnerHTML(document.getElementById("mainContent"), ajx.responseText); // does run <script> tags in HTML
hello();
}
};
ajx.open("POST", "/example.php", true);
ajx.send(FD);
document.getElementById("mainContent").innerHTML = 'Loading...';
return false;
}
//https://stackoverflow.com/a/47614491/3170029
var setInnerHTML = function(elm, html) {
elm.innerHTML = html;
Array.from(elm.querySelectorAll("script")).forEach(oldScript => {
const newScript = document.createElement("script");
Array.from(oldScript.attributes)
.forEach(attr => newScript.setAttribute(attr.name, attr.value));
newScript.appendChild(document.createTextNode(oldScript.innerHTML));
oldScript.parentNode.replaceChild(newScript, oldScript);
});
}
</script>
Its concept is clear. When you get the response data from PHP file then first extract <script ..... </script> tags from it and add them in index.html file hear by using createElement('script') and copy all the script to this then you can easily call your function after response data anywhere.
In other words, You can create an executing script element outside of that initial parse using the DOM method of calling createElement('script'), setting its src/content, and adding it to the document. The alternative is what jQuery's getScript90 does.

Call output of a PHP randomizer via AJAX

Current setting:
In the same PHP document I have a PHP randomizer function and the HTML that calls that function -- a separate txt document with strings that are called by the php function:
Function
<?php
function rand_line($fileName, $maxLineLength = 4096) {
$handle = #fopen($fileName, "strings.txt");
if ($handle) {
$random_line = null;
$line = null;
$count = 0;
while (($line = fgets($handle, $maxLineLength)) !== false) {
$count++;
if(rand() % $count == 0) {
$random_line = $line;
}
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
fclose($handle);
return null;
} else {
fclose($handle);
}
return $random_line;
}
}
?>
I call the function in the HTML using:
<?php echo rand_line("strings.txt");?>
<input type="button" value="Another String" onClick="window.location.reload()">
This tends to be slow when multiple users access the page and press the button to obtain a new status.
What I would like to achieve:
Improve the performance and make the whole thing not so heavy: maybe the randomizer is unnecessarily complicated and I could work with AJAX calls for example, but if possible keeping the string list inside the strings.txt file and separated from the PHP script and HTML.
Sorry if I don't know what I'm talking about... I'm not a proficient programmer. Just a guy that hacks stuff together once in a while :)
You really don't want to use window.location.reload();
That is terrible... You do not want to refresh a page...
location.reload() sends http request for a whole new page (whole HTML), and then not only that your browser needs to render whole HTML again, you have to transfer more duplicated data through a network, from point A to point B.
You should send HTTP request only for a data that you need (you don't need whole HTML again, you loaded it the 1st time you visited page).
Instead, use XMLHttpRequest javascript library (AJAX) to request only for a portion of data (in your case => random line string)
HTML:
<!DOCTYPE html>
<html>
<head lang="en">
<script type="text/javascript">
function loadDoc(url, cfunc) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (xhttp.readyState == 4 && xhttp.status == 200) {
cfunc(xhttp);
}
};
xhttp.open("GET", url, true)
xhttp.send();
}
function randomLine(xhttp) {
alert(xhttp.responseText);
}
</script>
</head>
<body>
<input type="button" value="Get random line" onClick="loadDoc('http://localhost:8080/myScript.php', randomLine)">
</body>
</html>
PHP:
myScript.php
<?php
function rand_line($fileName, $maxLineLength = 4096)
{
...
}
echo rand_line("strings.txt");
?>
*EDIT #2*
Fully-functioning script. Grabs initial strings via PHP, and stores in array for later JavaScript usage. Minimizes # of calls.
PHP to grab strings from file; generates a default (random) string, as well as an array of strings for later use with button.
/**
* #input array $file
* #return array (mixed) [0] => string, [1] => array
*/
$randomStringFromFile = function($file) {
if (!$file) return false;
/**
* #return Removes carriage returns from the file
* and wraps $val with single-quotes so as
* to not break JavaScript
*/
$add_quotes = function(&$val) {
return str_replace("\n", "", "'$val'");
};
return [$file[rand(0, count($file)-1)], array_map($add_quotes, $file)];
};
$randomString = $randomStringFromFile( #file('strings.txt') ) ?: false;
JavaScript
<div id="string_container"><?php echo $randomString[0]; // defaults random string to page ?></div><br>
<button onclick="getString();">Another String</button>
<script>
var getString = function() {
var arr = [<?php echo implode(',', $randomString[1]); ?>],
setString = document.getElementById('string_container').innerHTML = arr[Math.floor(Math.random() * arr.length)];
};
</script>
Place the above in your page and you should be good to go.
EDIT (ORIGINAL)
We can remove PHP from the equation entirely using the following (fastest method):
<div id="string_container"></div><br>
<button onclick="getString();">Another String</button>
<script>
var getString = function() {
var request = new XMLHttpRequest(),
file = 'strings.txt';
request.open('GET', file);
request.onload = function() {
if (request.status === 200) {
var arr = request.responseText.split("\n"), /** assuming line breaks in file are standard carriage returns (Unix); "\r" if Windows */
setString = document.getElementById('string_container').innerHTML = arr[Math.floor(Math.random() * arr.length-1)];
}
};
request.send();
};
</script>
ORIGINAL w/PHP
We can simplify the PHP even further, removing loops from the equation altogether.
$randomStringFromFile = function($file) {
if (!$file) return false;
return $file[rand(0, count($file)-1)];
};
echo $randomStringFromFile( #file('strings.txt') ) ?: 'No worky!';
Using file() will return the contents in an array, thus allowing you to simply select a key at random and return the value.
NOTE On average, $file[rand(0, count($file)-1)] outperformed array_rand() (E.g. $file[array_rand($file)];) when selecting a key at random. By negligible amounts, have you.. ~0.0002s vs ~0.0005s, respectively.
You can simplify your code
function rand_line($fileName, $maxLineLength = 4096) {
$f = file($fileName);
$length = $maxLineLength + 1;
do {
$line = $f[array_rand($f)];
$length = strlen($line);
} while ($length > $maxLineLength);
return $line;
}

Running javascript code inside php doesn't work

this is my whole javascript code
what im trying to do here is loop through html table and look for checked checkbox and retrieve the data in every row of checked checkbox
but i need to run this is php.
<script type='text/javascript'>//<![CDATA[
$(window).load(function () {
$('#save').click(function () {
$('#dataTable').find('tr').each(function () {
var row = $(this);
if (row.find('input[type="checkbox"]').is(':checked') ) {
//alert('You must fill the text area!');
var $row1 = $(this).closest("tr"), // Finds the closest row <tr>
$tdi = $row1.find("td:nth-child(1)");
$.each($tdi, function () { // Visits every single <td> element
var thirdrowval = $(this).text(); // Prints out the text within the <td>
//document.getElementById("signatoryid").value = thirdrowval
alert(thirdrowval);
});
}
});
});
});//]]>
</script>
and after reading in this site i found a way to do it and here is the code. but it doesn't run the javascript. i expect an alert to pop up. but it doesn't worked as expected
$row1 = "";
$row = "";
$thirdrowval = "";
$tdi = "";
echo "
<script type=\"text/javascript\">
$('#dataTable').find('tr').each(function () {
var row = $(this);
if (row.find('input[type='checkbox']').is(':checked') ) {
var $row1 = $(this).closest('tr'),
$tdi = $row1.find('td:nth-child(1)');
$.each($tdi, function () {
var thirdrowval = $(this).text();
alert(thirdrowval);
});
}
});
</script>
";
Try to include your table $('#dataTable') also in your php file.
I think javascript can't find the element that named #dataTable
in the line
if (row.find('input[type='checkbox']').is(':checked') ) {
you will have to escape the inner quotes ' it should be
if (row.find('input[type=\'checkbox\']').is(':checked') ) {
also you have to pay attention that variables in strings with double quotes like
echo "$row1";
will be replaced with the value of the php variable $row1. So in your example it will be replaced with an empty string. If this is not the exspected behaviour you can use single quotes:
echo '$row1';
this will print $row1

add google ads in the middle of content page

I would like to add google ads after the first paragraph on every page on my wiki.
I have a code that checks if a tag is there, if it isn't then the tag is added and this tag calls the code for the google ads.
However, the rest of the text on the page is not showing after the ads.
This is my code: (based on the AdsWhereever extension)
$wgHooks['ParserFirstCallInit'][] = 'AdsSetup'; $wgHooks['EditPage::showEditForm:initial'][] = 'CheckHasTag';
function AdsSetup( &$parser ) {
$parser->setHook( 'ads', 'AdsRender' );
return true;}
function AdsRender($input, $args ) {
$input =""; $url = array(); global $wgOut;
$ad['goo1'] = '<html><br><script type="text/javascript">
google_ad_client = "xxx";
google_ad_width = 728;
google_ad_height = 90;
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script><br></html>';
$media = $args['media'];
return $ad[$media];
}
// check if content has <goo1> tag
function CheckHasTag($editPage){global $wgOut;
$wgOut->addScript('<script type="text/javascript">
var editTextboxText = document.getElementById("wpTextbox1").value;
var searchFor = "goo1";
var searchResult = editTextboxText.search(searchFor);
if(searchResult == -1){
var a = editTextboxText;
var b = "\n<ads media=goo1>\n";
var findP = "\n";
var p = editTextboxText.search(findP);
var position = p;
document.getElementById("wpTextbox1").value = a.substr(0, position) + b + a.substr(position);
}</script>');
return true;
}
Your code relies on $wgRawHtml being set to true in LocalSettings.php. (This, by the way, is a huge security risk, and should never be used in public wikis.) If you did not set
$wgRawHtml to true, the last output of your tag function will be </html>, that will cause the browser to stop parsing the page, and produce no further output.
Something like this would probably work, without having to use the html-tag:
function AdsRender( $input, $args, $parser, $frame ) {
$output = '<div id="googlead"><script type="text/javascript">
google_ad_client = "xxx";
google_ad_width = 728;
google_ad_height = 90;
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div>';
return array( $output, "markerType" => 'nowiki' );
}
Btw, you have a lot of garbage in you example, it's easier to help you if you remove code that is not being used (like $url = array(); global $wgOut; etc)
It was missing a / in the tag which was why the rest of the text wasn't being displayed!
var b = "\n\n"

Get Meta Description from URL using jQuery or javascript

i want to get the meta description of the parent page from an iframe, what i did uptill now is that i get the url of the parent page, pass that url to jquery and try to get the meta description but it doesn't work, my code is as follows
<script type="text/javascript">
function addToInterest() {
var URL = parent.window.location;
var Title = parent.document.getElementsByTagName("title")[0].innerHTML;
var MetaDescription = "";
var Img_Src = "";
var metaDesc = $.get('http://myURL.com', function (data) {
MetaDescription = $(data).find('meta[name=description]').attr("content");
Img_Src = $(data).find('link[rel=image_src]').attr("href");
});
alert(MetaDescription);
alert(Img_Src);
}
</script>
But in both alerts, it shows nothing.. i have already tried the methods told here
but did not successfull.
any sample code please....
Regards:
Mudassir
$.get is asynchronous. Both your alerts executed just after $.get call, but at this moment HTTP request can be still in progress. You need to move your alerts inside of callback function:
<script type="text/javascript">
function addToInterest() {
var URL = parent.window.location;
var Title = parent.document.getElementsByTagName("title")[0].innerHTML;
var MetaDescription = "";
var Img_Src = "";
var metaDesc = $.get('http://myURL.com', function (data) {
MetaDescription = $(data).find('meta[name=description]').attr("content");
Img_Src = $(data).find('link[rel=image_src]').attr("href");
alert(MetaDescription);
alert(Img_Src);
});
}
</script>
Also note, what your code will hit Same Origin Policy. By default you can't dynamically load resources, placed on other host, than you script.

Categories