Archive for the 'DHTML' Category

23rd Jan 2009

Expanding All Tree Nodes

I am working on a project that requires the data provider for a tree component to be reloaded periodically. When I would reload the data, the tree would revert to it’s collapsed state. From a usability point of view, this was not the best of situations. So I started doing some research how to expand all of the nodes in a tree. I came across of a couple of places using loops such as:

private function expandTree():void{
for (var i:int = 0; i < thisTree.dataProvider.length; i ++){
thisTree.expandChildrenOf(thisTree.dataProvider[i], true)
}
}
private function collapseTree():void{
for (var i:int = 0; i < thisTree.dataProvider.length; i ++){
thisTree.expandChildrenOf(thisTree.dataProvider[i], false)
}
}

When looking at this, I noticed the name of the function is expandChildrenOf, which to me inferred it would expand all of the children of the given node. So I looked into a bit further and the description for this function in the documentation states (http://livedocs.adobe.com/flex/2/langref/mx/controls/Tree.html#expandChildrenOf()):

expandChildrenOf () method
public function expandChildrenOf(item:Object, open:Boolean):void

Opens or closes all the tree items below the specified item.
Parameters
item:Object — the starting item

open:Boolean — toggles an open or close operation

So if that is the case and I pass this function the root node of the dataProvider such as in the following:

this.myTree.expandChildrenOf(this.myTree.dataProvider[0],true);

It did as expected and expanded all of the nodes under the root node. No loop required.

Posted by Posted by Jeremy Wischusen under Filed under ActionScript 3, DHTML, Flex, PHP Comments 1 Comment »

24th May 2008

Using JavaScript Regular Expressions for Ajax Navigation

When I originally designed my site, I decided that I would make the navigation systems Ajax (partially because I wanted to expand my skills, partially to decrease load times, and partially because I thought I was being clever). So I got the basic nav systems working and I was all happy with myself right up until the first time I tried to provide direct link to one of my samples. As usual, I am not as clever as I first thought.

A direct link to the samples (or any other page for that matter) would load the page outside of the context of the nav system and site layout, which defeated the point of the nav systems and looked like crap (not that it is visually stunning within context, but even more so than normal).

I decided this was no good and started formulating ideas of how I could make particular locations within my site directly accessible without having to scrap my existing navigation system.

Upon reflection realized that one of the things jQuery makes pretty easy is triggering events on objects, such as clicks. So if I could identify the main and sub section I want to go to, I could trigger the click events for the appropriate links and end up where I wanted to be.

Now I just need to figure out how to pass that information. Fortunately, the other day there was a discussion on Flashkit about a URL system called SWFAddress. Basically, this system uses the named anchor system with the # sign so that you can change the last part of the URl string with out the browser actually taking you to another location. This leaves you with a parseable URL.

So now I had a way to get to my desired location (trigger click event), and a method of passing the data (the # url trick) I needed to be able to distinguish which path of the url referred to the main section and which referred to the sub. I decided to go with the following syntax:

http://www.visualflowdesigns.com/#main:main_page.html#sub:sub_page.html

All that was left is to parse the URL and trigger the click events for the links:

Main Section:

var mainSection = window.location.href.match(/#main:\w+\.html?/)
if(mainSection){
//perform string replacements to convert the id to jQuery syntax and to escape special jQuery caharcters
var goto = mainSection.toString().replace(/main:/,'').replace(/\./,'\\.');
$(goto).click()
}

Sub Section:

var sample = window.location.href.match(/#sub:\w+\.html?/)
if(sample){
//perform string replacements to convert the id to jQuery syntax and to escape special jQuery characters
var goto = sample.toString().replace(/sub:/,'').replace(/\./,'\\.');
$(goto).click()
}

The nice part about this is that since I am triggering the click events, my menus update themselves just as if the user had clicked on them.

The current system solves my immediate problem of not being able to provide direct links to my samples, but even as I wrote this I noticed that I am locking myself into HTML pages with my regular expression. However, now that I have the basic system working, I can play with and tweak it as needed.

As always Ideas and comments welcome.

Posted by Posted by Jeremy Wischusen under Filed under DHTML, jQuery Comments No Comments »

13th May 2008

Retaining a Dom Object Across Ajax Calls (In Order No Less)

I have been working on a project that displays a list of items that a user can take one of several actions on. Taking an action would change the display state and give the user a message that their action had been successfully completed, or that something went wrong. The user could then close the item and in doing so, update the list of items via an Ajax call.

This worked well enough, however, one of the project managers decided that they did not like the fact that the user had to take an action to update the list by closing one of the items they had acted upon, nor the fact that if they took actions on multiple items, they would have multiple feedback message displayed until they closed one of them triggering the update. So I ended up with the following requests:

  • Taking an action on another item in the list should close any other items that have previously had an action take on it.
  • If the user has less than 10 items in their cue, perform an Ajax call to see if they have any new items that have arrived each time they take an action.
  • The last message they received for the last item they took action on should remain across the Ajax calls.
  • If the item they took action on was in the middle of the list, then it should be in the same spot in the new list.

Now the response I was getting from the Ajax call was being sent into the div that contained the list of items. In other words, the entire list was being replaced. So now I had to figure out how to determine the last item an action was taken on, save it and insert it back into the same location in a new list of items that was replacing the old list.

jQuery to the rescue.

In order to display on the last item an action was taken on, I used a two step process. I used a class to identify items that had actions taken on them called actionTaken. So when an action is taken on an item, I remove all elements with that class and then assign that class to the item the action was just taken on. Since I hide all of the items before assigning the class to the last item I took action on, it essentially hides all of them except for the one I just took action on. This basically looks like:

$('.actionTaken').remove()
$('#listItem'+id).addClass('actionTaken'); .

Id in this case is a unique identifier generated in PHP and assigned to the div. So that takes care of only showing the last item a user took action on. This also works in the first case where there is no previous item since the call to remove simply does not find any element and does nothing.

Now I need to figure out how to keep that last item across Ajax calls. Since I now knew that only the last item they had taken action on would be displayed, and that item would have a particular class assigned to it, I could not retrieve that DOM node as follows:

var lastItem = $('.actionTaken').parent().html();

Next I need to determine where this item is located in the list. I do this by retrieving the ID of the item that follows the item of interest in the list.

var insertBefore = $('.actionTaken').parents('tr').next().attr('id');

Now that I have the last item and I know the item that follows it, I take the data I got back from the Ajax call and add it to the DOM.

$('#itemListDiv').html(str);

Finding the item that follows the items we are trying to retain works in most cases except one: if the item in question happens to have been at the end of the list. So I needed to determine if we had found an item following the item being retained. If we did, I insert it back into the DOM structure at the appropriate location (before the item it appeared before in the previous list), otherwise, I just throw it back onto the end of the list.

if (insertBefore ){
$('#itemTable #' +insertBefore ).before('<tr><td>' +lastItem + '</td></tr>');
}else{
$('#itemTable').append('<tr><td>' +lastItem + '</td></tr>');
}
}

There is more code to this system, but as far as the problems I initially outlined, that’s the relevant code. I now had a system that would only display the last item the user took action on and that item would be retained across Ajax callas and appear in the list at the same location.

Posted by Posted by Jeremy Wischusen under Filed under CSS, DHTML, jQuery Comments No Comments »

06th May 2008

Setting a Character Limit for TextArea with jQuery

So today I was asked to impose a character limit on a messaging system I have been working on. The message in question is input into a textarea in a form. So I vaguely remember something about a max character property and proceed to do a google search for character limit textarea. Well as it turns out, the character limit I was thinking of only applies to inputs of type text. What I found in my search results were various permutation of using JavaScript to impose a limit. Since I am now a big fan of jQuery, I decided to implement it using that.

Here is what I ended up doing.

  1. Assign a common class to the message text areas. Using a class as opposed to an ID allows us to apply this to multiple text areas on the same page, should the need arise.
  2. In the script file for the page bind a function to check the length of the text in the text area as follows:
    $(document).ready(initPage);
    function initPage(){
    $('.myTextAreaClass').keypress(limitMessageLength)
    }
  3. Create a function to limit the number of characters:
    function limitMessageLength(){
    var text = $(this).val();
    if (text.length > 100) {
    $(this).val(text.substr(0, 100));
    }
    }

Now any page that includes this script file and has forms with text areas with that class, will trigger the limiting function.

I have noticed some weirdness where when you reach the character limit, the last character changes to the last character you typed, but over all, seems to get the job done.

Posted by Posted by Jeremy Wischusen under Filed under DHTML Comments No Comments »

20th Apr 2008

CSS Based Percentage Bar

For one of my projects I had to create a visual representation of two percentages being compared side by side. I decided to do this using divs and CSS. With this design, all I have to do is set a value in my PHP for the width of the div highlighted in bold below and the sizing takes care of itself.

Here is what I came up with:

HTML:

<div class=”scoreBars”>
<div class=”scoreDivider”></div>

<div style=”width: 42%; height: 22px;background-color: #99CC00; position:absolute; top:0px; left:0px”></div>

<div style=” width:100%;height: 22px; position: absolute; z-index: 2; top: 0px; left: 0px;”>
<div style=”float: left; margin-top: 3px; color: rgb(255, 255, 255); font-weight: bold;”> 42% </div>
<div style=”float: right; margin-top: 3px; color: rgb(255, 255, 255); font-weight: bold;”> 58% </div>
</div>
</div>

CSS:

.scoreBars{
position:relative;

width:100%;
border:1px solid #999999;
height:22px;

/*This sets the color representing the right had side of the bars. The left hand value set in the HTML about simply covers this background color, so all I have to do is set the width for the div covering this color.*/
background-color:#3366CC;
}

/*The divider is simply a div with a right border that divides over all length of the bars into halves giving us an indication where 50% is.*/
.scoreDivider{
position:absolute;
width:50%;
border:dashed #FFFFFF;
border-width:0px 1px 0px 0px;
height:22px;
top:0px;
left:0px;
}

Result:

CSS Percent Bars

Posted by Posted by Jeremy Wischusen under Filed under CSS, DHTML Comments 2 Comments »

15th Apr 2008

CSS jQuery Tree Menu

The other day I decided it was time to redesign (or rather clean up) my portfolio site. In its old incarnation, I used a tree menu component that I had found online for my samples page. Since I was in the redesigning mood, I thought I would try building my own tree menu from scratch.

I had been using jQuery for some time at work and decided I would use that in combination with CSS and the good old unordered list.

The tree menu loads files identified in the id attribute into a content div via ajax. It allows nesting of sub menus, toggling and closes all other menus on the same nesting level so that only one menu is open a time.

Here is the code:

The CSS File:

/* CSS Document */
#sideMenu h3{
margin-top:2px;
}

/*Position the menu absolutely so that it can appear above other content and does not impact the alignment of the content div. Optional*/
#sideMenu{
position:absolute;
top:0px;
left:0px;
font-weight:bold;
padding-left:5px;
}

/*Since we are not using actual links, mimic link behavior using the cursor style*/
#sideMenu li{
cursor:pointer;
list-style-image:url(../images/petal_li.png)
}

/*Make any node that actually displays content (has an id attribute) a different color*/
#sideMenu ul li[id]{
color:#00FF00;
}

/*General list styling, do with as you like*/

#sideMenu ul{
list-style-position:outside;
margin:15px;
padding:5px;
}

/*Set nested ULs (i.e. submenus) to display none so that they are closed on page load. To display the menu in an expanded state on page load, remove the display property*/

#sideMenu ul ul {
display:none;
margin:5px;
padding:2px 10px;
}

/*This is the div that content is loaded into. Style as you like*/

#sampleDisplay{
padding-top:5px;
width:100%;
}

The JavaScript File:

// JavaScript Document

/*Top level menus are identified by nesting the title in a DIV tag rather than assigning the event to the LI itself. This is because when the event was tied to the LI, clicking on any of the sub menus contained in the LI would trigger the event for the LI meaning that all you got was a menu that opened and closed rather than being able to trigger the loading function in the LIs children. */

$(“#sideMenu li div”).click(categoryClick)

/* Only elements that define a page path for content need to trigger the load function. Hence use the CSS attribute selector to find nodes that define an ID attribute and bind the load function to them. This has implications in that you cannot assign IDs to elements in the menu that you do not want to trigger the load event, but this could be easily modified if need be and I have found this implementation to be quite flexible in terms of styling and functionality*/

$(“#sideMenu li[id]”).click(loadSample)

/*When a top level category is clicked, show sub menus and hide all other menus on the same nesting level. /*
function categoryClick(){
$(this).siblings().toggle();
$(this).parent().siblings().children(‘ul’).hide();
}
/*Load a page into the specfied element (in this case a div with the ID sampleDisplay) as identified by the id attribute of the element that triggered the function*/

function loadSample(){
// alert(“Loading sample ” + this.id);
$(“#sampleDisplay”).load(this.id)
}

The HTML File:

<link href=”css/samples.css” rel=”stylesheet” type=”text/css” />
<div id=”sideMenu”>
<h3>Projects</h3>
<ul>
<li><div>Flash 8</div>
<ul>
<li><div>Media</div>
<ul>
<li id=”haverick_player.html”>Tabbed Video Player</li>
</ul>
</li>
<li><div>Components</div>
<ul>
<li id=”rte.html”>Rich Text Editor</li>
</ul>
</li>
<li><div>Widgets</div>
<ul>
<li id=”wwyd_widget.htm”>Advice Widget</li>
<li id=”burn_widget.htm”>Drawing Widget</li>
</ul>
</li>
</ul>
</li>
<li><div>Flash 9</div>
<ul>
<li id=”ad_rotator.html”>Ad Rotator</li>
</ul>
</li>
<li><div>Flex</div>
<ul>
<li id=”flex_video_player.htm”>Video Player</li>
<li id=”flickr.html”>Flickr Search</li>
</ul>
</li>
</ul>
</div>
<div id=”sampleDisplay”><div align=”center” style=”height:20px; margin:10%”>You can view samples of my work by clicking on the menus to the left. </div></div>
<script type=”text/javascript” src=”scripts/samples.js”></script>

And that’s pretty much it. I just put up the site redesign today so far this menu has been doing everything I expect of it. You can check out out on my portfolio site (see Blog Roll) under the samples section.

Posted by Posted by Jeremy Wischusen under Filed under DHTML Comments 1 Comment »