Archive for the ‘Web Technologies’ Category

Reflex Feedback 0.3

A small update to the Reflex Feedback Widget,

  • Design tweaks (border, box-shadow, border-radius on textarea; padding-top on copyright)
  • widgetPos argument added to init(), valid values => ‘left’, ‘right’

reflex feedback widget 0.3

So you can now position the widget on the right edge of the page like this:

Reflex.init($('body'), 'controller/post_feedback.php', 'right');

More info about the widget itself can be found in the original blog post.

dotspott public pages

New feature added to dotspott earlier this week: you can now create a public URL for any of your spotts, which will generate a page that looks something like the following,

dotspott public page, 63 bites

… and is accessible to anyone on the web.

Currently this can only be done from the web client:

  • Login
  • Click “Share…” on the submenu for the spott you want to make a link for
  • Click the “Make Public” button; the spott will be made public and the URL will appear

Note: All spotts are private by default; they can only be seen by you when you login or by someone with whom you’ve shared the spott info via email.

Edit: I should mention this is a proof of concept of Unity. There are actually no async calls beyond those for Google Maps.

Reflex Feedback 0.2

An updated version of the Reflex Feedback widget is now up.

Changes:

  • New icons done by myself and released under the same license as the code; no longer using the ones by Yusuke Kamiyamane. This should also make it easier for those who want to do custom modifications as they don’t have to worry about an attribution requirement for the icons.
  • New menu layout and new buttons. Now using jQuery UI buttons for everything, which allows for compatibility with jQuery UI styling, ThemeRoller, etc.
  • CSS fixes to prevent some inherited styles from screwing up layout.

reflex feedback widget

For info on how to use the widget, see my original post on Reflex Feedback.

NYC yum yum

NYC yum yum is my web app for the NYC Big Apps 2.0 competition.

NYC yum yum

It’s a very simple app for quickly finding restaurants by cusine + location. For each resturaunt, it shows the restaurant inspection grade, to give you an idea of how clean and safe the food at the establishment is, and also pulls the Yelp star rating to give you and idea of how good the food is.

NYC yum yum front page

NYC yum yum results

Search by cuisine and location (specifically, neighborhood) I felt was really important. Searching by name is, of course, much simpler, but when it comes to finding a new restaurant your likely not to know the name beforehand. Even if you have been to the restaurant before, unless it’s a regular spot for you, you’d likely still has issues remembering the name given the number of places to eat in New York City.

That said, this was far more difficult than I anticipated and I’m sad to say the current implementation is far from ideal. Here’s why:

  • The raw data set from the NYC Data Mine contains no geographic coordinates (latitude, longitude), so to get an accurate location, the address must be geocoded. There are a number of services to do this, but they’re all pretty limited. Google’s Geocoding API was my first choice, but I was wary of the terms of use,

    … the Geocoding API may only be used in conjunction with a Google map; geocoding results without displaying them on a map is prohibited. For complete details on allowed usage, consult the Maps API Terms of Service License Restrictions.

    My second choice was geocoder.us, but it had issues geocoding locations outside of Manhattan. So I put aside the idea of doing a geocode.
  • My next attempt was to do queries by neighborhood. Surely, it would be easy to translate between neighborhoods and zip codes, right?! Nope. All I could find were commercial services (e.g. maponics) that did it, and I wasn’t willing to go down that road.
  • My final attempt and what’s implemented, is grabbing the zip code from the the marker location on the google map. This sorta works. The problem is that the area covered by a zip code doesn’t necessarily match up exactly with a neighborhood’s boundary. So a restaurant that may not be shown in the search if it falls into an adjacent zip code.

My big disappointment is how restrictive and inaccessible all of this geographic data is, and the lack of such data severely compromises the effectiveness of the search.

Another, somewhat major issue with the raw data set is how restaurants are categorized. I’m noticing tons of establishments are simply identified with the cuisine type of “American.” For example, B Cup is a café in the East Village. If I was looking for it, I would search for “Café/Coffee/Tea” not “American.”

NYC yum yum

In fact, I think “American” is way to generic to describe any sort of cuisine.

In any case, NYC yum yum still works pretty well and does hit of the target of being able to find good, clean places to eat at, quick and easily. I’ll likely be working on improvements to it in the near future.

Edit: mixed up geocoding and reverse geocoding

dotspott photo markers

The dotspott web client has been updated yet again, this time I’ve added support for photo markers.

dotspott photo markers

Reflex Feedback widget

I worked on a small AJAX widget for user feedback built atop jQuery UI: Reflex Feedback. It’s inspired by the widgets you see from services like Get Satisfaction and UserVoice, but much simpler and it’s a frontend-only widget, how you handle the feedback info on the backend is up to you.

Here’s what it looks like.

reflex feedback widget dialog

And here’s what the tag that opens the dialog looks like:

reflex feedback widget tag

To use it, download or clone the ReflexFeedback repo from bitbucket

Place the .js file wherever you’d like but the /reflex.content folder should a subdirectory in the same folder as the page loading the .js file. Load reflex.js as you would any other javascript file:

<script type="text/javascript" src="js/reflex.js"></script>

Call Reflex.init() to add the widget to the page. The first argument is the DOM element to attach the additional HTML/CSS code to. The seconds argument is the server-side script to call when the user clicks Send Feedback.

Reflex.init($('body'), 'controller/post_feedback.php');

That’s it for the frontend. You should see the tag show up in the right-hand corner and when clicked the dialog open.

For the backend, the AJAX call to send the feedback info will send a POST request with 2 fields: feedback_type, feedback_txt.

Reflex expects an XML reply from the server:

<reflex>
<result>ok</result>
</reflex>

ok indicates a successful result, any other reply is considered an error.

A successful result will close the dialog and show another with a thank you message.

reflex feedback thank you dialog

For an error, a message is shown below the Send Feedback button, informing the user that an error has occurred and to try again.

reflex feedback send fail

As for what to actually do with the feedback, that’s up to you, but what I’m doing is sending myself an email with the feedback info. I’ve posted my PHP script below; feel free to use it, modify it, etc. If you do use this code, be sure to fill in your mail server credentials and a from address; you’ll also need PEAR’s Mail package installed.

<?php

require_once "Mail.php";
require_once "Mail/mime.php";

header('Content-type: application/xml; charset=utf-8');
echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n";

if(!isset($_POST['feedback_type']) || !isset($_POST['feedback_txt']))
{
echo "<reflex><result>error:missing-arguments</result></reflex>";
}
else
{
$from = "...";
$to = "...";
$subject = "Feedback from user...";

$feedback_type = $_POST['feedback_type'];
$feedback_txt = $_POST['feedback_txt'];

$bodyHtml = "<html><body>";
$bodyHtml .= "<p>Type: {$feedback_type}</p>";
$bodyHtml .= "<p>Feedback: {$feedback_txt}</p>";
$bodyHtml .= "</body></html>";
$body = $bodyHtml;

$host = "...";
$port = "...";
$username = "...";
$password = "...";

$headers = array('MIME-Version' => '1.0rn',
'Content-type' => 'text/html; charset=utf-8',
'From' => $from, 'To' => $to, 'Subject' => $subject);


$smtp = Mail::factory('smtp',
array ('host' => $host,
'port' => $port,
'auth' => true,
'username' => $username,
'password' => $password));

$mail = $smtp->send($to, $headers, $body);

if (PEAR::isError($mail))
{
$err_details = $mail->getMessage();
echo "<reflex><result>error:send-failure</result><details>{$err_details}</details></reflex>";
}
else
{
echo "<reflex><result>ok</result></reflex>";
}
}

?>

That’s all for now. I’ll work on more features and options for customization in the future. You can see the widget in action over at dotspott.com

Local search on dotspott

Local search is now available on the dotspott web client; allowing you to search for local venues and add them to your list of spotts.

dotspott local search for cocoa bar

The Google Maps API v3, which is used by dotspott, doesn’t really allow for local search and the Local Search API itself is deprecated (however, as per Google’s deprecation policy, it should be available until Nov. 2013). What I did was use gmaps-api-v3-googlebar, which allows adding a google-bar like control to the map.

One interesting thing I needed to do that wasn’t directly possible with gmaps-api-v3-googlebar update a few other things after one of the search results were selected. I wanted to avoid touching the gmaps-api-v3-googlebar code, so I did this by getting a reference to the existing event handler, then overwriting it with a new function, which called the previous event handler function.

Here’s an example where we grab the reference to the existing selectResult event handler (searchResultPre), overwrite with a new event handler, call the previous handler (binding to window.gbar, the instance of window.jeremy.jGoogleBar; binding is necessary b/c the event handler references this internally), then add some new functionality where we modify a paragraph element in the DOM (id = map_position) to show the position of the local marker that is selected.

selectResultPre = window.jeremy.jGoogleBar.prototype['selectResult'];
window.jeremy.jGoogleBar.prototype[
'selectResult'] = function (result)
{
selectResultPre.call(window.gbar, result);

    
var searcher = window.jeremy.gLocalSearch.searchers[0];
    
var results = searcher['results'];
    
var lmarker = result['marker'];

    $(
'#map_position').text(lmarker.getPosition().toString());
}

oh, and yes, this is using jQuery; $(‘#map_position’) should have given it away.

@font-face

I’ve always played it safe with fonts when it comes to web design, sticking to fonts commonly available across operating systems such as Verdana, Tahoma, Trebuchet MS, etc. However, I’m pretty psyched to see how well the CSS @font-face attribute is supported. Format support is somewhat of a mess: EOT for Internet Explorer and TTF/OTF for WebKit-based browsers (Chrome, Safari). However, Firefox 3.6+ supports the new Web Open Font Format, which is poised to become the new standard and will, hopefully, quickly find it’s way into the other browsers.

If your in Firefox, Safari, or Chrome, here’s a font I’ve loved for a while, Titillium:

TitilliumText999wt

I’ve never really had problems finding fonts for free or even commercial use, but Font Squirrel now makes the whole search process dead simple and super easy. They also seem to have a pretty awesome converter; though I used this oft2woff converter for my little demo above.

dotspott

I’ve been working on a fairly major update to hotspotdot, both the web client and the webOS mobile app.

First, a new name, accompanied by a new logo.
hotspotdot is now dotspott:

dotspott logo

This should (hopefully) put an end to any confusion that the app has anything to do with wi-fi hotspots. It also allows for a much nicer URL as I was able to get dotspott.com (much more elegant compared to the previous, my.hotspotdot.net).

There’s some minor style changes to the index page. Also, some additional code for some minor improves in user experience, such as auto-focus on input fields when a dialog comes up.

dotspott index page

The most significant changes are to the main interface. There’s a new look and you’ll notice support for uploading photos. Also, there’s now a 2-column layout; this avoid the issue of having to keep scrolling down the page to show a new location on the map (which was at the top of the page). The map and header areas are fixed (position: fixed), so as you scroll, only the list of locations on the left will move. I debated whether to do this or to contain the list of locations in a div with overflow:auto or overflow:scroll, so the list would have its own scrollbar, and you wouldn’t scroll the entire page to move up and down the list. I have somewhat of a dislike for both solutions, although one was necessary. I opted for the position:fixed approach because manipulating scrollbars within a page is impossible on a touchscreen device (perhaps we’re at the time where we’ll see the end of overflow:auto and overflow:scroll, along with :hover)

dotspott main interface

The updated webOS app is almost done. I’m just doing some last minute testing before I put it up in the app store, so I’ll have some info and screenshots up soon.

Edit: h/t to Shifting Pixel for the cool Smart Image Resizer; I really wasn’t feeling up to writing image resizing and caching routines, and this little library was a perfect solution.

Share hotspots via email

A small, but useful addition to hotspotdot: you can now share hotspots via. email.

hotspot shared via. email, shown in gmail client

Currently only available on the web client, but this and a few other features will soon make their way into the webOS mobile app.

At one point I did consider making a larger social networking component integrated into the site – sharing hotspots with other hotspotdot users – however, I don’t think this would have been very useful, certainly not to me. In many ways hotspotdot is fairly anti-social, focused much more on functionality revolving around maintaining your personal repository of locations rather than the current location of your friends and whether or not they’ve checked-in at some commercial venue; the concept underlying other location services such as Google Latitude, foursquare, and Facebook Places.