Friday, August 31, 2012

"Dock to right" - Handy for Mobile, iPad, and Fixed-Width Sites

You fire up chrome to test mobile project x, or iPad project y. Next thing you're doing is undocking web inspector so isn't constrained to the dimensions to which you've resized the browser. But then you have to cmd-` or alt-tab between the console and the page you're working on. Annoying. And if you happen to have two of these, it can be even more annoying to keep track of what undocked web inspector belongs to what page.




No more!


To dock to right, open the Web Inspector, click on the gear icon at the bottom right, and check "Dock to right". This feature was made available in the stable channel on Mar 28/v18, so you should either have it or just need to update. You may also be able to accomplish this through the UI element that would normally undock the console - instead of just clicking it, click and hold, and it turns into a little iconized menu where the menu item is a toggle for dock right / dock bottom. One long click vs. 3 clicks - even better!





This feature is fantastic for working on mobile and ipad in portrait mode, but it can also be handy for working on fixed-width sites since they're usually <1024 wide, and you've probably got 1920 pixels of width to work with.


Thanks Chrome/Webkit devs!

Tuesday, March 20, 2012

You're funny, the Onion

Yeah, it's almost exactly the same amount of time to skip the ad as to just finish watching it.


.

Thursday, July 14, 2011

Inventory of text styles for a given psd

TODO - create a tool to capture the inventory of text styles for a given psd

Bonus - batch mode: create an inventory of text styles for all psds in a directory (or at least all open psds).

Sunday, May 15, 2011

On Site Comment

3rd party comment system

  • fb comments
  • disqus
  • intense debate
  • js-kit
  • sezwho

self-hosted comments

  • threaded comments
  • subscribe to replies
  • reply by email

Anti-spam options (for app-handled comments)

  • akismet (free for personal use, not for commercial use)
  • reCaptcha (free, bought by google)
  • app's "own" captcha
  • moderate all comments
  • moderate comments if they contain N or more links (default: N=1)
  • only allow comments from authenticated users
  • autoapprove comments from a commenter after first approval
  • moderate all comments for content items older than X days
  • close commenting for content items older than X days
  • ip-based throttling (system will only accept N comments per M units of time from a given IP)
  • system-wide throttling (system will only accept N SYSTEM-WIDE TOTAL comments per M units of time)

Security by obscurity?

  • require random special inputs
  • disallow extraneous inputs
  • require that a form take at least N units of time to complete (spammers may submit immediately, people take at least a couple seconds to type something)

Suggestions from "User-generated spam - Webmaster Tools Help"

http://www.google.com/support/webmasters/bin/answer.py?answer#81749

  • rel#"nofollow"

Use a blacklist to prevent repetitive spamming attempts.

  • Google often sees large numbers of fake profiles on one innocent site all linking to the same domain. Once you find a single spammy profile, make it simple to remove any others.

Add a "report spam" feature to user profiles and friend invitations.

  • Your users care about your community and are annoyed by spam too. Let them help you solve the problem.

Monitor your site for spammy pages.

  • One of the best tools for this is Google Alerts. Set up a site: query using commercial or adult keywords that you wouldn't expect to see on your site. Google Alerts is also a great tool to help detect hacked pages. The Keywords page in Webmaster Tools lists significant keywords found on your site, so it's a good idea to check this regularly for unexpected and volatile vocabulary.

// (end content from google.com)

Further thoughts and links

Monday, June 21, 2010

Table Row Height Reported Wrongly

Turns out that in all current browsers there may be a 1 pixel discrepancy between the reported height of a table row and the actual height of the table row.

Not only that, but identical table rows in the same table may differ in height from each other.

Figure 1

Friday, November 20, 2009

IE9 First Look

The folks over at the IEBlog just posted An early look at IE9 for developers.

Synopsis:

Javascript: almost as fast as ff 3.5, about half as fast as chrome. They brag about improved js speed, then turn around and slightly downplay the importance of it, pointing to the fact that there are many other factors that affect page render time.

CSS: They explain why they only got 32/100 on the acid3 test: Regarding the technologies that acid3 tests, "many [are] still in the “working draft” stage of standardization". (Editorial: And what? You don't deign to implement things that haven't fully settled down to your satisfaction? You're not getting any brownie points with consumers or developers with that attitude, IE team. Remember the good ol' days when you *invented* and implemented the standards before anyone else? Remember how it was that risk-taking, can-do, forge-ahead attitude that won you the browser war? You won't win this one by waiting for the spec to become 100% final before you dare to touch it.) Then the good news: we've got rounded corners now. CSS3 selectors seem to be coming along swimmingly, passing 574/578 tests on css3.info.

But perhaps the best news?

"We’re changing IE to use the DirectX family of Windows APIs to enable many advances for web developers. The starting point is moving all graphics and text rendering from the CPU to the graphics card using Direct2D and DirectWrite. Graphics hardware acceleration means that rich, graphically intensive sites can render faster while using less CPU."

Friday, September 25, 2009

Preload Images the Right Way

Sure, all of us cringe a little when we see that phrase. Even so, for things like overlaysof which modals and tooltips are memberspreloading the background images is a reasonable thing to do. (I still don't fully endorse it, more on that later.)1.

I tried this preload code:


(function(){
    var i, img, imageLoader = {
        imagesToLoad: [
            'resources/css/images/btn-default-sprite.png',
            'resources/css/images/bg-tooltip-left.png',
            'resources/css/images/bg-tooltip-right.png',
            'resources/css/images/bg-tooltip-image-left.png',
            'resources/css/images/bg-tooltip-image-right.png'
        ],
        loadedImages: []
    };
    for(i in imageLoader.imagesToLoad){
        img = new Image();
        img.src = imageLoader.imagesToLoad[i];
        imageLoader.loadedImages.push( img );
    }
})();

The images didn't seem to be loading any sooner though. So I put a tracer in the list - an image source reference that I knew didn't exist. Then I fired up the page and looked at fiddler. (I would've looked at firebug's net tab, but I was troubleshooting IE6 specifically.) No 404s. So then I tried this code:


(function(){
    var imagesToLoad = [
        'resources/css/images/btn-default-sprite.png',
        'resources/css/images/bg-tooltip-left.png',
        'resources/css/images/bg-tooltip-right.png',
        'resources/css/images/bg-tooltip-image-left.png',
        'resources/css/images/bg-tooltip-image-right.png'
    ];
    $('<div class="no-print" style="position:absolute;left:-9999px"/>')
        .appendTo('body')
        .html('<img src="'+imagesToLoad.join('"/><img src="')+'"/>');
})();

And I got my 404.

For the purposes of this discussion, preloading doesn't mean loading the images before the rest of the page, it means loading them before they're used.

Monday, August 24, 2009

Beyond Sprites - The New WAR

I was just looking at a set of image files which are used to decorate custom form elements. I was analyzing how best to turn them into sprites1. One particular set of 3 images caused me to dream up a 'new' web standard: a resource tar.

The set was a left end-cap, a right end-cap, and a repeatable middle section to accommodate a control of fixed height but variable width. The end caps were say, 20px wide, but the repeatable middle section image was - and only needed to be - 1px wide. Now, if I were to combine the 3 in a stacked sprite, the 1px wide middle section would have to be stretched to the 20px width to match the end-caps. True, widening the middle section would compress well in PNG or GIF format - as it was destined to become -- but these were just 3 of the 20 or so images. I could make the tiny sacrifices along the way and probably create 7 sprites out of the 20 images .. but that's still 7 http requests.

Maybe right now you're thinking what I was - there should be a way to send all 7 at once. And if there was a way to do *that* - then why muss about with all this sprite nonsense at all2? Just leave the images alone in their 20 separate files, but send them all in one jar. It would be the browser's responsibility to interpret a jar file that came from "http://site.com/path/to/jars/jarfile.jar" and had an internal directory structure of
/.
/img/
/img/1.gif
/img/2.gif
...
so that the images could be referenced in CSS as "http://site.com/path/to/jars/img/1.gif", "http://site.com/path/to/jars/img/2.gif"...

So what's with the title phrase "the new WAR"? Sending along the image assets for custom controls is just one application of this new "jar" or "war" file concept. Another is to send a packet that has the base images for a site: the logo and primary site decoration elements. Other people may conceive of other sets of resources that it make sense to combine and send along together in one packet.

1 For an excellent description of sprites, including some fantastic examples, see The Mystery Of CSS Sprites: Techniques, Tools And Tutorials.

2 Ok, the reason to still create the sprites is so that 'older' browsers - you know, the ones that don't have this as-yet unproposed feature - will still have 7 http requests instead of 20 (instead of the 1 they could have with this!)

Saturday, August 22, 2009

Auto-close open overlays


GLOBAL = {
    //...
    //...
    init:function(){
        //...
        //...
        //wire up language selection .. assuming it will be on [nearly] all pages.
        $('#glb-hdr-toolbar .heading').bind('click keypress',function(e){
            if(!e.keyCode || e.keyCode == 32 || e.keyCode == 13){ //32=space, 13=enter
                var p = this.parentNode;
                $(p).toggleClass('open')
                //keep track of open overlays so that we are able to intelligently auto-close-open-overlays
                GLOBAL.overlays.pushUnique(p);
            }
        });
        
        //wire up intelligent auto-close-open-overlays
        // part of the convention, or 'magic', is that a className of "open" is used to control whether the overlay is 'open'.
        $('body').bind('click keypress',function(e){
            if(!e.keyCode || e.keyCode == 32 || e.keyCode == 13){ //32=space, 13=enter
                var targ = e.target,
                    i = 0,
                    keepOpen,
                    list = GLOBAL.overlays.list;
                ///
                while(targ && ++i<10){
                    for(var j in list){
                        if(targ == list[j]){
                            keepOpen = list[j];
                        }
                    }
                    targ = targ.parentNode;
                }
                
                for(var j in list){
                    if(keepOpen != list[j]){
                        $(list[j]).removeClass('open'); //or, we could just .hide() it... or similar... 
                    }
                }
                
            }
        });
    },
    
    //keep track of open overlays so that we are able to intelligently auto-close-open-overlays
    overlays:{
        list:[],
        pushUnique:function(o){
            var l = GLOBAL.overlays.list;
            for(var i in l){
                if(l[i] == o) return;
            }
            l.push(o);
        }
    },
    //...
    //...
};

Wednesday, August 12, 2009

Offscreen, not invisible.

Ran into this .. had a container that I was hiding with visibility:hidden, while loading markup into it.

Worked great except, of course, for all versions of IE. IE wouldn't show the badge until you moused over it. I tried all the usual IE slap-in-the-face-so-you-behave tricks to no avail (zoom, position, z-index, background, borders).

So I chose to hide the container by positioning it offscreen with left:-9999px. Bingo.

The particular content I was loading was a linkedin iframe badge - the "inline" version off their developer api page. I was loathe to switch over to the "popup" version, and am glad I dodged that bullet.

Wednesday, July 8, 2009

custom scrollbar

jScrollPane .. I've heard bad things about it.

fleXscroll .. I've used it, it's nice, but it's not free.

jsScrolling .. I haven't used it, but it looks nice and it's free.

Improved email validation, plus multiple emails validation

jQuery validation plugin .. was causing ff2 to choke. It also didn't have a multiple-email validator .. or a split-up phone validator -- although on that last one, I highly advise you push back - a phone # field should just be ONE INPUT.


Tuesday, July 7, 2009

The *real* way to disable text selection

I was recently asked by UX to make the text of my fancy custom dropdown selects unselectable. A lot of silly scripts out there that disable text selection are application-unfriendly. They go beyond unselectable and make the element totally non-interactive. But I still want the dropdown to work when you click it. Solution = css for the "good" browsers, and javascript for internet explorer.

CSS


.unselectable{
    -moz-user-select: none;
    -webkit-user-select: none;
}


JS


if(document.attachEvent){
    function returnFalseFn(){
        return false;
    }
    jQuery('.unselectable').each(function(){
        this.attachEvent('onselectstart', returnFalseFn);
    });
}

Wednesday, June 24, 2009

Strange IE6 bug - show/hide select, hemorrhage option innerHTML

We've all had to code up those ever-so-fun branching selects. I chose to implement it by showing or hiding (display:block/none) the container of the label+select corresponding to the appropriate branch. And IE6 decided to hemorrhage option innerHTML onto the page - for 1 of the 3 branches: the middle one. I solved it by adding "position:absolute" to the css for the container.

Friday, June 12, 2009

Some cross-browser findings

ff2 mac: doesn't understand floating-point percentages (ie: 107.3% = 107%) - ran into this with font sizes.

ff3 thinks that if your parent is visibility:hidden, but you are visibility:visible, that you should display. (wrong.)

IE8 VHD from microsoft on vpc2007 is not the same as ie8 in the wild. Button element widths seem to be at least 1px wider in the wild.

Friday, May 22, 2009

A Little Elementool Love

I started a google code project because I've been using elementool lately and felt that it needed some help.

Elementool firefox greasemonkey userscript

Current features

  • Adds row-highlight rollovers
  • Click anywhere to go to the only link in that row (that bug)

Suggestions welcome!

Friday, May 15, 2009

JASH - debug safari

Need to debug javascript/css on .. safari? Sure, the thing is coming along in that respect, but its built-in tools and even firebug lite just don't cut it sometimes. Give JASH a go.

(Not sure I'd recommend JASH for ie debugging, since the script debugger / debugbar / ie developer toolbar are a little more convenient)

UPDATE: I've used JASH a little more, and found it useful a little less.

jQuery settles down with dojo, gains weight

Sure, this is months-old news, but still. I remember back in the good ol' days when jQuery was a young, athletic rising star. Then it met dojo and settled down.. and gained weight. Look under the jQuery hood and you'll see .. two libraries blast-welded together, complete with their own separate prenups, er, copyright blocks: jQuery and Sizzle, from the dojo foundation.

Wednesday, May 13, 2009

Disabled input fires no events

Evidently, a dom node "<input disabled="disabled"/>" will not fire any events, even if you do, say, something as direct as this: "<input disabled="disabled" onclick="alert('clicked it.');"/>"

Tuesday, May 12, 2009

IE JSON silent fail - size limit

Trying to get a ton (600K) of JSON via XHR into IE.. silently failing. Oh, it fetches the data, it just can't parse the data, either through jQuery's built-in JSON parsing or even by the ol' eval.

Trimming the data down to 60K, there were no problems. The data is a repeating set of dummy objects, so I'm almost certain that I didn't just happen to trim out some problem section of the data. I'm convinced that IE is choking on the data simply because it is more than it can handle. My guess is that JScript doesn't throw the usual "your script is taking too long to execute" warning when executing a single "eval".

I 'solved' the problem by ditching XHR and using dynamic script tags:

data.js


namespace.onData({theGigantic:json............});