# ## HTML5 placeholder feature fallback class
class PlaceholderFallback
constructor: (el) ->
@el = $(el)
@initialize()
# HTML5 <input> placeholder feature detection
browserHasPlaceholder: =>
"placeholder" of document.createElement("input")
# Reads the placeholder attribute and uses it in a javascript fallback, if needed
initialize: =>
if @browserHasPlaceholder() == false
placeholderText = @el.attr 'placeholder'
@el.removeAttr 'placeholder'
@el.val(placeholderText)
@el.focus (e) ->
if this.value == placeholderText
this.value = ''
@el.blur (e) ->
if this.value == ''
this.value = placeholderText
else
@el = null
# Usage:
placeholderFallback = new PlaceholderFallback( element )
UI Hacker - Code for Fun
A collection of handy code snippets in the languages that I use on a daily basis.
January 5, 2012
Coffeescript: HTML5 <input> placeholder attribute fallback
You want to use the new HTML5 placeholder attribute on input fields, but you also want to support older browsers. Here's a little Coffeescript class that takes an HTML element in the constructor, and uses jQuery to bind the focus and blur events to swap out text like a modern browser would without the script.
Labels:
blur,
coffeescript,
detection,
event,
fallback,
focus,
input,
javascript,
jquery,
js,
placeholder
December 19, 2011
CSS: Disable text selection highlighting
When working with touch & mouse events to drag html elements, I've occasionally resorted to disabling clicking/touching on child elements by doing something like this:
elem.onmousedown = function(e){ return false; };
elem.onselectstart = function(){ return false; };
But sometimes you want to be able to interact with those child elements... I found some nice CSS over here that prevents text & element highlighting when you're dragging with a mousemove or a touchmove event:
p {
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
December 11, 2011
Coffeescript: MapsLoader class for asynchronous loading of Google Maps API
I'm using CoffeeScript for my current project, and we needed a way to load the Google Maps API when a user hits a particular view. This static class is auto-initialized, and all you need to call is: MapsLoader.load(callbackFunction,true). If the API has already loaded, it will invoke your callback immediately. Make sure to pass the appropriate boolean if the user is on a mobile device (true), or a desktop browser (false).
class MapsLoader
constructor: ->
load: (successCallback,isMobileDevice) ->
@isMobileDevice = isMobileDevice
@successCallback = successCallback
if @hasLoaded != true
@loadGoogle()
else
@mapsLoaded()
loadGoogle: =>
# reference google loader callback to local method - clean up after callback
window.loadMaps = @loadMaps
apiKey = "-----your-api-key-here-----"
script = document.createElement("script")
script.src = "https://www.google.com/jsapi?key=#{apiKey}&callback=loadMaps"
script.type = "text/javascript"
document.getElementsByTagName("head")[0].appendChild(script)
loadMaps: =>
otherParams = if @isMobileDevice then "sensor=true" else "sensor=false"
google.load("maps", "3", {other_params: otherParams, "callback" : @mapsLoaded});
mapsLoaded: =>
@hasLoaded = true
window.loadMaps = null
if @successCallback
@successCallback()
@successCallback = null
@MapsLoader = new MapsLoader()
Labels:
coffeescript,
google maps,
javascript,
Phonegap
October 10, 2011
Javascript: Hide the iOS soft keyboard
I was having some trouble getting my text input field to relieve itself of focus on the iPhone, and after a little searching, I came up with a couple options. It's pretty self-explanatory. The 2nd line will de-focus all input fields, and it relies on jQuery. I found that calling blur() on the single focused textfield didn't always work. Either one of these lines should work independently, but both of them together cannot be stopped!
var hideKeyboard = function() {
document.activeElement.blur();
$("input").blur();
};
September 25, 2011
Given distance and friction, calculate the initial velocity to stop at the distance target
While simulating iOS scroll views in javascript, I needed to find the initial velocity to send the scroll content back into position if you drag it out of bounds. Since the in-bounds scroll view inertia was already working with a given friction, I wanted to use this to run the calculation. After some brute-force experimenting, I came up with the equation to calculate this velocity:
// set up vars
var curPos = 0;
var distance = 2000;
var friction = 0.8;
var velocity = distance / ( friction * ( 1 / ( 1 - friction ) ) );
// in timer:
setInterval(function(){
velocity *= friction;
curPos += velocity;
},30);
The curPos value will ease into the target distance, no matter what you set as the friction and distance. Friction must be a decimal between zero and one.
September 13, 2011
Xcode error: "The argument is invalid"
If you get this error while publishing from Xcode, you may have a rogue symlink in your project. As of Xcode 4.1, symlinks will give you the awesome, helpful error: "The argument is invalid"
Check your project for symlinks, and remove them. If you're symlinking another directory into your project, this would work in the iOS Simulator, but not on a device, so you'd probably want to come up with another strategy for including files from another project.
To help with finding symlinks, run the following command from the root of your project directory. It will list any symlinks and their original location.
find ./ -type l -exec ls -l {} \;
Labels:
bug,
cocoa,
command line,
idevice,
iOS,
objective-c,
Phonegap,
problems,
simulator,
xcode
September 1, 2011
Google Maps API: Polyline encoding/decoding issue
I'm using google's Geometry Library to encode large numbers of GPS location points into a compressed format for storage. You can add this capability to your .js by adding it to the quersystring in the javascript reference:
Encoding works great, but I ran into an issue where some of my encoded paths, generated by google.maps.geometry.encoding.encodePath() from my google.maps.Polyline object, would have major errors when using the google.maps.geometry.encoding.decodePath() method. My Polyline would have random right-angle turns that effectively ruined my path. I played around with the encoded string, trying to figure out what was causing the issue, to no avail. I found another implementation of the polyline encoding algorithm, and found an explanation of what was causing the issue.
It turns out that you need to escape the backslashes that may appear in the output string from google.maps.geometry.encoding.encodePath() (and the other library linked to above). So if you're storing the string for later, you want to do something like this:
Finally, after you set a decoded path as the data for a Polyline, use the following code to fit the Map to the bounds of your path:
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?libraries=geometry&sensor=true"></script>The library provides a very easy way to display a path, add points realtime, store this path as an encoded & compressed string, and feed that string back into a new map when you're ready to display it later. You can see a live example here.
Encoding works great, but I ran into an issue where some of my encoded paths, generated by google.maps.geometry.encoding.encodePath() from my google.maps.Polyline object, would have major errors when using the google.maps.geometry.encoding.decodePath() method. My Polyline would have random right-angle turns that effectively ruined my path. I played around with the encoded string, trying to figure out what was causing the issue, to no avail. I found another implementation of the polyline encoding algorithm, and found an explanation of what was causing the issue.
It turns out that you need to escape the backslashes that may appear in the output string from google.maps.geometry.encoding.encodePath() (and the other library linked to above). So if you're storing the string for later, you want to do something like this:
var encodedPath = google.maps.geometry.encoding.encodePath( _poly.getPath() ).replace(/\\/g,'\\\\');You can then feed that encoded string into a new Map's Polyline instance like so:
_poly.setPath( google.maps.geometry.encoding.decodePath( encodedPath ) );It seems like an oversight that this double-backslash issue isn't mentioned in the Google documentation. I spent hours before trying to figure out the problem in my mobile app before coming across the fix.
Finally, after you set a decoded path as the data for a Polyline, use the following code to fit the Map to the bounds of your path:
var bounds = new google.maps.LatLngBounds();
var path = _poly.getPath();
path.forEach(function( latlng ) {
bounds.extend( latlng );
});
_map.fitBounds( bounds );
Labels:
code,
compression,
encoding,
google maps,
gps,
javascript,
js,
location,
problems
Subscribe to:
Posts (Atom)
