Call JavaScript from Elixir code without Node install - html

I am looking for a way to call client side JavaScript code from within Elixir .leex files without needing to install Node.js
My goal is to convert html to an image bitstring with something like this library: http://html2canvas.hertzen.com/
I have also looked at https://github.com/revelrylabs/elixir-nodejs as an example.

In a .*eex file you can inject javascript into your elements as a string and it should work. For simple js I do this in my own heex sigils in .ex files. For example,
<button onclick="(() => document.documentElement.scrollTop = 0)()">
Scroll to top
</button>
If your html2canvas function is defined in the javascript bundle delivered to the client, then triggering the function you wrote as a string in your .*eex file should work.
In my opinion this shouldn't really be done for non-trivial js. If you are using Phoenix LiveView, look into hooks. You would write your custom js and trigger it off of a hook, or use a hook to push an event that you would handle server-side in Elixir.

Related

how to interact with HTML forms in delphi using TChromium

i need to update the design of a browser in delphi7 I was using the twebbrowser but he had many problems with javascript and navigation.. so i decide to migrate to Chromium. the problem is that I cannot find code on these components. does anyone know which command would be equivalent to this one in tchromium:
OleObject.Document.all.Item ('ElementbyId', 0) .value: = 'edit1.text';
i need to transfer a text from memo to textarea in html form and at the end send a click on the button on the html form. if anyone knows the commands and can share I appreciate it.
A more flexible alternative than DOM access could be to perform this in Javascript, with the ExecuteJavaScript method of TChromium.
From your summary description, the JS could be something like
document.getElementById('yourtextarea').value = <JSON stringified content of your memo>;
document.getElementById('yourform').submit();
Alternatively, you could implement a JS function in your HTML, and call it with ExecuteJavascript, this way there would not be anything specific (besides the function name) on the Delphi side, and the HTML would be free to evolve.
function setTextAreaAndSubmit(value) {
document.getElementById('yourtextarea').value = value;
document.getElementById('yourform').submit();
}

is it possible to trigger c++ code, initiated by html events in minko?

Using minko, "html overlay" feature, is it possible to send events to c++ code from html?
The example provided, with the framework clearly demonstrate how to send events from c++ towards html (by incrementing a counter and having it reflect in html), is it possible to have the communication the other way around?
Yes.
HTML DOM events are wrapped and made available as C++ signals. So you can do something like:
dom->getElementById("my-element-id")->onclick()->connect(
[](dom::AbstractDOMMouseEvent::Ptr event)
{
// do something...
}
);
It's actually done in the same example: https://github.com/aerys/minko/blob/master/example/html-overlay/src/Main.cpp#L110
You can also send and receive "messages" both ways using the AbstractDOM::sendMessage() method in C++ or Minko.sendMessage() function in JS. You can listen to those messages using AbstractDOM::onmessage() in C++ and Minko.addEventListener("message", yourCallbackFunction).
Note that you can also call AbstractDOM::eval() in your C++ code to execute JavaScript code. It's how we've implemented most of the things actually.

google closure library usage from google app scripts using HtmlService

Is it possible to access google closure library functions from google app scripts via HtmlService? The html files in the google scripts seems to be filtering out anything related to closure library.
project: I am exploring DOM manipulation utilities from Google Closure library from within the google app scripts using HtmlService. I intend to run this as a stand alone web app.
The closure functions work when directly loaded into the browser from its local client environment - but they dont work when injected from GAS app via the HtmlService utility.
Here is the code I am using in the GAS.
html file
<html>
<head>
<script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script>
<script>
goog.require('goog.dom');
function c_sayHi() {
var newHeader = goog.dom.createDom('h1', {'style': 'background-color:#EEE'},'Hello world!');
goog.dom.appendChild(document.body, newHeader);
}
</script>
</head>
<script>
function c_updateButton(date, button) {
button.value = "clicked at " + date;
}
</script>
<body onload="c_sayHi()">
<input type='button' value='Never Clicked'
onclick='google.script.run.withSuccessHandler(c_updateButton).withUserObject(this).s_getCurrentDate()'>
<input type='button' value='Never Clicked'
onclick='google.script.run.withSuccessHandler(c_updateButton).withUserObject(this).s_getCurrentDate()'>
</body>
</html>
Google Script file
function s_getCurrentDate() {
return new Date().toString();
}
function doGet(e) {
return HtmlService.createTemplateFromFile('hello').evaluate();
}
I have prefixed c_ to client side functions and s_ for server side fns. When running this as a web app,
Function c_sayHi has no effect - I am not sure if it is even invoked.
Functions s_getCurrentDate and c_updateButton work fine as described in google's documentation https://developers.google.com/apps-script/html_service.
Is there a way to get closure library working from the web apps as attempted above?
Couple of things here -
All .gs files is JavaScript that runs on the server side. So the DOM is not really relevant there.
You can run client side JavaScript by returning code in HtmlService. This is what I believe you want to do. However, jQuery is the best supported library on this approach. Closure might end up working but the team does not specifically test against that library.
The problem is that Closure's dependency structure is executing before the window load event, otherwise it will not work. So any require and provide statements are taken care of way before window load. When you inject them through the HTML Service, you are forcing their execution at a different stage then required, which causes everything to fail.
If you would be using a COMPILED Closure Library source, you will not have any problems with running Closure. Learn how to use the Compiler and Builder to make Closure Work properly. Also, you can use lazy loading to simulate your HTML Service.
With that, you can make javascript load dynamically onclick, onload or whatever the hell you want. This is called lazy-loading and it is used as a standard practice for all large web applications. Monitor the Network tab of Firebug when browsing through Gmail or Facebook.
Arun Nagarajan is right, jQuery is the easier solution but if you are doing something proper that requires breadth, scale and speed, jQuery is a toy for kids.

Html from Silverlight (not out of browser)

I am trying to open HTML file from the local URI which I use as XML Editor, to edit xml data that come from Silverlight application, then close browser window and return back edited xml data to the Silverlight application.
I tried to use HtmlPage.Window.Navigate but I don't quit like it.
I have tried using a method from: http://weblogs.asp.net/dwahlin/archive/2010/05/10/integrating-html-into-silverlight-applications.aspx
but instanly got an exception "failed to invoke ShowJobPlanIFrame"
Is there any way to handle this task?
"Out of browser" mode doesn't fit.
Thanks.
===========================================================================
Update:
It worked out using IFrame overlay.
Button click invokes the following code in C#:
var scriptObject = (ScriptObject)HtmlPage.Window.GetProperty("ShowJobPlanIFrame");
scriptObject.InvokeSelf(url);
Where "ShowJobPlanIFrame" is as defined at:
http://weblogs.asp.net/dwahlin/archive/2010/05/10/integrating-html-into-silverlight-applications.aspx
This allowed me to pass data into XML editor and then get it back.
An error with JavaScript function invocation I told above, was my fault in JavaScript code itself.
A very similar scenario: https://stackoverflow.com/a/7919065/384316
Try using an iframe overlay, then you can load any HTML-like content.
There is an excellent explanation of how to do this here:
http://www.wintellect.com/cs/blogs/jlikness/archive/2010/09/19/hosting-html-in-silverlight-not-out-of-browser.aspx
It worked out using IFrame overlay.
Button click invokes the following code in C#:
var scriptObject = (ScriptObject)HtmlPage.Window.GetProperty("ShowJobPlanIFrame");
scriptObject.InvokeSelf(url);
Where "ShowJobPlanIFrame" is as defined at:
http://weblogs.asp.net/dwahlin/archive/2010/05/10/integrating-html-into-silverlight-applications.aspx
This allowed me to pass data into XML editor and then get it back.
An error with JavaScript function invocation I told above, was my fault in JavaScript code itself.
Did you try NavigationFramework of Silverlight? It's capability may support your needs in a more simple way than using multiple browser pages.

How do hosted services like UserVoice embed their content on other web sites?

How do hosted services like UserVoice embed their content on other web sites?
I see that it is via including a JavaScript file from the service provider on your own page, however, what I'm interested in are the building blocks for creating a service like that.
For example, do they use a library like jQuery, mooTools, or prototypejs and how do they avoid namespace clashes?
Also wondered if there were any books, articles, blog posts that go over this specific use of JavaScript (not looking for general resources on JavaScript).
Regards and thanks in advance,
Eliot
Here is a great tutorial I found on How to build a web widget (using jQuery)
Generally, what you are describing is called a "Javascript Widget" (UserVoice's just happens to show up on the side of the page).
There is a good tutorial about creating Javascript Widgets that you can check out.
The basic structure of such an embeddable service would be:
If the service doesn't mandate that the script is to be included at the bottom of the page, hook the body onload event, without stepping on the toes of any existing handlers (by intercepting the existing handler function, which could in turn be chained to other functions).
Inject new HTML elements into the document. The HTML code would most likely be inlined into the script as string literals as setting innerHTML on a single injected element would be easier and faster than direct DOM manipulation using a flurry of function calls.
The entire script should live inside a closure to avoid name clashes.
A JS framework may or may not be used; caution is required when including a framework since it could clash with a pre-existing, different framework, or a different version of the same framework.
EDT: Generally you'll make your client/customer/friend include a script in their page, then via that script you can do following:
In pure JS you can load scripts from remote location (or not so remote) dynamically via
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'your/remote/scripts/path.js';
document.getElementsByTagName('body')[0].appendChild(script);
// $.getScript('your/remote/scripts/path.js'); in jquery but you'll be sure jQuery loaded on remote site
Then script you loaded can perform different actions like creating elements like this
var body = document.getElementsByTagName('body')[0];
var aDiv = document.createElement('script');
/* here you can modify your divs properties and look */
body.appendChild(aDiv);
// $('').appendTo('body'); for jQuery
For deeper look into JavaScript you can read for example Javascript: The Good Parts or Definitive Guide To Javascript.