Giter Site home page Giter Site logo

opal-browser's Introduction

Opal-Browser - Client side web development in pure Ruby, using Opal

Gem Version Code Climate Build Status Join Chat Stack Overflow Documentation

This library aims to be a full-blown wrapper for all the browser API as defined by HTML5.

It provides a very JQuery-like interface to DOM, but itself it doesn't use nor require JQuery nor opal-jquery (which is an alternative library for interfacing the web browser). The main difference though is that Opal-Browser goes far beyond what JQuery does.

Usage

Gemfile

source 'https://rubygems.org/'

gem 'opal-browser'

Server side (config.ru, Rakefile, Rails, Sinatra, Roda, etc. - not needed for static compilation)

require 'opal-browser'
# Your server code here

Browser side

require 'opal'
require 'native'
require 'promise'
require 'browser/setup/full'

# Your Opal code here
$document.body << "Hello world!"

Static Compile Opal + Opal-Browser library

bundle exec opal -c -q opal-browser -p native -p promise -p browser/setup/full -e '#' -E > opal-browser.js

Static Compile your application

bundle exec opal -Oc -s opal -s native -s promise -s browser/setup/full app/application.rb > application.js

And load it in HTML!

<!DOCTYPE html>
<html>
<head>
  <title>My Application</title>
</head>
<body>
  <script src='opal-browser.js' onload='Opal.require("native"); Opal.require("promise"); Opal.require("browser/setup/full");'></script>
  <script src='application.js'></script>
</body>
</html>

See the examples/integrations/ directory for various ideas on how to quickly start development using opal-browser.

Features

This is a list of many currently wrapped features and some details on them.

DOM

DOM support is complete as far as I know, it has a very Nokogiri feel to it with obvious differences where relevant (for instance, event handling).

$document.ready do
  alert "yo dawg, I'm all loaded up in here"
end

It also supports a markaby inspired builder DSL (using Paggio) which generates DOM nodes directly instead of creating a string.

$document.ready do
  DOM {
    div.info {
      span.red "I'm all cooked up."
    }
  }.append_to($document.body)
end

Events

Add an event to a given element:

$document.at_css("button").on(:click) do |e|
  e.prevent # Prevent the default action (eg. form submission)
  # You can also use `e.stop` to stop propagating the event to other handlers.
  alert "Button clicked!"
end

Or add it to a parent element and use a delegator, so that an event gets fired when any button children of $document is clicked:

$document.on(:click, "button") do |e|
  e.prevent
  # e.on is a button that has been clicked
  e.on.inner_text = "Clicked!"
end

Run an event once with #one instead of #on, or disable an event with #off.

CSSOM

CSSOM support (using Paggio) is still incomplete but the useful parts are implemented, this includes a DSL for generating a CSS style and the same DSL is also used to change style declarations (which can either belong to a DOM::Element or a CSS::Rule::Style).

$document.body.style.apply {
  background color: 'black'
  color 'white'
  font family: 'Verdana'
}

AJAX & SJAX

The XMLHttpRequest API has been wrapped completely, it also optionally supports binary results as typed-arrays.

It easily allows for synchronous and asynchronous requests.

require 'browser/http'

Browser::HTTP.get "/something.json" do
  on :success do |res|
    alert res.json.inspect
  end
end

WebSocket

Websockets have been fully wrapped and they are easily configurable with blocks.

require 'browser/socket'

Browser::Socket.new 'ws://echo.websocket.org' do
  on :open do
    every 1 do
      puts "ping"
    end
  end

  on :message do |e|
    log "Received #{e.data}"
  end
end

EventSource

Event sources have been implemented and are easily configurable with blocks.

require 'browser/event_source'

Browser::EventSource.new '/events' do |es|
  es.on :message do |e|
    alert e.data
  end

  es.on :custom do |e|
    alert "custom #{e.data}"
  end
end

History

The HTML5 History API has been fully wrapped.

current = $window.history.current
$window.history.replace("?get=params")
$window.history.push("?get=params")
$window.history.back

$window.on :popstate do |e|
  p "User clicked a back button! He is now on #{$window.history.current}"
end

Storage

The HTML5 Storage API has been wrapped and it exports a single Storage class that uses the most appropriate and available API to store data locally.

require 'browser/storage'

$storage = $window.storage
$storage[:hello] = "world"

Database SQL

WebSQL has been fully wrapped (Chromium-only)

require 'browser/database/sql'

db = Browser::Database::SQL.new 'test'
db.transaction {|t|
  t.query('CREATE TABLE test(ID INTEGER PRIMARY KEY ASC, text TEXT)').then {
    t.query('INSERT INTO test (id, text) VALUES(?, ?)', 1, 'huehue')
  }.then {
    t.query('INSERT INTO test (id, text) VALUES(?, ?)', 2, 'jajaja')
  }.then {
    t.query('SELECT * FROM test')
  }.then {|r|
    r.each {|row|
      alert row.inspect
    }
  }
}

Browser support

  • Edge (Current - 3) to Current
  • Firefox (Current - 3) to Current
  • Chrome (Current - 3) to Current
  • Safari (Current - 3) to Current
  • Opera (Current - 3) to Current

Any problem above browsers should be considered and reported as a bug.

(Current - 3) to Current denotes that we support the current major stable version of the browser and 3 versions preceding it. For example, if the current version of a browser is 24.x, we support all versions between 21.x to 24.x.

We will accept compatibility patches for even earlier browser versions. Opal-Browser is written in such a way, that it integrates a robust compatibility check system, similar to Modernizr, and the history of this library goes even as far as supporting Internet Explorer 6.

See the polyfills documentation if you wish to polyfill some behaviors not supported by the ancient web browsers (like querySelectorAll).

License

(The MIT License)

Copyright (C) 2013-2018 by meh
Copyright (C) 2019-2021 hmdne and the Opal-Browser contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

opal-browser's People

Contributors

ajjahn avatar anharu2394 avatar bigtunacan avatar dlee avatar elia avatar fazibear avatar ggrossetie avatar graywolf avatar hmdne avatar iliabylich avatar jgaskins avatar meh avatar merongivian avatar mibamur avatar michaelsp avatar ontonator avatar ryanstout avatar sleewoo avatar svoboda-jan avatar tongueroo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

opal-browser's Issues

Cannot load opal/browser

# Gemfile
source 'http://rubygems.org'

gem 'opal'
gem 'opal-sprockets'
gem 'opal-jquery'
gem 'opal-browser', github: 'opal/opal-browser'
# Rakefile
require 'opal'
require 'opal-sprockets'
require 'opal-jquery'
require 'opal/browser'

desc 'Build our app to build.js'
task :build do
  env = Opal::Environment.new
  env.append_path 'app'

  File.open('build.js', 'w+') do |out|
    out << env['application'].to_s
  end
end
# app/application.rb
require 'opal'
require 'opal-jquery'
require 'opal/browser'

$document.on :load do
  alert "yo dawg, I'm all loaded up in here"
end
> rake build
rake aborted!
cannot load such file -- opal/browser

$document.ready results in cannot instantiate a non derived Node object error

require 'opal'
require 'browser'

$document.ready

Using opal-browser (0.1.0.beta1):

Uncaught ArgumentError: cannot instantiate a non derived Node object error:10
(anonymous function) error:10
def.$raise kernel:452
$opal.defs.TMP_1 node:23
def.$DOM.TMP_1 dom:58
$a._p.TMP_1 node_set:11
Opal.$yield1 runtime.js?body=1:582
def.$each.TMP_12 native:267
def.$initialize node_set:7
def.$new.TMP_2 class:42
def.$children node:144
def.$inspect document:46
def.$method_missing.TMP_1 kernel:4
method_missing_stub runtime.js?body=1:466
(anonymous function) application:1
(anonymous function) application:1

WebSQL

WebSQL is deprecated when using safari , it doesn't work anymore

Instructions don't work

I'm trying to run code similar to the example:

:opal
  $document.ready do
    alert "blah"
  end

I get undefined method 'ready' for nil.

Similarly:

:opal
  alert "blah"

I get undefined method 'alert' for main

ws error on chrome 30+

Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch

ref: omorandi/TiInspector#7 (reference)

seems that passing null or undefined isn't enough, but removing the protocol from the native initialization works:

module Browser
class Socket

  def initialize(url, protocol = nil, &block)
    if native?(url)
      super(url)
    else
      super(protocol ? `new window.WebSocket(#{url.to_s}, #{protocol.to_n})` : 
                       `new window.WebSocket(#{url.to_s})`)
    end

    if block.arity == 0
      instance_exec(&block)
    else
      block.call(self)
    end if block
  end

end
end

Compile Error: browser/database/sql.rb -- Line 76

while compiling opal-browser, got the following error:

browser/database/sql:76:54: error: unexpected token tRCURLY
browser/database/sql:76: #{-> t { block.call(Transaction.new(self, t)) }})browser/database/sql:76: ^ /var/lib/gems/2.4.0/gems/parser-2.3.3.1/lib/parser/diagnostic/engine.rb:71:inprocess': unexpected token tRCURLY (SyntaxError)
from /var/lib/gems/2.4.0/gems/parser-2.3.3.1/lib/parser/base.rb:263:in on_error' from /usr/lib/ruby/2.4.0/racc/parser.rb:259:in _racc_do_parse_c'
from /usr/lib/ruby/2.4.0/racc/parser.rb:259:in do_parse' from /var/lib/gems/2.4.0/gems/parser-2.3.3.1/lib/parser/base.rb:162:in parse'
from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/parser.rb:41:in parse' from /var/lib/gems/2.4.0/gems/parser-2.3.3.1/lib/parser/base.rb:209:in tokenize'
from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/compiler.rb:180:in parse' from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/compiler.rb:166:in compile'
from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/builder_processors.rb:88:in compiled' from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/builder_processors.rb:98:in requires'
from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/builder.rb:199:in process_require' from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/builder.rb:88:in block in build_str'
from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/builder.rb:88:in map' from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/builder.rb:88:in build_str'
from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/cli.rb:109:in block in create_builder' from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/cli.rb:149:in evals_or_file'
from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/cli.rb:109:in create_builder' from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/cli.rb:84:in builder'
from /var/lib/gems/2.4.0/gems/opal-0.11.0/lib/opal/cli.rb:62:in run' from /var/lib/gems/2.4.0/gems/opal-0.11.0/exe/opal:24:in <top (required)>'
from /usr/local/bin/opal:23:in load' from /usr/local/bin/opal:23:in

'

`Browser::HTTP.post` stringifies nested hash data

The following code:

data = { post: { body: "hello" } }
Browser::HTTP.post url, data do |request|
  # ...
end

… generates these POST params (inside a Rails app): {"post"=>"{\"body\"=>\"hello\"} (note the inner hash is actually a string). I couldn't figure out how to get this working, so I decided to open an issue. Feel free to let me know if I'm just plain doing it wrong. :-)

some media methods are missing

I didn't succeed to make a pull request
Just need to add:
def pause #@native.pause()`
end

def currentTime= (val)
#@native.currentTime = #{val};
end

def currentTime
#@native.currentTime
end`
to the 'media.rb files'
thanks

Chainable attributes for class + id DOM builder DSL

Running with the principle of least surprise, I'd expect the following to work:

$document.ready? do
  DOM do
    canvas.game!.lol.wut width: 500, height: 500
  end.append_to $document.body
end

However, this generates

<canvas id="game" class="lol wut">{"width"=>500, "height"=>500}</canvas>

My reasoning here is when constructing DOM elements, especially divs, frequently the id and classes are the primary concern, and attributes second. (This is implied by id and class attributes being special-cased by the DSL.) Years of HAML may have reinforced this preference, but I find it to be quite pleasantly readable.

Contrast with:

$document.ready? do
  DOM do
    canvas(width: 500, height: 500).game!.lol.wut
  end.append_to $document.body
end

which is what I must do at present.

I'm working on a PR, but I'm having trouble running the test suite, so I'm fumbling in the dark a little.

Example usage of opal-browser/* for all use cases

We should compile a simple documentation oriented script that demonstrates clearly all of the various methods implemented in opal-browser/* and keep it up-to-date so that it provides an easy reference to see all that is implemented and how to use them, in a very basic way, for user reference and documentation purposes.

Browser::Storage won't work

Whem I write something to local storage and save it, after refresh I'll get this errors:

Opal 0.8:

Uncaught TypeError: Opal.cget is not a function

Opal 0.9

Uncaught NameError: uninitialized constant Object::Browser::Storage

Purpose of Element class ?

I am curious as to what is the purpose of having an Element class inheriting from Node, rather than having all the functionality in Node itself.

README error.

Following code not worked

Browser::HTTP.get "/something.json" do
  on :success do |res|
    alert res.json.inspect
  end
end

we must require 'browser/http' first.

Keyboard/Mouse api?

I'm trying to wrap my head around it the event api, more specifically keyboard/mouse. Is there an example you can give me real quick. Doesn't have to be detailed. Thanks.

require 'browser/setup/full' not work.

#<Sprockets::FileNotFound: couldn't find file 'browser/setup/full' with type 'application/javascript'

 ╰─ $ bundle list |grep opal
  * opal (1.2.0)
  * opal-browser (0.2.0)
  * opal-sprockets (1.0.1)

A file required wasn't found

I was trying to generate the js file so I can include into my HTML as follows

opal --compile lib/opal-browser.rb > opal-browser.js

It is erring out with the following

A file required by "lib/opal-browser.rb" wasn't found. (Opal::Builder::MissingRequire)

can't find file: "opal/browser" in [
  "/Users/meh/.rvm/gems/ruby-1.9.3-p547@ob/gems/opal-0.8.0/opal",
  "/Users/meh/.rvm/gems/ruby-1.9.3-p547@ob/gems/opal-0.8.0/stdlib",
  "/Users/meh/.rvm/gems/ruby-1.9.3-p547@ob/gems/opal-0.8.0/lib"
]

Documentation of Event System Request

Dear Developers,

I've been looking over the event subsystem, and although I can roughly follow the code - it would really help if you could produce some in-depth and substantive examples of EACH of the event use cases. I notice that your Wiki is empty, and it seems a splendid spot for such example code to go.

Thanks,

Enhancement: Add CSS *definition* altering capabilities

I cobbled some simple code together that allows me to cache, create, update, and remove CSS rules of the page itself. I want you to take this code and incorporate something based upon it into your Browser::CSS tool set. Setting DOM Element style attributes is cool, but this gives you the ability to animate things by just hacking the CSS rules themselves. I hope you find it useful.

Code: https://gist.github.com/mistergibson/0393c96978fd2b1a09d6b0612af191f0

Cherry picking.

Since everyone wants a more cherry-pickable opal-browser, and so do I, can we get some discussion going on how granular the cherry-picking should be?

Which parts of opal-browser are you using and which parts are getting included that you don't care about?

Why does Browser::Interval accepts seconds as param?

setInterval accepts milliseconds as its parameter, and Browser::Interval accepts seconds. This is very confusing, I just spent quite some time thinking it doesn't work at all, where it simply had very long interval.

Don't you think it should accepts milliseconds as setInterval does?

Browser::DOM::NodeSet missing #each method ?

Browser::DOM::NodeSet calls #each in many places but #each is not implemented.

Also, in Browser::DOM::Node#<<(node) the argument is checked to see whether it responds to #each, which if a NodeSet it should but doesn't.

This test code was failing for me at c << headers:

  def index_ready # in a Volt controller
    c = container
    c << headers
    c.append_to($document.body)
  end

   def container
      DOM {
        div(class: 'container', id: 'container1')
      }
    end

    def headers
      DOM {
        div.h1.style(color: 'blue') {
          "Heading 1"
        }
        div.h2.style(color: 'red')  {
          "Heading2"
        }
      }
    end

The following patch to NodeSet fixed the problem:

class NodeSet
  ...
  def each(&block)
    @literal.each do |e|
      yield e
    end
end

Cloning node

Hello!

How I can clone node?

I think Node#clone (or Node#dup) obvious way, but he seems to only clone Opal-object, not the node.

Search by repository and documentation did not give any results.

Thanks.

basic install and test - RubyMine2018 ubuntu14.04

Hi all, Thank you for opal, no one likes js when there is ruby.

I am hitting a few problems with gem versions that create depreciation warnings. (DEPRECATION WARNING: Sprockets method register_engine is deprecated.
Please register a mime type using register_mime_type then
use register_compressor or register_transformer.)

Could anyone please tell me what ruby version I should be building under ?
Best regards,ozpos

Can't require opal-browser

Am getting the following error while trying to build with the gem:

rake aborted!
Opal::Builder::MissingRequire: A file required by "application" wasn't found.
can't find file: "opal/browser" in ["/Users/jikku/.rvm/gems/ruby-2.1.1/gems/opal-0.7.0/opal", "/Users/jikku/.rvm/gems/ruby-2.1.1/gems/opal-0.7.0/stdlib", "/Users/jikku/.rvm/gems/ruby-2.1.1/gems/opal-0.7.0/lib", "/Users/jikku/.rvm/gems/ruby-2.1.1/gems/opal-jquery-0.3.0/lib", "/Users/jikku/.rvm/gems/ruby-2.1.1/gems/opal-browser-0.1.0.beta1/opal", "/Users/jikku/.rvm/gems/ruby-2.1.1/gems/paggio-0.2.4/lib", "/Users/jikku/Opal/conway/app"]

`Proc.new` works differently in Opal and Ruby

Compare

[wolf@saito ~]$ opal -e "def foo; Proc.new; end" -e "pp foo {}"

/tmp/opal-nodejs-runner-20180319-15650-ygcnqf:5022
	  throw exception;
	  ^
ArgumentError: tried to create a Proc object without a block
	at singleton_class_alloc.TMP_Proc_new_1 [as $new] (/tmp/opal-nodejs-runner-20180319-15650-ygcnqf:16893:14)
	at Object_alloc.$$foo [as $foo] (/tmp/opal-nodejs-runner-20180319-15650-ygcnqf:21632:54)
	at Opal.send (/tmp/opal-nodejs-runner-20180319-15650-ygcnqf:1605:19)
	at /tmp/opal-nodejs-runner-20180319-15650-ygcnqf:21634:19
	at Object.<anonymous> (/tmp/opal-nodejs-runner-20180319-15650-ygcnqf:21637:3)
	at Module._compile (module.js:662:30)
	at Object.Module._extensions..js (module.js:673:10)
	at Module.load (module.js:575:32)
	at tryModuleLoad (module.js:515:12)
	at Function.Module._load (module.js:507:3)

with

[wolf@saito ~]$ ruby -e "def foo; Proc.new; end" -e "pp foo {}"
#<Proc:0x000009206e9ab810@-e:2>

Browser::Socket won't handle events when connected to websocket-rack server.

Here's my server code:

require 'rack/websocket'

class WebSocket < Rack::WebSocket::Application

  def on_open env
    EM.add_periodic_timer 5 do
      send_data "ping"
    end
    send_data 'Welcome!'
  end

  def on_message env, msg
    puts "message received: " + msg
  end
end

Opal application:

require 'opal'
require 'browser'
require 'browser/socket'
require 'browser/console'

Browser::Socket.new "ws://#{$window.location.host}/socket" do

  on :open do
    $console.log "Connection opened to host: #{$window.location.host}"
    every 1 do
      $console.log 'Sending ping'
      puts "ping"
    end
  end

  on :message do |e|
    $console.log "Received #{e.data}"
    puts 'pong' if e.data.eql? 'ping'
  end
end

config.ru:

require 'bundler'
Bundler.require

map '/socket' do
  run socket
end

map '/' do
  app = Opal::Server.new do |server|
    server.append_path 'app'
    server.main = 'application'
    server.index_path = File.join 'app', 'views', 'index.erb'
  end
  run app
end

index.erb:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <%= javascript_include_tag 'application' %>
</head>
<body>

</body>
</html>

Both websocket-rack and Browser::Socket are working fine, when are tested with third party tools (i.e. simple Javascript example, in case of websocket-rack, and echo.websocket.org, in case of Browser::Socket), but failed to interact with each other. I cannot see any replies on both side.
Seems this is a problem of Browser::Socket, as it hangs with Status Code: HTTP/1.1 101 Switching Protocols, i.e. I cannot see HTTP/1.1 101 Web Socket Protocol Handshake, like that is in case of echo.websocket.org.

debugger not always work when use with Firefox 91.0.2 64-bit. (But always work on Chrome 93.0.4577.63 64-bit)

I am not sure about this issue is for opal-browser or opal, so, open this issue too.

opal/opal#2295

Describe the bug

debugger not break after added on firefox browser.

Opal version: 1.2.0
Opal browser: github master lastest.

To Reproduce

require 'opal'
require 'js'
require 'native'
require 'promise'
require 'browser/setup/mini'
require 'browser/http'

$document.ready do
  `debugger`
  p "hello"
end

Sorry for can't offer more detail, because i don't know how to debug this issue.

simple to say, debugger is working first(though not every time), and it not work anymore suddenly.

i can add alert "hello" or p "hello" after debugger, those code work as if never debugger exists.

after i try on chrome, it always work, so, i consider this is a issue anyway.

please help me for offer more detail i want.

thank you.

Counter intuitive behavior of #css, #css_at etc. when applied to NodeSet

I see that in https://github.com/opal/opal-browser/blob/master/opal/browser/dom/node_set.rb#L17-L36 , methods applied to NodeSet are transparently applied to each dom node in set iteratively, with the return value always being the original set.

However this may be counter-intuitive if a user attempts to call finder methods like css or css_at on a NodeSet as then the return value will simply be the original set rather than aggregation of selections over each node in the set, as may be expected due to familiarity with popular js libraries like jquery.

I would suggest defining finder methods for NodeSet which aggregate the result of running the corresponding methods on each item in set.

I can work on a fix if there is consensus regarding changing this behavior.

Browser::Socket prevents instance methods from being called

I've been writing my own client-side MVC for my amusement, and came across this problem.

Here is a controller. Note, this is not a Rails controller but inherits from a class called ApplicationController which doesn't do anything at the moment.

class StreamController < ApplicationController

  def debug(str)
    Element.find("#debug").append "<p>#{str}</p>"
  end

  def connect
    Document.ready? do

      debug "yo"

      Browser::Socket.new "ws://localhost:9000/ws" do

        on :message do |e|
          Element.find("#msg").append "<p>#{e.data}</p>"
        end

        on :close do |e|
          debug "socket closed"
        end

        on :open do |e|
          debug "connected..."
        end

        Element.find("#submit").on :click do |e|
          e.prevent_default
          nick = Element.find("#nick").value
          msg = Element.find("#message").value
          write "#{nick}: #{msg}"
          Element.find("#message").value = ""
        end

      end

    end

  end

end

When the controller is initialized, the debug method is called and inserts "yo" into the DOM.

However, when the block passed to Browser::Socket calls the same controller method, I get this error:

Uncaught NoMethodError: undefined method debug' for #Browser::Socket:221`

I'm pretty sure this is different behavior than what's displayed in YARV(or RubySpec for that matter).

I cannot tell if this is a problem with opal-browser or Opal itself. If this is a result of the nature of JavaScript, perhaps it should be documented somewhere

File input field support

I was trying to add file upload support to a Clearwater app (it's using opal-browser for DOM interactions now), but I noticed that Browser::DOM::Element::Input doesn't support <input type="file">. I tried monkeypatching it in so I could submit it as a PR, but wrapping the native JS FileList and File objects were a bit more than my head was willing to process at the time. Any ideas on how to go about adding this?

Consider supporting WebComponents

WebComponents is made from few APIs supported natively on the browser. The two most relevant are Custom Elements and Shadow Dom.

The v0 specification for Custom Elements require just calling a bunch of functions to register elements and define attributes to it:

https://www.html5rocks.com/en/tutorials/webcomponents/customelements/

I believe some of them show be part of the opal-browser gem.

The next iteration on WebComponents is the CustomElements v1: https://developers.google.com/web/fundamentals/web-components/customelements

In order to support that, we need to be able to extend HTMLElement and interact with the constructor.

AFAIK this two are not support on Opal right now (hope we can have a workaround in the future).

Using opal-browser in repl

Is it possible to inspect opal-browser through the repl? I was able to require opal and inspect it, but similarly requiring opal-browser didn't seem to work.

Window#close not work

popup = Browser::Window.open("http://url", name: 'test', width: 800, height: 600)
popup.close

This code not work, this is a warrning from console.

Scripts may close only the windows that were opened by it.

Build from `rake`

We need to implement the ability to build opal-browser.js and opal-browser-canvas.js by themselves for inclusion in the CDN. This would be best implemented via a rake task it appears.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.