Development

Beautiful, accessible Forms

So, I have done a bit of research on forms. Trying to make them as happy as possible for design, accessibility and usability. It seems that, as important as forms are to the web, there would be some agreement or idea and the best way to accomplish this. There may be, but I didn’t find it, so I created one. This is an HTML and CSS contract to make the forms happy.

So, here is the basic HTML example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div class="form">
    <fieldset>
      <legend>Main Title</legend>
      <ol class="formlist">
        <li>
          <label>Label:</label>
          <div>
            <asp:textbox runat="server" id="txtExample" ></asp:textbox>
          </div>
          <hr />
        </li>
        <li class="submitcontainer">
          <asp:button runat="server" id="btnExample" onClick="btnExample_OnClick" text="Submit" />
        </li>
      </ol>
    </fieldset>
  </div>

These examples are using C# so the div tag is a div class=”form” instead of just a form tag. This is because C# / asp.net uses a huge form tag the covers the whole page. I am not commenting on that at the moment maybe later.

and here is how it would render as plain HTML

There are several simple advantages to this form layout. First is the accessibility features. This taps into the screen readers default handling of fieldsets and ols to make navigation easier for them. It also has all the markup necessary, with out extras, to style up the form pretty much how ever you want it. Using the div to separate the label with the control is that you have room to do what ever you need to for the control including placing lots of controls and even embedded forms without any extra work.

There is also a way to add errors and info to the form very easily.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<div class="form">
    <fieldset>
      <legend>Main Title</legend>
      <ol class="formlist">
        <asp:panel runat="server" id="pnlExample">
          <li>
            <label class="none"></label>
            <asp:panel runat="server" id="pnlErrorsExample" CssClass="errors"> <!-- the spans or asp:labels may be added dynamically by using this panel -->
              <span class="error">This is a global error message that may be displayed on error that would say, hey this form has these errors: </span>
              <span class="error">You need to type something in the TextBox</span>
              <span class="error">You need to click the submit button</span>
            </asp:panel>
          </li>
        </asp:panel>
        <li>
          <label>Label:
            <asp:RequiredFieldValidator ID="rfvExample" runat="server" ErrorMessage="This is required" Display="Dynamic" ControlToValidate="txtExample" CssClass="error">
            </asp:RequiredFieldValidator>
          </label>
          <div>
            <div class="information">
              <span class="info">This describes the example here.</span>
            </div>
            <asp:textbox runat="server" id="txtExample" ></asp:textbox>
          </div>
          <hr />
        </li>
        <li class="submitcontainer">
          <asp:button runat="server" id="btnExample" onClick="btnExample_OnClick" text="Submit" />
        </li>
      </ol>
    </fieldset>
  </div>

Again, these examples are for use with asp.net controls, but you can easily use this for any language by replacing the

and here is how this would look with no CSS:

what is good about the way that these are built is that it is very accessibility friendly. The global error message is at the front of the form, so screen readers will get to that first. Next the errors are included in the labels of the controls, so as the screen reader introduces what the control is it will also read what errors are related to the controls so the user can know what needs to be fixed without navigating around to find it.

Now lets style these up. I am going to use the theme that I have built for the administration section of NAU Extended campuses but the styles are very customizable and interchangeable.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
.form fieldset {
  margin: 0 0 1em 0;
  border: 1px solid #DDF;
  }
 
.form fieldset legend {
  margin: 0 0 .5em 0;
  padding: 2px .5em 0 .5em;
  color: #036;
  background: transparent;
  font-size: 21px; 
  font-family: "Times New Roman", Times, serif;
  }

.form  ol.formlist {
  padding: 0;
  margin: 0;
  font-size: 12px;
  font-family: "Times New Roman", Times, serif;
  }
 
.form .col {
  float:left;
  width: 49%;
  min-width: 350px;
  border-right: 1px solid #ccc;
  padding-right: 15px;
  }
 
.form .col:last-child {
  border-right: none;
  padding-right: 0;
  }

.form li {
  list-style: none;
  padding: 0;  
  margin: 4px 2px 0 10px;
  clear: both;
  padding-top: 2px;
  }
 
.form li > label {
  display: block;
  width: 120px;
  float: left;
  clear: left;
  margin: 0 15px 0 0;
  text-align: right; 
  }
 
.form li > label.none {
  width: 0;
  margin: 0;
  }
 
.form li hr.none {
  border: none;
  border-bottom: 1px solid transparent;
  background: transparent;
  }
 
.form li > label span {
  display: block;
  }
 
.form li > label span[style*="inline"] {
  display: block !important; 
  }
 
.form li > div {
  margin: 0 0 0 140px;
  padding: 0;
  }

.form li > label.none + div {
  margin: 0;
  }
   
.form hr {
  margin-top: 2px;
  clear: both;
  border: none;
  border-top: 1px solid #CEE6F7;
  }

.form ol > li:last-child > hr {
  border: none;
  border-bottom: 1px solid transparent;
  }

.form .formlist textarea, .form input, .form select {  
  margin: 0 0 5px 0;   
  }

.form input[type="textbox"], .form select, .form textbox {
  min-width: 100px;
  }

.form .block {
  display: block;    
  }

.form .errors {
  border: 1px solid #903;
  background: #F5D8D9;
  padding: 5px;
  margin-bottom: 5px;
  }

.form .error {
  font-size: 11px;
  color: #903 !important;
  text-align: right;
  margin:  0 0 5px 0;
  display: block;
  }
 
.form .errors .error {
  text-align: left;
  }

.form .information {
  border: 1px solid #090;
  background: #ECFFD9;
  padding: 5px;
  margin-bottom: 5px;
  }
 
.form .info {
  font-size: 11px;
  color: #030;
  text-align: right;
  margin:  0 0 5px 0;
  display: block;
  }

.form .submitcontainer {
  margin: 25px 0 35px 164px;
  padding: 0;
  border: none;
  }

.form fieldset .submitcontainer {
  margin: 15px 0 35px 149px;
  }

I am not going to pull apart everything in the css file, but I do want to mention that it is built to include most possible scenarios including columns.
The CSS file is also built to the standard shown in the post Css Management Standard.

Here is the basic form and the error/info form with the styles in place. You can view source and use as you would like.

Like I said this design is what is used in the Admin section of NAU EC. This way of coding up the form is extreamly customizable which is one of the reasons why it is so good. So Code, Design, and Enjoy.

So, HTML5 anyone?

Ok so I am getting ready for an HTML5 CSS3 demostration on wednesday and so I made a few demonstrations and I wanted to share them here. Go ahead and view source. Have fun.

This is to be viewed in chrome or safari, Firefox 4 might work, it uses flexbox and won’t work in a lot of browsers yet. I am going to give an image of what it is suppost to look like and then the html example. I was going to use some javascript to have it display the correct time, but then I decided not to just so that I could say here is a 100% css3 html clock. So this is a pure 100% html css clock, there are no images involved, just divs, spans, and css3.

Now the HTML:

12
111
102
93
84
75
6

Some Back end

update: Dyanmic Linq library

So I realized that, even though I do a lot of back end work, I haven’t put any of it here. So I am going to. I don’t really know why I don’t put much in here. I guess maybe because I don’t think many people actually look at this site, maybe I am just poor at writing stuff down and taking the time to document. Regardless I think this may be a good place for me to reference stuff so I am going to put stuff here and if other people see it then fine.

Anyway I was thinking a little about linq in c#. Now I spent a little bit of time in Java and really like some of the hibernate stuff there. So here is something that was typical. I used the stripes framework and had a little bit (OK a lotta bit of) from my brother in law. He really knows his stuff. You could say he wrote part of the book on stripes. Anyway. In stripes there is a DAO object. A really great generics dao. the great part of this is that it is built from a string so

1
List<person> people = Dao.list("Select p from Person p where p.name = ?", stringName);

Really great stuff, making sql calls from the code with no sql, just objects. So when I went into linq I thought it would be similar but it isn’t.

There is some great stuff with linq but until I can figure out this problem it will be a little more cumbersome than I want it to be. So here is what is great about the hibernate stuff. Let’s look at that call again but add something else.

1
 Dao.list("Select p from Person p where p." + insertVarHere + " =?", stringName);

That is dynamic. I can look for any column with any variable because it is a string. I just need to find someway to submit the linq statement as a string and I would have it. For example in my last project I was in a position where I needed to filter a grid. There were a lot of filters going on at once so instead of having filters trump other filter I decided to put everything in one method call and use session to store all the filters. This solved everything but one little detail, the linq to do it with.

There are 8 columns and each has a set of filters, this was modled after the filter that excel does. So I can filter by the values in the cells as well as sort ascending and descending. The Grid that was used was very complex and so I built a simple gridview and added all the features myself with javascript. So again the problem. I am filtering all at once and I have 10 columns that can have filters. The linq looked like this. ‘columnName’ is the commandArgument and direction is the ‘commandName’ from the grid.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 switch (columnName)
            {
                case "CommentDate":
                    if (direction == "asc")
                    {
                        sortedNotes = from a in notesToSort
                                      orderby a.CommentDate ascending
                                      select a;
                    }
                    else
                    {
                        sortedNotes = from a in notesToSort
                                      orderby a.CommentDate descending
                                      select a;
                    }
                    break;

                case "AdvisorName":
                    if (direction == "asc")
                    {
                        sortedNotes = from a in notesToSort
                                      orderby a.AdvisorName ascending
                                      select a;
                    }
                    else
                    {
                        sortedNotes = from a in notesToSort
                                      orderby a.AdvisorName descending
                                      select a;
                    }
                    break;

Of course that isn’t the end of the statement, but enough to get the picture. It is a switch for each of the columns. This had to be done this way because I don’t have the ability to pass the column as a string. that would have helped like this:

1
2
3
sortedNotes = @"from a in notesToSort
                    orderby a."
+ columnName + " " + direction + @"
                    select a"
;

That would have reduced about 100 lines of code. I am still trying to figure out how I could do that, feed linq as a string. Later on the same project I used something that was a little better but still not a string.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if (filters != null)
            {
                if ((from advisor in filters["advisor"] select advisor).Count() > 0)
                    queryFiltered = queryFiltered.Where(s => (from advisor in filters["advisor"]
                                                              select advisor).Contains(s.AdvisorName));
                if ((from campus in filters["campus"] select campus).Count() > 0)
                    queryFiltered = queryFiltered.Where(s => (from campus in filters["campus"]
                                                              select campus).Contains(s.StudentCampusDescr));
                if ((from acad in filters["acad"] select acad).Count() > 0)
                    queryFiltered = queryFiltered.Where(s => (from acad in filters["acad"]
                                                              select acad).Contains(s.StudentPlanDescr));
                if ((from contact in filters["contact"] select contact).Count() > 0)
                    queryFiltered = queryFiltered.Where(s => (from contact in filters["contact"]
                                                              select contact).Contains(s.ContactMethod));
                if ((from commentType in filters["commentType"] select commentType).Count() > 0)
                    queryFiltered = queryFiltered.Where(s => (from commentType in filters["commentType"]
                                                              select commentType).Contains(s.CommentType));
                if ((from commentCat in filters["commentCat"] select commentCat).Count() > 0)
                    queryFiltered = queryFiltered.Where(s => (from commentCat in filters["commentCat"]
                                                              select commentCat).Contains(s.CommentCategoryDescr));
            }

This was a little better at doing dynamic linq, it allowed for logic inside of the linq statement and a much needed addition, but I really would like to see linq have a string feed. I think I am going to keep working on that, maybe I will have to create, somehow, one of those generic doa objects, who knows.

Css Management Standard

This is a really good system for managing system wide css. CSS_Management_standards

I have a few alternates to it in the form of putting page specific css. In the standard, for organization sake, I am including page level css in the head of the document. An alternate to this is to move it to an external page. Both have large benefits. The first deals with organization, with lots of files comes lots of management needs. The second allows for caching and more granular @imports.

Anyway. This has proved very well through my projects and thought I could offer some Ideas out there.

Electronic Advising Notebook

The Electronic Advising Notebook is a very fun project. I was able to start the project with an ai file and an old system. Through several stages I took this project to mach-up to basic prototype to full scale system. The comment grid system needed a lot more functionality then I could get out of any control so I needed to hand code the javascript/html/css to get the right results. The whole project is line after line of custom javascript/jQuery. I designed the user interface to fit in several different “wrappers” to fit in and stand out.

The backend is build in C# and we used a lot of linq with generics. Great combination. This has been a really fun project to work on. I may find some post dealing with the components created in the system such as custom, generic modal windows.

Get Adobe Flash player

CSS3 Parent Selector Idea.

Update: did a little more research and found this email archive that has this idea but a little different syntax using a :matches pseudo class.

(Just for the sake of those who are looking for information on parent selectors, they do not currently exist in css selectors. This is based on some thought on how the syntax might be for them.)

Well, First I thought I would put this here on my blog because I was pa-roozing around and had been thinking a bit about parent selectors in css. Thinking about how I would like a parent selector to work this is what I came up with, if you like it let me know, if you don’t let me know too.

When I am selecting an element in css I want to be as specific and necessary but not more so. Sometimes when I select something, like say, ul > li ul li a:hover span { … }, I want to change the li of the hovered a, but I can’t. I would only be able to specify the hover state of the li then override that later or use javascript. What I would like to be able to do is to do this, and I am going to provide a few different ways that it could be done:

ul > li ul this(li) a:hover span {…}
ul > li ul li a:hover span this(4) {…}(I don’t like this on anymore. It would be different to implement and not what I was going for.)
or it could be specified using a symbol
ul > li ul $li a:hover span {…}

This is not a discussion about what symbol or word should be used, it is mearly for the concept. So what happens is you type your full selector, then you specify which element you want the style to apply to.

The way that I see it working, in concept, is to select to the this() to get all the, in this case, ‘li’s then select again after to return a bool, if the li meets the rest of the condition. It doesn’t seem like that would take much more than running two selection rules. But I could be wrong and I can’t overemphasis how much I don’t know how this would work for the people who develop the browsers, ie what it takes to code it up and how many recourses it takes.

Chances are not many people will read this, but there is my two cents on the matter :) .

The most obscure bug I have ever seen

This is a webkit bug, and one of the weirdest I have ever come across. If someone has this problem they will really like this post if they find it.

here is the problem.

View the weird bug

so what is happening when all these several item come into place, probably kinda like a planetary alignment that happens like once in 500000 years, there is an unexplained horizontal scroll bar that appears for no apparent reason. I still don’t know the reason but I know the solution.

the item that need to come into place:

  1. a container for the ol that has an overflow auto, and of course a reason to scroll
  2. a label in the li that is floated left – not right
  3. an hr under the label that has a clear
  4. and the hr needs to have border: none;
  5. and finally an empty span by the hr

crazy huh! like I said it is very obscure.

The fix, really, remove any one of these 5 items. what I did to make sure that I always have one of the five removed was to put a border-bottom: 1px solid transparent; on the hr I wanted to look like it wasn’t there after the border: none;. And there you go a solution to a crazy weird bug.

Here is the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<style type="text/css">
        #studentinfo {
            height: 200px;            
            overflow: auto;
            }    
     
    .form li > label { 
      float: left; 
      }

    .form hr {
      clear: both;
      }
     
    .form li:first-child > hr {
      border: none;    
      }
   
    /* only for legebility - nothing to do with the bug */ 
    .form li > div {
      margin-left: 200px;
      }
    .form li {
      list-style: none;
      }
</style>

  <div id="pnlStudentInfo" class="form duo">
      <fieldset>
            <legend>legend</legend>
           
            <div id="studentinfo">
                <ol class="formlist">
                    <li>
                        <label>label for empty span:</label>
                        <div>
                            <span></span>                                              
                        </div>
                        <hr />
                    </li>
                    <li>
                        <label>label:</label>
                        <div>
                            <span>non empty span</span>
                        </div>
                        <hr />
                    </li>
                    <li>
                        <label>label:</label>
                        <div>
                            <span>non empty span</span>
                        </div>
                        <hr />
                    </li>
                    <li>
                        <label>label:</label>
                        <div>
                            <span>non empty span</span>
                        </div>
                        <hr />
                    </li>
                    <li>
                        <label>label:</label>
                        <div>
                            <span>non empty span</span>
                        </div>
                        <hr />
                    </li>
                    <li>
                        <label>label:</label>
                        <div>
                            <span>non empty span</span>
                        </div>
                        <hr />
                    </li>
                    <li>
                        <label>label:</label>
                        <div>
                            <span>non empty span</span>
                        </div>
                        <hr />
                    </li>
                    <li>
                        <label>label:</label>
                        <div>
                            <span>non empty span</span>
                        </div>
                        <hr />
                    </li>
                    <li>
                        <label>label:</label>
                        <div>
                            <span>non empty span</span>
                        </div>
                        <hr />
                    </li>                                                                  
                </ol>                        
            </div>
        </fieldset>            
    </div>

So I wanted to put some CSS stuff I learned here.

I just learned about this and wanted to put it up here.

the “box-sizing” property. A little background, this is basically a property to bring the style into or out of the box model. So say I have a div with stuff in it. I give that div some padding of 15px and a 1px border and make it nice and pretty, then decide to make two columns so I give it a width and float it, fine right. Well, IE likes to say, if you give me a width I am going to include that width in the border and padding. So a div that is 200px wide will be 200px wide. Every other browser does it like this, you give me a div and a width I will apply the width to the content section of the div and then put your padding and borders on it. So a div that is 200px wide with 15px padding and 1px border that gives me a total space that is 232px wide.

There have been people say that both are right and I am not going to get into that here except to say that I am with the second, non IE, way of doing thing, not because I can’t say IE is right but because I feel the second is the correct way to do it.

Anyway, This takes care of that problem by giving the control to the authors. box-sizing takes two values – border-box and content-box. Content-box is the standard for the CSS2.1 spec this is the second above where the width effects the content rather than the whole. Border-box is what IE does taking the width from the outer most element the border hence the name.

So the argument can stop and people can be happy once again! – for reference see - CSS3 spec

@font-face and google api

So, we all know the problems with fonts on the web. I just needed to enter the vast supply of font articles out there with this one. Because those old font problems aren’t valid anymore. And a few of the old tools like Cufon and Sifr don’t need to be used anymore.

the Google @font-face

So first I want to mention a little about the ‘new’ google API that allows the use of a selected number of fonts. I do want to mention here that the google API for the font selection is really pretty cool, if you look at the guts of it what they are doing is the @font-face but with some cool stuff behind the scene. They are using the @font-face declaration but the file it points to is a url that, I am assuming because I haven’t looked at that page yet (I did check it out and this is exactly what it does.) takes the browser that you are using and delivers the font type required for the browser.

here are a few places you can go.

Here is the embeded font

1
2
3
4
5
6
7
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Tangerine">
<style>
.font {
         font-family: 'Tangerine', serif;
         font-size: 48px;
         }
</style>

It really is that simple!! Really great tool.

the @font-face

So, this in my opinion is the greatest thing since string cheese. This is amazing … if it was all done, implemented, and had no strings attached. There are several problems here but aren’t too hard get over. So here are the “strings”

  1. Copyright

    this is the most important problem. When you put a .ttf file up on the web at a location that the css file can get to, you would be hard pressed to keep the file away from those who view your site. The makers of Garamond, Helvetica, Futura, and most others don’t really want to give away their fonts. So we would be limited to most free and open source fonts. But that is a huge variety, though you won’t have your favs there.

  2. Browser Support

    Previously this was the biggest issue, each browser had a different way to use fonts. But now it is only one extra line of css code. So this isn’t much of an issue anymore. There are still some problems like the iPad / iPhone / iPod touch and the Android phones. But all in all it is much better support. So here is that extra line of code I was talking about (and that includes a few extra steps.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@font-face {
    font-family: 'AlteHaasGrotesk';
    src: url('/fonts/altehaasgroteskregular-webfont.eot');
    src: local('?'), url('/fonts/altehaasgroteskregular-webfont.woff') format('woff'), url('/fonts/altehaasgroteskregular-webfont.ttf') format('truetype');
    font-weight: normal;
    font-style: normal;
    }

@font-face {
    font-family: 'AlteHaasGrotesk';
    src: url('/fonts/altehaasgroteskbold-webfont.eot');
    src: local('?'), url('/fonts/altehaasgroteskbold-webfont.woff') format('woff'), url('/fonts/altehaasgroteskbold-webfont.ttf') format('truetype');
    font-weight: bold;
    font-style: normal;
    }

/* to use it */

.cssFont {
    font-weight: normal;
    font-style: normal;
    line-height: normal;
    font-family: 'AlteHaasGrotesk', serif;
    font-size: 34px;
    }
.bold {
    font-weight: bold;
    }

.bold:hover {
    color: #369;
    }

The “Font-Face” Font
Another sample now in Bold

one of the best tools I have found is this: Font Squirrel
They have a great selection of open source commercial fonts and the tools to use for all browsers including .eot for IE and they convert it all for you. This makes it really easy to use the @font-face tool!!

Conclusion – there is no reason everyone shouldn’t be using this right now!

Visual Studio Validators

I just ran into a problem with the tag in Visual Studio I thought it would be worth mentioning here.

Then problem comes because VS assumed that anytime you have a requiredfeildvalidator you’ll want that inline. So the way that they hide / show that validation is by adding an inline style=”display:none;”. That part isn’t so bad, it is the next part. Instead of removing the display:none to restore the block of code, the replace display:none with style=”display:inline”. This is bad!

The inline style will always trump my style sheet unless there is am !important there. so here are a few resolution to the problem and why they are bad. and then the one that I used, why it is good, and why it is bad.

first,
<br /> after the validation. bad – this will have to be placed after every tag everywhere, and what if I want to change the validation back to inline later.

Second,
using Javascript, there are two ways to do this, one as a supplament, meaning to place javascript on the page to select what you really want to select, but that would have to be placed on every page or alternativly changing the rendering in Visual Studio. I don’t really want to open the guts of Visual studio so that is bad also.

Third,
You can create a custom control that will extend the Validation, but then you would have to use that tag instead of the one Microsoft gives you. In my case that would mean changing hundreds of tags through the web app I work on for NAU.

And Last,

Using CSS. This is not a perfect solution. but here is the CSS that worked in my case.

1
2
3
.form li > label span[style*="inline"] {
    display: block !important; 
    }

the [E*="foo"] selector is a new css3 attribute selector that will select the element with an attribute that matches the string “foo”. This is a really cool selector that works in IE8 > . Unfortunalty there are still quite a few people that use ie7. So this isn’t ideal but in my case it will work.

Jquery Side Slide

Here is a side slide jquery element I just created for Northern Arizona University. The code is pretty simple, and is pretty effective. Here is a sample page: Horizontal Slider example page. just view source to see how it works.

Actionscript Pan (Drag) and Throw

UPDATE : this has been accepted as a tutorial on Tuts plus!! Go here active.tutsplus.com

This actionscript class will allow you to toss any object in your flash movie! Here is the class PanAndThrow

There will be an updated post on this soon on how to use it. till then here is the new file. The old implementation is under a different blog post (http://www.coltpini.com/?p=149), that may be of some help for you until I get the new stuff up. I haven’t changed much just added some new features.

Flash Reverse Kinematics

So, I have been doing a project for NAU that could benefit from the new armature for Flash. So I have been trying it out. Here is the result of some frustrating moments in flash. (move the limbs of the girl below)

Get Adobe Flash player

What I have found about this tool is that there is a reason that all the tutorials are very simple objects. If you need some complexity it is really tough to get everything working right.

There are also some bugs that I have found with the bones tool. After converting an object to an armature you can use the transform tool to adjust and fine tune each object, but what they don’t tell you is that it will move, from slightly to dramatically, each object used in the armature.

So, to conclude, it is a great tool for simple object manipulation, don’t go and try to make an entire person with a spine and completely movable parts! (Go ahead I dare you to make a shoulder that pivots the arms and head with the spine.)

and please if anyone has suggestions, I would love to learn from you.

Pan and Throw

UPDATED AGAIN : this has been accepted as a tutorial on Tuts plus!! Go here active.tutsplus.com

Download the pan and throw class -panandthrow.zip UPDATED! Goto this blog entry. http://www.coltpini.com/?p=287

This is a small tutorial on how to make an object pan and throw in actionscript 3.0 using flex. I am going to assume that you know how to set up a project and some fundamental things about actionscript. The greatest thing that happened with actionscript 3 is that now, with the improvements, it is a lot more object oriented. That means, basically, I can create snippets of code to use again and again and package them into namespaces and classes to use again and again. What I am going to show here is a class that I created to make any object throwable.

Get Adobe Flash player

First we are going to create an mxml and throw in some objects. I am just going to throw some up here as this isn’t the main part of the tutorial.

1
2
3
<mx:Canvas id="outside" height="100%" width="100%" backgroundColor="#002F2F" verticalScrollPolicy="off" horizontalScrollPolicy="off" > 
  <mx:Box id="inside" height="100" width="100" backgroundColor="#046380" cornerRadius="50" borderStyle="solid" borderThickness="0" ></mx:Box>
</mx:Canvas>

this is pretty straight forward, create a event box, and a child box and make the size different and we will talk about the differences a little later.

To panAndThrow the object is even simpler.

1
2
var pt:PanAndThrow = new PanAndThrow();
pt.init(inside,outside,.9,true,true,true);

Don’t forget to import your classes.

Now we are going to look at the code that makes this all happen, this is the real meat behind this tutorial.

So lets build panAndThrow.as, the PanAndThrow Class.

I am putting this in the package called “classes” how original. lets start with at the beginning, the init.

1
public function init(ObjectToMove:UIComponent, ObjectToEventise:UIComponent, DecayAmount:Number, isMoveY:Boolean = true, isMoveX:Boolean = true, OnlyMoveOnTargetClick:Boolean = true ):void

that is a lot of overloads, but that is why this is so easy. If, when we are done you want to play and tinker, you are welcome to. (If you come up with something great, let me know about it!)

Okay so let’s look at the overloads (we’ll talk about the why’s when we discuss the code).

objectToMove – this is the object that you want to interact with the mouse.

objectToEventise – This is the event object, but I didn’t call it event because it doesn’t have to be, but most of the time it will be. this is just the object that will be receiving the events. The first variable is a little deceptive, because we don’t directly interact with it, but we interact with this one. The first one just looks like that is what we are interacting with.

DecayAmount – this is where we set up our friction. 1 is no friction and 0 is total friction.

isMoveX – this asks if you want the moving object to move in the x direction.

isMoveY – this asks if you want the moving object to move in the y direction.

OnlyMoveOnTargetClick – this asks if you want the object to move anytime the mouse is down, or just while the mouse was clicked over the object to move.

so now the init function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  private var MouseDragged:Boolean = new Boolean();
  private var MouseDraggedOut:Boolean = new Boolean();
  private var MousePrevX:Number = 0;
  private var MousePrevY:Number = 0;
  private var arMousePrevX:Number = 0;
  private var arMousePrevY:Number = 0;
  private var MouseCurrX:Number = 0;
  private var MouseCurrY:Number = 0;
  private var originalDecay:Number = .9;
  private var Decay:Number = originalDecay;
  private var buttonDown:Boolean = false;
  private var moveY:Boolean = true;
  private var moveX:Boolean = true;
  private var overTarget:Boolean = false;
  private var xOppositeEdge:Boolean = false;
  private var yOppositeEdge:Boolean = false;
  private var TargetClick:Boolean = true;      
       
  private var t:Timer;
  private var timerInterval:int = 100;       
       
  private var targetObject:UIComponent = new UIComponent();
  private var eventObject:UIComponent = new UIComponent();

public function init(ObjectToMove:UIComponent, ObjectToEventise:UIComponent, DecayAmount:Number, isMoveY:Boolean = true, isMoveX:Boolean = true, OnlyMoveOnTargetClick:Boolean = true ):void
{
  targetObject = ObjectToMove;
  eventObject = ObjectToEventise;
  originalDecay = DecayAmount;
                 
  moveX = isMoveX;
  moveY = isMoveY;
  TargetClick = OnlyMoveOnTargetClick;         
                 
  t = new Timer(timerInterval);
  start();       
}  
   
public function start():void
{
  targetObject.addEventListener(MouseEvent.MOUSE_DOWN, handleOverTarget);
  eventObject.addEventListener(MouseEvent.MOUSE_MOVE, moveIt);
  eventObject.addEventListener(MouseEvent.MOUSE_UP, throwIt);
  eventObject.addEventListener(MouseEvent.MOUSE_OVER, upper);
  eventObject.addEventListener(MouseEvent.MOUSE_DOWN, downer);
  t.addEventListener(TimerEvent.TIMER, timerOut);
  t.start();
}

with the init function you need to know a couple of other things so I included them here. So the first part is just setting the overloaded values to the global vars. The only other thing done here is assigning event listeners to our eventObject. We have the MouseEvent of all varieties and a timer.

So, enough set up lets get to the meat of it now.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private function moveIt(e:MouseEvent):void
{        
  if(e.buttonDown && overTarget)
  {          
    buttonDown = true;
    MouseDragged = true;
    MouseCurrX = eventObject.mouseX;
    MouseCurrY = eventObject.mouseY;
    arMousePrevX = MousePrevX;
    arMousePrevY = MousePrevY;
         
    var Topper:int = (eventObject.mouseY - MousePrevY) + targetObject.y;
    var Sider:int = (eventObject.mouseX - MousePrevX) + targetObject.x;
           
    if(moveY){targetObject.y = Topper;}
    if(moveX){targetObject.x = Sider;}             
         
    Decay = originalDecay;                   
  }
  else
  {                      
    buttonDown = false;
    overTarget = false;
  }
           
  MousePrevX = eventObject.mouseX;
  MousePrevY = eventObject.mouseY;
     
  if(targetObject.width > eventObject.width){xOppositeEdge = true;}
  else{xOppositeEdge = false;}   
  if(targetObject.height > eventObject.height){yOppositeEdge = true;}
  else{yOppositeEdge = false;} 
 
  t.stop();
  t.start();
}

So here is what happens, we just set up a MOUSE_MOVE listener in the last step, so every time the mouse moves over our event object this function gets called, moveIt. This is our pan function. Lets go through this step by step.

The first if is to see if our button is down and if overTarget is true. The over target variable is a bool, you may need to refer back to the variable declarations at the beginning of our class. If the onlyMoveOnTargetClick was false in the init overload, then this will always be true. If it was false then we set it to true on an event listener.

After we go into the if we set some vars. First, because e.buttonDown was true we  set our own flag, buttonDown to true. Well use that in the throw function. MouseDragged is to test if the mouse was moved while the button was down, so here it is true because we have an on mouse move event with button down. so another flag to be use later.

Now we set our mouse cursor position and store the previous mouse position in our artificial (ar) mousePrevious. this will be used on the throw also.

Next the move math. we take the current cursor position and get the difference between that and the old position then add that to the current objects location. The reason we have the previous location is because we set it after the if else.

after we add the difference to our current position we set that equal to the target objects x and y. So really, like I said we aren’t interacting this object directly, we just make people think they are. we are just interacting with the event object.
Next we check to see which element is bigger the parent or object.
then after that we stop then start our timer. Lets look at the timer handler

1
2
3
4
private function timerOut(e:TimerEvent):void
{
  MouseDragged = false;
}

we just set another flag. This is so that when someone moves the object then stops but doesn’t release the mouse our object won’t move after they let the button go. We set the time duration for 100 milliseconds so it is pretty quick. Lets look a the rest of our handler function then on to the big daddy, the throw function.

1
2
3
4
5
6
7
8
private function downer(e:MouseEvent):void
{
  buttonDown = true; 
  if(!TargetClick)
  {
    overTarget = true;
  }  
}

downer sets our button down flag to true when ever our button is pressed, this is a just in case thing, and it sets our overTarget flag that we test for in the drag function if we don’t care where the target click is.

1
2
3
4
5
6
7
private function handleOverTarget(e:MouseEvent):void
{
  if(e.currentTarget == targetObject || !TargetClick)
  {
    overTarget = true;
  }      
}

This says that if, when our button is pressed we are over the target object or the target click is set to false then we set to true, we set this to false on the mouse move event.

1
2
3
4
private function upper(e:MouseEvent):void
{
  buttonDown = false;
}

this collects anytime the button is released, another just in case, just in case the mouse is released while the mouse isn’t moving.

1
2
3
4
5
private function throwIt(e:MouseEvent):void
{
  if(MouseDragged)
  eventObject.addEventListener(Event.ENTER_FRAME, theRepeater);
}

this is the heart of it all. A small one but this sets our throw in place. This just tests if the mouse was dragged, if it was then we can throw it on release. The throw is like a javascript repeater function but instead of calling itself like javascript, you call a ENTER_FRAME event. This tell the app to run this function every time we enter a new frame. Default for flash is 12 fps, I like to bump it up to 24.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
private function theRepeater(e:Event):void
{              
         
  var oldxer:Number = MouseCurrX;
  var oldyer:Number = MouseCurrY;      
       
  var xDiff:Number = MouseCurrX - arMousePrevX;
  var yDiff:Number = MouseCurrY - arMousePrevY;
       
    if(!buttonDown)
  {
    xDiff = xDiff * Decay;
    yDiff = yDiff * Decay;  

    if(xOppositeEdge)
    {  
            if(targetObject.x < (eventObject.width - targetObject.width - 50)){xDiff = -1 * xDiff; targetObject.x = eventObject.width - targetObject.width - 50;}
      if(targetObject.x > 50){xDiff = -1 * xDiff; targetObject.x = 50; }                       
  }
  else
  {
    if(targetObject.x <  -5){xDiff = -1 * xDiff; targetObject.x = -5;}
    if(targetObject.x > (eventObject.width - (targetObject.width - 5))){xDiff = -1 * xDiff; targetObject.x = eventObject.width - (targetObject.width - 5);}
  }
  if(yOppositeEdge)
  {                
    if(targetObject.y < (eventObject.height - targetObject.height - 50)){yDiff = -1 * yDiff; targetObject.y = eventObject.height - targetObject.height - 50;}
    if(targetObject.y > 50){yDiff = -1 * yDiff; targetObject.y = 50;}
  }
  else
  {
    if(targetObject.y < -5){yDiff = -1 * yDiff; targetObject.y = -5;}
    if(targetObject.y > (eventObject.height - (targetObject.height - 5))){yDiff = -1 * yDiff; targetObject.y = eventObject.height - (targetObject.height - 5);}                
  }  

  var sider:int = xDiff + targetObject.x;
  var Topper:int = yDiff + targetObject.y;
           
  MouseCurrX = MouseCurrX + xDiff;
  MouseCurrY = MouseCurrY + yDiff;
           
  if(moveY){targetObject.y = Topper;}
  if(moveX){targetObject.x = sider; }
           
  arMousePrevX = oldxer;
  arMousePrevY = oldyer;        

  }
                 
  if(Math.abs(xDiff) < 1 && Math.abs(yDiff) < 1)
   {
    eventObject.removeEventListener(Event.ENTER_FRAME, theRepeater);             
   }
  if(buttonDown)
   {
    eventObject.removeEventListener(Event.ENTER_FRAME, theRepeater);
   }
}

Ok so here is the big daddy. The throw function. The principle is really simple. When the button is let off and our enter frame event is fired we take over the position of the throw object and make it act as though the mouse was still moving, only we are feeing it artificial values. So now we create and old x and y value and get the current mouse x and y that we loaded in our mouse move event. We then get the difference between the two, (if we skip over the if and else if segment for a second) we add the difference to the x and y , set the new mouse current and reset the artificial values. Does this sound a little familiar? We are doing almost the same thing as the move function.
Now I want to explain that part we skipped over. This one is the hardest to wrap your head around, at least for me when writing it. What this does is check which side your target object wants to bounce on then bounces it when it hits the edge. when your target it larger than the event object you want almost all of the target object to disappear. I will show some examples of implementation.
There is a lot going on here so let me try and explain. If we want the opposite edge, then well take the x of the target object and see if it is smaller than -5 we will negate the xDiff to send the target object in the opposite direction. same with all sides, on the right and bottom we test if the x or y is 5 pixels less than the width of the object from the edge because the top right corner is where the x and y are registering from, not the center.

We do the same for the inside edge except we are hitting the opposite edge with our math.

last function.

1
2
3
4
5
6
7
8
9
10
11
public function stop():void
{
  eventObject.removeEventListener(Event.ENTER_FRAME, theRepeater);
  eventObject.removeEventListener(MouseEvent.MOUSE_MOVE, moveIt);
  eventObject.removeEventListener(MouseEvent.MOUSE_UP, throwIt);
  eventObject.removeEventListener(MouseEvent.MOUSE_OUT, throwItOut);
  eventObject.removeEventListener(MouseEvent.MOUSE_OVER, upper);
  eventObject.removeEventListener(MouseEvent.MOUSE_DOWN, downer);
  t.removeEventListener(TimerEvent.TIMER, timerOut);
  t.stop();
}

This calles a stop, those buttons on the examples stop the panAndThrow, and stop it.

That is it. I know I may have not gone into so much detail but this is already pretty long. So here are some usage examples and alternate configurations. All of these changes don’t touch the class we made, just the mxml implementation.
here is one where the TargetObject is bigger than the event object.

Get Adobe Flash player

And with this one I am moving three objects, one is moving x and y, one is moving y and one is moving x. I am using no friction in this example.

Get Adobe Flash player