Building just a simple Hello World app in KRL is fairly simple. There are only so many ways to put a notify on the page. Kicking it up a notch and adding in a form and some persistance really opens up the doors to a lot of possibilities and different ways of doing it. I thought it might be interesting to document the evolution as I attempt to create a good advanced Hello World example app for Kynetx.
Version 0
ruleset a60x557 { meta { name "advanced-hello-world" description << advanced-hello-world >> author "Mike Grace" logging on } rule plain_krl_way { select when pageview "example\.com" pre { form =<< <form id="my-form"> Your Name: <input type="text" name="user-name"/> <input type="submit" value="Submit"/> </form> >>; } { notify("Remembering your name",form) with sticky = true; watch("#my-form", "submit"); } } rule get_form { select when web submit "#my-form" pre { userName = event:param("user-name"); } { notify("Thanks #{userName}!","") with sticky = true; } } }
- put form on page
- watch form
- respond to form submit with notify
This is super simple but falls short in several areas
- nothing to let the user know that the server is currently working on processing the form submit
- form can be submitted more than once
- submitted name isn’t stored into persistance
- interesting but not really useful in my opinion
- this isn’t how I get data out of forms (will show later)
Action shots:
running app for first time on example.com
submitting form first time
submitting form as many times as I want
Version 1
ruleset a60x557 { meta { name "advanced-hello-world" description << advanced-hello-world >> author "Mike Grace" logging on } rule what_should_i_do { select when pageview "example\.com" pre { userName = ent:userName || ""; form =<< <form id="my-form"> Your Name: <input type="text" name="user-name"/> <input type="submit" value="Submit"/> </form> >>; } if (userName eq "") then { notify("Remembering your name",form) with sticky = true; watch("#my-form", "submit"); } notfired { raise explicit event user_name_known with userName = userName; } } rule user_name_known { select when explicit user_name_known pre { userName = event:param("userName"); } { notify("#{userName} is 'da bomb!","") with sticky = true; } } rule get_form { select when web submit "#my-form" pre { userName = event:param("user-name"); } { notify("Thanks #{userName}!","") with sticky = true; } fired { set ent:userName userName; } } }
- 14 get user’s name from persistance and set to blank string if not found
- 22 if the user’s name is not found in persistance then put the form up and watch for the form submit
- 26 if the user’s name was found in persistance then raise an explicit event to handle user’s name being found
- 34 get user’s name from passed parameters is raised explicit event. Could have just pulled it from persistance but then you wouldn’t have gotten to see how to pass parameters in explicit events.
- 50 set the user’s name into persistance when the rule runs responding to form submit event
This example is much better but still leaves a lot out.
- no form validation
- no way for user to change set user name once submitted
- still no indication that form submission is ‘in progress’
- still able to submit multiple times
Action shots:
running app on example.com for the first time
submitting form for the first time
submitting the form as many times as I want
After page reload and running app again
Version 2
ruleset a60x557 { meta { name "advanced-hello-world" description << advanced-hello-world >> author "Mike Grace" logging on } global { css << a { color: white; } >>; } rule what_should_i_do { select when pageview "example\.com" pre { userName = ent:userName || ""; form =<< <form id="my-form"> Your Name: <input type="text" name="user-name"/> <input type="submit" value="Submit"/> </form> >>; greeting =<< <p>#{userName} is 'da bomb!'</p> <p>Clear saved name by running the app on <a href="http://example.com/?clear">example.com/?clear</a></p> >>; content = (userName eq "") => form | greeting; } { notify("Hello World (advanced)", content) with sticky = true and opacity = 1; watch("#my-form", "submit"); } } rule get_form { select when web submit "#my-form" pre { userName = event:param("user-name"); } { notify("Thanks #{userName}!","") with sticky = true; } fired { set ent:userName userName; } } rule clearing { select when pageview "example\.com\/\?clear" notify("Cleared",""); fired { clear ent:userName; } } }
- 12 set CSS so link on black background is visible
- 29 setup greeting HTML at the same time as the form
- 33 decide what to put on the page using condition expression
- 54 clear saved name when user runs on specified clear page
This is getting closer but still lacks
- form validation or disallowing user to submit multiple times
- when persistance is cleared the greeting is also displayed
- no indication that form submission is ‘in progress’
- still not the way I would do it
Action Shots:
running app first time
submitting name first time
submitting name many times
running app again after refresh of page
running app on designated clear page
Version 3
ruleset a60x557 { meta { name "advanced-hello-world" description << advanced-hello-world >> author "Mike Grace" logging on } global { css << .kGrowl-notification a { color: white; } #a60x557-working, #a60x557-notice { display: none; } >>; } rule what_should_i_do { select when pageview "example\.com(?!.+clear)" pre { userName = ent:userName || ""; form =<< <p id="a60x557-notice">Your name input must be more than 2 characters</p> <p id="a60x557-form">Your Name: <input type="text" id="a60x557-user-name"/> <button id="a60x557-submit">Submit</button></p> <img id="a60x557-working" style="display: none" src="http://kynetx-apps.s3.amazonaws.com/advanced-hello-world/working.gif"/> >>; greeting =<< <p>#{userName} is 'da bomb!'</p> <p>Clear saved name by running the app on <a href="http://example.com/?clear">example.com/?clear</a></p> >>; content = (userName eq "") => form | greeting; } { notify("Hello World (advanced)", content) with sticky = true and opacity = 1; emit <| $K("#a60x557-submit").bind("click", function() { // get user name from input var userName = $K("#a60x557-user-name").val(); // check input if (userName.length > 2) { // don't allow user to submit more than once $K(this).unbind("click"); // get app object to raise web event app = KOBJ.get_application("a60x557"); // raise web event to system with user name app.raise_event("user_name_submitted", {"user-name":userName}); // show user 'in progress' $K("#a60x557-form,#a60x557-notice").remove(); $K("#a60x557-working").show(); } else { $K("#a60x557-notice").show() }; }); |>; } } rule get_form { select when web user_name_submitted pre { userName = event:param("user-name"); reset =<< <p>Clear saved name by running the app on <a href="http://example.com/?clear">example.com/?clear</a></p> >>; } { emit <| // close previous notify $K(".kGrowl-notification .close").trigger("click"); |>; notify("Thanks #{userName}!", reset) with sticky = true and opacity = 1; } fired { set ent:userName userName; } } rule clearing { select when pageview "example\.com\/\?clear" notify("The saved name has been cleared",""); fired { clear ent:userName; } } }
- updated CSS to only change links inside the notify
- 24 don’t show form/welcome back notify if on the clear page
- 28 add notice to show if user input doesn’t match validation rule
- 30 add working notification image to let user know app is ‘in progress’
- 41 watch for user to submit form using jquery
- 47 check user input against validation rule
- 49 release click listener so form only gets submitted once
- 52 get application JS object to raise web event
- 55 raise web event with user’s name
- 58 remove form stuff
- 59 show working spinner image
- 61 show notice if user’s input doesn’t pass input validation
- 79 close previous notify once saved form returns
Now this advanced hello world example app
- only allows the user to submit name once
- allows user to clear set name
- better CSS selectors
- form validation
- in progress visual
- stores user’s name into persistance
- this is how I would do it
Action shots:
running app first time
submitting name first time
name successfully saved
running app again after reload
running app on designated clear page
Get the bookmarklet to try it out yourself!
Gratuitous day 38 crazy face