Archive for July, 2006

CSS hacking for FF, IE7, IE6-

July 30, 2006

min-height: 350px; /*for Firefox: */

_height: 352px; / *for IE6*/

/*FF*/
margin-left: -19px;
/*IE7*/
*margin-left: 20px;
/*IE6 and below*/
_margin-left: -15px;

I came across this hack by studying CSS of Yahoo!’s new home page. In short, underscored attributes are for winIE.

I came across this using “expression” in CSS for IE 6-. Here is the CSS snippet:

max-width: 340px;
width:expression(document.body.clientWidth > 340? “340px”: “auto” );
max-height: 225px;
width:expression(document.body.clientHeight > 225? “225px”: “auto” );

I think they mentioned that IE 7 had fixed the bug.

Advertisements

Freaked-out movieclip

July 29, 2006

I was trying to fix a freaked-out photo gallery done by someone else. The gallery loads different slideshows into the main screen when the user clicks on the buttons. When a second slideshow is clicked on before the first is finished loading, the movie started blinking in and out. I am not quite sure who is the evil, either “loadMovie” or “setInterval” (which was used in the preloader) and I am so tired now to figure it out. I fixed it (well it seems to be now) by changed two places:

1. Use MovieClipLoader to loadclip() instead of using loadMovie();

2. Use onEnterframe instead of setInterval for the preloader.

Pass parameters to movieclip subclasses

July 26, 2006

Being a motion graphic designer, I need flexibility in control of the movieclip classes. Subclasses of movieclips are often instantiated by coding using “attachMovie()”, thus makes it cumbersome to control and change the their positions.

One solution, if you want manipulate subclasses as visually as you can to movieclips, you can make them components and thus would be able to feed initializing parameters statically.
In a simple scenario, I just use place holder ghost movieclips solely for the purpose of positioning and then attach subclass dynamically. Like this:

var title = “2000”;
var bodyTxt = “To cancel a mask created with ActionScript, pass the value null to the setMask() method. The following code cancels the mask without affecting the mask layer in the timeline.”;
var expTxt_mc = _root.attachMovie(“expTxt_mc”, “expTxt_mc1”, this.getNextHighestDepth(), {
_x:dot_mc._x,
_y:dot_mc._y,
title: title,
bodyTxt: bodyTxt
});

Combine scripted and timeline animation

July 25, 2006

I am recently doing a small Flash animation that uses both timeline and scripted animation. The scripted animation is continued right after the timeline animation finishes. I found it hard to target the movieclips since they either didn’t have instance names or were merely “graphics”. Using the “Inset a target path” tool in “Actions” panel doesn’t help since Flash starts looking for all the mc instances that don’t have instance names; and the tricky part is that Flash does it this on one instance at a time. So imagine if you have tons of keyframes on the main timeline…

One solution I found was to simply duplicate the key frames that contains the movieclip that you want to target, give them an instance name and move them to a new layer.

Here is how it works:

Skin rico accordion component

July 20, 2006

Use Rico.accordion behavior to transform a structured CSS Divs into accordion component.

The Divs that host the accordion component needs to be in a structure like this:

<div id=”accordionInstanceName”>

<div id=”paneNum1″ class=”paneRule”>

<div class=”headerPanel”>Intro</div>

<div class=”contentPanel”>blahblahblah

<div class=”footerPanel”></div>

</div>

<!–//other tabs of the accordion component……–>

</div>

</div>

In order to skin the header, you need to change both the css that sets the style rules for the accordion and the javascript file when instantiating the accordion.

The following example demostrates a way of setting a customized header in an accordion component:

1) Set the background to transparent in the js:

//rico accordion
var options = {
expandedBg : ‘transparent’,//instead of color hex set it to transparent so that the background image wil show through,
hoverBg : ‘transparent’,//’#63699c’,
collapsedBg : ‘transparent’,//’#6b79a5′,
expandedTextColor : ‘#ffffff’,
expandedFontWeight : ‘bold’,
hoverTextColor : ‘#ffffff’,
collapsedTextColor : ‘#ced7ef’,
collapsedFontWeight : ‘bold’,
hoverTextColor : ‘#FFFFFF’,
borderColor : ‘#FFFFFF’,
panelHeight : 366,//370,//325
onHideTab : null,
onShowTab : onShowTab,
onLoadShowTab : 0
}

accr = new Rico.Accordion(‘accordionDiv’, options);
2) In the CSS:

.contentMod #sidebar .header{
/*some other rules…*/
background: url(img/accr_header.gif) no-repeat;

}

Classic Javascript/Actionscript event handlers in MVC

July 10, 2006

Event handlers are the “Controller” part of MVC in a page.

In most situations, the controller needs to be instantiated when data are ready (for example, when an xml stream is parsed). When triggered, controller often leads to events that display data. It is often convenient to directly attach data to the visual objects that the event handlers are attached to, so that when triggered, the event handler function can grab the data by simply referring to “this.data” since the “this” is scoped to the visual object at the moment the event handler is attached to it. Handy data are good, but this confuses model with presentation and also results in redundant data. One trick I played recently was to build an index attribute in the visual object that serves as sort of a lookup table for relevant data. The data are stored in a seperate object (centralized as model) and can be accessed by different controllers.

The followings are the snippets of code in action:

//When data are available, loop through the data and do all the mover’s job while we initialize/define the event handler

for (var i=0; i<data_arr.length; i++){

//…do some moving job

var divNode = document.createElement(“div”);
divNode.index = i;
divNode.onclick = onTitleClick;

……

}

function onTitleClick(){

var index = this.index;
var tab_index = ARCHIVED_ID;
var dataTab = navData[tab_index];
var data = dataTab.localData;
var gmarker = data[index][“gmarker”];
var infoTabs = data[index][“infoTabs”];
gmarker.openInfoWindowTabsHtml(infoTabs);
}

The above snippet of code is the more “conventional” way of assigning an event handler. In a more OO way, it can be something like this (due to different implementations of event handling in javascript, there is now no consistent way across browsers):

function createMarker(id, gmarker, infoTabs, divNode){
GEvent.addListener(gmarker, “click”, function() {
gmarker.openInfoWindowTabsHtml(infoTabs);
hilightTitle(divNode);
});

//…other things
return gmarker;
}

The event handler is wrapped up in a function call that passes on all the data chunks as parameters to the former. This somehow serves as a machanism to (misteriously) keep track of which controller is associated with which piece of data (like the gmarker<->infoTabs pair) without assigning the data as dynamic attributes to the controller objects.

So to sum it up, the steps are:

1. Query and parse data;

2. Define and attach the event handlers when parsing the data.

3. Build lookup attribute as attribute of the visual object that the event handler is attached to; or simply attach relevant snippet data directly to the visual objects when data don’t need to be shared across multiple controllers; or in a more OO way, pass the data as parameters directly when defining/assigning the event handlers.

css box model recap

July 4, 2006

While spending some time to figure out the “intricacies” of box model, I made the following big discoveries:

1. Element width/height doesn’t refer to the total width/height of the element. It only controls the most inner “content box”, which is surrounded by padding. The total element dimension is controlled by width/height along with padding, border-width and margin.

2. Border doesn’t occupy either margin or padding area. So the rule “border: 20px;” will actually increase the totoal box element dimension by 20px both ways (x and y).

3. Background image will fill the area defined by “content box” (whose dimension controlled by width/height) and padding.

These discoveries are simply illustrated as below:

css box model

BTW, this doesn’t cover the way IE 5/6 in Win implements box model in quirks mode;)

Making XMLHttpRequest using form, a.k.a. cancel form submission

July 2, 2006

The trick is how to make an XMLHttpRequest call to a page (mostly a server-side script like PHP) instead of (without) letting the browser loading that page. You just need to cancel the form submission by appending “return false” at the end of the xmlhttprequest call.

<!–HTML

<form action=””><input id=”btn” type=”button” name=”submit” value=”Search!” /></form>

//–>

<!–javascript

function sub( f){

//do something first, like make validating the form and making an XMLHttpRequest, etc.,

//return false will cancel form submission
return false;

}

window.onload = function(){

var btnEl = document.getElementById(“btn”);

if (btnEl){

btnEl.onclick = function(){

//this.form refers to the button’s form value

//just in case you need to grab some “input” values directly from the form

sub(this.form);
}
}

}

//–>

Here is a good article talking about “From Tricks” back in 1997.