Is it possible to trigger a wikitext-macro with java-script?

Hi!
I have a macro which gets some text from my server with a XMLHttpRequest,
Is it possible to trigger a wikitext-macro at the end of the java-script to perform operations with the retrieved data?

Best wishes Jan

I did move this thread into the Discussions section and removed the wiki flag.

“Tips & Tricks” should contain “solutions” that may be of general interest for the community.

Once your problem is solved, we would love to get a new wiki in the “Tips & Tricks” section.

Depending on what you want to do, a JavaScript macro to perform an HTTP request may not be the right choice here. It would be helpful if you described the bigger picture of what you are trying to achieve.

Hi Saq,
thanks for your help!

The .js you find below is part of quite a big mechanism:

It retrieves text from three different sources and creates temporary tiddlers with them,
namely an image-url, a geoposition and a comment for the image. (The anti parameter is necessary to avoid the proxies. )

There is a bunch of actions (listops and setfield) I have to perform with them afterwards to make the retrieved data appear in the right places. Some of these actions depend on list-filters, so it is practical to use the wonderful opportunities TW furnishes there.

So far I perform these actions with a button which is okay for me but is an extra step which is a little incomprehensible for my pupils who also shall use this to exchange files via the server.
So it would be nice to eliminate the extra-click by triggering it directly from the .js .

Best wishes Jan

/*\
title: $:/core/modules/macros/urltext.js
type: application/javascript
module-type: macro
Macro retrieving text from the server
\*/

(function(){
   /*jslint node: true, browser: true */
   /*global $tw: false */
   "use strict";

/*
Information about this macro
*/
   exports.name = "geturl";
   exports.params = [
      {name: "anti"}
   ];

/*
Run the macro
*/
   exports.run = function() {
   var monitor = setInterval(function(){
    var elem = document.activeElement;
    if(elem && elem.tagName == 'IFRAME'){
    setTimeout(TimeoutFunction, 320);
   clearInterval(monitor);
   }
   }, 100);
   };

function TimeoutFunction() {
      var anti = $tw.wiki.getTiddlerText("$:/temp/anti","3261");
      if (anti == null) {
         var anti = "3261";
         }
      var strang  = String(anti);
      var kartouche = strang + "-kartouche-temp.txt";
      var client = new XMLHttpRequest();client.open('GET', kartouche , false);
      client.setRequestHeader('Content-type', 'Content-Type: text/html; charset=ISO-8859-1');
      client.onreadystatechange = function() {
    if (client.readyState == 4 && client.status == 200)
    {
      var titel = client.responseText.replace("+", "%20");
      var fields = {title: '$:/temp/URL', text:  titel}
       $tw.wiki.addTiddler(new $tw.Tiddler(fields))
    }
    }
   client.send();
   var kassiber = strang + "-kassiber-temp.txt";
var inhalt = new XMLHttpRequest();inhalt.open('GET', kassiber, false);
      inhalt.setRequestHeader('Content-type', 'Content-Type: text/html; charset=ISO-8859-1');
      inhalt.onreadystatechange = function() {
    if (inhalt.readyState == 4 && inhalt.status == 200)
    {
      var nachricht = inhalt.responseText.replace("+", "%20");
      var fields = {title: '$:/temp/URL-Text', text:  nachricht, type: 'application/json'}
       $tw.wiki.addTiddler(new $tw.Tiddler(fields))
    }
    }
   inhalt.send();
     var geo = strang + "-position-temp.txt";
     var position = new XMLHttpRequest();position.open('GET', geo, false);
      position.setRequestHeader('Content-type', 'Content-Type: text/html; charset=ISO-8859-1');
      position.onreadystatechange = function() {
    if (position.readyState == 4 && position.status == 200)
    {
      var koordinaten = position.responseText.replace("+", "%20");
      var fields = {title: '$:/temp/URL-Position', text:  koordinaten}
       $tw.wiki.addTiddler(new $tw.Tiddler(fields))
    } else {
	var refreshnote =$tw.notifier.display("$:/plugins/JJ/InterAction/RefreshFrame")
    } 
    }
   position.send();
}
})();

First off, using a macro for this purpose is not in line with core recommendations and may cause you problems further down the line. Your code creates tiddlers, macros are only allowed to return text.

This would be better implemented as an action widget, or even better a widget message handled by the root widget.

With regards to invoking macros from JavaScript, I assume your macros contain action widgets. You could try something like this but really, the structure is wrong for this to be called from a macro:

$tw.rootWidget.invokeActionString(actions, $tw.rootWidget,null, variables)

where variables is an object providing any additional variables needed by your actions. The actions will run out of context and local variables defined where the macro was run will not be available to the actions.

Hi Saq,
as you can see my knowledge of js and inparticular of the implementation of js in TW is very basic, I never managed to create a widget and all im tinkering here is blind bricolage.
As I now understand widget is necessary to import/define all the variables that would be used in an actionstring. That is why it is not possible to create a wikitext-macro called say <<importfromServerActions>> that contains all the necessary ActionWidgets and invoke it?
Sorry to repeat what you said … but this helps my slow understanding.
Best wishes Jan

Perhaps you can post the actions that you want to run on the tiddlers created by the HTTP request - that is the contents of the macro <<importfromServerActions>> .That will allow me to provide better guidance.

1 Like

Hi Saq,
Thanks for your time and help!
It is not easy to describe, because this .js is the base for retrieving of all user-postings on my server. So I will roughly describe what the whole mechanism does:
Users are allowed to post images, small texts, tiddlers they made (as .json) and entire bundles (mimicking the format that is created by the $:/Import-mechanism).
I made a PHP to show them in an IFrame and clicking them the server puts the text-data (or the links to the images) in the locations where the js retrieves them with the request. The click on the Iframe also triggers that mechanism in the TW so that it creates temporary tiddlers which are then analyzed in TW so that it shows the buttons that trigger the desired actions.
For me, having to click one more time is not only okay but usefull, because this helps me to avoid importing things I do not want to have or overwrite in my TW because it is in autosave-mode most of the time.
At the moment, I am working a mechanism that allows my pupils to work together on a stage-play, which means that they are importing little pieces that the others in the group made. And there it would be great to make them appear directly after they chose them in the IFrame.
So in principle the operation would be importing the tiddler or packet of tiddlers from a json-file which is now stored in the temporary tiddler - and this direct import should only happen, if the upload-password is not set.

Best wishes Jan.

Hi @JanJo interesting project and the description is helpful. A proper approach to this would require a rewrite using WidgetMessages.

In terms of short term needs, if you want guidance on how to trigger actions from JavaScript, I need to see what these actions look like. These would be the actions that are triggered by the second button, after the temporary tiddlers exist.

Hi Saq,
the text written to the generated Temp-tiddler is a tiddler or a set of tiddler as .json-files.

Examples:
Single Tiddler:CLyx~JJ–1.1___JJ 1.json (233 Bytes)

A sort of double-wrapped Import-Tiddler:CLyx~JJ–Kombi_1.1.json (1.0 KB)

The aim is to import these directly (so that the users do not have to use the
$:/Import - Tiddler if the wiki is not in autosave mode.)

Best wishes Jan