Wednesday, 9 January 2008

Weblocks: starting with a blank slate

If you do the customary Hello World application in Weblocks, the UI looks something like this:



The code to create this page is:


(weblocks:defwebapp 'our-application)
(defun init-user-session (comp)
(setf (weblocks:composite-widgets comp)
(list "Hello!")))
(weblocks:reset-sessions)
;; Starts the server on localhost:8080
(weblocks:start-weblocks)


This minimal application brings in the following CSS files:

  • layout.css

  • dialog.css

  • main.css


And the following Javscript files:

  • scriptaculous.js

  • builder.js

  • shortcut.js

  • weblocks.js

  • dialog.js


Additionally, scriptalicious brings in a bunch of more dependencies that double the number of JS files.

The JS files are obviously what give you the nice Ajaxian effects and desktop application-like feel when you work with Weblocks widgets. However, I typically like to start from scratch so I can control what the framework brings in.

When you instantiate your Weblocks application (via weblocks:defwebapp), the variable weblocks:*application-public-dependencies* is set to a default list:

CL-USER> weblocks:*application-public-dependencies*
(#P"stylesheets/layout.css" #P"stylesheets/main.css" #P"stylesheets/dialog.css"
#P"scripts/prototype.js" #P"scripts/scriptaculous.js" #P"scripts/shortcut.js"
#P"scripts/weblocks.js" #P"scripts/dialog.js")

So that answers the question of where all those files come from. Set this list to nil and reload the page. You should get something like this:



If you look at the HTML for the page (through Firebug) you will see something like this:


Still pretty noisy. I don't care much about the meta tag, but I've got to get rid of the divs.

For every request, the function weblocks:render-page is called to actually generate the necessary HTML. This function just sends the head tag contents and is where all the external references are inserted into the output. It also opens the body tag but then calls the render-page-body function to actually output the body of the page. I redefine the function from:

(defmethod render-page-body (body-fn)
(with-html
(:div :class "page-wrapper"
(render-extra-tags "page-extra-top-" 3)
(htm (str body-fn))
(render-extra-tags "page-extra-bottom-" 3))))

To:

CL-USER> (defmethod weblocks:render-page-body (body-fn)
(weblocks:with-html
(cl-who:htm (cl-who:str body-fn))))

Now if you reload the page, the HTML looks something like this:

To get rid of the footer, redefine the after method on render-page-body to do nothing (or remove it altogether);

CL-USER> (defmethod weblocks:render-page-body :after (rendered-html))

Now the HTML looks like:

The divs come from our init-session function where we defined it to be:

(defun init-user-session (comp)
(setf (weblocks:composite-widgets comp)
(list "Hello!")))

That was enough to keep me happy however. Hope that helps!

2 comments:

crazia said...

good posting!! If I want to add my own resources(script, css files) to your "blank slate" app , How can I do it?

Plz help me for that

Sohail Somani said...

Thanks!

You'd have to find out how the head content is generated and override that function. I'm not sure how that is done these days :)