How to run scripts loaded in callback in Devexpress CallbackPanel - callback

On my page I use Devexpress CallbackPanel to dynamically load its content including javascript blocks. Since DX does not (by default) run these scripts on callback end I found a workaround.

Only thing you need is to specify id of script block starting with prefix "dxss_" and then the magic works.
<script type="text/javascript" id="dxss_AnyTextHere">
//some script here
</script>

You can use the ASPxCallback client side event specified by "ClientSideEvents-EndCallback" where you can specify a javascript function. From this function, you can call whatever scripts you add during the callback.

Related

Dynamically inject content into JSDoc #example

I'm using JSDoc to document my javascript API.
I have an #example where I exhibit a minimized loader script (similar to the Google Analytics script). The loader script loads additional javascript from https://<server>/myProduct/lib/script.js.
My JSDoc documentation is bundled with myProduct, so there are aways /myProduct/lib/script.js and /myProduct/docs/ side-by-side. However, myProduct can be hosted by my customers anywhere, so I don't know what the <server> is.
I would like to be able to use document.location.href to detect current browser URL, and display a working loader script in my #example, so that customer can simply copy & paste a working script from documentation without having to manually edit the <server> part.
My question is: Does JSDoc offer any means to dynamically inject content into #example?
I could just manually edit the JSDoc output and include some custom javascript manually, which replaces <server> with the actual current server on run-time. However, this would be tedious to do every time my documentation updates.
No, JsDoc doesn't provide for injecting external content, and while it is certainly possible to create a JsDoc plugin to include external content during document generation, I don't think this would get you where you need to be.
I think the simplest answer would be to post-process the output of JsDoc to add a simple script, like
<script>
// retrieve the hostname from the current url.
const getServiceHostName = () =>
document.location.href.replace(/http:\/\/([\/]+)\/.+$/, '$1');
// replace the content of the span#service-host with the current hostname.
document.onload = function () {
document.getElementById("service-host").textContent=getServiceHostName();
};
</script>
to your html files just above the </body> tag.
Then, in the example content, insert a <span id="service-host"></span> where you'd like the service hostname to appear.
Another approach might be to take advantage of the fact that JsDoc passes the content attached to the #description tag directly into the html output.
So, this appears to do the expected:
/**
* Hostname: "<span id="service-host">hostname</span>"
*
* <script src="https://code.jquery.com/jquery-3.6.0.min.js"
* integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
* crossorigin="anonymous"></script>
*
* <script>
* $(document).ready(function() {
* $("#service-host").html(document.location.href);
* });
* </script>
*
* #name How-To-Monkey-Patch-JsDoc
*
*/
Note that the content of #example is wrapped in <pre><code>...</code></pre> in the html output which will definitely cause you problems, but it should be easy to post-process the html inline using the code above, by adding some recognizable token (perhaps [[HOSTNAME]]) into the example content and on document load, replace it with the desired value.
Please note also that this approach has the possibility of opening your docs to security issues, which is why I'd use the first solution above.

eliminate inline <script> in file generated by doxygen

A proposed change to the Content Security Policy (CSP) of our web server to disallow inline script
is causing a problem with the documentation generated by doxygen. Specifically, the problem occurs
in the generated index.html file, and the following lines:
<!-- Generated by Doxygen 1.8.15 -->
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* #license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */
$(function() {
initMenu('',false,false,'search.php','Search');
})
/* #license-end */</script>
If the initMenu() code is put into a separate file that is just included like other JavaScript files, everything
works just fine. Is there a doxygen option to put all JavaScript into files rather that inline? We can
post process the generated file to do this, but may not know when the "pattern" of this code may
change due to updates in doxygen itself. And we may not know if using additional doxygen features will result in other inline JavaScript.
Any suggestions would be welcome.
Thank you
Fritz Sieker
First off Content Security Policy is useful but far from being an absolute authority. There are other completely useless headers such as those that block referrers based on "privacy".
Secondly there is no such thing as "text/javascript", perhaps they meant application/javascript?
If you're using good (though very non-common practices) you don't have any script elements in the body element (use defer="true" on script elements in the head). By doing that you'll better understand the structure of JavaScript and that in turn will help you become more proficient/capable/help more people/make more money/etc.
You can use document.getElementsByTagName('body')[0].getElementsByTagName('script') to find all the script elements in the body element that don't belong there.
If you do have script elements in the body element beforehand and moving them to the head element is not feasible right now you're likely going to have to work with inherent logic, in short those script elements will always be inserted in to the DOM in a specific and reasonably easily reproducible area of your code (like as the very last elements). In such a case you can find them via the following:
document.getElementsByTagName('body')[0].lastChild
document.getElementsByTagName('body')[0].lastChild.previousSibling
document.getElementsByTagName('body')[0].lastChild.previousSibling.previousSibling
Keep in mind that pressing Enter in your code to make it more readable will insert a textNode so you may want to append nodeName to those instances and look for "script":
console.log(document.getElementsByTagName('body')[0].lastChild.nodeName);
There is the DOM TreeWalker that might help you out here, subjective to the end result in your DOM. I don't know offhand if you can transverse all the elements in reverse (probably).
Once you know what you want to delete instead of making everything convoluted just send that object (or id) to the following:
function element_del(id)
{
if (typeof id=='string' && id_(id) && id_(id).parentNode.removeChild)
{
id_(id).parentNode.removeChild(id_(id));
}
else if (typeof id=='object' && typeof id.parentNode=='object') {id.parentNode.removeChild(id);}
}
//Example:
element_del(document.getElementsByTagName('body')[0].lastChild);
I hope this helps!

AEM 6.x: How to pass an HTL variable to clientlib/JS?

So I have the following lines which loads my javascript.
<sly data-sly-use.clientLib="${'/libs/granite/sightly/templates/clientlib.html'}" data-sly-unwrap />
<sly data-sly-call="${clientLib.js # categories='myhost.mycustomJS'}" data-sly-unwrap />
I have an HTL property (example: ${properties.myCustomProperty}) that I want to pass to myCustomJS.
Any ideas how it can be done?
I've looked around the net but didn't find anything useful.
Thank you.
You are trying to access a server side property with client side script. As you may realize sightly executes at server end and rendered output is returned to browser. In your case you need to send the properties to browser to make it available for clientside scripts to consume.
Technique 1: (Recommended) Data attributes -
This is easiest to send since DOM structure doesnt change. Pass the values as data elements and retrieve using jquery. For example:
var value = $('#mydiv').data('custom-property');
console.log(value);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mydiv" data-custom-property="${properties.myCustomProperty}" />
Technique 2: (Old school) - Hidden variable - Add hidden variable into component rendering script; set the value of variable with HTL property and read the variable from clientside js using getElementById or jquery.
Technique 3: (Not recommended) - Make a trip to server. If you dont want to dilute your DOM (maybe property is secret or not SEO friendly), you may need to make an ajax call to a sling servlet that returns the property value. There are multiple examples available for sling servlet you can refer to.
ACS Sample, AEM 6.3 servlet, 1 more example.
But do remember its not worth to make a trip to server just for 1 property.

Getting the emberjs starter-kit to work with coffeescript

i'm trying to get the starter-kit example of ember.js to work directly with an app written in coffeescript (with the use of http://coffeescript.org/extras/coffee-script.js).
I want to use this in an development environment, without the need to convert the coffescript to javascript first (manually or with tools like jitter).
Basically i just replaced the line
<script src="js/app.js"></script>
with the lines
<script src="js/libs/coffee-script-1.3.3.min.js"></script>
<script type="text/coffeescript" src="coffee/app.coffee"></script>
in the index.html
All changes i've made can be found in my fork on github at https://github.com/GordonSchmidt/starter-kit
The coffescript itself seems to be fine, because when i convert it to javascript first the starter-kit application works with this javascript. But when i use the coffeescript directly it throws the error "assertion failed: Unable to find view at path 'App.MyView'" in line 45 of ember-0.9.8.1.js. The coffee-script.js all by itself seems to work as well (see demo.html). So it has to be a conflict between ember.js and coffee-script.js.
But I'm not able to find this error. Can someone please point me in the right direction?
from coffeescript.org
The usual caveats about CoffeeScript apply — your inline scripts will
run within a closure wrapper, so if you want to expose global
variables or functions, attach them to the window object.
your coffeescript should look something like this:
<script type="text/coffeescript">
window.App = App = Em.Application.create()
App.MyView = Em.View.extend(
mouseDown: -> window.alert "hello world!"
)​
</script>
see here for a fiddle

Accessing session information in JavaScript

I am newer one in ASP.net. I want to store text in the text box from JavaScript to session variables and pass those session variables to client side JavaScript. Is this possible?
You will need to do this in the code behind.
To store the value from the textbox in the session, in the correct event handler you would need to put code like:
if (!IsPostback) {
Session("TextboxContent") = txtTextbox.Text;
}
And to populate it in client side javascript, it depends on if you are using a library or not, but something that should work regardless is to have the following in your markup:
<script type="text/javascript">
var tb = document.getElementById('<%= txtTextbox.ClientID');
if (tb) tb.value = '<%= Session("TextboxContent").ToString().Replace("'", #"\'") %>';
</script>
Note that having code like I have done here in <%= %> ("alligator tags") is generally considered pretty bad practice, but you can use an <asp:Literal> or whatever if you like.