I'd like to get the keyboard input of a user in Websharper for an entire page (or whatever gets me closest), and I can't see any nice way of doing this.
I've attempted something along the lines of
JQuery.Of("document").Keyup(fun _ _ -> Window.Self.Alert("boo"))
But I keep running into a lot of NotImplementedExceptions. Are these really not implemented? Or am I hitting some weird edge case because I'm going against the grain?
Update:
I've got version 2.4.85.235 installed from nuget, if that means anything to anyone. I'm also using VS 2012.
I've also tested with a fresh sitelets templated site from VS 2010, and I see the same thing. I've installed the latest package from the WebSharper site.
Make sure that you're not calling client-side methods that are not implemented on the server. If that's the case separate client and server code, display the involved elements and invoke the JavaScript through the Web Control mechanism and use "html", "body" or Dom.Document.Current as a selector. Below is a sample for displaying an alert every time the enter key is pressed:
module Client =
open IntelliFactory.WebSharper
open IntelliFactory.WebSharper.Html
open IntelliFactory.WebSharper.JQuery
[<JavaScriptAttribute>]
let paragraph () =
P [Text "Press the Enter key to display an alert box."]
|>! OnAfterRender (fun x ->
JQuery.Of("html").Keydown(fun _ event ->
match event.Which with
| 13 -> JavaScript.Alert "Enter key was pressed."
| _ -> ()).Ignore)
type ParagraphViewer () =
inherit Web.Control()
[<JavaScript>]
override this.Body = paragraph () :> _
Related
I have a selenium UI test written with F# (using canopy selenium nuget package). I have a module that defines page selectors and helper functions. The page module is called by a test module. Within the test module, I am calling a function called 'handlemobimodals()', which runs four sub functions (if/else code blocks) that look for the existence of an element on a page and click on it, if it exists.
The problem I'm facing is that when the 'handlemobimodals()' function is called for a second time within the test, I get a Stack Overflow Exception (WebDriver Process is terminated due to StackOverflowException), right after its first sub function is called.
The function runs completely fine for the first time (called indirectly from another function earlier in the test), but fails the second time when called directly in the test. I'm pretty new to F# and I can't figure out how I'm causing a recursion in my test as the stackoverflow exception suggests.
Any insights would be greatly appreciated.
Snippet from Page Module:
module some_page
let isOKGotItDisplayed () =
isDisplayed <| "div.action-button.dismiss-overlay"
let clickOKGotit() =
if isOKGotItDisplayed() = true then
click "OK, GOT IT"
describe "OK, Got It clicked"
else describe "Got nothing"
let isGoToSearchDisplayed() =
isDisplayed <| "button:contains('Go to Search')"
let clickGoToSearch() =
if isGoToSearchDisplayed() = true then
click "button:contains('Go to Search')"
describe "go search button clicked"
else describe "Got nothing"
let isSkipDisplayed() =
isDisplayed <| "#uploadPhotos > div.continue.skip"
let clickSkip() =
if isSkipDisplayed() = true then
click "Skip"
describe "Skip link clicked"
else describe "Got nothing"
let mobiOkayGotItDisplayed () =
isDisplayed <| "Okay, got it"
let mobiOKGotit() =
if mobiOkayGotItDisplayed() = true then
click "Okay, got it"
describe "Okay, got it"
else describe "Got nothing"
let handleMobiModals() =
clickSkip()
clickOKGotit()
clickGoToSearch()
mobiOKGotit()
loginForPathAs user =
username << "somename"
paswword << "somepassword"
handleMobiModals()
Snippet from Test Module (note the first instance of the handleMobiModals function is called in the LoginforPathAs function, which is defined in the same page definition module):
module_sometest
open some_page
"Test 001: Log in and do something" &&& fun _ ->
newBrowser platform
loginForPathAs user1
displayed quicknoteSendButton
click quicknoteSendButton
handleMobiModals ()
displayed "Subscribe"
Note: Snippets are edited for simplicity and clarity.
It's not a direct answer, but I believe it would help to find the problem much easier. I did notice something that makes it somewhat difficult to debug this problem. You're calling multiple functions from another function, and calling this single function from a test. Splitting out these functions into separate tests and changing the tests into WIP mode should help to pinpoint your issue. There are a lot of possible points of failure within that one test.
For instance, you can use before(fun _ -> some function(s) here) or once(fun _ -> some function(s) here) within your context in Canopy to start a new browser and login, separating that part from the test.
This issue appears to have resolved itself. I believe my most recent auto-update for Chrome fixed the problem.
I have a problem to close a program in Erlang. I use wxWidgets.
-module(g).
-compile(export_all).
-define(height, 500).
-define(width, 500).
-include_lib("wx/include/wx.hrl").
-define(EXIT,?wxID_EXIT).
init() ->
start().
start() ->
Wx = wx:new(),
Frame = wxFrame:new(Wx, -1, "Line", [{size, {?height, ?width}}]),
setup(Frame),
wxFrame:show(Frame),
loop(Frame).
setup(Frame) ->
menuBar(Frame),
wxFrame:connect(Frame, close_window).
menuBar(Frame) ->
MenuBar = wxMenuBar:new(),
File = wxMenu:new(),
wxMenuBar:append(MenuBar,File,"&Fichier"),
wxFrame:setMenuBar(Frame,MenuBar),
Quit = wxMenuItem:new ([{id,400},{text, "&Quit"}]),
wxMenu:append (File, Quit).
loop(Frame) ->
receive
#wx{event=#wxCommand{type=close_window}} ->
io:format("quit icon"),
wxWindow:close(Frame,[]);
#wx{id=?EXIT, event=#wxCommand{type=command_menu_selected}} ->
io:format("quit file menu"),
wxWindow:close(Frame,[])
end.
But the program doesn't close; neither the quit icon or Quit from the menu do anything.
You're almost there, but there's a few mistakes.
First, there's never any event being generated for your quit selection on your mention, you need to use connect again, like this:
Quit = wxMenuItem:new ([{id,400},{text, "&Quit"}]),
wxFrame:connect(Frame, command_menu_selected),
Now you have an event for each of the quit methods, but neither of them is working still.
The event for your quit icon isn't matching because you have the wrong event type in your pattern match, and the event for the menu quit selection isn't matching because you're looking for an ID of ?EXIT, which is defined as ?wxID_EDIT, which is defined as.. well clearly not 400, the ID you used when you created your quit menu item. So your receive clause needs to be changed to something like this:
receive
#wx{event=#wxClose{type=close_window}} ->
io:format("quit icon"),
wxFrame:destroy(Frame);
#wx{id=400, event=#wxCommand{type=command_menu_selected}} ->
io:format("quit file menu"),
wxFrame:destroy(Frame)
end.
In addition to Michael's answer regarding using connect/3 to listen for menu commands, nearly any frame will require a few standard event connections to behave the way you expect them to on closing in addition to whatever specific things you have going on. Note that this is connecting to the close_window event and using the option {skip, true}. This is so the signal doesn't stop propagating before it hits the part of Wx that will handle it the way you expect (one click to close) instead of requiring two clicks to close the frame on some platforms.
The basic skeleton often looks like this:
init(Args) ->
Wx = wx:new(),
Frame = wxFrame:new(Wx, ?wxID_ANY, ""),
% Generate whatever state the process represents
State = some_state_initializer(Args),
% Go through the steps to create your widget layout, etc.
WidgetReferences = make_ui(Frame),
% The standardish connects nearly any frame will need.
ok = wxFrame:connect(Frame, close_window, [{skip, true}]),
ok = wxFrame:connect(Frame, command_button_clicked),
ok = wxFrame:connect(Frame, command_menu_selected),
% Add more connects here depending on what you need.
% Adjust the frame size and location, if necessary
Pos = initial_position(Args),
Size = initial_size(Args),
ok = wxFrame:move(Frame, Pos),
ok = wxFrame:setSize(Frame, Size),
wxFrame:show(Frame),
% Optional step to add this frame to a UI state manager if you're
% writing a multi-window application.
ok = gui_manager:add_live(self()),
% Required return for wx_object behavior
{Frame, State}.
Digressing a bit from the original, but strongly related...
Many wxWidgets application have something very similar to this, customized as necessary not by writing all that out again, but by defining your own callback module and passing it in as an argument:
init({Mod, Args}) ->
% ...
PartialState = blank_state([{mod, Mod}, {frame, Frame}, {wx, Wx}]),
State = Mod:finalize(PartialState, Args),
Where blank_state/1 accepts a proplist and returns whatever the actual data structure will be later (usually a record at this level, that looks something like #s{mod, frame, wx, widgets, data}), and Mod:finalize/2 takes the incomplete state and the initial args and returns a completed GUI frame plus whatever program state it is supposed to manage -- in particular the widgets data structure that carries references to any GUI elements you will need to listen for, match on, or manipulate later.
Later on you have some very basic generic handlers all frames might need to deal with, and pass any other messages through to the specific Mod:
handle_call(Message, From, State = #s{mod = Mod}) ->
Mod:handle_call(Message, From, State).
handle_cast(blit, State) ->
{ok, NewState} = do_blit(State),
{noreply, NewState};
handle_cast(show, State) ->
ok = do_show(State),
{noreply, State};
handle_cast(Message, State = #s{mod = Mod}) ->
Mod:handle_cast(Message, State).
In this case do_blit/1 winds up calling Mod:blit/1 in the callback module which rebuilds and refreshes the GUI, rebuilding it from zero by calling a function that does that within wx:batch/1 to make it appear instant to the user:
blit(State) ->
wx:batch(fun() -> freshen_ui(State) end).
If you have a lot of elements to change in the GUI at once, blitting is far smoother and faster from the user's perspective than incrementally shuffling things around or hiding/showing elements as you go -- and is much more certain to feel the same across platforms and various computer speeds and userland loads (some Wx backends give a lot of flicker or intermediate display weirdness otherwise).
The do_show/1 function usually looks something like
do_show(#s{frame = Frame}) ->
ok = wxFrame:raise(Frame),
wxFrame:requestUserAttention(Frame).
(I have been meaning to write a basic "here is one way to structure a multi-window wxErlang application" tutorial/example but just haven't gotten around to it, so a lot of details are missing here but you'll stumble on them on your own after writing a couple of programs.)
I am developing a mobile application using phonegap, Initially I have developed using WEBSQL but now I m planning to move it on INDEXDB. The problem is it does not have direct support on IOS , so on doing much R&D I came to know using IndexedDB Polyfil we can implement it on IOS too
http://blog.nparashuram.com/2012/10/indexeddb-example-on-cordova-phonegap.html
http://nparashuram.com/IndexedDBShim/
Can some please help me how to implement this as there are not enough documentation for this and I cannot figure out a any other solution / api except this
I have tested this on safari 5.1.7
Below is my code and Error Image
var request1 = indexedDB.open(dbName, 5);
request1.onsuccess = function (evt) {
db = request1.result;
var transaction = db.transaction(["AcceptedOrders"], "readwrite");
var objectStore = transaction.objectStore("AcceptedOrders");
for (var i in data) {
var request = objectStore.add(data[i]);
request.onsuccess = function (event) {
// alert("am again inserted")
// event.target.result == customerData[i].ssn;
};
}
};
request1.onerror = function (evt) {
alert("IndexedDB error: " + evt.target.errorCode);
};
Error Image
One blind guess
Maybe your dbName contains illegal characters for WebSQL database names. The polyfill doesn't translate your database names in any kind. So if you create a database called my-test, it would try to create a WebSQL database with the name my-test. This name is acceptable for an IndexedDB database, but in WebSQL you'll get in trouble because of the - character. So your database name has to match both, the IndexedDB and the WebSQL name conventions.
... otherwise use the debugger
You could set a break point onto your alert(...); line and use the debugger to look inside the evt object. This way you may get either more information about the error itself or more information to share with us.
To do so, enable the development menu in the Safari advanced settings, hit F10 and go to Developer > Start debugging JavaScript (something like that, my Safari is in a different language). Now open then "Scripts" tab in the developer window, select your script and set the break point by clicking on the line number. Reload the page and it should stop right in your error callback, where you can inspect the evt object.
If this doesn't help, you could get the non-minified version of the polyfill and try set some breakpoints around their open function to find the origin of this error.
You could try my open source library https://bitbucket.org/ytkyaw/ydn-db/wiki/Home. It works on iOS and Android.
Is there an idiomatic way for me trigger my formlet's submit action when a keydown event is pressed?
Should I drop back down to DOM manipulation, or is there some Enhancement that I can use?
Unfortunately, at the moment there is no standard way to do this. We do intend to add it in a future version though, either as an Enhance combinator or as a new option to Enhance.WithCustomSubmit*.
We actually encountered the same problem when creating FPish, and we use the following workaround:
[<JavaScript>]
let TriggerOnEnter (formlet : Formlet<'T>) =
formlet
|> Formlet.MapElement (fun elem ->
let e = JQuery.JQuery.Of(elem.Body)
e.Keypress(fun _ k ->
// Opera uses charCode
if k?keyCode = 13 || k?charCode = 13 then
JavaScript.SetTimeout (fun _ ->
e.Find("input[type=button]").Trigger("click").Ignore
) 100 |> ignore
k.StopPropagation()
).Ignore
elem
)
Note that it triggers the first button in the form, so you might need adjustments to the jQuery selector to make it actually trigger the submit button.
We have a fairly large USSD application that uses Erlang's gen_fsm module to manage the menu options.
The current version has a single menus_fsm.erl file that contains 5000+ lines gen_fsm related code. Our next version gives us an opportunity to split menus_fsm.erl into separate files to make it more maintainable in the future.
In the old version, to display the help menu we do the following (help_menu/1 gets called from code not shown that displays the main menu):
-module(menus_fsm).
% Snipped some irrelvant code
help_menu(StateData) ->
% Display the first menu
send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2"),
{next_state, waitHelpMenuChoice, StateData, ?MENU_TOUT};
waitHelpMenuChoice(Params, StateData) ->
io:format("Got Help menu response: ~p", [Params]),
doTerminate(ok,"Help Menu", StateData).
I've left out a lot of code that shows the entry point into the FSM and so on.
In the new version, we'd want to move help_menu/1 and waitHelpMenuChoice/2 to a new module help_menu, which gets called from menus_fsm, like so:
-module( help_menu ).
% Snipped some irrelevant code
help_menu(StateData) ->
menus_fsm:send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2"),
{next_state, waitHelpMenuChoice, StateData, ?MENU_TOUT};
waitHelpMenuChoice(Params, StateData) ->
io:format("Got Help menu response: ~p", [Params]),
menus_fsm:doTerminate(ok,"Help Menu", StateData).
The problem is with the line {next_state, waitHelpMenuChoice, StateData, ?MENU_TOUT};: gen_fsm expects the waitHelpMenuChoice to be in the module menus_fsm which takes me back to where we started.
I've tried to replace the problematic line with
{next_state, fun help_menu:waitHelpMenuChoice/2, StateData, ?MENU_TOUT};
but that just leas to an error like the following:
{badarg,[{erlang,apply,[conv_fsm,#Fun<help_menu.waitHelpMenuChoice.2>,[]]}
Does anyone have any suggestions of how to get around this?
Maybe you could use http://www.erlang.org/doc/man/gen_fsm.html#enter_loop-6 to do that? Not sure if it would work to call it inside of another fsm, but it might be worth a try.
I managed to find a solution to my own question. If this seems obvious, it could be because I'm a bit new to Erlang.
I added a new function wait_for_menu_response/2 to module menus_fsm that handles state transitions on behalf of the other modules.
-module(menus_fsm),
-export([wait_for_menu_response/2]).
% ...snip...
wait_for_menu_response(Params, {Function, StateData}) ->
Function(Params, StateData).
Then the help_menu module was changed as follows:
-module( help_menu ).
% ...snip...
help_menu(StateData) ->
menus_fsm:send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2"),
{next_state, wait_for_menu_response, {fun waitHelpMenuChoice/2, StateData}, ?MENU_TOUT}.
waitHelpMenuChoice(Params, StateData) ->
io:format("Got Help menu response: ~p", [Params]),
menus_fsm:doTerminate(ok,"Help Menu", StateData).
so gen_fsm stays within the menus_fsm module when it invokes wait_for_menu_response, but wait_for_menu_response is now free to invoke help_menu:waitHelpMenuChoice/2. help_menu:waitHelpMenuChoice/2 did not need to be modified in any way.
Actually, in my final version, the menus_fsm:send_menu function was modified to accept the fun waitHelpMenuChoice/2 as its third parameter, so that the help_menu function simply becomes:
help_menu(StateData) ->
menus_fsm:send_menu(StateData, "Please Select:\n1. Option 1\n2. Option 2",
fun waitHelpMenuChoice/2).
but I think my explanation above illustrates the idea better.