I'm using update panel, my response have some javascript like bellow. After a success response, I need to eval it, load it (with external script)
ex: my html response
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript">
alert('asd');
</script>
<div>test</div>
<div>blah blah blah</div>
I'm not sure whether this question is still important for you, however I will try to provide a reasonable answer below.
AJAX framework does not evaluate scripts which are returned via UpdatePanel calls. You have to re-attach external scripts to document, so that browser could request for them and evaluate all inline scripts. You can use a small module I have paste below.
var UpdatePanelEnhancer = function ()
{
var divSelector = '#liveArea';
function evaluateScripts()
{
$(divSelector).find('script').each(function ()
{
if (this.src)
{
$('body').append(this);
}
else
{
var content = $(this).html();
eval(content);
}
});
};
Sys.Application.add_load(evaluateScripts);
} ();
The weak part of it is that you have to provide a selector for the element where module should look for a scripts to evaluate ('liveArea' in example), although you can extend the module and provide some cinfiguration to it. Also, I would strongly recommend you to load external javascripts before. If you cannot do it for some reason you should additionally check whether script is already referenced or not to avoid necessary calls and potentially unexpected behaviors and errors .
Related
I am new to Google analytics and Google Tag Manager and currently I am confused with using external JS libraries. Any help would be appreciated.
I need to use 'https://cdnjs.cloudflare.com/ajax/libs/fingerprintjs2/2.1.0/fingerprint2.min.js' in my custom javascript code in google tag manager. I have tried to include the script as a custom html or even custom template. The script is successfully added to the head and I see it in the inspection. But in my custom JS code , when I try to call and use library functions , it throws exception saying that the lib object is not defined.
I tried sequencing tags also , to make sure script loading tags are fired before my custom js code execution. But that did not fix the problem.
Any suggestion on how to include external JS libraries in your GTM custom JS code? I hope I explained the problem properly.
Thanks !
This example posted by jwest75674 should help. As you need to declare var = fingerprint in your script to allow Google Tag Manager to capture the data after the script has run
In short, you can copy the script below an add it as Custom HTML Tag in GTM (https://github.com/Valve/fingerprintjs2)
<script src="https://cdn.jsdelivr.net/npm/fingerprintjs2#2.1.0/dist/fingerprint2.min.js"></script>
<script type="text/javascript">
var fingerprint; // Variable to allow the Google Tag Manager to capture the data after this script has run.
if (window.requestIdleCallback) {
requestIdleCallback(function () {
Fingerprint2.get(function (components) {
console.log(components) // an array of components: {key: ..., value: ...}
})
})
} else {
setTimeout(function () {
Fingerprint2.get(function (components) {
console.log(components) // an array of components: {key: ..., value: ...}
})
}, 500)
}
</script>
This is how i construct it:
var fs = require("fs");
var jsdom = require("jsdom");
var htmlSource = fs.readFileSync("./test.html", "utf8");
var doc = jsdom.jsdom(htmlSource, {
features: {
FetchExternalResources : ['script'],
ProcessExternalResources : ['script'],
MutationEvents : '2.0'
},
parsingMode: "auto",
created: function (error, window) {
console.log(window.b); // always undefined
}
});
jsdom.jQueryify(doc.defaultView, 'https://code.jquery.com/jquery-2.1.3.min.js', function() {
console.log( doc.defaultView.b ); // undefined with local jquery in html
});
the html:
<!DOCTYPE HTML>
<html>
<head></head>
<body>
<script src="./js/lib/vendor/jquery.js"></script>
<!-- <script src="http://code.jquery.com/jquery.js"></script> -->
<script type="text/javascript">
var a = $("body"); // script crashes here
var b = "b";
</script>
</body>
</html>
As soon as i replace the jquery path in the html with a http source it works. The local path is perfectly relative to the working dir of the shell / actual node script. To be honest i don't even know why i need jQueryify, but without it the window never has jQuery and even with it, it still needs the http source inside the html document.
You're not telling jsdom where the base of your website lies. It has no idea how to resolve the (relative) path you give it (and tries to resolve from the default about:blank, which just doesn't work). This also the reason why it works with an absolute (http) URL, it doesn't need to know where to resolve from since it's absolute.
You'll need to provide the url option in your initialization to give it the base url (which should look like file:///path/to/your/file).
jQuerify just inserts a script tag with the path you give it - when you get the reference in the html working, you don't need it.
I found out. I'll mark Sebmasters answer as accepted because it solved one of two problems. The other cause was that I didn't properly wait for the load event, thus the code beyond the external scripts wasn't parsed yet.
What i needed to do was after the jsdom() call add a load listener to doc.defaultView.
The reason it worked when using jQuerify was simply because it created enough of a timeout for the embedded script to load.
I had the same issue when full relative path of the jquery library to the jQueryify function. and I solved this problem by providing the full path instead.
const jsdom = require('node-jsdom')
const jqueryPath = __dirname + '/node_modules/jquery/dist/jquery.js'
window = jsdom.jsdom().parentWindow
jsdom.jQueryify(window, jqueryPath, function() {
window.$('body').append('<div class="testing">Hello World, It works')
console.log(window.$('.testing').text())
})
Some properties of my model should be loaded asynchronously (implemented by promises). I don't want to wait it - I want to render it right now and partially update it when promises will be resolved. Does handlebars.js support it?
Handlebars does not support async. This makes it impossible to use Promises for expressions and helpers. You could use await but this suspends execution, so no rendering takes place until the Promise is settled. Other templating frameworks like dust.js offer async functionality.
I think i can propose a workaround to get the async (or promises) to (seem to) work. Below is the example. Essentially this is what i am doing
First return a div with an unique Id (i am using namespace + auto increment here)
Do your processing (ajax or what ever slowly). Once done replace the innerHTML of the div in step1 with new data by accessing it via the unique id
code below. Observe the tripple bracket ({{{ }}}). This is to make sure generated HTML is not escaped
<script id="handlebars-demo" type="text/x-handlebars-template">
<div>
-->> {{{functionName "functionParam" }}} <<--
</div>
</script>
<div id="output" />
<script>
window.id=0;
Handlebars.registerHelper('functionName', function(funcParam ){
let tempId = "my_namespace_" + window.id++;
$.post("https://something.com/abc").done(function(data){
$("#"+tempId ).html(data.something);
}
)
return '<div id='+tempId+'>loading</div>'
});
var template = document.getElementById("handlebars-demo").innerHTML;
var templateScript = Handlebars.compile(template);
var context = { };
var html = templateScript(context);
document.getElementById("output").innerHTML= html;
</script>
I am creating a dynamic tab/contentPane as below in home.xhtml file and i am trying to call a function display which is present in order.xhtml,its not getting called. what ever java script is there in order.xhtml is not getting loaded.
In home.xhtml
if(dijit.byId('ordersummary')!=null){
dijit.byId('ordersummary').destroy();
}
newTab= new dijit.layout.ContentPane({
id : 'ordersummary',
title : 'Order Summary',
href : 'order.xhtml',
closable : true
});
dijit.byId('tabContainer').addChild(newTab);
dijit.byId('tabContainer').selectChild(dijit.byId("ordersummary"));
javascript in order.xhtml
<script type="text/javascript">
//<![CDATA[
function display(){
alert(" I M BEING CALLED");
}
</script>
There are two ways about this, either a make the script type dojo/method.
Or use the extended dojox/layout/ContentPane.
http://livedocs.dojotoolkit.org/dijit/layout/ContentPane#executing-javascript-inside-contentpane
While I'm not familiar with the dojo toolkit, I think you should put the JavaScript function in the main file or load the JavaScript dynamically like;
How do I include a JavaScript file in another JavaScript file?
dijit.layout.ContentPane will not support javascript,i mean it will not execute the javascript content in the input file.
dojox.layout.ContentPane is advanced one and it will support javascript.
Is it possible to render Javascript in nested mustache.js templates as follows?
myApp.mustache:
{{#myapp}}
{{>userApp}}
{{/myapp}}
userApp.mustache:
{{#user}}
<script>
$(function () {
$("a[id='a_popover_{{username}}']").popover()
})
</script>
{{/user}}
The templates render correctly with pystache (Python's mustache library), but mustache.js, handlebars.js, ICanHaz.js, and ICanHandlebarz.js all complain something like #user was not closed properly.
Pretty sure the </script> bit is the problem, the browser sees that and parses it as end of the template script. Try escaping it like so: <\/script>
I was also stuck into similar issue, what ended up was creating a new script element, because even if the javascript code was rendered , is was not executed after appending into the body, it acts like string.
$('script:last').html('alert("ok !")'); // won't work
sample code for my case:
var render = Mustache.to_html(template, data_sources);
var sc = document.createElement('script');
sc.innerHTML = render;
var p_div = document.getElementById('template_wrap_div').parentNode;
p_div.innerHTML = "";
p_div.appendChild(sc);
Hope that gives some idea and help.