Pull to Refresh

Pull to refresh is a common design pattern amongst major mobile apps. Facebook, twitter, gmail, etc all use a “pull to refresh” technique. In my previous post on the new Quick Return design pattern, I discussed a way to implement this in a desktop environment. Now, I present to you, how to implement the “Pull to Refresh” design pattern on the desktop:

Demo

Usage:

Simply download the JS source or copy/paste the JS source below and include it in your markup.

A global, called Refreshable, becomes available once the script is included. To use, you can call its initialize(), which takes in 2 options as an object{}:

  1. refreshAction
  2. refreshContainer

refreshAction must be a function. It is the action you want to bind to the refresh event triggered on the refreshContainer.

refreshContainer needs to be addressed by an ID. The script, at this time, doesn’t support an array of elements.

So, in the source below you’ll see where I initialized it saying:

Refreshable.initialize({
refreshAction: function() {
$.getJSON("http://date.jsontest.com/", function(data) {
$("#container p").html("Today is " + data.date + " and it is " + data.time);
});
},
refreshContainer: "#container"
});

I’m passing in a function that goes and fetches the current date and time from a provider, then updates the container w/ this information.

HTML:

<div id="container" class="container">
<p>Pull my bottom</p>
</div>

CSS:

.container { 
width: 350px;
height: 350px;
padding: 5px;
margin: 5px;
background: #ccc;
position: relative;
border-bottom-right-radius: 10px;
}

JS:

var Refreshable = (function () {
var refreshAction;
var refreshContainer;
var $refreshContainer;
var refreshContainerHeight;
var refreshElString;
var $refreshEl;
var offset;
var offsetDiff; startHover = function (evt) {
$(this).css("background-color", "rgba(0,0,0,0.5)");
}
stopHover = function (evt) {
$(this).css("background-color", "transparent");
}
allowResize = function (evt) {
evt.preventDefault();
$refreshContainer.addClass("resizable");
offset = evt.pageY;
}
stopResize = function (evt) {
$refreshContainer.removeClass("resizable");
$refreshContainer.animate({
height: refreshContainerHeight
});
offset = 0;
}
resize = function (evt) {
if ($refreshContainer.hasClass("resizable")) {
offsetDiff = evt.pageY - offset;
if (offsetDiff > 0) {
$refreshContainer.innerHeight(refreshContainerHeight + offsetDiff);
}
if (offsetDiff > refreshContainerHeight * 0.25) {
$refreshContainer.trigger("refresh");
}
}
}
var refreshIt = function () {
stopResize();
refreshAction();
} return {
initialize: function (options) {
refreshAction = options.refreshAction;
refreshContainer = options.refreshContainer;
$refreshContainer = $(options.refreshContainer);
refreshContainerHeight = $(refreshContainer).innerHeight();
refreshElString = '<div class="refreshEl" style="position:absolute; width: 100%; height: 45px; bottom: 0; left: 0; cursor: s-resize; outline: 50px transparent solid; z-index: 999999; border-bottom-right-radius: 10px;"></div>';
$refreshContainer.append(refreshElString);
$refreshEl = $refreshContainer.children(".refreshEl").first();

this.eventRegister();
return this;
}, eventRegister: function () {
$refreshContainer.on("refresh", refreshIt);
$refreshEl.on("mousedown", allowResize)
.on("mouseup", stopResize)
.on("mousemove", resize)
.on("mouseleave", stopHover)
.on("mouseover", startHover); }
}; })();
//Code you saw before Refreshable.initialize({
refreshAction: function() {
$.getJSON("http://date.jsontest.com/", function(data) {
$("#container p").html("Today is " + data.date + " and it is " + data.time);
});
},
refreshContainer: "#container"
});

I wanted to keep the CSS down to a minimum for portability. The CSS included is simply for the container to serve as a demo, it doesn’t have to be followed strictly.

The only requirement of the CSS is that it needs to be positioned relatively. Otherwise, the refresh element appended to the bottom will not seat inside the container.

That’s all I have for now. As with my other posts, I’ll be making edits to make the code better, more extendable, etc.

Thanks for reading.

 

Actually Vertically-Aligned CSS (no javascript necessary, horizontally aligned bonus!)

.vertical-align-container { height: 100%; position: absolute; top: 0; right: 0; bottom: 0; left: 0; text-align: center; }
.vertical-align-container::after { content: ''; display: inline-block; height: 100%; margin-right: -0.25em; vertical-align: middle; }
.vertical-align-container > .vertical-align-content { display: inline-block; vertical-align: middle; }

That’s it. That’s the magic secret.

For those of you that just want to c/p to see it for yourselves:
<html>
<head>
<style>
.vertical-align-container { height: 100%; position: absolute; top: 0; right: 0; bottom: 0; left: 0; text-align: center; }
.vertical-align-container::after { content: ''; display: inline-block; height: 100%; margin-right: -0.25em; vertical-align: middle; }
.vertical-align-container > .vertical-align-content { display: inline-block; vertical-align: middle; }
</style>
</head>
<body>
<div class="vertical-align-container">
<div class="vertical-align-content">
Here is something vertically aligned
</div>
</div>
</body>
</html>

I hope you find this helpful. If you do –

Follow me on twitter @william_beard

Sanitize Backbone.js Models to prevent XSS

This isn’t groundbreaking code, but you may find it useful to know how to take a step to prevent XSS attacks when implementing Backbone MV*. Some JavaScript frameworks automatically escape or sanitize the values being passed to the model. Backbone does not. However, the library it’s built on (Underscore.js) does provide an easy way to escape values.

First, in your Model, create your initialize() method, and in it, use the _.each method to iterate over the attributes object, passing the value to a method belonging to the Model named “sanitize”.

var CartItem = Backbone.Model.extend({
  initialize: function() {
    _.each(this.attributes, function (val, key)
      this.set(key, this.sanitize(val));
    }, this);
  }
});

Let’s add our sanitize() method. In this method, simply take in the string as a parameter, and return the escaped version of it, using Underscore’s _.escape method.

var CartItem = Backbone.Model.extend({
  initialize: function() {
    _.each(this.attributes, function (val, key) {
      this.set(key, this.sanitize(val));
    }, this);
  },
  sanitize: function (str) { 
    return _.escape(str) 
  } 

});

I recommend sanitizing in your model’s initializer so that you ensure it’s properly scrubbed before calling Model.save() and sending nasty XSS or SQL injection to your server. Also, sanitize anywhere you update the model or allow edits to the model.

I hope you found this post useful. If you have anything to add or find any problems, let me know.

formValidator.js – Simple jQuery form validation plugin

Made my first jQuery plugin for validating forms on the front-end, before submit. It has some options as well to make it more flexible for your needs.

To use the plugin, please download the source from my github repo: https://github.com/wbeard/formvalidator

I plan on adding more to it. Here are some things to cover:

To Use:

import jQuery 1.72 js file

import validate.js file

link validate.css file

attach to desired form (e.g. $(“selector”).formValidator();

can take options such as background & color for customization (e.g. $(“selector”).formValidator({ “background”: “red”, “color”: “white” });

when you define a dom element add the appropriate classes for validation to happen on change or keyup, whichever is defined in the plugin

Classes:

required – defines required input

numeric – requires numeric input

phone – masks text with (###) ###-####

date – masks text with date mm/20yy

card – accepts only 3,4,5, or 6 as valid first character and determines appropriate max length of cvv input box and itself

email – simple regex expression being checked against

Options:

background – Sring value. Background of tooltip, default is transparent

color – String value. Font color of tooltip, default is red

orientation – String value.  Position of tooltip. Valid options are right, top, left, or bottom. Default is right.

disableSubmit – Boolean. Determines whether submit button associated with selected form should be disabled until all fields are valid. Default is true.

excludedList – If there are other buttons being selected and you would like to explicitly not select them, pass them in an array,  with a jQuery selector, e.g. $(“.selector”)

Feel free to check out the source or fork at https://github.com/wbeard/formvalidator/

I’ll be making this more scalable and easy to use. Its been made more specifically for an .aspx page for collecting payments, so some of its quirks were caused by the quirks of creating jQuery for aspx & .net. I’ll be making a more generic approach and will update accordingly.

Thanks!

Finding Motivation

The ThinkerIs it bad to be motivated by jealousy? Or the want to rub your success in somebody else’s face? To get the satisfaction of telling them, “I told you so”?

It’s hard to find motivation in this world. There are so many cliche reasons out there to strive to be the best, perhaps it’s healthy to have motivation, no matter the means.

This sort of internal conflict reminds me of the dogma of Jedi vs. dogma of the Dark Side. One is more powerful than the other, they are both driven by 2 completely different emotional forces. But, one is more sustainable than another. Who then, is right?

It’s hard to say.

In time

Love: We fall in it and out of it as if it were a net. We make it as if it were an object. We have it for others from family, to friends, to significant others. Yet, none of us can agree on what it is, or how to define it.

Life: It is nothing but a soil through which we extend our roots. Experiences are the minerals which enrich us and spread our roots through life. Once in a while, our roots cross and grow through the roots of others. The more experiences you physically share with others, the longer your connection through life lasts. The less you experience with others, the more in solitude you grow.

Finite

Photo by Jordan Douglas

A calm, glistening sheen of blue,
Reflects a life so unfamiliar to millions.
And conceals an entire truth,
Held by a life which stands with resilience.

It’s exposed the life of one
Who stands tall but alone.
Outgrown by its will to the sun,
The ground has decayed and its roots are shown.

The persistent nature of nature itself,
In where a cycle destroys a life,
Seems to make room on a shelf,
And pounds like a drum to give a rhythm to strife.

Though, what makes this exception so uncanny
Is not found in its persistency,
But rather, in its foundation
And overexposed consistency.

So, how can one who shows his cards,
Win with a hand of such low probability?
Perhaps it’s the faith in what he possesses,
Knowing nature could not replace such rarity.

Photo by Jordan Douglas

Gulf Coast Entrepreneurs: Moskeedo

I’m contributing this to Pensacola State College’s eCorsair as well, but figured that there was some merit to having this on my blog as well, seeing that I’ve yet to make a Tech contribution to my blog. Lately, I’ve really gained an interest in the Tech startup world and have been so busy reading Mashable and Techcrunch, my writing has been shriveled into nothing. Here goes the first series in what I’m calling “Gulf Coast Entrepreneurs”.

You don’t have to live in Silicon Valley to start and grow a successful tech startup. Boston, New York, Austin, and even our neighbors over in Tallahasse, at Silicon Tally, are all trying to incubate the latest and greatest ideas in technology.

Recently, I sat down with a local developer and entrepreneur, Will Ricketts. I picked his brain on the subject of his upcoming app, Moskeedo, the challenges for other developers, and the state of affairs of the mobile world.

First off, where did you grow up? Was it around here? Did you go to school here?

Continue reading

I always think of titles later

He puts mends on fences,

People, places, and their expenses

Never focuses on their intentions

No, he’s never been that sensitive

To the true means and ways

Of the businessmen these days

He puts on his blinders and pays

No attention to those sorts of things

Until one day he was dead

Found with a gun to his head

He had three notes by his bed

One word on each page, they read

“Love” and “Life” and written in between

Was one word, four syllables: “Everything”

It was then in that moment that John had seen

Not a world for what it was, but what it had to be.

Putting Together the Petals: A Chronological Analysis of “A Rose for Emily”

I’ve been getting a ton of traffic on this post recently. Please leave comments if you have any questions or found it hard to read in this format on WordPress. I’d like to learn a little more about why you’re reading it. Doing a term paper? Just a fan of William Faulkner?

As the sleepy reader saunters through the meadow of Faulkner’s A Rose for Emily, he may make his way through its many different paths. Most power-walk their way on a straight path, the most efficient and timely. They see the Old South juxtaposed to the New, the dilapidated cotton gins absorbed by gas stations, the antiquated mansions and Emily Grierson, the loner; all the fundamentals of a Southern Gothic. Others take the long road and discover the forest is scattered, telling its story with convoluted minutia easy to trip over and not easy to see. Faulkner, in his true style, has written a story in a way never thought possible of a literary scholar, mathematically. What are the motives in making the recollection of time scattered about like leaves on a lawn? From an author’s point of view, it could be to confuse the reader and persuade him to criticize the text more and more until the puzzle is solved. Thinking as a narrator, it could be to obscure the events into a story more convenient for their purposes. The possibilities of both the intentions and the methods are endless. To me, the author and the narrator come to a point of agreement as to what the intention of the story is when speaking of the confederate soldiers at Emily’s wake. The soldiers were said to recall the times that “…they had danced with her and courted her perhaps, confusing time with its mathematical progression, as the old do, to whom all the past is not a diminishing road but, instead, a huge meadow which no winter ever quite touches…” (Faulkner 34). I believe Faulkner, ultimately, demonstrates that a memorable artifact has been lost and it will soon be forgotten by a progressing society.

Continue reading