Kendo UI: Creating an Dynamic Input Form from an External JSON ViewModel

One of my favorite features of Kendo UI is its support for MVVM through the kendo.observable object. Creating an observable ViewModel allows you to declaratively and intuitively bind data using the “data-bind” attribute, with virtually no code.

Using this method, you can even generate a form on the fly, specifying not only different field types, but even different attributes such as “required” and setting a CSS class to highlight specific fields. This is what we’ll look at today.

Read more at the Falafel Software Blog: Kendo UI: Creating an Dynamic Input Form from an External JSON ViewModel

Custom Javascript Banner Rotator – Part 2: jQuery!

As I suggested in part 1 of this series, I recently discovered the wonderful world of jQuery, the “write less, do more javascript library”. And sure enough, this is one tool that really lives up to its name! Not only can you do all sorts of neat (even useful!) javascript effects and events, but they are suprisingly easy to do! I had put learning this on the backburner a while back, but after publishing my Banner Rotator, I figured it was about time to bring that sucker front and center and start cooking!

The banner rotator script I posted yesterday presented the perfect opportunity to jump in. Using this incredible framework, not only was I able to wrap the functionality into a plugin, but I was able to improve and refactor it to make it reusable (which is a good thing because I’m going to be using it on the city’s Convention Center website). It turned out to be so easy, I don’t even have to waste time with a back story. Let’s go straight to the code!

First thing you want to do when making a jQuery plugin is create the function and assign it to jQuery. I’ve also included the (improved!) local variables from last time to keep track of where we are in the rotation.

.

var imgSrcs = [];
var curSrc = 0;

var imgElems;
var curElem = 0;

var fadeSpeed;
var imageTimeout;

function img(src, alt){
this.src = src;
this.alt = alt;
}

jQuery.fn.bannerswapper = function()
{};

Notice that I’ve created a class img to hold the image data, including source and alternate text attributes.

Now we want to provide a way for users to supply arguments for imageTimeout and fadeSpeed. In addition, this time, we’re going to be reading from an XML file which contains the list of images (along with their alt tags!) to build our list. Handling paramters is pretty straightforward:

jQuery.fn.bannerswapper = function(xmlFile, settings)
{
var banner = this;
settings = jQuery.extend({
fade: 6000,
timeout: 10000
}, settings);
}
fadeSpeed = settings.fade;
imageTimeout = settings.timeout;

the jQuery.extend allows us to declare the settings variables, including default values. In this case, fade is set to 6000ms, and timeout (time between frames) is 10000. If users supply parameters (as we’ll see later) then these default values will be replaced. Also note that because xmlFile is explicitly defined in the function signature, it is now a REQUIRED variable.

Next, we want to read the xml file, and create our array of elements. I cannot emphasize in words just how easy this is to do with jQuery, so I’ll let the code speak for itself:

// load image sources
$.get(xmlFile, function(xml)
{
var i = 0;
$(xml).find('image').each(function()
{
imgSrcs[i++] = new img($(this).attr('src'), $(this).attr('alt'));
});

// make sure there are at least 2 elements
if (imgSrcs.length < 2) return;

// only create element if it's not already there
if (banner.length == 1) banner.append(document.createElement('img'));

// get array of image elements to swap
imgElems = $('img', banner);

// start toggling!
toggle();
});

That is literally ALL there is to it! I create a new instance of the img class for each element in the xml file and append it to the array. Once the array is complete, we just call toggle and we’re on our way!

One thing I did discover was that my previous example did not handle situations where there are an ODD number of images. So below is an improved method which toggles the image back and forth, taking this into account:

function toggle()
{
// move to next image
if (++curSrc >= imgSrcs.length) curSrc = 0;

// grab ref to elements for updating
var frontImg = imgElems[curElem];
if (++curElem > 1) curElem = 0;
var backImg = imgElems[curElem];

// set current image to hide next
frontImg.className = "";
frontImg.removeAttribute('style');

// prepare to swap image
backImg.className = "show";
backImg.src = imgSrcs[curSrc].src;
backImg.alt = imgSrcs[curSrc].alt;

// fade in next image and repeat
setTimeout(function() { $('.show').fadeIn(fadeSpeed, toggle); }, imageTimeout);
}

Can you believe it’s really that easy? Now all we have to do is call our plugin, here is the syntax.

<asp:ScriptManagerProxy ID="ScriptManager" runat="server">
<
Scripts>
<
asp:ScriptReference Path="/files/scripts/jquery/jquery-1.2.6.pack.js" />
<
asp:ScriptReference Path="/files/scripts/jquery/bannerswapper/jquery.BannerSwapper.js" />
</
Scripts>
</
asp:ScriptManagerProxy>
<script type="text/javascript">
$().ready(function()
{
$('#banner_container').bannerswapper('/files/scripts/jquery/images.xml');
});
</script>
<
div id="banner_container">
<
img src="/images/banners/banner10.jpg" alt="" />
</
div>

Also note that I’ve moved all of the stylings to an external sheet so that needs to be included in your page header as well.

I’ve packed all the files I used (excluding the images) into a zip which I’ve uploaded to myBloop. If you’d like to take a look at the full source, please use the link below. Your comments are appreciated!

Download Banner Swapper jQuery Plugin

Custom Javascript Banner Rotator – Part 1

These days, a feature that city websites should never be without is the banner rotator, that is, an image up at the top of the site that cycles through various featured photos. The City of McAllen naturally was no exception, as you can see for yourself. The problem was that, being relatively inexperienced in Javascript, I’ve never made my own ‘slideshow’ type application before. Usually I will either download an existing script (or [[shudder]] a FLASH object…) and modify it to fit my needs.

In my search to find the perfect rotator, I went through dozens, including the Teleirk Rad Rotator, obout Show, both of which, for the most part, worked pretty well and weren’t TOO difficult to customize…

Unfortunately, I didn’t like the approach that these (and as I discovered, most) controls used. Basically what happens is they load up a full array of images, create separate elements for each one, then toggle the visibility of each one in a cycle. This is pretty much the same problem I had that led me to build my Ajax News Rotator. Even worse, if javascript is disabled, the Rad Rotator renders an empty element! Other controls would experience erratic behavior as well, either rendering blank, or worse, showing ALL the elements in a mishmash of images. This problem was compounded by the fact that some of these controls (such as Rad Rotator) load all of the elements at once, meaning load time is stalled while all the content and images are loaded into their own separate frame!

And that’s when it dawned on me. All of these frames are exactly the same, so why do we need one for every single element? Ideally, we would only need the ONE frame, instead replacing it over and over with the content, loaded on demand with javascript. While this is certainly possible, having only one frame prevents us from doing transition effects, such as fade or slide, or anything that requires two elements to be blended together.

so my solution was to narrow it down to TWO frames, one for the start element, which is added statically on the page, and a second to “swap” the image, loaded dynamically at run time. Doing things this way allows the page to render correctly if Javascript is disabled, because it will just show the first frame. All I have to do now is swap the image back and forth across the two elements!

Neat huh? Alright, enough background, on to the code!

I’d like to start first by giving credit here to Rob Watson, because I used his excellent Fading Image Slide Show tutorial as a basis for my solution. His entry is pretty thorough, so I’m only going to touch on my changes.

The first thing to do was to remove the for-loop that appended every element, instead only adding a second img element to “swap” to. See instead of using the array to CREATE the img elements, I’m instead using the array to REPLACE the two elements with the SRC from the current item in the array!

// create new img element for rotationvar t = document.createElement('img');
t.setAttribute('src', images[nextImage]);
t.setAttribute('width', imageWidth);
t.setAttribute('height', imageHeight);
t.style.position = 'absolute';
t.style.visibility = 'hidden';
el.appendChild(t);

Next we want to grab a reference to these two elements so we can load them on demand and start the cycle.

// grab references to the two img elementsimgs = el.getElementsByTagName('img');

// begin rotationwindow.setTimeout(startFading, imageTimeout);

both startFading and setOpacity work pretty much the same as Rob’s:

function startFading()
{
    // grab the next element and fade it in var el = imgs[curImg];
    el.style.visibility = 'visible';
    el.style.zIndex = 2;
    setOpacity(el, 0);
    fadeImage(el, 0);

    // swap to the next img element curImg = (curImg == 1) ? 0 : 1;
}

function setOpacity(el, opacity)
{
    opacity /= 100;
    el.style.opacity = opacity;
    el.style.MozOpacity = opacity;
    el.style.filter = "alpha(opacity=" + (opacity * 100) + ")";
}

The biggest change comes in the fadeImage method. Basically the idea is to populate the NEXT image with the src from the images array and set it as hidden. Once that’s complete, all we have to do is fade it in:

function fadeImage(el, currentOpacity)
{
    // increase opacity currentOpacity += 2;

    // if full opaque if (currentOpacity > 100)
    {
        // reset in case over setOpacity(el, 100);

        // move to next image in array if (++nextImage > 4) nextImage = 0;

        // reset swapped img element to next image var prevEl = imgs[curImg];
        prevEl.setAttribute('src', images[nextImage]);
        prevEl.style.visibility = 'hidden';
        el.style.zIndex = 1;

        // continue rotation window.setTimeout(startFading, imageTimeout);
    }
    else {
        // fade in setOpacity(el, currentOpacity);
        window.setTimeout(function() { fadeImage(el, currentOpacity); }, 50);
    }

}

All that’s left to do now is call the function! Remember that we pre-populate the container div with the first image, that way if Javascript is disabled, users will still see the first (and only) image.

<asp:ScriptManagerProxy ID="ScriptManager" runat="server"> <Scripts> <asp:ScriptReference Path="/files/scripts/BannerSwapper.js" /> </Scripts></asp:ScriptManagerProxy><div id="fading_image_container"> <img src="/images/banners/banner10.jpg" alt="" style="width: 930px; height: 230px;
            position: absolute" /></div> <script type="text/javascript"> Init();
</script>

As you can see, I used a scriptmanagerproxy control to register my external js file, then call the Init function to get things started. Unfortunately this Init gets called on every page load, including partial postbacks (ajax) so if you’re using these, make sure to add a check in the javascript file to make sure that the second img element hasn’t already been added:

// make sure we're in the init phasvar el = document.getElementById('fading_image_container');
var count = el.getElementsByTagName('img').length;
if (count > 1) return;

And that’s all there is to it! You can see this in action at McAllen.net. The banner up at the top uses this script! But it won’t be up for long because it’s soon to get replaced with Part 2, where I wrap this script in a jQuery plugin! stay tuned!