Archive for the ‘Web Development’ Category

Adobe Contribute CS5 Repeatable Regions Broken On Edit

Tuesday, January 25th, 2011

I’ve been working on some Contribute templates for a client. I noticed that repeatable regions weren’t working right. Instead of adding a new item to the region when clicking the plus (or deleting when clicking the minus), the “cursor” would simply move to the next item. The only other reference I could find to the problem was some random, unresolved thread on some website I’ve never heard of.

After a lot of digging around in the code, I figured out the problem. If your template includes another file that has repeatable regions, the repeatable regions in your main template will stop working when you edit the page again. As described, the cursor will move up and down the existing regions instead of adding new regions.

For example, I have a navigation template that has repeatable regions.

1
2
3
4
5
<ul id="nav">
<!-- TemplateBeginRepeat name="Navigation" --> 
<li><!-- TemplateBeginEditable name="Nav Item" --><a href="#">Home</a><!-- TemplateEndEditable --></li>
<!-- TemplateEndRepeat --> 
</ul>

I included that file via the standard PHP include . When editing, Contribute seemed to get confused about the repeatable regions in the navigation when Contribute manually imported the navigation file.

The fix is either to not use repeatable regions in your include files (not an option) or to trick Contribute into not trying to include the included file. Contribute is at least smart enough to know how to do the standard PHP includes. So, I had to break a rule and use eval like this:

1
<?php eval("include('./nav.php');"); ?>

PHP evals the string and ultimately includes the file. Contribute doesn’t understand the code and does nothing, which removes the problematic code and causes repeatable regions to work as expected.

Site Specific Hacks

Wednesday, April 8th, 2009

The other day, I finally got curious about the Site Specific Hacks option in the Develop menu of Safari. It turns out that browsers do their own hacks to certain known problem sites to make them work. Safari allows developers to turn off these hacks in the event that the developer is fixing a site that has hacks in Safari.

Opera, on the other hand, has a very advanced method for dealing with site specific hacks. It’s worth a read just so to know what kind of stuff goes on in the browser that most people, including developers, never think about. They also link to how other browsers deal with the problem.

Internet Explorer 8 Released

Thursday, March 19th, 2009

If you didn’t already hear (and I bet you already did), Internet Explorer 8 has been released. For several months, I’ve been using the release candidates with the Internet Explorer 7 Compatibility Mode to test sites in IE7 and IE8. So far, IE8 seems like a pretty good release. I haven’t had a chance to update yet, but I’m hoping hard that things have only gotten better.

Browsers and Form Collection

Wednesday, February 18th, 2009

I’ve been writing a new form hijacker. Since this one is a pretty big deal for me, I wanted to make sure it was properly implemented. I implemented against my interpretation of the HTML 4 specification and did a pretty good job since I’m exactly compatible with Firefox, Opera, and Internet Explorer 8. Safari, Internet Explorer 6, and Internet Explorer 7 seem to have some bugs.

Safari seems to send the values of unnameed selects, despite these elements being invalid. So, you may get a query string like text1=test&=selval if your select that contained an option="selval" doesn’t have a name.

Internet Explorer 6 and 7 both mishandle buttons. Internet Explorer 6 sends all buttons with name attributes set, even though it should only send the button if it was clicked. Internet Explorer 7 doesn’t send unclicked buttons, but any time Internet Explorer 6 or 7 sends a button it sends the button‘s innerHTML instead of the value.

So, given the deficiencies above, here’s how to compensate. If you’re using PHP, you don’t need to worry about Safari sending nameless selects as PHP seems to ignore them (or at least in parse_str). If you plan to use buttons, never give them names or values. Use radio controls if you have to do conditional actions based on what the user clicks.

I still have some other testing to do, but these findings should help you cover your bases if you’re working with forms.

Yahoo! Updates Graded Browser Support

Thursday, January 29th, 2009

Yahoo! updated it’s Graded Browser Support yesterday. The changes involved dropping support for non-Safari browsers on Mac OS X 10.4 and non-Internet Explorer browsers on Windows 2000. Support for Internet Explorer 8 was added for Windows XP and Windows Vista.

This has given clout to support Internet Explorer 8 (which is in Release Candidate version now) in addition to versions 6 and 7. Here’s hoping Microsoft forces Internet Explorer 8 upgrades now that version targeting has been implemented.

Adding Location Awareness to Your Site

Friday, January 9th, 2009

I recently launched a new personal site.  I wanted to integrate some level of location awareness to it.  My initial design sketches called for the weather information and a position on a map of my last known location.

Initially, I was using a program on my iPhone called Loopt.  Loopt is like Twitter with location.  That involved jumping through hoops, as Loopt’s RSS feed only shows the GPS position of the last post.  Not only would I have to post a message every time I got somewhere, I’d have to reverse geocode my position to grab the zip code to send to get the weather information.  I achieved this through JavaScript with the Google Maps API.  This worked until I found out about Fire Eagle.

All Fire Eagle does is log your location. Luckily, Fire Eagle has an API. Eagle Feed turns your location into a publicly accessible RSS feed. So, getting your location is as easy as parsing an RSS feed. By setting the read level of Eagle Feed to my zip code, the title of the single item in the RSS feed reports my city, state, and zip (e.g. Birmingham, AL 35223), and my GPS coordinates are also in the feed.

You can update Fire Eagle by manually by entering your location on the site. However, there are mobile applications, such as Active Eagle on the iPhone, that use the GPS functionality of your device to update Fire Eagle. In Active Eagle, I simply tap “Update Fire Eagle” to update my location, and my Eagle Feed.

Once you can get your feed there are plenty of cool things you can do.

I wrote a simple PHP script to open my feed (or pull it from a cached file), grab the human-readable location from the title and parse out the zip code and my GPS position.

1
2
3
4
5
6
7
8
9
10
11
$out = file_get_contents($feed_url);
 
preg_match_all('/<title>(.*?)<\/title>/', $out, $loc_matches);
$human_loc = $loc_matches[1][1];
preg_match('/\d{5}/', $human_loc, $loc_matches);
$human_zip = $loc_matches[0];
 
preg_match('/<abbr class="latitude".*?>(.*?)<\/abbr>/', $out, $lat);
$loc_lat = $lat[1];
preg_match('/<abbr class="longitude".*?>(.*?)<\/abbr>/', $out, $long);
$loc_long = $long[1];

I then pass my zip code to Yahoo’s weather feeds to get weather data. I also pass my GPS position to Google Maps Static API to get a map of where I am.

Another idea would be to show Flickr photos in your area via the Flickr API. I’m sure there are tons of other things that would be fun or useful. Come up with some more ideas and make some cool stuff.

Forms With Elements With Form Attribute Names

Tuesday, September 23rd, 2008

I commonly create a form element that dictates the action I want the server to perform, like <input type="hidden" name="action" value="save">. This allows me to have a switch to determine what to do with the data in any situation instead of posting and getting to multiple places. I found a bug in Internet Explorer 7’s JavaScript today that introduces a problem with my naming scheme.

When doing Ajax, I often use form.getAttribute('action') to get the location to send the request to. This allows me to keep my code more portable. However, in Internet Explorer 7 (or IE7 for short), if there is also a form element with name="action", IE7 returns the input object instead of the value of the attribute as though I typed formname.action or, in long hand, document.forms['formname'].elements['action'].

To my knowledge, there is no work around other than changing the name of the element. So, I’ll be using name="faction" from now on. That’s short for “form action” but “faction” itself is fairly apt given IE’s behavior is different from all other browsers, making it a faction.

MySQL FIND_IN_SET

Thursday, July 31st, 2008

I always forget this mySQL function, so I figured I should make note of it somewhere. It’s called FIND_IN_SET. You specify a variable and a list of possible matches and it returns the position of the string in the list. It’s very helpful for sorting things in a defined list provided by the client.

Internet Explorer Version Targeting Finally Makes Sense

Tuesday, March 4th, 2008

I kept mum about Internet Explorer 8’s version targeting to see how things played out. It looks like Microsoft did the right thing for real web developers.

Version targeting allows the web developer to pick which version of Internet Explorer’s rendering engine he or she would like to use. This is great for big sites (like banks) because they can forever have a site that works in buggy Internet Explorer 6. No more freak outs when Internet Explorer updates like there were with the update to version 7. The problem wasn’t that they were introducing a proprietary header / meta tag. The problem was that all future versions of Internet Explorer would render like version 7 unless the developer opted in for the newest rendering mode. That’s right. A large majority of people would be forever designing with Internet Explorer 7!

The solution several web celebs they would adopt would be to set the version to edge to always get the latest version in an attempt to tell Microsoft that good developers don’t want to use it. The problem is that developers had to use it to not use it.

Fortunately, Microsoft came to their senses and announced they would keep version targeting but have the default behavior use the latest rendering engine. The claim is that they are trying to support the new Interoperability Principles published in February. No doubt part of the problem was the overwhelming response against defaulting to version 7 from the web standards community. Either way, I’m glad Microsoft decided not to pander to the people causing the problem.

Everyone is happy now that Internet Explorer 8 will really pass Acid 2.

  1. Jeffery Zeldman’s Post
  2. Lachlan Hunt’s Post
  3. Roger Johansson’s Post
  4. Hixie’s Blurb
  5. Web Standard Project’s Post
  6. And it even made it to Slashdot

I am thankful I don’t have to add (in addition to conditional comments) more Microsoft related junk to the head of my boilerplate.

Element Swapping with Unobtrusive JavaScript

Monday, February 11th, 2008

There may come a time when you need to show different content on one page based on a user-selected option. Here’s a quick tutorial.

The first step is to set up your content properly. In this example, I’ll use a select to swap between two form elements, though the basic premise can be applied to other design patters such as module tabs. Here is how the form should look.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<form method="post" action="post.php">
 <div>
  <label>
   How Should I Reply To You?
   <select name="type" id="type">
    <option value="email">E-mail</option>
    <option value="phone">Phone</option>
   </select>
  </label>
 </div>
 <div id="byemail">
  <label>
   Enter Your Email:
   <input type="text" name="email">
  </label>
 </div>
 <div id="byphone">
  <label>
   Enter Your Phone Number:
   <input type="text" name="phone">
  </label>
 </div>
</form>

That is the basic setup you need. You have something for the user to select (that has an id to assign, in this case, an onchange event), and something to swap between that have ids. Now you need some JavaScript. Comments are inline to explain things.

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
/* Assign the onload event to the function init. */
/* Test which way adding events is supported. */
if(window.addEventListener) {
	/* W3C method. */
	window.addEventListener('load', init, false);
} else if(window.attachEvent) {
	/* IE method. */
	window.attachEvent('onload', init);
} else {
	/* Old school method. */
	window.onload = init;
}
 
/* This is the function that runs after the page loads. */
function init() {
	/* Get the select element you want the onchange to be applied to. I use the j_ prefix because sometimes errors happen when variables are named the same thing as IDs in the HTML. */
	var j_type = document.getElementById('type');
	/* If the element exists, we can assign the onchange event to call the swap function using the same type test we used before. */
	if(j_type) {
		if(j_type.addEventListener) {
			j_type.addEventListener('change', swap, false);
		} else if(j_type.attachEvent) {
			j_type.attachEvent('onchange', swap);
		} else {
			j_type.onload = swap;
		}
		/* Now, we need to fire the event to get the default. */
		if(document.createEvent) {
			/* The W3C method. */
			var j_event = document.createEvent('HTMLEvents');
			j_event.initEvent("change", true, true);
			j_type.dispatchEvent(j_event);
		} else if(document.createEventObject) {
			/* The IE method. */
			j_type.fireEvent("onchange");
		}
	}
}
 
/* This is the function that does the work of swapping the elements. */
function swap(e) {
	/* Get both the elements you want to swap between. */
	var j_email = document.getElementById('byemail');
	var j_phone = document.getElementById('byphone');
	/* Grab the event from the W3C method or the IE method. */
	var e = e || window.srcEvent;
	/* Grab the event target from the W3C method or the IE method. */
	var target = e.target || e.srcElement;
	/* Grab the target's value */
	var t_value = target.value;
	/* If both swap elements exist... */
	if(j_email && j_phone) {
		/* Depending on which option, hide or show the form elements. */
		if(t_value == 'email') {
			j_email.style.display = 'block';
			j_phone.style.display = 'none';
		} else if(t_value == 'phone') {
			j_email.style.display = 'none';
			j_phone.style.display = 'block';
		} else {
			j_email.style.display = 'none';
			j_phone.style.display = 'none';
		}
	}
	return true;
}

Save the script above to a file and include it in the head of your document that the form is in. You’ll have the swapping capabilities you desire using unobtrusive JavaScript and modern DOM techniques.

This was tested in Safari 3, FireFox 2, Opera 9.25, and Internet Explorer 7.