Monday, January 03, 2011
A little over a year ago I was inspired to start on a photography project I would have to participate in every single day for the duration of 2010. At first it seemed a little overwhelming, but after some searches online it seems that there are actually quite a few people out there that have successfully done this exact same thing. This was a huge relief to me to at least know that this was a feasible thing to do!
So I started a Tumblr blog and began taking photos every day. At first it came easy because I had so many ideas and it was new. I also was uploading these photos to Facebook so that people I see on a daily basis would know about the project and be able to see what I was doing. In hindsight this was probably the best decision because so many of my friends would say the most encouraging things to me about my photos. This was really big for me because, as you might imagine, forcing yourself to do a specific out-of-the-ordinary task every single day can become quite a burden. So a HUGE “thank you” goes out to all my friends in my life, and also to everyone online whom I’ve never met. You all were a gigantic blessing and encouragement to me.
So, to sum it all up: it was a success! I managed to take a photo every day of 2010 except for one (oops.) The one day I missed is something I can excuse myself for; I was in Africa and exhausted on that particular day. I made up for it by simply extending the project into the first day of 2011. Not ideal, but a fair trade off.
Overall, I’m so extremely glad that I did it, and I’m very proud of what I came up with. Of course some photos I like a lot more than others, a few I wish I could do over again, but in the end it is what it is and I’m happy with how it turned out. Would I do it again? NO WAY! This turned out to be an incredible amount of work! Much more than I anticipated.
Read more...
Posted by Chris Barr on 01/03 at 09:59 PM
Filed under
Africa,
Photography,
Code,
Personal •
•
Permanent link
Monday, May 03, 2010
In mobile Safari on the iPhone, iPod Touch, and iPad (as well as the webkit based browser on Android phones) it's not immediately obvious how to scroll a div that has overflow:auto; set on it. If this were a desktop browser you would see scrollbars and be able to manipulate those or even use your mouse wheel. No such concepts exist on a touch screen device!
To scroll the entire page you just touch it and move your finger. But when you touch the element that would normally scroll, the entire page scrolls instead. This is a little bit broken in my opinion since there's no visual indicator that you aren't seeing all the content. However, if you are on a site and you know there's a scrollable div there is a simple (but not obvious) workaround. Simple use two fingers at the same time and scroll them in the same direction.
This works OK but like I said it's not obvious, there's still no indicator that the content is scrollable, and when you use more than one finger you might accidentally trigger some other gesture like scaling the page. I recently ran into this exact issue at work and came up with a pretty solid solution in javascript. I broke this down into two simple functions, but the last one is where the magic happens.
This first function simply attempts to create a new touch event. Only touch screen browsers like mobile Safari have these events, so if it doesn't throw an error then we are using a touch screen device. Otherwise it's probably a desktop browser.
function isTouchDevice(){
try{
document.createEvent("TouchEvent");
return true;
}catch(e){
return false;
}
}
Next, this function calls the isTouchDevice() function, and if it succeeds we attach some special touch events to the page. First when a touch event begins (the touchstart event) we get the current scroll position and prevent the default browser behavior, which in this case would be to scroll the page. Next when you move your finger the touchmove event is called. Here we just subtract the position of your finger from the scroll position we saved earlier and again prevent the page from scrolling.
function touchScroll(id){
if(isTouchDevice()){ //if touch events exist...
var el=document.getElementById(id);
var scrollStartPos=0;
document.getElementById(id).addEventListener("touchstart", function(event) {
scrollStartPos=this.scrollTop+event.touches[0].pageY;
event.preventDefault();
},false);
document.getElementById(id).addEventListener("touchmove", function(event) {
this.scrollTop=scrollStartPos-event.touches[0].pageY;
event.preventDefault();
},false);
}
}
So that's it, just include these functions on your page and just call it by passing in the ID of the element you want to scroll. Like so: touchScroll("MyElement");. You can see a working demo here: http://chris-barr.com/files/touchScroll.htm. I feel like this is a better way of doing things because it's more intuitive since you're just using one finger, and it's potentially more obvious. Even if you don't immediately know there's hidden content, you might accidentally touch this while scrolling the page and realize there's more to see in this div.
Posted by Chris Barr on 05/03 at 11:48 PM
Filed under
Web,
Code,
Javascript,
CSS •
•
Permanent link
I was bored, so I made one. Check it out here: http://chris-barr.com/files/text%20clock/
Posted by Chris Barr on 05/03 at 11:41 PM
Filed under
Projects,
Web,
Code,
Javascript •
•
Permanent link
Tuesday, September 22, 2009
Adding shadows or rounded corners to any element is way more trouble than it should be, especially if you're tried out some of the newer CSS3 properties. A simple two lines of CSS can get you these amazingly gorgeous effects, but as expected they aren't supported in every browser (I'm looking at you Internet Explorer!) Note: This post was updated on 9/21/2010 to include support for detection of these features in the Internet Explorer 9 beta!
Some older versions of browsers that do support these features don't use the official W3C method and you have you use a vendor specific CSS property,like so:
#coolElement{
box-shadow:#000 3px 3px 8px;
-moz-box-shadow:#000 3px 3px 8px;
-webkit-box-shadow:#000 3px 3px 8px;
border-radius:5px;
-moz-border-radius:5px;
-webkit-border-radius:5px;
}
So, that of course won't work in IE, and if you want to have rounded corners or shadows on IE you have to make some custom PNG images and align everything properly. It's a lot of work, but it must be done if you want it to look consistent across all browsers. I realized today that ideally I want to do both, meaning that I want to use the pure CSS method when it's available in the browser, and the old clunky way otherwise.
Sure I could just see what works in each browser and only allow certain versions of browsers, but I'd always have to come back and update that list as future browsers add support for these things. Instead, why not test and see if the browser supports these features first, and then decide what to do.
function supportsBoxShadow(){
var s=document.body.style;
return s.WebkitBoxShadow!== undefined||s.MozBoxShadow!==undefined||s.BoxShadow!==undefined||s.boxShadow!==undefined;
}
function supportsBoderRadius(){
var s=document.body.style;
return s.WebkitBorderRadius!== undefined||s.MozBorderRadius!==undefined||s.BorderRadius!==undefined||s.borderRadius!==undefined;
}
Those functions will return true if the CSS property is supported in the browser, and not just the W3C property, but the vendor specific property as well. If there's some other property you want to test, follow the same pattern and just use CamelCase and remove the hyphens.
So putting this into practice is pretty simple, assuming we use the CSS property defined above.
if(supportsBoxShadow()){
//Woo! We don't have to do anything! CSS does all the work!
}else{
//Write your complex code here to position your PNG shadows.... :(
}
Posted by Chris Barr on 09/22 at 09:43 AM
Filed under
Web,
Code,
Javascript,
CSS •
•
Permanent link
Tuesday, July 21, 2009
Just wanted to post a quick blog update with a cool jQuery trick I’ve been using recently. Every now and then I need to compare one jQuery object to another but a simple $(this) == someObject doesn’t do anything. As it turns out jQuery objects are actually stored internally as an array and you can’t just directly compare arrays.
So with that in mind, the easiest and quickest solution is to just access the items in the array and compare those instead. Luckily the very first item in the jQuery array is all we need here, so to access it you simply need to put in square brackets the array item number you want like so: $(this)[0]. So check out the code example below.
<div id="nav">
<a href="#">link 1</a>
<a href="#">link 2</a>
<a href="#">link 3</a>
<a href="#">link 4</a>
</div>
<script type="text'javascript">
$(
allItems = $("#nav a");
secondItem = $("#nav a:nth-child(2)");
//loop through each item in this jQuery collection
allItems.each(function(){
//Compare the current jQuery object with the saved jQuery object
//by accessing the first item in the array of each object.
if($(this)[0] == secondItem[0]){
//we are on the second item! Give it a red background
$(this).css("background-color","red");
}
});
});
</script>
Posted by Chris Barr on 07/21 at 09:21 PM
Filed under
General,
Web,
Code,
Javascript •
•
Permanent link
Tuesday, April 14, 2009
So, I wrote a game! It's something I've been wanting to do and had the idea for a while now. The premise of the game is that a random word is selected, a search of Flickr.com is performed with that word and you see the images from that search. Now you have 30 seconds to guess what that word is!
The game is entirely written in javascript/jQuery and is completely themable with jQuery UI. I wrote the majority of it in one afternoon, and made some updates the following week based on some great feedback from friends on Twitter and just some better usability ideas I had.
Take a shot at it and let me know what you think. I hope to find the time soon to make even more improvements to the game.
Play Guessr!
Posted by Chris Barr on 04/14 at 09:41 PM
Filed under
Photography,
Design,
Projects,
Web,
Code,
Javascript,
Gaming •
•
Permanent link
Sunday, March 29, 2009
I just got back from the Mix '09 conference in Las Vegas, and it was so much better than I expected! For being a Microsoft sponsored conference mostly focusing on .NET and other MS technologies, there was about 50% Mac users there and most of these people were designers. It was a really nice mix (haha?) of designers and developers. I've got some photos from my trip up here on Flickr.
I think one of the best things they do is put up ALL the session videos online for free! There's some really valuable information in these!
http://videos.visitmix.com/MIX09 (also you can view past years MIX sessions at http://videos.visitmix.com )
Here's some highlights I'm going to recommend:
- Web Form Design - absolutely one of the best sessions I attended. Watch this video! He talks about why forms suck and what we as designers can do to help the process along. Very very well done and extremely informative. As soon as this session was over I went and bought the speakers book.
- The Way of the Whiteboard: Persuading with Pictures - Anotehr great session, but not necessarily directly related to web design. It's on how to get ideas out of your head and communicate them properly to people via a whiteboard of napkin.
- Measuring Social Media Marketing - If you or your company does any kind of social media marketing, this is a great one.
The following sessions I did not attend, but they seem great:
And finally, for any other ASP.NET or Visual Studio users, These are somre great previews of what's coming soon!
Wednesday, March 18, 2009
Well, my first day is finally coming to an end as I write this post - a really great first day considering how this first looked as I got here...
My flight out of Pensacola was delayed by 2 hours, but I was lucky enough to still make my connection in Atlanta to Vegas. My luggage however, was not so lucky. I had to go back to the hotel that night with only my laptop and camera. No change of clothes, no toothpaste, and being forced to sleep in my contacts. Thank God my bag was brought in on the next flight from Atlanta, so I was able to get it delivered.
Diego and I got up early, took a brief walk around the Venetian for a quick errand. Also, our hotel has no 13th floor.
Initial impression about MIX were not good. Very little signage and no directions. We got the general idea of where the conference might be, but no specific information. Then it occurred to me, what else should I expect from Microsoft organizing a conference? Once you figure it all out, you’re good to go - but that initial learning of where everything is located was the hard part.
First things first - breakfast and then check Twitter. There’s no wifi at the hotel, but there’s gigantic 8 foot wifi repeaters for the conference - making sure you can be connected from anywhere. Very nice touch. Not to mention, the food provided here is stellar!
On to registration, and then our first workshop entitled “Design Fundamentals for Developers” presented by Robby Ingebretsen. Robby did a great job - really well organized slides and information - i took notes until my laptop battery died - which reminds me, i need to take notes by a plug next time...
This workshop was not at all what I expected, and it turned out to be very informative - I feel like I learned plenty right there. I was expecting it to be somewhat technical since it was aimed at developers, but it was quite the opposite, very abstract and all about what art and design is. No code at all. Snacks and drinks provided of course.
haha? Apple juice on a Windows napkin!
Some big points I took away from this workshop:
- The opposite of design is not no design, it’s bad design! The very act of creating anything at all implies a design and therefore must be considered.
- Coding has exact answers to problems, design does not.
- Design has ponies and babies. Everyone loves babies and won’t let go of them, even if they aren’t right for a project. Everyone wants a pony, but you can’t always have them and they may not be practical. A good designer will be able to let go of their babies and let others know they can’t have a pony.
- The triumph of design is when the complex seems simple
- Gradients != design
I also noticed the presenter was presenting from a Mac, and there were way more Macs here than I thought I would see at a mostly Microsoft event.
Next, it’s lunchtime! Again, absolutely amazing meals provided. Veal, ravioli, green tomatoes, potato salad, and an incredible line of deserts.
Off to the next workshop, which started out OK, but we decided to leave after the first hour. The presentation and information provided was not nearly as good as the first one.
I did have a few take-away points here though: Designers tend to design projects for the “10 second wow” - meaning you are immediately impressed visually, but may not come back later for real information (think of any “flash” site you’ve ever seen). Developers tend to make projects that don’t really appeal to you at first, but after a while you learn to like the information and function - the “10 minute wow” (think of Twitter - ever tried to explain it to a new user?). A balance between these is needed.
As you move down the chart from designer to developer, you can compare each step to a character from Lord of the Rings. Also notice how the amount of facial hair increases in a logarithmic fashion.
After this, some other guy got up to speak about Silverlight and how to pay attention to details in your project and he really lost our interest. Not well organized, not prepared, and he started to get technical on some things we weren’t familiar with.
He also really turned me off to wanting to ever use Silverlight. One thing he kept talking about was how hard it is to get text to look good in his Silverlight apps. His solution? Duplicate every single text element, offset it by 1 pixel, and lower the opacity. Thus creating a fake anti-aliased effect. LAME!
That’s the point when we decided to leave and pick out sessions for the rest of the week. I got back on the Twitter, both posting and checking out what was happening on the #MIX09 hashtag. I noticed a picture from @jarrod_dixon that looked like it was only about 10 feet offset to the right of where I was sitting. I sent him a tweet just to say hi - then Diego and I got up to do it for real.
As it turned out, we met two cool people named Jared and Geoff who do a lot of the work for Stack Overflow (A site I use and love, and will now use more)! We had a long talk about code, Vegas, what they do, what we do, photography, etc. I’m very glad we got to meet them.
Microsoft Surface was also here! I’ve been wanting to sit down and play with one of these things since it was first announced! Very very cool technology that I hope comes way down in price and becomes more common.
Overall, the screen is not as high of a resolution as I had first imagined, and it can actually be quite laggy at times depending on what you’re doing - but it runs on some fairly meager hardware (mid range Core2 Duo and an average ATI card), so I can understand that. But for $15,000 I thought it would be top notch hardware in there.
The surface itself is not made of smooth glass as I imagined, it’s actually a diffuse textured plastic, but very easy to slide your hand around on as well. Talking to the Microsoft Reps there, it’s just running Vista under the hood and these are just special Surface apps. with in Visual Studio with WPF.
There’s and entire fully lit stage for Rock band - and there’s a tournament tomorrow. That should be fun to watch!
We were all given the schwag bag of course which mostly contained a bunch of crappy ads, but also had some great stuff in there as well. T-shirt, book, notepad, a sharepoint water bottle and an IE8 coffee thing. I might slip off the IE8 logo and use it that way.
That was a busy day! After some dinner, I walked around a bit at night and snapped some photos. I want to try and do this every night that I’m here.
Posted by Chris Barr on 03/18 at 09:10 AM
Filed under
Photography,
Design,
Web,
Code,
MIX '09,
Tech •
•
Permanent link
Wednesday, March 04, 2009
The other day I ran across a very useful article about the $$ selector in Firebug for Javascript and how to use it to loop through your stylesheets to find unused CSS styles. Very cool. The original code snippet would output everything to the firebug console, which I found to be useless on larger sites because I would hit Firebug's limit too often.
I modified it a bit to output the CSS to the actual site instead inside a styled element. So to use this on your own site, just copy and paste the code below into Firebug's console and hit run.
//Create a styled place to output styles to
var output = document.createElement('pre');
output.setAttribute("id","unusedCSSstyles");
output.setAttribute("style","height:95%; overflow:auto; text-align:left; background:#000000; border:2px outset #00CC33; color:#00CC33; opacity:0.9; padding:3px; position:fixed !important; left:5px; top:20px; width:95%; z-index:9998; font-size:12px;");
//create a styled close button
var closeBtn = document.createElement('a');
closeBtn.setAttribute("id","cssCloseBtn");
closeBtn.setAttribute("href","#");
closeBtn.setAttribute("onclick","document.body.removeChild(document.getElementById('unusedCSSstyles')); document.body.removeChild(document.getElementById('cssCloseBtn')); return false;");
closeBtn.setAttribute("style","position:fixed !important; left:2; top:0; z-index:9999; color:red; font-size:16px; padding:3px 20px; background-color:#000000; border:1px solid #FFF;");
closeBtn.innerHTML="close";
//add button and output element to body
document.body.appendChild(closeBtn);
document.body.appendChild(output);
//Find each stylesheet
for(var i = 0; i < document.styleSheets.length; i++) {
//write the filename to output element
output.innerHTML+="<br /><h3>"+document.styleSheets[i].href+"</h3>";
//find CSS rules
for (var j = 0; j < document.styleSheets[i].cssRules.length; j++) {
s = document.styleSheets[i].cssRules[j].selectorText;
//write unused CSS rules to output element
if ($$(s).length === 0) output.innerHTML+="<strong>["+j+"]</strong> "+s+"<br />";
}
}
Do note that this has a few limitations:
- It cannot find stylesheets from another domain or subdomains
- It cannot find inline styles or the
<style> tags anywhere
- It will not work on sites that use Mootools since it also uses the
$$ selector. (this site does, so don't try it here!)
If you're really serious about finding what CSS styles you haven't used on your site, you might want to check out a Firefox plugin called Dust Me Selectors
Posted by Chris Barr on 03/04 at 11:20 AM
Filed under
Web,
Code,
Javascript,
CSS,
Productivity •
•
Permanent link
Saturday, February 07, 2009
I was recently working on an interface where there would be a log of dragging, scrolling and clicking - an unfortunate side effect of these type of things is that the user may sometimes unintentionally select text. Which this doesn't break anything, it just looks bad can ruin the smooth experience you are trying to present the user with. It turns out that every browser has either some kind of hidden CSS or javascript function to prevent text selection.
I searched around and eventually came across this page on James Dempster's site. He wrote a simple jQuery plugin to turn off text selection only for the elements you specify. His plugin works just fine, but I believe it can be simplified. Below is my version.
$(function(){
$.extend($.fn.disableTextSelect = function() {
return this.each(function(){
if($.browser.mozilla){//Firefox
$(this).css('MozUserSelect','none');
}else if($.browser.msie){//IE
$(this).bind('selectstart',function(){return false;});
}else{//Opera, etc.
$(this).mousedown(function(){return false;});
}
});
});
$('.noSelect').disableTextSelect();//No text selection on elements with a class of 'noSelect'
});
After you include jQuery on your page, just include this script and any element with a class of noSelect will not be able to have it's text highlighted — easy! (Obviously you can change the class name to be whatever you want though.)
Do take note that the plugin is contained within the $(document).ready(function(){/*your code here*/}); (which can also be written as $(function(){/*your code here*/}).) That just sets it up as a method to be called. To call the method and disable text selection you just get a standard jQuery element and add the method onto it : $('.noSelect').disableTextSelect();
Posted by Chris Barr on 02/07 at 07:30 PM
Filed under
Web,
Code,
Javascript •
•
Permanent link
Friday, January 30, 2009
At work we develop in the ASP.NET framework (with VB), which is powerful but it has a lot of oddities - especially for me writing all the markup and CSS. My biggest gripe has been with the ID property of any element. You give it an ID, and then ASP all assign it a different one when it renders! For example, lets say I write the following code:
<asp:Panel runat="server" id="MyPanel">Hello</asp:Panel>
What actually gets rendered to the page may look something like this depending on how many Masterpages and controls its been nested inside of:
<div id="ctl00_ctl00__userMessage_uxUpnMessage_MyPanel">Hello</div>
Why the long ID Microsoft? I understand that sometimes ASP will need these unique ID's for forms and postbacks, but in reality for many things (especially things that only relate to page structure or style) you don't need this unique ID, you only need the ID you gave it! Today I was messing around with exactly how to do this and I came across a solution! Check out the VB code below:
Protected Overrides Sub OnPreRender(ByVal e As EventArgs)
Me.MyPanel.ID = String.Empty
Me.MyPanel.Attributes.Add("id", "MyPanel")
MyBase.OnPreRender(e)
End Sub
So just put that as the last step of your VB code, and it renders the exact way it should now - with the ID you told it to have in the first place. It's a bit of a hack, or a way to trick ASP into doing what I want, but ti works great. I'm sure there's a better way to implement this, or perhaps even extend certain elements to have a RenderID="MyNewIDName" property that would set the ID property from the front end instead.
Anyway, that's my big discovery for today. Hope it can help someone else out who was as frustrated as I was.
Posted by Chris Barr on 01/30 at 11:08 AM
Filed under
Web,
Code,
ASP •
•
Permanent link
Saturday, December 13, 2008
Compressing your javascript and CSS is a easy way to save bandwidth and make a site’s download and performance feel a bit snappier. There’s lots of tools to allow you to do this, but from my research it seems that Yahoo!‘s YUI compressor is the overall best. Sure there’s others out there like JSmin and Dean Edward’s packer, but YUI offers a higher compression ratio, it also works with CSS files, and it’ won’t obfuscate your code.
Compressors work by removing all comments and whitespace (line breaks), and in some cases they will actually analyze your code and shrink variable names. Using compression can result in up to a 60% decrease in file size! So lets get started in learning how to use the YUI compressor!
Read more...
Posted by Chris Barr on 12/13 at 11:52 PM
Filed under
General,
Web,
Code,
Javascript •
•
Permanent link
Saturday, December 06, 2008
A long time ago I wrote a small plugin for Mootools to resize textareas on the fly, which I simply called Textarea resizer. It was only compatible with Mootools 1.11, and since then Mootools 1.2 has been released and I’ve switched to jQuery for all the stuff I do.
Someone over at ljpilon.nl emailed me to let me know they re-wrote my plugin for Mootools 1.2 compatibility! You can find it over at their site at: http://ljpilon.nl/mootools/2008/12/03/textarea-resizer-for-mootools-12/
Posted by Chris Barr on 12/06 at 03:32 PM
Filed under
Web,
Code,
Javascript •
•
Permanent link
Saturday, November 22, 2008
Recently I needed a way to click a button and add a new row to a table with an animation using jQuery for people to add new data for a section. Simple right? Well I set up my table with a blank row at the bottom that I hid with CSS, and then when I press a button it clones that row it and puts it at the top with a .slideDown() animation. Here's the code I used:
$("#addRow").click(function(){
$("#blankRow").clone().prependTo("#myTable tbody").removeAttr("id").slideDown(500);
});
Looks pretty straightforward right? Well it works, but it doesn't seem to render correctly. Here's a demo of this in action to see what I mean.
Turns out that for most jQuery animations when they complete, the display CSS property is set to display:block;. Normally that's all fine and good, but a table row has to be set to display:table-row;. I can't edit how that animation finishes since it's part of jQuery, so now what?
View a Demo
View the Code
Download It!
Well someone on the jQuery Google Group had the great idea to just fill each table cell with a <div>, put all the contents I needed in there, and simply apply the .slideDown() animations to that <div> since by default they are set to display:block; anyway. Brilliant! Basically we never animate the table row itself, only the elements inside it.
I put together a pretty full featured demo with some other cool jQuery tricks I've been learning recently, so take a look and I hope this will help someone else out.
Posted by Chris Barr on 11/22 at 06:24 PM
Filed under
Projects,
Web,
Code,
Javascript •
•
Permanent link
Wednesday, April 30, 2008
While working on a simple website that didn't need any kind of CMS with it, I came up with a very simple way of creating a dynamic navigation bar with PHP. The code is pretty simple, but I've always done this manually before and this just makes it simple. So here it is.
First we create a function in PHP:
function createNav($title, $link){
if("/".$link == $_SERVER['PHP_SELF']){
return "<li id=\"current\">".$title."</li>\r";
}else{
return "<li><a href=\"".$link."\">".$title."</a></li>\r";
}
}
And then this is how you call it:
echo createNav("Home","index.php");
So if you are on the page that navigation button relates to it will give you <li id="current">Home</li>. If you're on any other page, it gives you <li><a href="index.php">Home</a></li>.
Easy enough. So just call that for each button you need between your <ul> tags:
<ul>
<?php
echo createNav("Home","index.php");
echo createNav("About","about.php");
echo createNav("Products","products.php");
echo createNav("Contact","contact.php");
?>
</ul>
I know it's nothing spectacular, but it sped up the coding process for me once I figured it out, and it will certainly be a lot faster in the future if anything needs to be changed or added.
Posted by Chris Barr on 04/30 at 10:05 AM
Filed under
Web,
Code,
PHP •
•
Permanent link