How to run shell command from javascript client-side? - javascript

I have the simplest program: 1 HTML file, 1 CSS file, and 1 JS file, just run directly on my own computer. And all I'm trying to do is that when you press a button in the program, one single shell command (Windows) is run directly on the computer. This will generate file, which in turn will be used further inside the program.
It appears you cannot access your local files through JS alone, so I installed NodeJS (which is completely new to me). But I still can't get it to work that way either.
The only way I finally got NodeJS to host the HTML page in a way that the JS and CSS files also work, is by copying the code I got here: https://stackoverflow.com/a/13635318. (I called it server.js).
But I still haven't been able to find a way to call upon server.js while client-sided to run that shell command. Some posts suggest using AJAX for this, like here https://stackoverflow.com/a/53897335, but I haven't been able to find any way to successfully catch that in server.js.

I figured out how do it in another roundabout way:
With Django you can easily combine JS and Python, and Python can run shell commands much more easily.
In case someone wants the exact code:
Python (views.py):
import subprocess
def home(request):
if request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
subprocess.call(["ls", "-l"])
return render(request, 'index.html')
Javascript:
function toView() {
var csrftoken = $("[name=csrfmiddlewaretoken]").val();
$.ajax({
method: 'POST',
url: '',
headers:{
"X-CSRFToken": csrftoken
},
data: {},
success: function (data) {
alert("it worked!");
},
error: function (data) {
alert("it didnt work");
}
});
}
HTML (index.html):
<form method="post">
{% csrf_token %}
<button type="button" onclick="toView()">Do x</button>
</form>

Related

(CEP/ExtendScript) Is it possible to include a JSX file from a server?

I am developing an extension for InDesign and I would like to store the jsx file on a server. This would allow me to update the plugin if I change something in the jsx without the user having to re-download the extension.
I tried to directly do an include in the jsx that is mentioned in the manifest to try to point to the real jsx like this:
local-index.jsx :
//#include "https://server-name/adobe/addins/extendscript/server-index.jsx"
(local-index would only serve as a bridge between JavaScript and
ExtendScript)
(server-index would contain all the methods I use on
the JavaScript side with CSInterface.evalScript();)
It doesn't work and I couldn't find any information on the web. Is it possible or does the jsx file have to be local ?
Thanks in advance !
You can make AJAX request in local JS to retrieve JSX string from server
See example below
Server side PHP code be like:
<?php
//JSX Code
echo
"
alert ('Hello From Server');
file = new File('~/Desktop/fromServer.txt');
file.open('w');
file.write('Hi');
file.close();
";
//OR JSXBIN Code
//Use eval and remove line breaks from JSXBIN String
echo "eval('#JSXBIN#ES#2.0#MyBbyBn0AFJAnA.....')";
?>
JS code client side:
$.ajax({
type: "GET",
cache:false,
url: URL,
complete: function (Res) {
scr = Res.responseText;
csInterface.evalScript(scr);
},
async: false //For Synchronous Excecution
});

Run a python script using requirements with browser JavaScript

My main goal here is to execute a python script I have written when I run a function triggered through HTML. Here is how I have things currently set up:
I have a JavaScript File containing python run functions:
const PythonShell = require('python-shell').PythonShell;
class AHK {
static async runScript() {
PythonShell.run('/ahk/script.py', null, function (err) {
if (err) throw err;
console.log('finished');
});
}
module.exports = AHK;
I have my main.js file which would be the js code for the HTML to handle. I'd like for it to take in the module AHK. Something simple like this:
const AHK = require('./ahk');
function runFunction(x){
if(x = 1)
AHK.runScript()
}
And then I have some HTML with a javascript tag
<script type="text/javascript">
let x =1; //this is just to show x is getting populated. In the actual code it's constantly changing values
async function predict() {
if(x > 1)
runFunction(x)
}
</script>
Biggest issue I'm facing:
I've become aware that browser javascript doesn't like requirements/modules. For example, the main.js file doesn't like having a requirement at the top. I've tried using things like requirejs, but I can't seem to figure out how to make something like this work. I basically need it so that when the requirement is met and the function runFunction is run, the python script is executed on my machine.
Important to note that this is all running for a personal project on my computer, so it will never not be local.
Make the application on your pc an API and use the web page to send a request to the API telling it which python script to run. I haven't used python too much but I believe you can make an API with it. Then you can just make buttons for each python program you want to run and have these buttons send a request to the API.

Trying to use XML returned by merriam webster dictionary API but request getting failed. Status returned is zero. What to do?

I saw this great API (http://www.dictionaryapi.com/products/api-collegiate-dictionary.htm) by merriam webster that returns an XML file with all the details in it including definitions and pronunciations.
This API requires a key so i registered and got a key for my account.
I am making the request using Javascript(XHR) but the status returned is zero.
Then i googled the error it said that it may be because my request is going from a "file:///" protocol instead of "http://", so i installed LAMP stack on my PC then hosted the file on my localhost server and even then no luck.
Another thread said that i cant make cross domain requests.
Please can you help me. Below is my HTML code from which i call function in my javascript file.
<html>
<head>
<script type="text/javascript" src="context-script.js">
</script>
</head>
<body>
<h1>Merriam Webster</h1>
<div>
<b>To:</b> <span id="to"></span><br />
<b>From:</b> <span id="from"></span><br />
<b>Message:</b> <span id="message"></span><br/>
<b>Sound:</b><span id="sound"></span><br />
</div>
<script>
callOtherDomain();
</script>
</body>
</html>
Below is my JAvascript file context-script.js code:
function callOtherDomain()
{
invocation = new XMLHttpRequest();
var url = 'http://www.dictionaryapi.com/api/v1/references/collegiate/xml/happy?key=8f394b2c-77e8-433d-b599-f3ca87660067';
//url="note.xml";
if(invocation)
{
invocation.open('GET', url, true);
invocation.withCredentials = "true";
invocation.onreadystatechange = handler;
invocation.send();
alert("ref");
}
}
function handler(evtXHR)
{
if (invocation.readyState == 4)
{
alert("erg");
if (invocation.status == 200)
{
var response = invocation.responseXML;
document.getElementById("to").innerHTML=
response.getElementsByTagName("dt")[0].childNodes[0].nodeValue;
document.getElementById("from").innerHTML=
response.getElementsByTagName("dt")[1].childNodes[0].nodeValue;
document.getElementById("message").innerHTML=
response.getElementsByTagName("dt")[2].childNodes[0].nodeValue;
}
else
alert(invocation.status);
}
else
dump("currently the application is at" + invocation.readyState);
}
But when i change the URL to "note.xml" which is locally stored on the localhost code works absolutely fine.
Thanks in advance.
While this question is several years old, I worked with dictionaryapi.com previously and the solution is two-fold:
Your first step to host on a local server was right on (localhost:8000 or http://127.0.0.1:8000). I prefer using the Python SimpleHTTPServer, started in the root directory of the page you're trying to host with whichever CLI tool you're most familiar/comfortable with, py -m http.server.
After that, just complete a jQuery call using ajax, get, or XMLHttpRequest—whichever you prefer. For example:
$.ajax({
url: 'http://www.dictionaryapi.com/api/v1/references/collegiate/xml/[YourWord]?key=[YourKeyHere],
method: "GET"
}).done(function(response){
console.log(response);
});

Issue when separating JS code from grails view to external JS file

I have some working JS code which I put on the sections of my create and edit views, and it's working fine.
However, when I attempted to move the code to a separate JS file, the code would no longer call the controller action.
Here the JS code:
<g:javascript>
$(document).ready(function(){
<g:remoteFunction controller="project" action="ajaxGetClient" onSuccess="updateClient(data)"/>
});
function updateClient(data){
var element = $("#project\\.client");
element.empty();
element.val(data.name);
}
</g:javascript>
Here's the controller action:
def ajaxGetClient = {
if(!params.id){
params.id = Project.find("FROM Project ORDER BY id").id
}
def projectInstance = Project.get(params.id)
render projectInstance?.client as JSON
}
And here's the GSP code:
<g:textField name="project.client" id="project.client" maxlength="9" required="" disabled=""/>
<g:select id="project" name="project.id" from="${myPackage.Project.list()}" optionKey="id" required="" value="${productInstance?.project?.id}" class="many-to-one"
onchange="${
remoteFunction(
controller: 'project',
action: 'ajaxGetClient',
onSuccess: 'updateClient(data)',
params: '\'id=\' + this.value'
)}"
/>
I added a resource to ApplicationResources.groovy and changed the above JS code to this:
<g:javascript library="updateclient"/>
I simply copy/pasted the code into a JS file and then got a message:
Uncaught SyntaxError: Unexpected token <
which I understood came from it not recognizing the GSP syntax, so I tried some AJAX, which I'm pretty unexperienced at:
$(document).ready(function(){
$.ajax({
type: 'POST',
url: "${remoteFunction(controller:'project', action:'ajaxGetClient', onSuccess:'updateClient(data)')}"
});
});
Here's what I'm getting from the browser console:
http://localhost:8080/MyApp/product/$%7BremoteFunction(controller:'project',%20action:'ajaxGetClient',%20onSuccess:'updateClient(data)')%7D 404 (Not Found)
Quite frankly, I'm at a loss right now. Any help would be appreciated.
The reason for this is that Javascript (.js) and other non GSP (.gsp) files aren't parsed through the Groovy server pages engine. Thus, tag libraries such as the or ${g.remoteFunction} aren't parsed.
There are several ways to accomplish this however.
One is to keep the code in your GSP and not externalize it into javascript files.
Second is to move your code into javascript files but have configuration values in your GSP file. Here is a very simple example of using the message taglib:
// inside the .js file
function myFunction() {
console.log("I would use this value: "+_VALUE_FROM_GSP);
}
<script type="text/javascript">
// inside the .gsp file
var _VALUE_FROM_GSP = "${message(code: 'just.an.example')";
</script>
Finally, there plugins (listed below) that allows you specify some resources (javascript files in your case) to be parsed through the Groovy Server Pages engine.
GSP-arse plugin and GSP Resources
I'll be answering my own question here, since the bulk of it came from valuable advice from a friend of mine, but Joshua's answer was also very important, so I ended up combining both of them.
This is how I solved it:
On the GSP:
<script type="text/javascript">
var _URL = '${resource(dir: "")}/project/ajaxGetClient';
</script>
<g:javascript library="updateclient"/>
The reason I'm using the <script> tag is because in order for the _URL variable to become usable across different files, it had to be declared before the file using it. At least that's what this other SO answer said:
Global variables in Javascript across multiple files
Separate JS file:
$(document).ready(function(){
getClientAjax(null);
});
function getClientAjax(id) {
$.ajax({
url: _URL,
type: "POST",
data: { id: id },
success: function(data) {
updateClient(data);
}
});
}
function updateClient(data){
var element = $("#project\\.client");
element.empty();
element.val(data.name);
}
And the controller action remained the same.
At the end, there had to be created another JS function, but I gotta say I'm happy with the result.
Thanks for all the help.

jquery load() equivalent for offline use

I am looking for an equivalent to jquery's load() method that will work offline. I know from jquery's documentation that it only works on a server. I have some files from which I need to call the html found inside a particular <div> in those files. I simply want to take the entire site and put it on a computer without an internet connection, and have that portion of the site (the load() portion) function just as if it was connected to the internet. Thanks.
Edit: BTW, it doesn't have to be js; it can be any language that will work.
Edit2:
My sample code (just in case there are syntax errors I am missing; this is for the files in the same directory):
function clickMe() {
var book = document.getElementById("book").value;
var chapter = document.getElementById("chapter").value;
var myFile = "'" + book + chapter + ".html'";
$('#text').load(myFile + '#source')
}
You can't achieve load() over the file protocol, no other ajax request is going to work for html files. I have tried even with the crossDomain and isLocale option on without anything success, even if precising the protocol.
The problem is that even if jQuery is trying the browser will stop the request for security issues (well most browsers as the snippet below works in FF) as it allows you to load locale file so you could get access to a lot of things.
The one thing you could load locally is javascript files, but that probably means changing a lot of the application/website architecture.
Only works in FF
$.ajax({
url: 'test.html',
type: 'GET',
dataType: 'text',
isLocale: true,
success: function(data) {
document.body.innerHTML = data;
}
});
What FF does well is that it detect that the file requesting local files is on the file protocol too when other don't. I am not sure if it has restriction over the type of files you can request.
You can still use the JQuery load function in this context:
You would could add an OfflineContent div on your page:
<div id="OfflineContent">
</div>
And then click a button which calls:
$('#OfflineContent').load('OfflinePage.html #contentToLoad');
Button code:
$("#btnLoadContent").click(function() {
$('#OfflineContent').load('OfflinePage.html #contentToLoad');
});
In the OfflinePage.html you could have to have another section called contentToLoad which would display on the initial page.

Categories