From 9ea62765b6f2e00e109efaabc490cb55a43bbf3a Mon Sep 17 00:00:00 2001 From: Christopher Boone Date: Sun, 11 Mar 2012 13:05:52 -0700 Subject: [PATCH] Add hashgrid --- ajax/libs/hashgrid/6/hashgrid.js | 425 +++++++++++++++++++++++++++++++ ajax/libs/hashgrid/package.json | 26 ++ 2 files changed, 451 insertions(+) create mode 100644 ajax/libs/hashgrid/6/hashgrid.js create mode 100644 ajax/libs/hashgrid/package.json diff --git a/ajax/libs/hashgrid/6/hashgrid.js b/ajax/libs/hashgrid/6/hashgrid.js new file mode 100644 index 000000000..09f75452b --- /dev/null +++ b/ajax/libs/hashgrid/6/hashgrid.js @@ -0,0 +1,425 @@ +/** + * hashgrid (jQuery version) + * http://github.com/dotjay/hashgrid + * Version 6, 10 Jun 2011 + * Written by Jon Gibbins at Analog, http://analog.coop/ + * + * Contibutors: + * Sean Coates, http://seancoates.com/ + * Phil Dokas, http://jetless.org/ + * Andrew Jaswa, http://andrewjaswa.com/ + */ + +/** + * @license Copyright 2011 Analog Coop Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Usage + * + * // The basic #grid setup looks like this + * var grid = new hashgrid(); + * + * // Or you can set a custom id for your grid, e.g. #mygrid + * var grid = new hashgrid("mygrid"); + * + * // But there are a whole bunch of additional options you can set + * var grid = new hashgrid({ + * id: 'mygrid', // id for the grid container + * modifierKey: 'alt', // optional 'ctrl', 'alt' or 'shift' + * showGridKey: 's', // key to show the grid + * holdGridKey: 'enter', // key to hold the grid in place + * foregroundKey: 'f', // key to toggle foreground/background + * jumpGridsKey: 'd', // key to cycle through the grid classes + * numberOfGrids: 2, // number of grid classes used + * classPrefix: 'class', // prefix for the grid classes + * cookiePrefix: 'mygrid' // prefix for the cookie name + * }); + */ + + +/** + * Make sure we have the library + * TODO: Use an adapter + */ +if (typeof jQuery == "undefined") { + alert("Hashgrid: jQuery not loaded. Make sure it's linked to your pages."); +} + + +/** + * hashgrid overlay + * @constructor + */ +var hashgrid = function(set) { + + var options = { + id: 'grid', // id for the grid container + modifierKey: null, // optional 'ctrl', 'alt' or 'shift' + showGridKey: 'g', // key to show the grid + holdGridKey: 'h', // key to hold the grid in place + foregroundKey: 'f', // key to toggle foreground/background + jumpGridsKey: 'j', // key to cycle through the grid classes + numberOfGrids: 1, // number of grid classes used + classPrefix: 'grid-', // prefix for the grid classes + cookiePrefix: 'hashgrid'// prefix for the cookie name + }, + classNumber = 1, + gridLines, + gridWidth, + i, + line, + lineHeight, + numGridLines, + overlay, + overlayCookie, + overlayEl, + overlayOn = false, + overlayVert, + overlayZState = 'B', + overlayZBackground = -1, + overlayZForeground = 9999, + pageHeight, + setKey, + state, + sticky = false, + top; + + // Apply options + if (typeof set == 'object') { + for (setKey in set) { + options[setKey] = set[setKey]; + } + } + else if (typeof set == 'string') { + options.id = set; + } + + // Remove any conflicting overlay + if ($('#' + options.id).length > 0) { + $('#' + options.id).remove(); + } + + // Create overlay, hidden before adding to DOM + overlayEl = $('
'); + overlayEl + .attr('id', options.id) + .css({ + display: 'none', + 'pointer-events': 'none' + }); + $("body").prepend(overlayEl); + overlay = $('#' + options.id); + + // Unless a custom z-index is set, ensure the overlay will be behind everything + if (overlay.css('z-index') == 'auto') overlay.css('z-index', overlayZBackground); + + // Override the default overlay height with the actual page height + pageHeight = parseFloat($(document).height()); + overlay.height(pageHeight); + + // Add the first grid line so that we can measure it + overlay.append('
'); + + // Position off-screen and display to calculate height + top = overlay.css("top"); + overlay.css({ + top: "-999px", + display: "block" + }); + + // Calculate the number of grid lines needed + line = $('#' + options.id + '-horiz'); + lineHeight = line.outerHeight(); + + // Hide and reset top + overlay.css({ + display: "none", + top: top + }); + + // Break on zero line height + if (lineHeight <= 0) { + return false; + } + + // Add the remaining grid lines + numGridLines = Math.floor(pageHeight / lineHeight); + gridLines = ''; + + for (i = numGridLines - 1; i >= 1; i--) { + gridLines += '
'; + } + overlay.append(gridLines); + + // vertical grid + overlay.append($('
')); + overlayVert = overlay.children('.vert-container'); + gridWidth = overlay.width(); + overlayVert.css({width: gridWidth, position: 'absolute', top: 0}); + overlayVert.append('
 
'); + + // 30 is an arbitrarily large number... + // can't calculate the margin width properly + gridLines = ''; + for (i = 0; i < 30; i++) { + gridLines += '
 
'; + } + overlayVert.append(gridLines); + overlayVert.children() + .height(pageHeight) + .css({ display: 'inline-block' }); + + // Check for saved state + overlayCookie = readCookie(options.cookiePrefix + options.id); + if (typeof overlayCookie == 'string') { + state = overlayCookie.split(','); + state[2] = Number(state[2]); + if ((typeof state[2] == 'number') && !isNaN(state[2])) { + classNumber = state[2].toFixed(0); + overlay.addClass(options.classPrefix + classNumber); + } + if (state[1] == 'F') { + overlayZState = 'F'; + overlay.css('z-index', overlayZForeground); + } + if (state[0] == '1') { + overlayOn = true; + sticky = true; + showOverlay(); + } + } + else { + overlay.addClass(options.classPrefix + classNumber); + } + + // Keyboard controls + $(document).bind('keydown', keydownHandler); + $(document).bind('keyup', keyupHandler); + + /** + * Helpers + */ + + function getModifier(e) { + if (options.modifierKey == null) return true; // Bypass by default + var m = true; + switch(options.modifierKey) { + case 'ctrl': + m = (e.ctrlKey ? e.ctrlKey : false); + break; + + case 'alt': + m = (e.altKey ? e.altKey : false); + break; + + case 'shift': + m = (e.shiftKey ? e.shiftKey : false); + break; + } + return m; + } + + function getKey(e) { + var k = false, c = (e.keyCode ? e.keyCode : e.which); + // Handle keywords + if (c == 13) k = 'enter'; + // Handle letters + else k = String.fromCharCode(c).toLowerCase(); + return k; + } + + function saveState() { + createCookie(options.cookiePrefix + options.id, (sticky ? '1' : '0') + ',' + overlayZState + ',' + classNumber, 1); + } + + function showOverlay() { + overlay.show(); + overlayVert.css({width: overlay.width()}); + // hide any vertical blocks that aren't at the top of the viewport + overlayVert.children('.vert').each(function () { + $(this).css('display','inline-block'); + if ($(this).offset().top > 0) { + $(this).hide(); + } + }); + } + + /** + * Event handlers + */ + + function keydownHandler(e) { + var k, + m, + source = e.target.tagName.toLowerCase(); + + if ((source == 'input') || (source == 'textarea') || (source == 'select')) { + return true; + } + + m = getModifier(e); + if (!m) { + return true; + } + + k = getKey(e); + if (!k) { + return true; + } + + switch(k) { + case options.showGridKey: + if (!overlayOn) { + showOverlay(); + overlayOn = true; + } + else if (sticky) { + overlay.hide(); + overlayOn = false; + sticky = false; + saveState(); + } + break; + case options.holdGridKey: + if (overlayOn && !sticky) { + // Turn sticky overlay on + sticky = true; + saveState(); + } + break; + case options.foregroundKey: + if (overlayOn) { + // Toggle sticky overlay z-index + if (overlay.css('z-index') == overlayZForeground) { + overlay.css('z-index', overlayZBackground); + overlayZState = 'B'; + } + else { + overlay.css('z-index', overlayZForeground); + overlayZState = 'F'; + } + saveState(); + } + break; + case options.jumpGridsKey: + if (overlayOn && (options.numberOfGrids > 1)) { + // Cycle through the available grids + overlay.removeClass(options.classPrefix + classNumber); + classNumber++; + if (classNumber > options.numberOfGrids) classNumber = 1; + overlay.addClass(options.classPrefix + classNumber); + showOverlay(); + if (/webkit/.test( navigator.userAgent.toLowerCase() )) { + forceRepaint(); + } + saveState(); + } + break; + } + + return true; + } + + function keyupHandler(e) { + var k, + m = getModifier(e); + + if (!m) { + return true; + } + + k = getKey(e); + + if (k && (k == options.showGridKey) && !sticky) { + overlay.hide(); + overlayOn = false; + } + + return true; + } + + /** + * Cookie functions + * + * By Peter-Paul Koch: + * http://www.quirksmode.org/js/cookies.html + */ + function createCookie(name, value, days) { + var date, + expires = ""; + + if (days) { + date = new Date(); + date.setTime( date.getTime() + (days*24*60*60*1000) ); + expires = "; expires=" + date.toGMTString(); + } + + document.cookie = name + "=" + value + expires + "; path=/"; + } + + function readCookie(name) { + var c, + ca = document.cookie.split(';'), + i = 0, + len = ca.length, + nameEQ = name + "="; + + for (; i < len; i++) { + c = ca[i]; + + while (c.charAt(0) == ' ') { + c = c.substring(1, c.length); + } + + if (c.indexOf(nameEQ) == 0) { + return c.substring(nameEQ.length, c.length); + } + } + return null; + } + + function eraseCookie(name) { + createCookie(name, "", -1); + } + + /** + * Forces a repaint (because WebKit has issues) + * http://www.sitepoint.com/forums/showthread.php?p=4538763 + * http://www.phpied.com/the-new-game-show-will-it-reflow/ + */ + function forceRepaint() { + var ss = document.styleSheets[0]; + try { + ss.addRule('.xxxxxx', 'position: relative'); + ss.removeRule(ss.rules.length - 1); + } catch(e) {} + } + + return {}; +}; + + +/** + * You can call hashgrid from your own code, but it's loaded here as + * an example for your convenience. + */ +$(document).ready(function() { + + var grid = new hashgrid({ + numberOfGrids: 2 + }); + +}); diff --git a/ajax/libs/hashgrid/package.json b/ajax/libs/hashgrid/package.json new file mode 100644 index 000000000..7e8d24a85 --- /dev/null +++ b/ajax/libs/hashgrid/package.json @@ -0,0 +1,26 @@ +{ + "name": "hashgrid", + "filename": "hashgrid.js", + "version": "6", + "description": "A little tool that inserts a layout grid in web pages, allows you to hold it in place, and toggle between displaying it in the foreground or background.", + "homepage": "http://hashgrid.com/", + "keywords": [ + "grid", + "layout", + "design", + "columns" + ], + "maintainers": [ + { + "name": "Analog Coop", + "email": "hello@analog.coop", + "web": "http://analog.coop/" + } + ], + "repositories": [ + { + "type": "git", + "url": "https://github.com/dotjay/hashgrid" + } + ] +}