Comments (11)
Hi,
can you please give some samples about using jquery or dom (like document.querySelectorAll), how to pass parameters to js commands ?
it's very interesting to be able coding with ruby in navigator, thanks for this
sorry about my english (i'm french)
from opal.
Well, using your given example Im currently trying to solve two issues: accessing 'global' js objects/variables (e.g. document
), and calling native functions on objects (e.g. .querySelectorAll
).
Accessing global js objects
The opal compiler has no way to know about global objects at compile time, i.e. it cannot look through your code and determine that document
is actually the global document variable. Rubys syntax says that if a variable is not defined in the current scope, then it is intact a method call (called on the receiver). Unless every identifier is compiled to check for this, we cannot know how to treat it.
One solution I'm looking at is to override the use of global variables to compile down to basic javascript variable names. For example, the following ruby code:
foo = $document;
Would compile into something like:
var foo = document;
The opal compiler will determine that global var access is just accessing global javascript variables. Obviously special ruby globals ($$
, $:
, etc) will compile into a wrapper to their respective ruby variables. Similarly, global assignment could (should?) generate a global javascript variable.
If we wanted to be clever, we could compile these globals to check for a variable existence first and return nil
if the given global var doesn't exist - so our example above could become:
var foo = (typeof document != undefined ? document : nil);
This is the best way I can see for easy access to js variables while keeping (mostly) ruby semantics.
Calling native functions
Once we have a reference to these global variables, accessing their functions is the tricky part. A feature (or pain) of js is that you can access functions, or other properties, of an object by omitting call parens (unlike ruby which calls a method anyway).
To keep things in opal fast, strings, numbers and arrays point to their native javascript equivalents. This has a side effect that every ruby array, string and number have these js properties already attached. The opal compiler therefore appends m$
to every method name so that [1, 2, 3].length
compiles into [1, 2, 3].m$length()
which avoids naming clashes as much as possible.
This also means that accessing a function, like querySelectorAll
is not so easy, as calling that method on our document variable will compile into document.m$querySelectorAll()
, which is why I proposed the ::
syntax for native function calls.
The alternative
The alternative to these two 'solutions' is to make use of the current back tick syntax that can hold raw javascript, and is just output as given. For example, to use your given method, you could do:
elements = `document.querySelectorAll('div')`
# pass elements somewhere else
do_something_with_elements elements
# raises an error as elements does not have any ruby methods..
elements.try_some_method()
As nice as being able to directly call js methods would be, loosing specific ruby features that make ruby great would remove the benefit of being able to use ruby in the browser. I hope this clears up the current method of accessing js objects and what might make it into opal next.
from opal.
wahooo! thanks a lot, i'm going to play with it
from opal.
OK, i've understood
def change(txt)
`document.querySelector('h1').innerHTML = txt;`
end
from opal.
Nice project, is it supposed to be compatible with Node.js?
About access to JS, maybe it's possible to use something like this?
[1, 2, 3, 4].native.length
[1, 2, 3, 4].js.length
from opal.
It does work with node.js, but not in the master branch. I will be pushing node.js support in a day or so once I tidy up the file system methods.
I do like the approach using native
, or some other special keyword - there is temporary code in the propery_access
branch for accessing global js variables using something similar, using a special opal
keyword:
opal.document # => document
opal.window # => window
I'll keep you updated here on the node.js updates.
from opal.
Why not using Ruby's global syntax to access globals?
$document
and $window
sounds better than opal.document
and opal.window
to me.
Didn't give a look at the property_access
branch but I would go with defining if something is native or not in the class, with something on the lines of native :length, :size, :whatever
and then check during compile if it's a native or a method call. Also adding Object#native
, like @alexeyPetrushin suggested, would be cool.
from opal.
Yeah, the global syntax seems the better way. I think it should be used just for accessing globals - not writing, i.e. when setting a ruby global it shouldnt really set a global in js.
As for the property access, well, compile time detection wouldnt be all that easy. The compiler will not have access to some prototypes to check, for instance it won't know which jquery properties are simple properties, like length
and selector
, or which are actual functions. I guess you could have a couple of class methods such as:
class JQuery
native_proptery :length, :selector
native_function :next, :prev
end
... or something similar.
from opal.
Agree with the global setter being Ruby only.
I'd sincerely go with the super
syntax to discern properties from functions, as in, always need parenthesis to call a native function.
from opal.
Im not sure I follow.. how would the compiler determine that a method call on a object is trying to access native properties/functions compared to a normal ruby method call? The dynamism of ruby means theres no guaranteed way to know the type of the receiver and therefore what its native properties are.
from opal.
Well, you coul keep a native thing table somewhere, but yeah, you're probably right, easier to go with native_property
and native_function
:)
from opal.
Related Issues (20)
- Feature: Opalfile
- Bug: Methods defined by `Module#define_method` with UnboundMethod do not accept a block
- Bug: jsid_cache breaks for `"toString"`, and I suspect other methods of JS Object HOT 6
- is it possible to require 'openssl' in opalrb? HOT 1
- is it possible to require 'openssl' in opalrb? HOT 1
- Bug: `def` + `define_method` + `return` cause `LocalJumpError` HOT 1
- Feature: mirror Opal only classes into CRuby
- Bug: define_method -> block -> return -- unexpected return
- Bug: String#strip differs in handling the NBSP character
- 1.8.2 release was not completed HOT 2
- Bug: `Hash#compare_by_identity` does not work with string keys
- Bug: Bad behaviour with combination of: StringScanner#scan, multiline regexp, multiple lines HOT 2
- Bug: String interpolation with bridged classes does not call `to_s` HOT 2
- Bug: Cannot run minitest on Ruby 3.3 HOT 1
- Feature: Date and DateTime classes from Ruby HOT 5
- Bug: `load` cannot be invoked on a path unless `require` has been called on it first
- Feature: `puts` & `p` can handle native JS objects not wrapped by `Native` for simple debugging/troubleshooting
- Rack, Roda, Sinatra and other framework compatibility (when running on Opal and Node or alternative)
- Feature: Interact with JS Object directly without having to manually wrap with Native HOT 1
- Bug: Segmentation fault when building with Opal::Builder#build_str HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from opal.