Data from parse.com

In Color scheme explorer we take the color table from Parse.com. The parse.com javascript API is a very nice capability based on Backbonejs, that is heavily promise based to support asynchronicity.​ Here’s how to use that to query the data associated with a color scheme. This is similar to how the data was loaded to parse.com in the first place.

 

Asynchronous loading

When it starts up, or you change scheme you may notice this
 
 
Here’s what’s happening then…[deprecated due to parse.com having moved]
function getSelectedScheme (scheme) {
                //get current parse data for scheme - async
                $('#status').text("...getting selected scheme " + scheme);
                var parseKeys = getParseKeys();
                Parse.initialize(parseKeys.appId, parseKeys.jsKey);
                var ColorTable = Parse.Object.extend("ColorTable");
                schemeFromParse = schemePromise(ColorTable, scheme);
                schemeFromParse.fail(function (error) {
                    $('#status').text("error getting scheme " + scheme + JSON.stringify(error));
                });
                schemeFromParse.done(function (results) {
                    $('#status').text("found " + results.length + " colors in scheme " + scheme );
                });
                return schemeFromParse;
            }
// get the data for chosen scheme from parse
function schemePromise(model, scheme, allResults, allPromise) {
// find a scheme at a time
var schemeArray = [];
var promise = allPromise || $.Deferred();

findChunk(model, scheme, allResults || [])
.done(function (results, allOver) {
if (allOver) {
// we are done
// normalize to an array from parse ob
for (var i =0;i<results.length;i++) {
schemeArray.push({label: results[i].get("label"),
hex: results[i].get("hex"),
scheme: results[i].get("scheme"),
code: results[i].get("code"),
key: results[i].get("key")});
}
promise.resolve(schemeArray);
} else {
// may be more
schemePromise(model, scheme, results, promise);
}
})
.fail(function (error) {
promise.reject(error);
});
return promise.promise();
}
 // return in chunks to the parse.com limit
            function findChunk(model, scheme, allData) {
                // we have to find in chunks since there is a limit on query size
                // will return a promise
                var limit = 1000;
                var skip = allData.length;
                var findPromise = $.Deferred();
                var query = new Parse.Query(model);
                if (scheme) query.equalTo("scheme", scheme);
                query
                    .limit(limit)
                    .skip(skip)
                    .find()
                    .then(function (results) {
                    findPromise.resolve(allData.concat(results), !results.length);
                }, function (error) {
                    findPromise.reject(error);
                });
                return findPromise.promise();
            }
The two key points are
  • parse.com has a limit on the number of rows it can return from a query, so it needs to be chunked up.
  • What is actually returned is not the result of the query, but a promise that will be resolved when all the data is chunked up. Essentially, a promise is wrapped around the completion of each of the parse.com query promises which is only resolved when there are no more chunks to return
 
Other things, like building up the DOM, and even getting input can be done while this is happening. Eventually when the promise is resolved, then we can do the work of constructing the color palettes, either of some random color, or of a hex value if the user has entered one in the meantime.
// get the currently selected scheme, and if nothing entered yet, generate a random scheme
    getSelectedScheme($('#schemeselector').val())
       .done( function() {
            if (!$('#hexinput').val()) calculateColors (rgbToHTMLHex(randomColor),"random color");
        });

This use of promises nicely abstracts away the details of what was promised, leaving the code free of distractions. That means I can use exactly the same function for a change event on the scheme selector combo.

 $('#schemeselector').change(function() {
      getSelectedScheme($(this).val());
 });

More on the color scheme app?