Call a JavaScript function from C++ - javascript

I have a CDHTMLDialog, with which I have 2 HTML pages and a .js file with a few fairly simple functions.
I would like to be able to call one of the JS functions from my program with a simple data type passed with it. e.g. MyFunc(int). Nothing needs to be returned.
I would appreciate any guidance on how I go about this,
thanks.
Edit: Thanks to CR for his answer, and everyone else who submitted there ideas too.
Something a little like this worked in the end (stripped a little error handling from it for clarity):
void callJavaScriptFunc(int Fruit)
{
HRESULT hRes;
CString FuncStr;
CString LangStr = "javascript";
VARIANT vEmpty = {0};
CComPtr<IHTMLDocument2> HTML2Doc;
CComPtr<IHTMLWindow2> HTML2Wind;
hRes = GetDHtmlDocument(&HTML2Doc);
hRes = HTML2Doc->get_parentWindow(&HTML2Wind);
if( Fruit > 0 )
{
FuncStr = "myFunc(808)"; // Javascript parameters can be used
hRes = HTML2Wind->execScript(FuncStr.AllocSysString(), LangStr.AllocSysString(), &vEmpty);
}
}

Easiest approach would be to use the execScript() method in the IHTMLWindow2 interface.
So you could get the IHTMLDocument2 interface from your CDHTMLDialog by calling GetDHtmlDocument, then get the parentWindow from IHTMLDocument2. The parent window will have the IHTMLWindow2 interface that supports execScript().
There might be an easier way to get the IHTMLWindow2 interface from your CDHTMLDialog but I'm used to working at a lower level.

the SpiderMonkey library can "Call a JavaScript function from C++", please refer to
http://egachine.berlios.de/embedding-sm-best-practice/ar01s02.html#id2464522
but in your case, maybe this is not the answer.

To give you a hint - javascript injection in server-side-technologies is usually performed through bulk-load at startup (GWT) or injected when the HTML is generated and served each post-back (ASP.NET).
The important point of both approaches is that they inject the javascript calls somewhere in the page (or in a separated .js file linked in the HTML in case of GWT) when generating the HTML page.
Even if you're on win development (looks like it since you're on MFCs) it might be the case that you have to insert your js method call in the HTML and then load (or reload if you wish to interact with the html from your MFC app) the HTML file in your CHTMLDialog.
I don't see any other way of achieving this (maybe I am just not aware of some suitable out-of-the-box functionality) other than editing your HTML and (re)loading it - which is pretty convenient and workable if you have to call your js method once off or just inject some kind of event-handling logic.
Might be a bit of a pain if you have to interact with the page from your MFC app. In this case you have to re-generate your HTML and reload it in your CHTMLDialog.
Either way you can simply have some kind of placeholder in your HTML file, look for that and replace with your javascript code, then load the page in your CHTMLDialog:
onclick="__my_Javascript_Call_HERE__"

Related

What kind of pattern is this?

I've learnt development by looking at other people's codes, so I'm not very good with terminologies. Lately I've been writting my JS/Jquery this way:
$(document).ready(function() {
testingFunc.init();
});
var testingFunc = {
$object: $('#object'),
init: function() {
var _that = this;
console.log($object);
}
}
Can someone please tell me if this a pattern of some sort? Or can someone please tell me how to describe the code I've done above?
This particular style represented in your code is an "object literal" pattern. It differs only slightly from a "module" pattern when you find yourself not requiring specific properties or methods to be private.
Before getting into a trap of terminologies, you may want to understand (in principle) what Javascript patterns are, and then identify those which may be architecturally best-fit for your project.
You may get an in-depth understanding from this mini-book from Addy Osmani:
http://addyosmani.com/resources/essentialjsdesignpatterns/book/
And a high-level article from him:
http://addyosmani.com/largescalejavascript/
The first part is using a jQuery selector with the listener "ready". What this means is that the callback function attached to the selector and listener will run once the document (in this case the browser window) is ready (in web terms, this means when the page finishes loading).
The second part of your code is following a standard called object literal, which is a JavaScript methodology that follows the principles of key->value
Perhaps you can name it the Object Literal pattern like used by Rebecca Murphey in her article. However I do not think that it's widely adopted as an official name for this kind of code structure, but it seems appropriate.
I guess you are wondering about the ready function. In order to understand how it works, you have to know that when you load an HTML page into you browser, the HTML structure is turned into a javascript tree called "DOM" (Document Object Model). In your sample, the DOM is referenced through the variable named document. To populate this tree, each markup has to be initialized as a javascript object. Once this job is done, the "ready" event is raised, invoking every function which is bound to it. To summarize :
$(document).ready(function () { testingFunc.init(); });
// translation : Once the DOM has been initialized, call "init".
Regarding your code, $('#object') attempts to query the DOM tree to find a node with an id set to "object" (e.g. <div id="object">). However, the document is probably not yet fully initialized. As a result, this query might fail. To avoid this risk you should rather do this :
var testingFunc = {
$object: null,
init: function() {
this.$object = $('#object');
console.log(this.$object);
}
}
You can think of the DOM as a folder structure, where each folder and file is an HTML markup. jQuery browses the DOM tree the same way that you browse your files explorer.

IPython: Adding Javascript scripts to IPython notebook

As a part of a project, I need to embedd some javascripts inside an IPython module.
This is what I want to do:
from IPython.display import display,Javascript
Javascript('echo("sdfds");',lib='/home/student/Gl.js')
My Gl.js looks like this
function echo(a){
alert(a);
}
Is there some way so that I can embed "Gl.js" and other such external scripts inside the notebook, such that I dont have to include them as 'lib' argument everytime I try to execute some Javascript code which requires to that library.
As a very short-term solution, you can make use of the IPython display() and HTML() functions to inject some JavaScript into the page.
from IPython.display import display, HTML
js = "<script>alert('Hello World!');</script>"
display(HTML(js))
Although I do not recommend this over the official custom.js method, I do sometimes find it useful to quickly test something or to dynamically generate a small JavaScript snippet.
Embedding D3 in an IPython Notebook
https://blog.thedataincubator.com/2015/08/embedding-d3-in-an-ipython-notebook/
To summarize the code.
Import the script:
%%javascript
require.config({
paths: {
d3: '//cdnjs.cloudflare.com/ajax/libs/d3/3.4.8/d3.min'
}
});
Add an element like this:
%%javascript
element.append("<div id='chart1'></div>");
Or this:
from IPython.display import Javascript
#runs arbitrary javascript, client-side
Javascript("""
window.vizObj={};
""".format(df.to_json()))
IPython Notebook: Javascript/Python Bi-directional Communication
http://jakevdp.github.io/blog/2013/06/01/ipython-notebook-javascript-python-communication/
A more extensive post explaining how to access Python variables in JavaScript and vice versa.
I've been fighting with this problem for several days now, here's something that looks like it works; buyer beware though, this is a minimal working solution and it's neither pretty nor optimal - a nicer solution would be very welcome!
First, in .ipython/<profile>/static/custom/myScript.js, we do some require.js magic:
define(function(){
var foo = function(){
console.log('bar');
}
return {
foo : foo
}
});
Copy this pattern for as many functions as you like. Then, in .ipython/<profile>/static/custom/custom.js, drag those out into something persistent:
$([IPython.events]).on('notebook_loaded.Notebook', function(){
require(['custom/myScript'], function(custom){
window.foo = custom.foo;
} );
});
Yes, I am a horrible person for throwing stuff on the window object, namespace things as you deem appropriate. But now in the notebook, a cell like
%%javascript
foo();
should do exactly what it looks like it should, without the user having to explicitly import your JS. I would love to see a simpler solution for this (plz devs can we plz have $.getScript('/static/custom/util.js'); in custom.js to load up a bunch of global JS functions) - but this is the best I've got for now. This singing and dancing aside, HUGE ups to the IPython notebook team, this is an awesome platform!
Not out of the box by installing a package, at least for now.
The way to do it is to use custom.js and jQuery getScript to inject the js into the notebook.
I explicitly stay vague on how to do it, as it is a dev feature changing from time to time.
What you should know is that the static folder in user profile is merged with webserver static assets allowing you to access any file that are in this folder by asking for the right url.
Also this question has been asked a few hours ago on IPython weekly video "lab meeting" broadcasted live and disponible on youtube (you might have a longer answer), I've opened discussion with the author of the question here
For some reason, I have problems with IPython.display.Javascript. Here is my alternative, which can handle both importing external .js files and running custom code:
from IPython.display import display, HTML
def javascript(*st,file=None):
if len(st) == 1 and file is None:
s = st[0]
elif len(st) == 0 and file is not None:
s = open(file).read()
else:
raise ValueError('Pass either a string or file=.')
display(HTML("<script type='text/javascript'>" + s + "</script>"))
Usage is as follows:
javascript('alert("hi")')
javascript(file='Gl.js')
javascript('echo("sdfds")')
You can use IJavascript (a Javascript kernel for Jupyter notebooks).
I was interested in calling JavaScript from a Jupyter code (Python) cell to process strings, and have the processed string output in the (same) code cell output; thanks to Inject/execute JS code to IPython notebook and forbid its further execution on page reload and Why cannot python call Javascript() from within a python function? now I have this example:
from IPython.display import display, Javascript, Markdown as md, HTML
def js_convert_str_html(instring_str):
js_convert = """
<div id="_my_special_div"></div>
<script>
var myinputstring = '{0}';
function do_convert_str_html(instr) {{
return instr.toUpperCase();
}}
document.getElementById("_my_special_div").textContent = do_convert_str_html(myinputstring);
</script>
""".format(instring_str)
return HTML(js_convert)
jsobj = js_convert_str_html("hello world")
display(jsobj)
Note that the JavaScript-processed string does not get returned to Python per se; rather, the JavaScript itself creates its own div, and adds the result of the string conversion to it.

Call/generate dynamic javascript from silverlight

I'm not sure this is supported but wanted to see if any of you had come up with something creative to work around this.
Is there a way to call javascript from silverlight, without having to define any javascript functions on the aspx page/external js?
I'd like to be able to do something like:
HtmlPage.Window.Invoke("(function () { window.lastErrorMessage = 'foo'; })();")
Which, to forgo conversations about style, I'd agree goes against many best practices rules, but my current purpose is brainstorm some quick-and-dirty error reporting (could you even call it reporting?) before we implement the existing database-centric error logging in this solution.
Any thoughts? The idea is to generate something discreet that a user wouldn't feel intruded upon or something too technical (like IE's script error dialog), but something our app support could get a little more info from without access to code bases etc.
Thanks, Matthew
The method you are looking for is Eval not Invoke:-
HtmlPage.Window.Eval("(function () { window.lastErrorMessage = 'foo'; })();")
You could add your JavaScript dynamically to the hosting page DOM using HtmlPage.Document and then execute your added methods. Or are you trying not to modify the page at all?
HtmlElement head = HtmlPage.Document.GetElementsByTagName("head")[0] as HtmlElement;
HtmlDocument htmlDocument = HtmlPage.Document;
HtmlElement scriptElement = htmlDocument.CreateElement("script");
scriptElement.SetAttribute("type", #"text/javascript");
scriptElement.SetProperty("text", "function testMe(p) { alert(p); }");
head.AppendChild(scriptElement);
// Invoke like this
HtmlPage.Window.Invoke("testMe", "hello");

How to split JavaScript code into multiple files and use them without including them via script tag in HTML?

I am making use of constructors (classes) extensively and would like each constructor to be in a separate file (something like Java). Suppose I have constructors say Class1, Class2, ... Class10 and I only want to use Class1 and Class5 I need to use script tags to include Class1.js and Class2.js into the HTML page. Later if I also need to use Class3 and Class6 I again need to go to the HTML page and add script tags for them. Maintenance with this approach is too poor.
Is there something in JavaScript similar to include directive of C? If not, is there a way to emulate this behavior?
You can use jQuery.getScript:
http://api.jquery.com/jQuery.getScript
Or any of the many javascript loaders like YUI, JSLoader, etc. See comparison here:
https://spreadsheets.google.com/lv?key=tDdcrv9wNQRCNCRCflWxhYQ
You can use something like this:
jsimport = function(url) {
var _head = document.getElementsByTagName("head")[0];
var _script = document.createElement('script');
_script.type = 'text/javascript';
_script.src = url;
_head.appendChild(_script);
}
then use it in your code like:
jsimport("example.class.js");
Be careful to use this when the head is already in the DOM, else it won't work.
Yes: You can create script tags from JavaScript and load required classes on demand.
See here for a couple of solutions: http://ntt.cc/2008/02/10/4-ways-to-dynamically-load-external-javascriptwith-source.html
With careful use of id attributes or a global variable that contains "already loaded" scripts, it should be possible to develop a dependency resolution framework for JavaScript like Maven or OSGi for Java.
When we are talking about JavaScript, I feel it is better to include one file that includes everything you need instead of requesting a new file every time you need something that you don't currently have access to.
Each time you send out for another file, the browser will do many things. It checks if the requested file can in fact be found by sending an HTTPRequest, and if the browser has already seen this, is it cached and unchanged?
What you are wanting to do is not in the spirit of JavaScript. Doing what you are explaining will produce addition load times, and you wouldn't be able to do anything until the file has completely loaded, which creates wait times.
It would be better to use one file for this, include at the inner end of the </body tag (which won't cause the browser to wait until the script is done to load the page), then create one simple function that will execute when the page is completely loaded.
For example:
<html>
<head></head>
<body>
<!-- HTML code here... -->
<script src="javascript.js"></script>
<script>
(function r(f) {
/in/.test(document.readyState) ? setTimeout('r(' + f + ')', 9) : f()
})(function() {
// When the page has completey loaded
alert("DOM has loaded and is ready!");
});
</script>
</body>
</html>
you can include one js file into another js file by doing something like this in the begginig of your js file:
document.write("<script type='text/javascript' src='another.js'></script>");
The best approach in your situation is using of compiler of some kind. The greatest one is Google Closure Compiler. This is part of Google Closure Libraty which has structure similar to what you described.

How to use javascript namespaces correctly in a View / PartialView

i've been playing with MVC for a while now, but since the project i'm on is starting to get wind in its sails more and more people are added to it. Since i'm in charge of hacking around to find out some "best practice", i'm especially wary about the possible misuses of javascript and would like to find out what would be the best way to have our views and partial views play nicely with javascript.
For the moment, we're having code that looks like this (only simplified for example's sake)
<script type="text/javascript">
function DisableInputsForSubmit() {
if ($('#IsDisabled').is(':checked')) {
$('#Parameters :input').attr('disabled', true);
} else {
$('#Parameters :input').removeAttr('disabled');
}
}
</script>
<%=Html.SubmitButton("submit", Html.ResourceText("submit"), New With {.class = "button", .onclick = "DisableInputsForSubmit(); if ($('#EditParameters').validate().form()) {SetContentArea(GetHtmlDisplay('SaveParameters', 'Area', 'Controller'), $('#Parameters').serialize());} return false;"})%><%=Html.ResourceIcon("Save")%>
Here, we're saving a form and posting it to the server, but we disable inputs we don't want to validate if a checkbox is checked.
a bit of context
Please ignore the Html.Resource* bits, it's the resource management
helpers
The SetContentArea method wraps ajax calls, and GetHtmlDisplay
resolves url regarding an area,
controller and action
We've got combres installed that takes care of compressing, minifying
and serving third-parties libraries and what i've clearly identified as reusable javascript
My problem is that if somebody else defines a function DisableInputsForSubmit at another level (let's say the master page, or in another javascript file), problems may arise.
Lots of videos on the web (Resig on the design of jQuery, or Douglas Crockford for his talk at Google about the good parts of javascript) talk about using the namespaces in your libraries/frameworks.
So far so good, but in this case, it looks a bit overkill. What is the recommended way to go? Should i:
Create a whole framework inside a namespace, and reference it globally in the application? Looks like a lot of work for something so tiny as this method
Create a skeleton framework, and use local javascript in my views/partials, eventually promoting parts of the inline javascript to framework status, depending on the usage we have? In this case, how can i cleanly isolate the inline javascript from other views/partials?
Don't worry and rely on UI testing to catch the problem if it ever happens?
As a matter of fact, i think that even the JS code i've written that is in a separate file will benefit from your answers :)
As a matter of safety/best practice, you should always use the module pattern. If you also use event handlers rather than shoving javascript into the onclick attribute, you don't have to worry about naming conflicts and your js is easier to read:
<script type="text/javascript">
(function() {
// your button selector may be different
$("input[type='submit'].button").click(function(ev) {
DisableInputsForSubmit();
if ($('#EditParameters').validate().form()) {
SetContentArea(GetHtmlDisplay('SaveParameters', 'Area','Controller'), $('#Parameters').serialize());
}
ev.preventDefault();
});
function DisableInputsForSubmit() {
if ($('#IsDisabled').is(':checked')) {
$('#Parameters :input').attr('disabled', true);
} else {
$('#Parameters :input').removeAttr('disabled');
}
}
})();
</script>
This is trivially easy to extract into an external file if you decide to.
Edit in response to comment:
To make a function re-usable, I would just use a namespace, yes. Something like this:
(function() {
MyNS = MyNS || {};
MyNS.DisableInputsForSubmit = function() {
//yada yada
}
})();

Categories

Resources