aichaos / rivescript-js

A RiveScript interpreter for JavaScript. RiveScript is a scripting language for chatterbots.
https://www.rivescript.com/
MIT License
377 stars 145 forks source link

I want to call external custom js or jquery lib, how do I do it? #369

Closed zipooclassic closed 2 years ago

zipooclassic commented 3 years ago

Good morning Thanks for providing great open source.

I have a question

  1. When calling the object below, the $ value is not recognized.
  2. I want to call the testApi() function in the api.js file, but it is not recognized. I want to call external custom js or jquery lib, how do I do it?

-- object.rive file '> object d3c5ca7e0d368c1ad0e59f37953eed43 javascript testApi(); $(document).ready(function(){ alert('aaaa'); }); < object

-- Rivescript let bot = new RiveScript({ utf8: true, debug: false, forceCase: true, throwExceptions: false, strict:true, concat:"" });

bot.loadFile([ "/brain/begin.rive", "/brain/object.rive", ], on_load_success, on_load_error);

kirsle commented 3 years ago

Hello!

It looks like you're embedding RiveScript on a web page. As long as jQuery ($) is on the global page scope it should be reachable from the object macro; e.g. by using the classic <script src="jquery.min.js"> method to add jQuery to the web page.

If you're using a build step like Webpack to get jQuery, you'll need it to be accessible from within the object macro function. I have two ideas how you might do this:

  1. Using the scope parameter to the reply() function you can pass in an external meaning for the this keyword, and the object macro is able to access functions and variables from the context of the caller. There's an example script that does this.
  2. If you declare the macro in the parent JavaScript application, via rs.setSubroutine(), it can reach any variable within scope of where that function was declared in your code, including any node.js imported library names. You would do this instead of the >object command in RiveScript code, and the body of the macro function is the same otherwise.
    • `rs.setSubroutine("name", function(rs, args) { ... });

It might help to shed light on how the >object command is evaluated in RiveScript: with a JS eval() function. The macro parsed from the RiveScript document is evaluated from the context of the rivescript/lang/javascript package here: https://github.com/aichaos/rivescript-js/blob/473fca7f91fe30f60c532d6a5c3607a5b0786931/src/lang/javascript.js#L45-L52 and so the global scope to the function is rather limited to the scope of that module and can't reach almost any names except for globally available names.

Reaching your api.js function will be similar to reaching the jQuery $ function.