JavaScript run-time rendered forms

One more challenge I’ve had these days, I wanted to have a way to define my forms in xml format and render them at run time on the web page. And on web page I want to have just content place holders, so if I work together with web designer, he can jut define the place where the will be rendered.

So to skip all unnecessary introduction, let me show you how whole thing works.

My form place holder looks like this:

<div class="jform">contactform.xml</div>

As you can see I just added a div that has class jqform (I used short for jQuery forms). In text section of this content container I've put the name of the file I will use, the one that contains my XML form definition.

My contactform.xml definition file of the form is following:

<form title="Contact Us" url="save.aspx" submitLabel="Send" replyCallback="__formSubmited">
  <formItem title="Name">
    <input type="text" id="name" />
  </formItem>
  <formItem title="Email">
    <input type="text" id="email" />
  </formItem>
  <formItem title="Message">
    <input type="text" multiline="yes" id="message" />
  </formItem>
</form>

As you can see this form has a title, it has an URL where I will submit form, it  has also submitLabel field that contains a text of the Submit button, the last parameter you see there is replyCallback which the name of the function I will use to pass result of the data post, please note that data i pass to this function is in escaped format.

If url is not specified it will render just form, without any submit buttons and form post functionality included.

And after rendering this form  would look like this:

image

Now, to make things working as I need we going to add into head section of our html the following:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>

    <script type="text/javascript" src="http://jqcommons.googlecode.com/svn/trunk/jqc.core.js"></script>

    <script src="jqforms.js" type="text/javascript"></script>

As you can see I use jQuery library hosted by Google and second reference is to jQuery Commons, my recent contribution for webware developers. This lib contains set of functions that makes my life easier, like string operations, date formatting and so on, bunch of goodies.

As you recall, above I mentioned replyCallback function, let’s make it simple:

<script type="text/javascript">
        function __formSubmited(reply) {
            alert(unescape(reply));
        }
    </script>

As I told you string comes in escaped format, so to work with this string I need to unescape it back.

The whole magic done actually by third JavaScript file that I added to my HTML, you can see it referred as jqforms.js. So what it does, is on document_ready event it checks for jqform class enabled containers and renders a form out of XML definition you referred within a container.

You can see whole thing in action at http://labs.skitsanos.com/demos/jsforms/ and ‘jQuery Forms Player’ (jqforms.js) prototype you can get from http://labs.skitsanos.com/demos/jsforms/jqforms.js

Now this thing saves me unreal amount of time, hope it will for you as well.

Configuring Stopeo service under ASP.NET

First of all, what is Stopeo? With stopeo, You can easily check your server performance and keep an eye for any overloads. So...

*How to use stopeo.com from Wojtek Siudzinski on Vimeo.

So now when you know what is all about I will give you a tip how to make Stopeo works with ASP.NET web sites, as it does in my case with SiteAdmin CMS generated sites.

Stopeo requires just two things, to know when page render started and when it’s finished, so implementation is simple, insert following code into server side script part, for example like this:

<script runat="server">
Protected stopeoStart As DateTime
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
  stopeoStart = Now End Sub
</script>

Then,  in very bottom, of the page you just put following code:

<!-- stopeo: <%=Now.Subtract(stopeoStart).TotalSeconds%>s -->

So what it does is returning you time span in seconds format, like 0.000… Now you can feed Stopeo with it.

Injecting content fragments into stand alone page

One more little tip for you today. When you are working with SiteAdmin CMS and facing the situation where you can’t use master pages but rather need a way to inject a content into existing stand alone static page, there is one simple way to do that.

Technically in your html code you need to define content areas that you want to be filled from CMS, something like:


<div …>
  <asp:Literal runat="server" ID="pageContent" />
</div>

You can have these content areas on your page as many as you want. Then, you need to add little piece of code into your server side script area:

<script runat="server">
    Protected mgr As New Wdk.ContentManagement.Pages.Manager
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim p As Wdk.ContentManagement.Pages.PageType = mgr.getPageByFilename(IO.Path.GetFileName(Request.Path))
        pageContent.Text = p.Content
        Page.Title = p.Title
    End Sub
</script>

As you can see here I ask CMS Page Manager to retrieve me a page with given file name and instead typing this file name this time I just take the name out of the request path.

If page is exists its content will be used to fill our defined pageContent zone, if page not found you will have something like this rendered instead:

Requested page {page_name_goes_here.aspx} not found

So no dead links in case you forgot to create a page with this name.

jQuery based DOM element replace

Another challenge for today, sound’s like a simple thing to do, but can turn into pain in the butt if you need something really quick. This time I’m talking about replacing DOM element in real time on client side. Something like I have:

<a href=”/profiles/Joe Doe.aspx”>Joe Doe</a>

and I need to turn it into something like this:

<div class=”selected”>Joe Doe</div>

So I need to find given element in DOM based on a given condition, in my case text of this element must be Joe Doe, and then turn it into div container with given class.

To do that I chose jQuery AJAX framework, since I consider it as flexible and easy to use, and I’m going to extend its functionality a bit to fit my needs, I need a plug-in that will return me an element if it contains given text:

$.extend($.expr[':'], {
got: function(el, i, m) {
return ($(el).html() == m[3]);
}
});

This allows me make queries like a:got(some text to match) to get the element with given text. Below I will show more precise example.

Another thing I need is to have ability to replace given element with another one, and I will do it again by extending jQuery functionality with adding .replace function:

$.fn.replace = function(o) { return this.after(o).remove(); };

Now I can do very complex thing:

$('#mainContent a:got(<%=IO.Path.GetFileNameWithoutExtension(Request.Path) %>)').replace('<div class="staffselected"><%=IO.Path.GetFileNameWithoutExtension(Request.Path) %></div>');

That is in more simplified version does this:

$('#mainContent a:got(Joe Doe)').replace('<div class="selected">Joe Doe</div>');

Additional notes. The reason I had to add ‘got’ query extension is because not all browsers support DOM based XPath selection via jQuery, ideally you could just do a[text=Joe Doe] and it would work fine, it does actually in some browsers, but since I needed something really cross-browser, I had to find another way to things right and a:got(Joe Doe) does the job.

One more. Just got feedback via twitter from @matt_kruse, that recent jQuery has functions replaceWith and :contains(), that do the same thing, well ;), less code for you and now you know 2 ways of doing things.

Importing content blocks

When you hit the moment when you need to import old content or content blocks into CMS or just on disk and you don’t have much time you have to think about writing own bot. Bots can do a lot for you, if you plan them in a right way.

It almost brought me into panic when I seen how many files I need to CMS, all files done with Adobe/Macromedia Dreamweaver via templates, just pure HTML and all I actually need is piece of this HTML, technically each page had 3 tables of 939 pixels wide surrounded with tons of other content, but all I needed is the middle table, since that’s my content source for my new web site.

So question is how I’m going to rip content block in most effective way and with minimal time waste. Since I did hundreds of content crawlers, search engine robots and so on, first thing came to my mind is to load the page content, find the target content block, rip it out of there, load the template for new web site and inject content block inside.

In this particular web site some of my content hosted by WDK.VFS engine and some on physical disk where I have master page defined to use for my content blocks.

So, to make the story short, all you need is just two things:

  • HTML Agility Pack (download from http://www.codeplex.com/htmlagilitypack), we will use it for making our little content processor/ripper bot.
  • Prepared empty template that you will use as skeleton

Once u downloaded HTML Agility Pack and put .dll file of it into /bin in your web site, you can prepare my content page template that you will use to wrap around your imported content block:

<%@ Page Title="" Language="VB" MasterPageFile="~/default.master" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">

</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="contentBody" runat="Server">

###content

</asp:Content>

I called this file empty.aspx and placed it in my site folder. As you can see I have there ###content, that’s the keyword I will replace with content block.

<%@ Page Language="VB" %>

<%@ Import Namespace="HtmlAgilityPack" %>

<script runat="server">

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)

Dim template As String = New IO.StreamReader(AppDomain.CurrentDomain.BaseDirectory + "_utils\empty.aspx").ReadToEnd

For Each file As String In IO.Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + "applications")

Dim doc As New HtmlDocument

doc.Load(file)

Dim el As HtmlNode = doc.DocumentNode.SelectSingleNode("//table[@width='939'][2]")

If el IsNot Nothing Then

el.SetAttributeValue("width", "100%")

Dim t As String = String.Copy(template)

t = t.Replace("###content", el.OuterHtml)

t = t.Replace(".htm", ".aspx")

Dim sw As New IO.StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "applications\" + IO.Path.GetFileNameWithoutExtension(file) + ".aspx")

sw.Write(t)

sw.Close()

End If

Next

Response.Write("---done")

End Sub

</script>

What it does is following:

  • Preload template (empty.aspx),
  • Process each file in given directory, in my case it will be ROOT/applications, then load each file into string buffer,
  • Then load this buffer into HtmlDocument (this is where we need Html Agility Pack), which I'm using for navigating within DOM,
  • After I’m finding target element, in my case I'm looking for second table that has width set to 939,
  • I check if I have any results, and if I have, I copy my template content into a new string, replace my ###content keyword with HTML content of my found content block, also in my case I need to replace all links within content block from .htm to .aspx format,
  • and the last thing we are going to do is to store new file on disk.
  • Done

If you still have a question, let me know;)

WDK.VFS – Virtual File System for your CMS

SiteAdmin CMS includes custom made Virtual Path Provider WDK.VFS that works as Virtual File System in order to serve the content to your visitors. WDK.VFS automates page rendering tasks for your web site and minimizes possible web application coding required.

Basically, if you have some of the pages created within your SiteAdmin CMS and wdk.vfs.dll already in your bin folder all your virtual pages would be accessible under following location:

http://yoursite/content/page-file-name.aspx

Where page-file-name.aspx is the file name from your CMS Pages module.

Please keep in mind that after installing WDK.VFS there are some restrictions applies on folder naming. Means some of the site folder names can’t be used because those names are reserved by WDK.VFS.

VFS Reserved Names

There is a number of reserved folder names in WDK Virtual File System. Having following names reserved, basically, means that you are not allowed to name your “physical” folders on disk with these names:

  • content
  • events
  • enews
  • controls
  • files
  • system
VFS system resources served by WDK.VFS engine
  • /enews/subscribe.aspx - Newsletter subscription form
  • /content/search.aspx - Search page for /content/ area. Search available for all pages that have .aspx file extension and file names not starts with $ sign
  • /system/login.aspx - login form where users can authorize themselves in order to access resources that requires authentication.

Content Rendering Approaches

There are many ways how you can use SiteAdmin for content rendering. Easiest of them is using templates to build design independent web site.

In ASP.Net when you developing design independent web site you have at least two options for templating:

· Use ASP.Net Master Pages,

· Or, use custom made plain HTML only templates.

Master Pages

Microsoft ASP.NET 2.0 introduces a new concept known as Master Pages, in which you create a common base master file that provides a consistent layout for multiple pages in your application.

To create a Master Page, you identify common appearance and behavior factors for the pages in your application, and move those to a master page. In the master page, you add placeholders called ContentPlaceHolders where the content (child) pages will insert their custom content. When users request the content pages, ASP.NET merges the output of the content pages with the output of the master page, resulting in a page that combines the master page layout with the output of the content page. It is very similar to plain HTML templates approach that we presented within SiteAdmin in 2002.

RIA, AJAX, etc…

There are already more than 200 different AJAX frameworks exists, many of them for using within Microsoft .Net Framework, or even server platform independent. Web sites deployed with SiteAdmin successfully been tested with some of them, like:

Most of the web applications based on SiteAdmin CMS we deploy with jQuery which is very easy to use and having simple syntax. This allows us to unload server side load and shift it on client side, making UI working faster and more interactive. We are going to post here tips and tricks for using jQuery with SiteAdmin CMS.

Enabling Modules for SiteAdmin CMS on each host

Because SiteAdmin CMS is made as hosting platform, it can handle individual configuration. Application instance configuration is defined fia cms.modules.config file.

This cms.modules.config file must be allocated in your web root.

To enable application you need to trigger @enabled attribute to 'true' in Application element where label is equal to folder name in SiteAdmin folder. Default modules policy is disabled, in other words no modules will be shown unless they are enabled.

<?xml version="1.0" encoding="utf-8" ?>
<Modules>
    <Application label="Pages" enabled="true" />
    <Application label="Events" enabled="true" />
</Modules>

About SiteAdmin CMS

SiteAdmin CMS is a powerful but simple, extremely easy to use, almost free, easy to deploy content management system.

SiteAdmin CMS offers a rich set of features despite its low price point. It is a leader in its price and feature class. Today's SiteAdmin is a new ultimate approach to the web site content management. Our. Net powered web application suite allows you to build and run enterprise-size web site within hours, without spending weeks and months on programming web site modules to handle required functionality.

One of the big advantages of SiteAdmin driven web sites is that you can deploy your web application to serve many browsing platforms at once. Sort of one size fits all. It perfectly serves all sorts of existed browsers, no mater if you accessing web site on your PC or mobile device.

With SiteAdmin you can reuse content in other places, not just the web, so that one content writer can cover multiple venues at once.

Features

  • Component based;
  • Has more than 30 components for different purposes;
  • There is no programing involved to run your site;*
  • Supports unlimited content pages;
  • Supports components and modules written by third-party developers;
  • Uses Microsoft SQL Server 2005 as database engine;
  • Uses SQL Server 2005 Xmldb capabilities to store content objects;
  • Runs on almost any hosting service that supports ASP.NET 2.0;
  • Most of content rendering functionality handled automatically by WDK.VFS - Virtual File System for SiteAdmin CMS.
Basic Requirements
  • Microsoft Windows 2000/XP/2003/Vista;
  • Microsoft .NET 2.0 Framework;
  • IIS or any other web server that can serve ASP.NET 2.0 web applications;
  • SQL Server 2005 Express or any other Edition;
  • Almost no programming skills, system is so easy to configure.

About...

…SiteAdmin CMS is a powerful but simple, extremely easy to use, low priced, easy to deploy content management system. SiteAdmin CMS offers a rich set of features despite its low price point. It is a leader in its price and feature class…