Foliotek Developer Blog

Spectrum Colorpicker In Foliotek Presentation

Spectrum, my JavaScript colorpicker project, has gotten some good news lately!

It was adopted by the WebKit project for use in the Web Inspector, which was on a few people’s wishlists, including my own.

Foliotek Getting Involved

We decided to add (and expand on) functionality and improve the design for use in Foliotek Presentation.

Geoff Leigh and I worked together, thinking about the color picking process from scratch and came up with a good workflow, I think.

Common Palettes

The palettes on the top are commonly used colors that are ‘sticky’. These are easy ways to grab a color that looks about right, and makes it easy to reuse colors. Clicking on any element from a palette instantly chooses the color and closes the colorpicker.

Template Palette

Part of what makes Foliotek Presentation cool is that we know so much about the designs that people use by analyzing the CSS and color changes that they do in our template editor. With this information, we bind a list of colors that are being used in their template. This opens up possibilities like reusing a heading color to accent a certain word in their portfolio.

User Colors

This is a list that remembers which colors you have chosen. It uses the localStorage object. It will automatically add any color you select that isn’t in the above palettes.

Since it is automatic, users do not need to add/remove/edit the custom palette. Right now, we think this is better than presenting the user with an interface for setting custom colors. We originally had some designs that handled this management, but we decided to go with the simpler solution for now.

Going Forward

I hope to continue development and make this the best JavaScript colorpicker available, keeping these goals in mind:

  • Good UX
  • Cross Browser Compatible (IE6 and up)
  • Doesn’t use any images
  • Easy to skin via CSS
  • Simple interface / easy to integrate with app

I am very happy with the changes and excited to be working on projects like these! You can follow development of the plugin, suggest features, or report bugs here: https://github.com/bgrins/spectrum.


Foliotek Open Sources AjaxQ jQuery Plugin

We have a lot of components we have built (and are in the process of building) for our presentation portfolio and assessment products.

We have decided to contribute some of this work to the open source community. The first one is a jQuery plugin for managing sequential ajax requests, called AjaxQ.

See the AjaxQ documentation or jump straight to the demonstration.

It is designed to follow the $.ajax, $.get, and $.post interfaces and return values, only taking one extra parameter (the queue name). Here is a brief sample of the functionality:

 $.ajaxq (“MyQueue”, {  
     url: ‘http://jsfiddle.net/echo/jsonp/’,  
     type: ‘post’,  
     dataType: “jsonp”  
 });

$.postq (“MyQueue”, ‘path/to/your/resource’, onsuccess);

$.getq (“MyQueue”, ‘path/to/another/resource’, onsuccess);  

Each request will only run once the other finished.

All of the source code is available on Github, available under the MIT License.


Weebly Automatically Generated Left Menu via jQuery

I’ve helped a few people put together websites using Weebly, since it’s a tool that non-technical people can easily use to manage and maintain their sites. However, Weebly currently does not offer the option of a left menu. I don’t particularly like all the moving dropdown menus. It just seems to busy for me.

So, here’s my solution to generate a left menu based based on the structure of the site. Basically, I grab the dropdown links and copy them into a side menu structure. I will note that you should be aware when you’re creating a site that the content will be shifted over. I have not adjusted the css to represent this myself, because it doesn’t really matter to me.

To see an example of this in action, go to www.highquest.info

Reference jQuery

Add a link to jQuery in the <head> section on index.html:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>  

The JavaScript

Add the following javascript code to the index.html page type html, probably at the bottom but inside the body tag. (or any other page types you’ve defined. You could actually have this for every page but the main page to keep left menus off that if you want.)
(Click Design => Edit HTML/CSS => index.html)

<script type="text/javascript">  
      // You need this since Weebly uses another JavaScript library 
      jQuery.noConflict();        </script>

 function AddMenu() {

 // Find active link var activeLink = jQuery("#active"); if (activeLink.length == 0) { activeLink = jQuery(".wsite-nav-current"); }

 var linkParent = activeLink;

 //find root page while (linkParent.parent().parent().hasClass("wsite-menu-wrap")) { linkParent = linkParent.parent().parent().parent(); }

 // add menus when there are sub items to the root page -- but don't when there are no children (main page) if (linkParent .find("div").length > 0) { var contentDiv = jQuery("#wsite-content");

 //I add a table structure, which I know isn't the best, but it works well here. contentDiv.html("

<table class="leftmenupage"><tr><td class="leftmenu">" + linkParent.html() + "</td><td class="rightcontent">" + contentDiv.html()+ "</td></tr></table>");

 jQuery(".leftmenu div").show(); }

 // Mark main nav link with id="active" var linkHref = linkParent.find("a").attr("href"); var navLinks = jQuery("#navigation a"); for (var i = 0; i

 }

 AddMenu();

The CSS

ul.wsite-menu li {  
    padding-bottom: 5px;
}

.leftmenupage {
    margin-left: -15px;
    width: 850px;
}

td.leftmenu {  
    width: 200px;
    white-space: nowrap;
    padding: 7px 7px;
    vertical-align: top;
    border-radius: 15px;
    background: #ddd;
    color: #333;
    padding: 12px 12px;
    min-width: 200px;
    min-height: 250px;
}

td.leftmenu li {  
    padding-bottom: 7px;
}

td.leftmenu a {  
    color: #333;
    font-size: 1.33em;
    padding: 5px 0px;
    display: block;
}

    td.leftmenu a:hover {
        text-decoration: underline;
    }

td.leftmenu li a {  
    font-size: 1em;
}

td.leftmenu li {  
    color: #333;
    font-size: 1em;
    padding: 2px 0px;
}

td.leftmenu li li {  
    color: #333;
    font-size: 1em;
    padding: 2px 0 2px 15px;
}

td.rightcontent {  
    width: 75%;
    padding-left: 25px;
    width: 650px;
}

Scrollable DataGrid table with Fixed Header with jQuery

Problem

Implement scrolling on a table, but make the header fixed.

I had a really long table and wanted to make it scrollable, but keep the header in place. I saw a few examples of this, but with very little explanation to go with it. So, I just did it myself.

Sample Markup

<div>  
  <table id="MyDataRows">
    <thead>
      <tr class="grid_header">
        <th>Col1</th>
        <th>Col2</th>
        <th>Col3</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Data</td>
        <td>Data</td>
        <td>Data</td>
      </tr>
    </tbody>
  </table>
</div>  

First Attempt

So, the first option I saw online was to add “overflow-y: auto; display: block; height: 330px;” to the tbody tag. I saw somewhere where this could work with a single column, but with multiple columns, the header is pushed to the right, and the table rows are pushed to the left. I played with this awhile, but never could get it to work.

Solution

While not as elegant as I would like, this solution does work. Of course, if you isolate the header and then wrap the data rows in a div with the overflow-y stuff, that would work. However, a datagrid populates the header automatically. You could build another datagrid and mess with that, but jQuery quickly solves the issue. Here’s the plan:

  • Add a place for the header to be moved outside of the table with the rows where the overflow-y will be used
  • Move the header
  • Realign the columns

New Markup

This is pretty basic. ?I added a table just before the table with data in it. ?This will hold the header. ?I also styled the div to allow for scrolling.

<table id="MyHeader"></table>  
<div style="overflow-y: auto; height: 330px;">  
  <table id="MyDataRows">
    <thead>
      <tr class="grid_header">
        <th>Col1</th>
        <th>Col2</th>
        <th>Col3</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Data</td>
        <td>Data</td>
        <td>Data</td>
      </tr>
    </tbody>
  </table>
</div>  

jQuery Code

<script type="text/javascript">// <![CDATA[  
$(function () {
    /* move the table header from the datagrid outside, so it doesn't scroll" */
    $("#MyHeader").append($("#StudentData thead"));
    $("#MyDataRows").css("margin-bottom", "0");</script>

 var ths = $("#MyHeader th"); var tds = $("#MyDataRows tr:first td");

 /* Reset the padding of the th's to match the td's */ ths.css("padding-left", tds.first().css("padding-left")); ths.css("padding-right", tds.first().css("padding-right"));

 /* Set the widths of all the th's (except the last to acccount for scroll bar) to the corresponding td width */ for (var i = 0; i

Final Markup

So, the end result is two tables whose column widths match but which function as a scrollable datagrid table with a fixed header.

<table id="MyHeader">  
  <thead>
    <tr class="grid_header">
      <th>Col1</th>
      <th>Col2</th>
      <th>Col3</th>
    </tr>
  </thead>
</table>  
<div style="overflow-y: auto; height: 330px;">  
  <table id="MyDataRows">
    <tbody>
      <tr>
        <td>Data</td>
        <td>Data</td>
        <td>Data</td>
      </tr>
    </tbody>
  </table>
</div>  

jQuery Check All Checkbox

The Problem

Create a “select all” checkbox that

  1. when checked or unchecked, applies its value to all the checkboxes defined as its children
  2. when a child checkbox is checked or unchecked, the “select all” checkbox is updated accordingly. ?So, if you click the “select all”, but then uncheck one child checbox, deselect the “select all” checkbox.

The Solution

initSelectAll: function ($chkAll, $checkboxes) {

 //when chkAll is clicked, update the other checkboxes with its value  
 $chkAll.click(function () {  
 $checkboxes.attr(“checked”, $chkAll.attr(“checked”));  
 });

 // when any child checkbox is checked or unchecked reset the chkAll value  
 // chkAll will be checked if number of checked checkboxes = total number of checkboxes.  
 $checkboxes.click(function () {  
     $chkAll.attr(“checked”, $checkboxes.filter(“:checked”).length ==        $checkboxes.length);  
     }  
 }

$chkAll = $(“#chkAll”); // or however you select the select all checkbox  
 $checkboxes = $(“#checkboxes :checkbox”);

$(function () {  
 initSelectAll($chkAll, $checkboxes);  
 });

xml