// ##PHP ADD IN: JS Autocomplete. jQuery.autocomplete = function (input, options) { // Create a link to self var me = this; // Create jQuery object for input element var $input = $(input).attr("autocomplete", "off"); // Apply inputClass if necessary if (options.inputClass) $input.addClass(options.inputClass); // Create results var results = document.createElement("div"); // Create jQuery object for results var $results = $(results); $results.hide().addClass(options.resultsClass).css("position", "absolute"); if (options.width > 0) $results.css("width", options.width); // Add to body element $("body").append(results); input.autocompleter = me; var timeout = null; var prev = ""; var active = -1; var cache = {}; var keyb = false; var hasFocus = false; var lastKeyPressCode = null; // flush cache function flushCache() { cache = {}; cache.data = {}; cache.length = 0; }; // flush cache flushCache(); // if there is a data array supplied if (options.data != null) { var sFirstChar = "", stMatchSets = {}, row = []; // no url was specified, we need to adjust the cache length to make sure it fits the local data store if (typeof options.url != "string") options.cacheLength = 1; // loop through the array and create a lookup structure for (var i = 0; i < options.data.length; i++) { // if row is a string, make an array otherwise just reference the array row = ((typeof options.data[i] == "string") ? [options.data[i]] : options.data[i]); // if the length is zero, don't add to list if (row[0].length > 0) { // get the first character sFirstChar = row[0].substring(0, 1).toLowerCase(); // if no lookup array for this character exists, look it up now if (!stMatchSets[sFirstChar]) stMatchSets[sFirstChar] = []; // if the match is a string stMatchSets[sFirstChar].push(row); } } // add the data items to the cache for (var k in stMatchSets) { // increase the cache size options.cacheLength++; // add to the cache addToCache(k, stMatchSets[k]); } } $input.keydown(function (e) { // track last key pressed lastKeyPressCode = e.keyCode; switch (e.keyCode) { case 38: // up e.preventDefault(); moveSelect(-1); break; case 40: // down e.preventDefault(); moveSelect(1); break; case 9: // tab case 13: // return if (selectCurrent()) { // make sure to blur off the current field $input.get(0).blur(); e.preventDefault(); } break; default: active = -1; if (timeout) clearTimeout(timeout); timeout = setTimeout(function () { onChange(); }, options.delay); break; } }).focus(function () { // track whether the field has focus, we shouldn't process any results if the field no longer has focus hasFocus = true; }).blur(function () { // track whether the field has focus hasFocus = false; hideResults(); }); hideResultsNow(); function onChange() { // ignore if the following keys are pressed: [del] [shift] [capslock] if (lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32)) return $results.hide(); var v = $input.val(); if (v == prev) return; prev = v; if (v.length >= options.minChars) { $input.addClass(options.loadingClass); requestData(v); } else { $input.removeClass(options.loadingClass); $results.hide(); } }; function moveSelect(step) { var lis = $("li", results); if (!lis) return; active += step; if (active < 0) { active = 0; } else if (active >= lis.size()) { active = lis.size() - 1; } lis.removeClass("ac_over"); $(lis[active]).addClass("ac_over"); // Weird behaviour in IE // if (lis[active] && lis[active].scrollIntoView) { // lis[active].scrollIntoView(false); // } }; function selectCurrent() { var li = $("li.ac_over", results)[0]; if (!li) { var $li = $("li", results); if (options.selectOnly) { if ($li.length == 1) li = $li[0]; } else if (options.selectFirst) { li = $li[0]; } } if (li) { selectItem(li); return true; } else { return false; } }; function selectItem(li) { if (!li) { li = document.createElement("li"); li.extra = []; li.selectValue = ""; } var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML); input.lastSelected = v; prev = v; $results.html(""); $input.val(v); hideResultsNow(); if (options.onItemSelect) setTimeout(function () { options.onItemSelect(li) }, 1); }; // selects a portion of the input string function createSelection(start, end) { // get a reference to the input element var field = $input.get(0); if (field.createTextRange) { var selRange = field.createTextRange(); selRange.collapse(true); selRange.moveStart("character", start); selRange.moveEnd("character", end); selRange.select(); } else if (field.setSelectionRange) { field.setSelectionRange(start, end); } else { if (field.selectionStart) { field.selectionStart = start; field.selectionEnd = end; } } field.focus(); }; // fills in the input box w/the first match (assumed to be the best match) function autoFill(sValue) { // if the last user key pressed was backspace, don't autofill if (lastKeyPressCode != 8) { // fill in the value (keep the case the user has typed) $input.val($input.val() + sValue.substring(prev.length)); // select the portion of the value not typed by the user (so the next character will erase) createSelection(prev.length, sValue.length); } }; function showResults() { // get the position of the input field right now (in case the DOM is shifted) var pos = findPos(input); // either use the specified width, or autocalculate based on form element var iWidth = (options.width > 0) ? options.width : $input.width(); // reposition $results.css({ width: parseInt(iWidth) + "px", top: (pos.y + input.offsetHeight) + "px", left: pos.x + "px" }).show(); }; function hideResults() { if (timeout) clearTimeout(timeout); timeout = setTimeout(hideResultsNow, 200); }; function hideResultsNow() { if (timeout) clearTimeout(timeout); $input.removeClass(options.loadingClass); if ($results.is(":visible")) { $results.hide(); } if (options.mustMatch) { var v = $input.val(); if (v != input.lastSelected) { selectItem(null); } } }; function receiveData(q, data) { if (data) { $input.removeClass(options.loadingClass); results.innerHTML = ""; // if the field no longer has focus or if there are no matches, do not display the drop down if (!hasFocus || data.length == 0) return hideResultsNow(); if ($.browser.msie) { // we put a styled iframe behind the calendar so HTML SELECT elements don't show through $results.append(document.createElement('iframe')); } results.appendChild(dataToDom(data)); // autofill in the complete box w/the first match as long as the user hasn't entered in more data if (options.autoFill && ($input.val().toLowerCase() == q.toLowerCase())) autoFill(data[0][0]); showResults(); } else { hideResultsNow(); } }; function parseData(data) { if (!data) return null; var parsed = []; var rows = data.split(options.lineSeparator); for (var i = 0; i < rows.length; i++) { var row = $.trim(rows[i]); if (row) { parsed[parsed.length] = row.split(options.cellSeparator); } } return parsed; }; function dataToDom(data) { var ul = document.createElement("ul"); var num = data.length; // limited results to a max number if ((options.maxItemsToShow > 0) && (options.maxItemsToShow < num)) num = options.maxItemsToShow; for (var i = 0; i < num; i++) { var row = data[i]; if (!row) continue; var li = document.createElement("li"); if (options.formatItem) { li.innerHTML = options.formatItem(row, i, num); li.selectValue = row[0]; } else { li.innerHTML = row[0]; li.selectValue = row[0]; } var extra = null; if (row.length > 1) { extra = []; for (var j = 1; j < row.length; j++) { extra[extra.length] = row[j]; } } li.extra = extra; ul.appendChild(li); $(li).hover( function () { $("li", ul).removeClass("ac_over"); $(this).addClass("ac_over"); active = $("li", ul).indexOf($(this).get(0)); }, function () { $(this).removeClass("ac_over"); }).click(function (e) { e.preventDefault(); e.stopPropagation(); selectItem(this) }); } return ul; }; function requestData(q) { if (!options.matchCase) q = q.toLowerCase(); var data = options.cacheLength ? loadFromCache(q) : null; // recieve the cached data if (data) { receiveData(q, data); // if an AJAX url has been supplied, try loading the data now } else if ((typeof options.url == "string") && (options.url.length > 0)) { $.get(makeUrl(q), function (data) { data = parseData(data); addToCache(q, data); receiveData(q, data); }); // if there's been no data found, remove the loading class } else { $input.removeClass(options.loadingClass); } }; function makeUrl(q) { var url = options.url + "?q=" + encodeURI(q); for (var i in options.extraParams) { url += "&" + i + "=" + encodeURI(options.extraParams[i]); } return url; }; function loadFromCache(q) { if (!q) return null; if (cache.data[q]) return cache.data[q]; if (options.matchSubset) { for (var i = q.length - 1; i >= options.minChars; i--) { var qs = q.substr(0, i); var c = cache.data[qs]; if (c) { var csub = []; for (var j = 0; j < c.length; j++) { var x = c[j]; var x0 = x[0]; if (matchSubset(x0, q)) { csub[csub.length] = x; } } return csub; } } } return null; }; function matchSubset(s, sub) { if (!options.matchCase) s = s.toLowerCase(); var i = s.indexOf(sub); if (i == -1) return false; return i == 0 || options.matchContains; }; this.flushCache = function () { flushCache(); }; this.setExtraParams = function (p) { options.extraParams = p; }; this.findValue = function () { var q = $input.val(); if (!options.matchCase) q = q.toLowerCase(); var data = options.cacheLength ? loadFromCache(q) : null; if (data) { findValueCallback(q, data); } else if ((typeof options.url == "string") && (options.url.length > 0)) { $.get(makeUrl(q), function (data) { data = parseData(data) addToCache(q, data); findValueCallback(q, data); }); } else { // no matches findValueCallback(q, null); } } function findValueCallback(q, data) { if (data) $input.removeClass(options.loadingClass); var num = (data) ? data.length : 0; var li = null; for (var i = 0; i < num; i++) { var row = data[i]; if (row[0].toLowerCase() == q.toLowerCase()) { li = document.createElement("li"); if (options.formatItem) { li.innerHTML = options.formatItem(row, i, num); li.selectValue = row[0]; } else { li.innerHTML = row[0]; li.selectValue = row[0]; } var extra = null; if (row.length > 1) { extra = []; for (var j = 1; j < row.length; j++) { extra[extra.length] = row[j]; } } li.extra = extra; } } if (options.onFindValue) setTimeout(function () { options.onFindValue(li) }, 1); } function addToCache(q, data) { if (!data || !q || !options.cacheLength) return; if (!cache.length || cache.length > options.cacheLength) { flushCache(); cache.length++; } else if (!cache[q]) { cache.length++; } cache.data[q] = data; }; function findPos(obj) { var curleft = obj.offsetLeft || 0; var curtop = obj.offsetTop || 0; while (obj = obj.offsetParent) { curleft += obj.offsetLeft curtop += obj.offsetTop } return { x: curleft, y: curtop }; } // Added by AK. this.replaceArray = function (data) { // flush cache flushCache(); if (data != null) { var sFirstChar = "", stMatchSets = {}, row = []; options.cacheLength = 1; // loop through the array and create a lookup structure for (var i = 0; i < data.length; i++) { // if row is a string, make an array otherwise just reference the array row = ((typeof data[i] == "string") ? [data[i]] : data[i]); // if the length is zero, don't add to list if (row[0].length > 0) { // get the first character sFirstChar = row[0].substring(0, 1).toLowerCase(); // if no lookup array for this character exists, look it up now if (!stMatchSets[sFirstChar]) stMatchSets[sFirstChar] = []; // if the match is a string stMatchSets[sFirstChar].push(row); } } // add the data items to the cache for (var k in stMatchSets) { // increase the cache size options.cacheLength++; // add to the cache addToCache(k, stMatchSets[k]); } } } } jQuery.fn.autocomplete = function (url, options, data) { // Make sure options exists options = options || {}; // Set url as option options.url = url; // set some bulk local data options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null; // Set default values for required options options.inputClass = options.inputClass || "ac_input"; options.resultsClass = options.resultsClass || "ac_results"; options.lineSeparator = options.lineSeparator || "\n"; options.cellSeparator = options.cellSeparator || "|"; options.minChars = options.minChars || 1; options.delay = options.delay || 400; options.matchCase = options.matchCase || 0; options.matchSubset = options.matchSubset || 1; options.matchContains = options.matchContains || 0; options.cacheLength = options.cacheLength || 1; options.mustMatch = options.mustMatch || 0; options.extraParams = options.extraParams || {}; options.loadingClass = options.loadingClass || "ac_loading"; options.selectFirst = options.selectFirst || false; options.selectOnly = options.selectOnly || false; options.maxItemsToShow = options.maxItemsToShow || -1; options.autoFill = options.autoFill || false; options.width = parseInt(options.width, 10) || 0; this.each(function () { var input = this; new jQuery.autocomplete(input, options); }); // Don't break the chain return this; } jQuery.fn.autocompleteArray = function (data, options) { return this.autocomplete(null, options, data); } jQuery.fn.indexOf = function (e) { for (var i = 0; i < this.length; i++) { if (this[i] == e) return i; } return -1; }; // ##PHP ADD IN: JS Transform. /* * transform: A jQuery cssHooks adding cross-browser 2d transform capabilities to $.fn.css() and $.fn.animate() * * limitations: * - requires jQuery 1.4.3+ * - Should you use the *translate* property, then your elements need to be absolutely positionned in a relatively positionned wrapper **or it will fail in IE678**. * - transformOrigin is not accessible * * latest version and complete README available on Github: * https://github.com/louisremi/jquery.transform.js * * Copyright 2011 @louis_remi * Licensed under the MIT license. * * This saved you an hour of work? * Send me music http://www.amazon.co.uk/wishlist/HNTU0468LQON * */ (function ($) { /* * Feature tests and global variables */ var div = document.createElement('div'), divStyle = div.style, propertyName = 'transform', suffix = 'Transform', testProperties = ['O' + suffix, 'ms' + suffix, 'Webkit' + suffix, 'Moz' + suffix, // prefix-less property propertyName], i = testProperties.length, supportProperty, supportMatrixFilter, propertyHook, propertyGet, rMatrix = /Matrix([^)]*)/; // test different vendor prefixes of this property while (i--) { if (testProperties[i] in divStyle) { $.support[propertyName] = supportProperty = testProperties[i]; continue; } } // IE678 alternative if (!supportProperty) { $.support.matrixFilter = supportMatrixFilter = divStyle.filter === ''; } // prevent IE memory leak div = divStyle = null; // px isn't the default unit of this property $.cssNumber[propertyName] = true; /* * fn.css() hooks */ if (supportProperty && supportProperty != propertyName) { // Modern browsers can use jQuery.cssProps as a basic hook $.cssProps[propertyName] = supportProperty; // Firefox needs a complete hook because it stuffs matrix with 'px' if (supportProperty == 'Moz' + suffix) { propertyHook = { get: function (elem, computed) { return (computed ? // remove 'px' from the computed matrix $.css(elem, supportProperty).split('px').join('') : elem.style[supportProperty]) }, set: function (elem, value) { // remove 'px' from matrices elem.style[supportProperty] = /matrix[^)p]*\)/.test(value) ? value.replace(/matrix((?:[^,]*,){4})([^,]*),([^)]*)/, 'matrix$1$2px,$3px') : value; } } /* Fix two jQuery bugs still present in 1.5.1 * - rupper is incompatible with IE9, see http://jqbug.com/8346 * - jQuery.css is not really jQuery.cssProps aware, see http://jqbug.com/8402 */ } else if (/^1\.[0-5](?:\.|$)/.test($.fn.jquery)) { propertyHook = { get: function (elem, computed) { return (computed ? $.css(elem, supportProperty.replace(/^ms/, 'Ms')) : elem.style[supportProperty]) } } } /* TODO: leverage hardware acceleration of 3d transform in Webkit only else if ( supportProperty == 'Webkit' + suffix && support3dTransform ) { propertyHook = { set: function( elem, value ) { elem.style[supportProperty] = value.replace(); } } }*/ } else if (supportMatrixFilter) { propertyHook = { get: function (elem, computed) { var elemStyle = (computed && elem.currentStyle ? elem.currentStyle : elem.style), matrix; if (elemStyle && rMatrix.test(elemStyle.filter)) { matrix = RegExp.$1.split(','); matrix = [ matrix[0].split('=')[1], matrix[2].split('=')[1], matrix[1].split('=')[1], matrix[3].split('=')[1]]; } else { matrix = [1, 0, 0, 1]; } matrix[4] = elemStyle ? elemStyle.left : 0; matrix[5] = elemStyle ? elemStyle.top : 0; return "matrix(" + matrix + ")"; }, set: function (elem, value, animate) { var elemStyle = elem.style, currentStyle, Matrix, filter; if (!animate) { elemStyle.zoom = 1; } value = matrix(value); // rotate, scale and skew if (!animate || animate.M) { Matrix = ["Matrix(" + "M11=" + value[0], "M12=" + value[2], "M21=" + value[1], "M22=" + value[3], "SizingMethod='auto expand'"].join(); filter = (currentStyle = elem.currentStyle) && currentStyle.filter || elemStyle.filter || ""; elemStyle.filter = rMatrix.test(filter) ? filter.replace(rMatrix, Matrix) : filter + " progid:DXImageTransform.Microsoft." + Matrix + ")"; // center the transform origin, from pbakaus's Transformie http://github.com/pbakaus/transformie if ((centerOrigin = $.transform.centerOrigin)) { elemStyle[centerOrigin == 'margin' ? 'marginLeft' : 'left'] = -(elem.offsetWidth / 2) + (elem.clientWidth / 2) + 'px'; elemStyle[centerOrigin == 'margin' ? 'marginTop' : 'top'] = -(elem.offsetHeight / 2) + (elem.clientHeight / 2) + 'px'; } } // translate if (!animate || animate.T) { // We assume that the elements are absolute positionned inside a relative positionned wrapper elemStyle.left = value[4] + 'px'; elemStyle.top = value[5] + 'px'; } } } } // populate jQuery.cssHooks with the appropriate hook if necessary if (propertyHook) { $.cssHooks[propertyName] = propertyHook; } // we need a unique setter for the animation logic propertyGet = propertyHook && propertyHook.get || $.css; /* * fn.animate() hooks */ $.fx.step.transform = function (fx) { var elem = fx.elem, start = fx.start, end = fx.end, split, pos = fx.pos, transform, translate, rotate, scale, skew, T = false, M = false, prop; translate = rotate = scale = skew = ''; // fx.end and fx.start need to be converted to their translate/rotate/scale/skew components // so that we can interpolate them if (!start || typeof start === "string") { // the following block can be commented out with jQuery 1.5.1+, see #7912 if (!start) { start = propertyGet(elem, supportProperty); } // force layout only once per animation if (supportMatrixFilter) { elem.style.zoom = 1; } // if the start computed matrix is in end, we are doing a relative animation split = end.split(start); if (split.length == 2) { // remove the start computed matrix to make animations more accurate end = split.join(''); fx.origin = start; start = 'none'; } // start is either 'none' or a matrix(...) that has to be parsed fx.start = start = start == 'none' ? { translate: [0, 0], rotate: 0, scale: [1, 1], skew: [0, 0] } : unmatrix(toArray(start)); // fx.end has to be parsed and decomposed fx.end = end = ~end.indexOf('matrix') ? // bullet-proof parser unmatrix(matrix(end)) : // faster and more precise parser components(end); // get rid of properties that do not change for (prop in start) { if (prop == 'rotate' ? start[prop] == end[prop] : start[prop][0] == end[prop][0] && start[prop][1] == end[prop][1]) { delete start[prop]; } } } /* * We want a fast interpolation algorithm. * This implies avoiding function calls and sacrifying DRY principle: * - avoid $.each(function(){}) * - round values using bitewise hacks, see http://jsperf.com/math-round-vs-hack/3 */ if (start.translate) { // round translate to the closest pixel translate = ' translate(' + ((start.translate[0] + (end.translate[0] - start.translate[0]) * pos + .5) | 0) + 'px,' + ((start.translate[1] + (end.translate[1] - start.translate[1]) * pos + .5) | 0) + 'px' + ')'; T = true; } if (start.rotate != undefined) { rotate = ' rotate(' + (start.rotate + (end.rotate - start.rotate) * pos) + 'rad)'; M = true; } if (start.scale) { scale = ' scale(' + (start.scale[0] + (end.scale[0] - start.scale[0]) * pos) + ',' + (start.scale[1] + (end.scale[1] - start.scale[1]) * pos) + ')'; M = true; } if (start.skew) { skew = ' skew(' + (start.skew[0] + (end.skew[0] - start.skew[0]) * pos) + 'rad,' + (start.skew[1] + (end.skew[1] - start.skew[1]) * pos) + 'rad' + ')'; M = true; } // In case of relative animation, restore the origin computed matrix here. transform = fx.origin ? fx.origin + translate + skew + scale + rotate : translate + rotate + scale + skew; propertyHook && propertyHook.set ? propertyHook.set(elem, transform, { M: M, T: T }) : elem.style[supportProperty] = transform; }; /* * Utility functions */ // turns a transform string into its 'matrix(A,B,C,D,X,Y)' form (as an array, though) function matrix(transform) { transform = transform.split(')'); var trim = $.trim // last element of the array is an empty string, get rid of it , i = transform.length - 1, split, prop, val, A = 1, B = 0, C = 0, D = 1, A_, B_, C_, D_, tmp1, tmp2, X = 0, Y = 0; // Loop through the transform properties, parse and multiply them while (i--) { split = transform[i].split('('); prop = trim(split[0]); val = split[1]; A_ = B_ = C_ = D_ = 0; switch (prop) { case 'translateX': X += parseInt(val, 10); continue; case 'translateY': Y += parseInt(val, 10); continue; case 'translate': val = val.split(','); X += parseInt(val[0], 10); Y += parseInt(val[1] || 0, 10); continue; case 'rotate': val = toRadian(val); A_ = Math.cos(val); B_ = Math.sin(val); C_ = -Math.sin(val); D_ = Math.cos(val); break; case 'scaleX': A_ = val; D_ = 1; break; case 'scaleY': A_ = 1; D_ = val; break; case 'scale': val = val.split(','); A_ = val[0]; D_ = val.length > 1 ? val[1] : val[0]; break; case 'skewX': A_ = D_ = 1; C_ = Math.tan(toRadian(val)); break; case 'skewY': A_ = D_ = 1; B_ = Math.tan(toRadian(val)); break; case 'skew': A_ = D_ = 1; val = val.split(','); C_ = Math.tan(toRadian(val[0])); B_ = Math.tan(toRadian(val[1] || 0)); break; case 'matrix': val = val.split(','); A_ = +val[0]; B_ = +val[1]; C_ = +val[2]; D_ = +val[3]; X += parseInt(val[4], 10); Y += parseInt(val[5], 10); } // Matrix product tmp1 = A * A_ + B * C_; B = A * B_ + B * D_; tmp2 = C * A_ + D * C_; D = C * B_ + D * D_; A = tmp1; C = tmp2; } return [A, B, C, D, X, Y]; } // turns a matrix into its rotate, scale and skew components // algorithm from http://hg.mozilla.org/mozilla-central/file/7cb3e9795d04/layout/style/nsStyleAnimation.cpp function unmatrix(matrix) { var scaleX, scaleY, skew, A = matrix[0], B = matrix[1], C = matrix[2], D = matrix[3]; // Make sure matrix is not singular if (A * D - B * C) { // step (3) scaleX = Math.sqrt(A * A + B * B); A /= scaleX; B /= scaleX; // step (4) skew = A * C + B * D; C -= A * skew; D -= B * skew; // step (5) scaleY = Math.sqrt(C * C + D * D); C /= scaleY; D /= scaleY; skew /= scaleY; // step (6) if (A * D < B * C) { //scaleY = -scaleY; //skew = -skew; A = -A; B = -B; skew = -skew; scaleX = -scaleX; } // matrix is singular and cannot be interpolated } else { rotate = scaleX = scaleY = skew = 0; } return { translate: [+matrix[4], +matrix[5]], rotate: Math.atan2(B, A), scale: [scaleX, scaleY], skew: [skew, 0] } } // parse tranform components of a transform string not containing 'matrix(...)' function components(transform) { // split the != transforms transform = transform.split(')'); var translate = [0, 0], rotate = 0, scale = [1, 1], skew = [0, 0], i = transform.length - 1, trim = $.trim, split, name, value; // add components while (i--) { split = transform[i].split('('); name = trim(split[0]); value = split[1]; if (name == 'translateX') { translate[0] += parseInt(value, 10); } else if (name == 'translateY') { translate[1] += parseInt(value, 10); } else if (name == 'translate') { value = value.split(','); translate[0] += parseInt(value[0], 10); translate[1] += parseInt(value[1] || 0, 10); } else if (name == 'rotate') { rotate += toRadian(value); } else if (name == 'scaleX') { scale[0] *= value; } else if (name == 'scaleY') { scale[1] *= value; } else if (name == 'scale') { value = value.split(','); scale[0] *= value[0]; scale[1] *= (value.length > 1 ? value[1] : value[0]); } else if (name == 'skewX') { skew[0] += toRadian(value); } else if (name == 'skewY') { skew[1] += toRadian(value); } else if (name == 'skew') { value = value.split(','); skew[0] += toRadian(value[0]); skew[1] += toRadian(value[1] || '0'); } } return { translate: translate, rotate: rotate, scale: scale, skew: skew }; } // converts an angle string in any unit to a radian Float function toRadian(value) { return~value.indexOf('deg') ? parseInt(value, 10) * (Math.PI * 2 / 360) : ~value.indexOf('grad') ? parseInt(value, 10) * (Math.PI / 200) : parseFloat(value); } // Converts 'matrix(A,B,C,D,X,Y)' to [A,B,C,D,X,Y] function toArray(matrix) { // Fremove the unit of X and Y for Firefox matrix = /\(([^,]*),([^,]*),([^,]*),([^,]*),([^,p]*)(?:px)?,([^)p]*)(?:px)?/.exec(matrix); return [matrix[1], matrix[2], matrix[3], matrix[4], matrix[5], matrix[6]]; } $.transform = { centerOrigin: 'margin' }; })(jQuery); // ##PHP ADD IN: JS FileDrop. /* * Default text - jQuery plugin for html5 dragging files from desktop to browser * * Author: Weixi Yen * * Email: [Firstname][Lastname]@gmail.com * * Copyright (c) 2010 Resopollution * * Licensed under the MIT license: * http://www.opensource.org/licenses/mit-license.php * * Project home: * http://www.github.com/weixiyen/jquery-filedrop * * Version: 0.1.0 * * Features: * Allows sending of extra parameters with file. * Works with Firefox 3.6+ * Future-compliant with HTML5 spec (will work with Webkit browsers and IE9) * Usage: * See README at project homepage * */ (function ($) { jQuery.event.props.push("dataTransfer"); var opts = {}, default_opts = { url: '', refresh: 1000, paramname: 'userfile', maxfiles: 25, maxfilesize: 1, // MBs data: {}, drop: empty, dragEnter: empty, dragOver: empty, dragLeave: empty, docEnter: empty, docOver: empty, docLeave: empty, beforeEach: empty, afterAll: empty, rename: empty, error: function (err, file, i) { alert(err); }, uploadStarted: empty, uploadFinished: empty, progressUpdated: empty, speedUpdated: empty, readFileAndBase64: function (file, base64) {} }, errors = ["BrowserNotSupported", "TooManyFiles", "FileTooLarge"], doc_leave_timer, stop_loop = false, files_count = 0, files; $.fn.filedrop = function (options) { console.log("FILE DROP INIT..."); opts = $.extend({}, default_opts, options); this.bind('drop', drop).bind('dragenter', dragEnter).bind('dragover', dragOver).bind('dragleave', dragLeave); $(document).bind('drop', docDrop).bind('dragenter', docEnter).bind('dragover', docOver).bind('dragleave', docLeave); }; function drop(e) { opts.drop(e); files = e.dataTransfer.files; if (files === null || files === undefined) { opts.error(errors[0]); return false; } files_count = files.length; upload(); e.preventDefault(); return false; } function getBuilder(filename, filedata, boundary) { var dashdash = '--', crlf = '\r\n', builder = ''; $.each(opts.data, function (i, val) { if (typeof val === 'function') val = val(); builder += dashdash; builder += boundary; builder += crlf; builder += 'Content-Disposition: form-data; name="' + i + '"'; builder += crlf; builder += crlf; builder += val; builder += crlf; }); builder += dashdash; builder += boundary; builder += crlf; builder += 'Content-Disposition: form-data; name="' + opts.paramname + '"'; builder += '; filename="' + filename + '"'; builder += crlf; builder += 'Content-Type: application/octet-stream'; builder += crlf; builder += crlf; builder += filedata; builder += crlf; builder += dashdash; builder += boundary; builder += dashdash; builder += crlf; return builder; } function progress(e) { if (e.lengthComputable) { var percentage = Math.round((e.loaded * 100) / e.total); if (this.currentProgress != percentage) { this.currentProgress = percentage; opts.progressUpdated(this.index, this.file, this.currentProgress); var elapsed = new Date().getTime(); var diffTime = elapsed - this.currentStart; if (diffTime >= opts.refresh) { var diffData = e.loaded - this.startData; var speed = diffData / diffTime; // KB per second opts.speedUpdated(this.index, this.file, speed); this.startData = e.loaded; this.currentStart = elapsed; } } } } function upload() { stop_loop = false; if (!files) { opts.error(errors[0]); return false; } var filesDone = 0, filesRejected = 0; if (files_count > opts.maxfiles) { opts.error(errors[1]); return false; } for (var i = 0; i < files_count; i++) { if (stop_loop) return false; try { if (beforeEach(files[i]) != false) { if (i === files_count) return; var reader = new FileReader(), max_file_size = 1048576 * opts.maxfilesize; reader.index = i; if (files[i].size > max_file_size) { opts.error(errors[2], files[i], i); filesRejected++; continue; } reader.onloadend = send; reader.readAsBinaryString(files[i]); } else { filesRejected++; } } catch (err) { opts.error(errors[0]); return false; } } function send(e) { // Sometimes the index is not attached to the // event object. Find it by size. Hack for sure. if (e.target.index == undefined) { e.target.index = getIndexBySize(e.total); } console.log("Halting upload and instead getting Base64 of content..."); //var fname = file.name; var filedata = e.target; /* console.log(e); var bData = Base64.encode(filedata.result); console.log("bData Size: " + bData.length); var dataAgain = Base64.decode(bData); console.log("dataAgain Size: " + dataAgain.length); */ var base64Data = window.btoa(filedata.result); //var css = "url(data:image/png;base64,"+bData2+");"; var file = files[e.target.index]; readFileAndBase64(file, base64Data); return; /* var xhr = new XMLHttpRequest(), upload = xhr.upload, file = files[e.target.index], index = e.target.index, start_time = new Date().getTime(), boundary = '------multipartformboundary' + (new Date).getTime(), builder; newName = rename(file.name); if (typeof newName === "string") { builder = getBuilder(newName, e.target.result, boundary); } else { builder = getBuilder(file.name, e.target.result, boundary); } upload.index = index; upload.file = file; upload.downloadStartTime = start_time; upload.currentStart = start_time; upload.currentProgress = 0; upload.startData = 0; upload.addEventListener("progress", progress, false); xhr.open("POST", opts.url, true); xhr.setRequestHeader('content-type', 'multipart/form-data; boundary=' + boundary); xhr.sendAsBinary(builder); opts.uploadStarted(index, file, files_count); xhr.onload = function () { if (xhr.responseText) { var now = new Date().getTime(), timeDiff = now - start_time, result = opts.uploadFinished(index, file, jQuery.parseJSON(xhr.responseText), timeDiff); filesDone++; if (filesDone == files_count - filesRejected) { afterAll(); } if (result === false) stop_loop = true; } }; */ } } function getIndexBySize(size) { for (var i = 0; i < files_count; i++) { if (files[i].size == size) { return i; } } return undefined; } function rename(name) { return opts.rename(name); } function beforeEach(file) { return opts.beforeEach(file); } function afterAll() { return opts.afterAll(); } function dragEnter(e) { clearTimeout(doc_leave_timer); e.preventDefault(); opts.dragEnter(e); } function dragOver(e) { //console.log("drag over."); clearTimeout(doc_leave_timer); e.preventDefault(); opts.docOver(e); opts.dragOver(e); } function dragLeave(e) { //console.log("drag leave."); clearTimeout(doc_leave_timer); opts.dragLeave(e); e.stopPropagation(); } function docDrop(e) { e.preventDefault(); opts.docLeave(e); return false; } function docEnter(e) { clearTimeout(doc_leave_timer); e.preventDefault(); opts.docEnter(e); return false; } function docOver(e) { clearTimeout(doc_leave_timer); e.preventDefault(); opts.docOver(e); return false; } function docLeave(e) { doc_leave_timer = setTimeout(function () { opts.docLeave(e); }, 200); } function readFileAndBase64(fname, base64) { //console.log("ReturningBase64."); opts.readFileAndBase64(fname, base64); } function empty() {} try { if (XMLHttpRequest.prototype.sendAsBinary) return; XMLHttpRequest.prototype.sendAsBinary = function (datastr) { function byteValue(x) { return x.charCodeAt(0) & 0xff; } var ords = Array.prototype.map.call(datastr, byteValue); var ui8a = new Uint8Array(ords); this.send(ui8a.buffer); } } catch (e) {} })(jQuery); // ##PHP ADD IN: JS Index. // Update javascript functionality to include some specific helpful actions String.prototype.toUpperCaseFirst = function() { return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase(); } String.prototype.capitalize = function() { return this.replace( /(^|[\s|\-])([a-z])/g , function(m,p1,p2){ return p1+p2.toUpperCase(); } ); }; String.prototype.trim = function() { this.replace(/(^\s*)|(\s*$)/gi,""); this.replace(/[ ]{2,}/gi," "); this.replace(/\n /,"\n"); return this; } Node.prototype.insertAfter = function(newNode, refNode) { if(refNode && refNode.nextSibling) { return this.insertBefore(newNode, refNode.nextSibling); } else { return this.appendChild(newNode); } } var editableSS = null; // FIXME: The following methods really want to be encapsulated in a JQuery extension... function initEditableStylesheet(){ var ss = document.styleSheets; for(var i=0; i=0; i--){ var r = editableSS.rules[i]; if(r.selectorText == selector){ // found a matching selector! editableSS.deleteRule(i); insertLocation = i; } } //*/ // now add the rule... editableSS.insertRule(selector + "{" + rawCSS + "}", insertLocation); console.log(editableSS); } } function addSelectorIfNotPresent(selector){ if(editableSS != null){ var haveIt = false; for(var i=0; i 0){ newDivIDCounter++; } return "Element_"+newDivIDCounter; } function addNewDivToParentAndSelectIt(parent, left, top){ var newDiv = document.createElement('div'); newDiv.setAttribute('id', getNextNewDivID()); newDiv.innerHTML = "
"; newDiv.setAttribute('class', "bt_"); newDiv.style.left = left+"px"; newDiv.style.top = top +"px"; newDiv.style.right = "auto"; newDiv.style.bottom = "auto"; newDiv.style.width = "50px"; newDiv.style.height = "50px"; newDiv.style.position = "absolute"; setupDivForInteraction(newDiv); $(parent).append(newDiv); $(parent).append("\n"); putAllBTDivsIntoTree(); if(!viewModeIsLive){ $(newDiv).addClass("bt_dev"); } selectDiv(newDiv); } function setupDivForInteraction(newDiv){ // FIXME: draggable and resizable should only be enabled if element style >> position: absolute; left: anything; top: anything; $(newDiv).draggable({ snap: true, snapTolerance: 4, grid: [ 5,5 ], containment: ".bt_BG", scroll: false, drag: function(event, ui){ putActiveDivElementPropertiesIntoEditor(); } }); $(newDiv).resizable({ grid: [5, 5], containment: ".bt_BG", handles: "all", start: function(event, ui){ console.log("Starting Resize..."); console.log(event); console.log(ui); var div = event.target; var l = $(div).css("left"); var r = $(div).css("right"); var w = $(div).css("width"); var t = $(div).css("top"); var b = $(div).css("bottom"); var h = $(div).css("height"); if(l != "auto" && r != "auto"){ // don't allow resize of width. $(div).resizable("option", "maxWidth", ui.originalSize.width); $(div).resizable("option", "minWidth", ui.originalSize.width); }else{ // allow resize of width. $(div).resizable("option", "maxWidth", null); $(div).resizable("option", "minWidth", null); } if(t != "auto" && b != "auto"){ // don't allow resize of width. $(div).resizable("option", "maxHeight", ui.originalSize.height); $(div).resizable("option", "minHeight", ui.originalSize.height); }else{ // allow resize of height. $(div).resizable("option", "maxHeight", null); $(div).resizable("option", "minHeight", null); } }, resize: function(event, ui){ var div = event.target; var l = $(div).css("left"); var r = $(div).css("right"); var t = $(div).css("top"); var b = $(div).css("bottom"); if(l != "auto" && r != "auto"){ $(div).css("width", "auto"); } if(t != "auto" && b != "auto"){ $(div).css("height", "auto"); } putActiveDivElementPropertiesIntoEditor(); } }); } function makeSureAllBTDivsAreSetupForInteraction(){ console.log("making sure all bt_ divs are setup for interaction."); $(".bt_BG").find(".bt_").each(function(index, el){ if(!$(el).hasClass("ui-draggable")){ setupDivForInteraction(el); } }); } function scrollIntoView(element, container, addon, pad) { var containerTop = $(container).scrollTop(); var containerOffsetTop = $(container).offset().top; var containerBottom = containerTop + $(container).height(); var elemTop = containerTop+$(element).offset().top-containerOffsetTop; //+addon; var elemBottom = elemTop + 20; //parseInt($(element).height()); console.log("containter("+containerTop+","+containerBottom+"), element("+elemTop+","+elemBottom+"), addon="+addon); if (elemTop < (containerTop+pad)) { $(container).scrollTop(elemTop-pad); } else if (elemBottom > (containerBottom-pad)) { $(container).scrollTop(elemBottom - $(container).height()+pad); } } // ################################################################################################### // SELECT / UNSELECT DIVS // ################################################################################################### var activeDiv = null; var activeClass = null; var modifyElementNotClass = true; function selectDiv(div){ //console.log(div); if(!div){ console.log("No bt_ div found..."); unselectAllDivs(); }else{ activeDiv = div; modifyElementNotClass = true; console.log("Selecting #" + $(div).attr("id")); $(".bt_editableProp").attr("contenteditable", true); $(div).addClass("ui-selected"); if($(div).parent().attr("id") != "main"){ $(div).parent().addClass("ui-selected-parent"); } putActiveDivContentIntoEditor(); putActiveDivElementPropertiesIntoEditor(); selectElementStyleAsClass(); populateActiveDivClassNamesList(); var divID = $(div).attr("id"); $("#bt_divNameNode_"+divID).children(".bt_treeNodeName").addClass("bt_treeNodeSelected"); scrollIntoView("#bt_divNameNode_"+divID, "#bt_resizableContent_Elements", -18, 5); $("#bt_divName").html(divID); $("#bt_sectTitlePropertiesElName").html(divID); $("#bt_sidebarClassTabContainer").show(); $(div).children(".ui-resizable-handle").css({display: "block"}); $("#bt_addNewProp").show(); $("#bt_sidebarContentEditor").blur(); } } function unselectAllDivs(){ //$(".ui-selected").removeClass("ui-draggable").removeClass("ui-resizable").removeClass("ui-selected"); $(".ui-selected").removeClass("ui-selected"); $(".ui-selected-parent").removeClass("ui-selected-parent"); $(".bt_BG").find(".ui-resizable-handle").css({display: "none"}); clearContentEditor(); clearPropertiesEditor(); $(".bt_treeNode").children(".bt_treeNodeName").removeClass("bt_treeNodeSelected"); $("#bt_divName").html(""); $("#bt_sectTitlePropertiesElName").html(""); $("#bt_sidebarClassesEditable").html(""); $("#bt_sidebarClassTabContainer").hide(); $(".bt_editableProp").attr("contenteditable", false); $("#bt_addNewProp").hide(); activeDiv = null; activeClass = null; console.log("unselectedAllDivs."); } function setFocusInMain(f){ console.log("Focus In Main: " + f); focusInMain = f; } // ################################################################################################### // SELECTING CLASS (or ELEMENT AS CLASS) // ################################################################################################### function selectElementStyleAsClass(){ console.log(" > SELECT #[Element]"); //console.log(div); $(".bt_sidebarClassSelected").removeClass("bt_sidebarClassSelected"); $("#bt_sidebarClass_Element").addClass("bt_sidebarClassSelected"); putActiveDivElementPropertiesIntoEditor(); showActiveDivContentEditor(); //console.log($("#bt_sidebarClass_Element").attr("class")); } function selectClass(el){ $(".bt_sidebarClass").removeClass("bt_sidebarClassSelected"); $(el).addClass("bt_sidebarClassSelected"); var classToSelect = $(el).attr("cName"); if(classToSelect){ console.log(" > SELECT ."+classToSelect); activeClass = classToSelect; putActiveClassPropertiesIntoEditor(); hideActiveDivContentEditor(); setFocusInMain(true); }else{ console.log("Could not find class to select."); } } function populateActiveDivClassNamesList(){ // Order is important here! classes should be listed in the order they are defined in CSS. console.log("populating class name list."); var preClassList =$(activeDiv).attr('class').split(/\s+/); var hiddenClasses = ["bt_", "bt_dev", "bt_devBG", "ui-selected", "ui-draggable", "ui-resizable", "ui-draggable-dragging"]; var classList = []; for(var i=0; i"; classNameDivHTML += sortedClassList[i]+""; var hoverStyle = getStyleListForSelector("."+sortedClassList[i]+":hover"); if(hoverStyle && hoverStyle.length > 0){ classNameDivHTML += "
"; classNameDivHTML += "hover
"; } } $("#bt_sidebarClassesEditable").html(classNameDivHTML); var alreadyAddedHTML = ""; for(var i=0; i
×
"; alreadyAddedHTML += sortedClassList[i]; if(getStyleListForSelector("."+sortedClassList[i]+":hover").length > 0){ alreadyAddedHTML += "
:hover
"; } alreadyAddedHTML += ""; } } $("#bt_dialogClassesAlreadyAddedList").html(alreadyAddedHTML); } function sortClassListBasedOnOrderDefined(classList){ if(!classList || classList.length == 0){ return classList; } var allClassesInOrder = getAllClassesInOrder(); //console.log("* All classes in order:"); //console.log(allClassesInOrder); var orderedClassList = []; for(var i=0; i 0){ // we're in a level... sn.styleWithoutParents = sn.styleWithoutHighestParent; var singleLevelParentStyle = sn.parents[0]; var matchingBranch = null; var abc = tree.children; for(var b=0; b> " + propName); addNewPropertyByName(propName); }else{ console.log("could not find propName attribute..."); } $('#bt_dialogAddProperty').dialog("close"); } function addNewPropertyByName(propName){ if(modifyElementNotClass){ if(activeDiv){ var val = $(activeDiv).css(propName); if(!val){ val = ""; } propToAdd = [propName, val, false]; putActiveDivElementPropertiesIntoEditor(); }else{ console.log("Arg. couldn't get an active div."); } }else{ if(activeClass){ var val = getStyleForSelector("."+activeClass, propName); if(!val){ val = ""; } propToAdd = [propName, val, false]; putActiveClassPropertiesIntoEditor(); }else{ console.log("Arg. couldn't get an active class."); } } } function addPropertyKeyPress(event){ console.log("add Prop key press!"); if(event.which == 13){ //console.log("ENTER"); var propName = $("#bt_addPropertySearchInput").val(); console.log("Add prop: " + propName); if(propName && propName != ""){ closeAddNewPropertyDialog(); addNewPropertyByName(propName); setFocusInMain(false); } return false; } } // ################################################################################################### // ADDING A NEW CLASS VIA DIALOG // ################################################################################################### function openNewClassDialog(){ //console.log("Opening new class dialog."); // setup autocomplete to have the current classes. resetAutocomplete_Classes(); // update the classes shown in the dialog. var allClasses = getAllClassesInOrder(); var classListHTML = ""; for(var i=0; i"+allClasses[i]; if(getStyleListForSelector("."+allClasses[i]+":hover").length > 0){ classListHTML += "
:hover
"; } classListHTML += ""; } } $("#bt_dialogAddClassesList").html(classListHTML); $("#bt_addClassTitle").html("Add a class to " + $(activeDiv).attr('id')); $('#bt_dialogAddClass').dialog({ autoOpen: true, width: 250, height: 400, draggable: false, resizable: false, modal: false, //true, closeOnEscape: true, title: "Add A Class", close: function(event, ui) { $("#bt_addClassSearchInput").blur(); setFocusInMain(true); } }); setFocusInMain(false); handleResizeOfOddThings(); $("#bt_addClassSearchInput").val(""); $("#bt_addClassSearchInput").focus(); } function closeAddNewClassDialog(){ if($("#bt_dialogAddClass").dialog("isOpen")){ $("#bt_addClassSearchInput").blur(); $('#bt_dialogAddClass').dialog("close"); } } function addClassKeyPress(event){ console.log("add Class key press!"); if(event.which == 13){ //console.log("ENTER"); var cName = $("#bt_addClassSearchInput").val(); console.log("Adding class: " + cName); if(cName && cName != ""){ closeAddNewClassDialog(); addNewClassByName(cName); setFocusInMain(true); } return false; } } function addNewClassByName(cName){ if(!cName){ console.log("couldn't get class name from element."); return; } if(activeDiv){ addSelectorIfNotPresent("."+cName); $(activeDiv).addClass(cName); populateActiveDivClassNamesList(); $('#bt_dialogAddClass').dialog("close"); selectClass($(".bt_sidebarClass[cName="+cName+"]")[0]); } } function createNewClassFromElementProperties(){ var cName = $("#bt_addClassSearchInput").val(); console.log("Adding class from element properties: " + cName); if(cName && cName != "" && activeDiv){ closeAddNewClassDialog(); addNewClassByName(cName); addAllElementPropertiesToClass(activeDiv, cName); selectClass($(".bt_sidebarClass[cName="+cName+"]")[0]); setFocusInMain(true); }else{ alert("Please type in a class name before trying to create it."); } } function addAllElementPropertiesToClass(div, cName){ if(!div || !div.style){ console.log("bad div in addAllElementPropertiesToClass..."); return; } var ds = div.style; var styles = []; for(var i=0; i 0){ var html = "
"; $(el).append(html); } }); html = trunk.outerHTML; // show step one instructions if no elements exist yet... if(trunk.innerHTML != ""){ $("#bt_resizableContent_Elements").removeClass("bt_ShowStepOne"); html = getBTDivHTMLForTreeBG($(".bt_BG")[0], 0, true) + html; }else{ $("#bt_resizableContent_Elements").addClass("bt_ShowStepOne"); } $("#bt_resizableContent_Elements").html(html); var treeNodeHeight = 18; $("#bt_resizableContent_Elements").find(".bt_treeNode").draggable({containment: "#bt_resizableContent_Elements", axis: 'y', opacity: 0.80, helper: 'clone', zIndex: 5, refreshPositions: true, //placeholder: "ui-state-highlight", forcePlaceholderSize: true, start: function(event, ui) { console.log("start div tree drag"); $(this).css("opacity", "0.20"); var helperPos = ui.position; $(ui.helper).css("background", "rgb(245, 245, 245)"); $(ui.helper).css("width", "auto"); $(ui.helper).css("left", helperPos.left); $(ui.helper).css("right", "0px"); $("#bt_treeNodeVisibleBounds").append("
"); // .bt_treeNodeSelectorChild for children }, drag: function(event, ui) { var scrollerOffsetTop = $("#bt_resizableContent_Elements").offset().top; var scrollPos = parseInt($("#bt_resizableContent_Elements")[0].scrollTop, 10); var scrollH = $("#bt_resizableContent_Elements").height(); var maxY = $("#bt_treeNodeVisibleBounds").height() - scrollPos + 18; var scrollMod = scrollPos % treeNodeHeight; var helperTop = Math.max(10, Math.min($(ui.helper).offset().top - scrollerOffsetTop, maxY)); var vPos = Math.floor((helperTop-5 + scrollMod)/treeNodeHeight) * treeNodeHeight - scrollMod; var vPosMod = (helperTop-5+treeNodeHeight*2 + scrollMod)%treeNodeHeight; //console.log("scrollMod: " + scrollMod + ", scrollerOffsetTop: " + scrollerOffsetTop + ", scrollPos: " + scrollPos + ", vPosMod: " + vPosMod); $("#bt_treeNodeSelector").css("top", vPos+"px"); // step 1: see what div we are over ( look for closest offset().top )... var selOffsetTop = $("#bt_treeNodeSelector").offset().top; var closestEl = null; var closestDist = 10; $("#bt_resizableContent_Elements").find(".bt_treeNode").each(function(index, el){ if($(el).is(':visible')){ var elOffsetTop = $(el).offset().top; var dist = Math.abs(elOffsetTop-selOffsetTop); if(dist < closestDist){ closestDist = dist; closestEl = el; } } }); if(closestEl != null){ // step 2: given the element we're over, determine the allowable actions (sibling/child/none?). //console.log("Closest DivTree Element = " + $(closestEl).attr("id") + " at distance=" + closestDist); // step 2.A: if we're over ourself, don't do anything... var h = $(this).outerHeight(); var t = $(this).offset().top; //console.log("This ["+t+","+h+"]"); var pointInClosestEl = $(closestEl).offset().top+5 ; if(pointInClosestEl >= t && pointInClosestEl <= t+h){ $("#bt_treeNodeSelector").addClass("bt_treeNodeSelectorHidden"); }else{ // step 2.B: If closestEl has children, and closestEl is expanded, don't allow adding as sibling (confusing because order is wrong). if($(closestEl).hasClass("bt_treeNodeIndent_BG") || ($(closestEl).children(".bt_treeNode").length > 0 && !$(closestEl).hasClass("bt_treeNodeCollapsed"))){ // only can add as child $("#bt_treeNodeSelector").removeClass("bt_treeNodeSelectorHidden").addClass("bt_treeNodeSelectorChild"); }else{ if(vPosMod > 10){ $("#bt_treeNodeSelector").removeClass("bt_treeNodeSelectorHidden").removeClass("bt_treeNodeSelectorChild"); }else{ $("#bt_treeNodeSelector").removeClass("bt_treeNodeSelectorHidden").addClass("bt_treeNodeSelectorChild"); } } } }else{ //console.log("no closest El... now what?"); if(vPos <= 0){ // setup for adding to head of div tree root. $("#bt_treeNodeSelector").removeClass("bt_treeNodeSelectorHidden").removeClass("bt_treeNodeSelectorChild"); closestEl = null; }else{ // setup for adding as last sibling on root tree. $("#bt_treeNodeSelector").removeClass("bt_treeNodeSelectorHidden").removeClass("bt_treeNodeSelectorChild"); closestEl = $("#bt_treeNodeVisibleBounds").children(".treeNode").last()[0]; } } var overID = ""; if(closestEl != null){ overID = $(closestEl).attr('id'); } console.log("ID over: " + overID); $("#bt_treeNodeSelector").attr("closestEl", overID); }, stop: function(event, ui) { $(this).css("opacity", "1"); try{ //console.log("move the elements first, then remove the treeNodeSelector"); if($("#bt_treeNodeSelector").hasClass("bt_treeNodeSelectorHidden")){ console.log("DivTree: No action, selector was hidden."); }else{ var baseEl = $(".bt_BG")[0]; var divBeforeID = $("#bt_treeNodeSelector").attr("closestEl").substring(15); var divToMoveID = $(this).children(".bt_treeNodeName").text(); console.log("divBefore: " + divBeforeID + ", divToMove: " + divToMoveID); var divToMove = $("#"+divToMoveID)[0]; if(divToMove){ if(divBeforeID && divBeforeID != ""){ var divBefore = $("#"+divBeforeID)[0]; if(divBefore){ if($("#bt_treeNodeSelector").hasClass("bt_treeNodeSelectorChild")){ console.log("DivTree: try to make child of selected div"); divBefore.insertAfter(divToMove, divBefore.lastChild); }else{ console.log("DivTree: try to add as sibling to selected div."); $(divToMove).insertBefore(divBefore); } }else{ console.log("DivTree: divBefore was defined, but could not be found. safely aborting. :("); } }else{ console.log("DivTree: no divBefore: place divToMove at the head on the root."); baseEl.insertAfter(divToMove, baseEl.lastChild); } }else{ console.log("DivTree: Couldn't find divToMove. safely aborting. :("); } } }catch(err){ console.log("DivTree: Div placement error"); console.log(err); } $("#bt_treeNodeSelector").remove(); putAllBTDivsIntoTree(); } }); } function getBTDivHTMLForTreeBG(div, indent, keepCollapseState){ var dName = $(div).attr("id"); var html = ""; // onclick="clicked(event,this)" onblur="blur_DivName(event,this);" onkeypress="return keypress_DivName(event,this);" spellcheck="false" contenteditable="true" html += "
"; html += "
"; return html; } function getBTDivHTMLForTree(div, indent, keepCollapseState){ var dName = $(div).attr("id"); var html = ""; // onclick="clicked(event,this)" onblur="blur_DivName(event,this);" onkeypress="return keypress_DivName(event,this);" spellcheck="false" contenteditable="true" html += "
"; html += "
"; return html; } function toggleTreeNodeCollapsed(el){ if($(el).parent().hasClass("bt_treeNodeCollapsed")){ $(el).parent().removeClass("bt_treeNodeCollapsed"); $(el).removeClass("bt_treeNodeCollapseHandle2"); $(el).parent().find(".bt_treeNode").show(); }else{ $(el).parent().addClass("bt_treeNodeCollapsed"); $(el).addClass("bt_treeNodeCollapseHandle2"); $(el).parent().find(".bt_treeNode").hide(); } } function clickedTreeNode(event, el){ unselectAllDivs(); var elToSelect = $("#"+$(el).text())[0]; selectDiv(elToSelect); if($(elToSelect).hasClass("bt_BG")){ // hide position, spacing, and border. $("#bt_stylePanel_Position").hide(); $("#bt_stylePanel_Spacing").hide(); $("#bt_stylePanel_Border").hide(); $("#bt_stylePanel_Content").hide(); }else{ // show them. $("#bt_stylePanel_Position").show(); $("#bt_stylePanel_Spacing").show(); $("#bt_stylePanel_Border").show(); $("#bt_stylePanel_Content").show(); } } function doubleClickedTreeNode(event, el){ $(el).attr("contenteditable", "true"); $(el).focus(); } function blurTreeNode(event, el){ if($(el).attr("contenteditable") && activeDiv){ // TODO: Strip name of special chars that shouldn't exist (#, ., <, >, etc.) before trying to rename. tryToRenameElement(activeDiv, $(el).text()); putAllBTDivsIntoTree(); var divID = $(activeDiv).attr("id"); $("#bt_divNameNode_"+divID).children(".bt_treeNodeName").addClass("bt_treeNodeSelected"); setFocusInMain(true); } } function keypressTreeNode(event, el){ console.log(event); if(event.which == 13){ //console.log("ENTER"); $(el).blur(); setFocusInMain(true); return false; } if(event.which == 32){ //console.log("SPACE"); return false; } if(event.which == 45 || event.which == 95 || (event.which >= 48 && event.which <= 57) || (event.which >= 65 && event.which <= 90) || (event.which >= 97 && event.which <= 122)){ // valid. (-, _, a-z, A-Z) }else{ return false; } } // ################################################################################################### // MOUSE CLICK, DRAG, AND DOUBLE-CLICK // ################################################################################################### $(document).click(function(event){ console.log("click!"); //console.log(event.target); // TODO: Close any other dialogs closeAddNewClassDialog(); closeAddNewPropertyDialog(); closeErrorDialog(); closeHistoryDialog(); closeHelp(); closeAllSpecialValueDialogs(); closeSubmitBugDialog(); if($(event.target).hasClass("bt_BG") || $(event.target).parents(".bt_BG").length > 0){ console.log("clicked in main."); setFocusInMain(true); unselectAllDivs(); if(!$(event.target).hasClass("bt_BG")){ var target = event.target; if(!$(event.target).hasClass("bt_")){ target = $(target).parents(".bt_")[0]; //console.log("getting parrent with bt_"); //console.log(target); } selectDiv(target); } }else{ setFocusInMain(false); } }); $(document).mouseup(function(e){ dVal_ColorSatLum_MouseIsDown = false; dVal_ColorHueLum_MouseIsDown = false; }); // TODO: Drag is a bit complicated, since jquery resize and drag operations gobble up the event and don't bubble it here... $(document).bind("drag", function(event){ if(!$(event.target).hasClass("ui-selected") && ($(event.target).hasClass("bt_BG") || $(event.target).parents(".bt_BG").length > 0)){ console.log("start drag!"); //console.log(event.target); setFocusInMain(true); unselectAllDivs(); if($(event.target).hasClass("bt_BG")){ var target = event.target; if(!$(event.target).hasClass("bt_")){ target = $(target).parents(".bt_")[0]; //console.log("getting parrent with bt_"); //console.log(target); } selectDiv(target); } }else{ if($(event.target).hasClass("ui-selected")){ setFocusInMain(true); // ?? putActiveDivElementPropertiesIntoEditor(event.target); }else{ console.log("FALSE DRAG"); setFocusInMain(false); } } }); $(document).dblclick(function(event){ //console.log("double click!"); unselectHighlightedPageContent(); //console.log(event.target); if($(event.target).hasClass("bt_BG") || $(event.target).parents(".bt_BG").length > 0){ unselectAllDivs(); if($(event.target).hasClass("bt_BG")){ // put it under main. var left = (Math.floor((event.pageX+5)/10)*10); var top = (Math.floor((event.pageY+5)/10)*10); addNewDivToParentAndSelectIt($(".bt_BG")[0], left, top); }else{ // put it under its parent. var target = event.target; if(!$(event.target).hasClass("bt_")){ target = $(target).parents(".bt_")[0]; } if(target){ var left = (Math.floor((event.pageX-$(target).offset().left)/10)*10); var top = (Math.floor((event.pageY-$(target).offset().top)/10)*10); addNewDivToParentAndSelectIt(target, left, top); } } } unselectHighlightedPageContent(); }); // ################################################################################################### // KEYDOWN / SHORTCUT HANDLERS FOR MAIN CONTENT MANIPULATION // ################################################################################################### var ctrlDown = false; var cmdDown = false; var ctrlKey = 17; var cmdKey = 91; var vKey = 86; var cKey = 67; var sKey = 83; document.addEventListener("keydown", function(e){ if(e.keyCode == 46 || e.keyCode == 8){ console.log("caught unsafe delte keypress. use event.cancelBubble=true if needed by the target element."); e.stopPropagation(); e.cancelBubble = true; e.preventDefault(); console.log(e); //alert("TRYING TO PREVENT BROWSER GO-BACK ACTION..."); return false; } }, false); $(document).keyup(function(e){ if (e.keyCode == ctrlKey){ ctrlDown = false; } if(e.keyCode == cmdKey){ cmdDown = false; } }); $(document).keydown(function(e){ if (e.keyCode == ctrlKey){ ctrlDown = true; return; } if(e.keyCode == cmdKey){ cmdDown = true; return; } if(!focusInMain){ return true; } if(helpIsOpen){ closeHelp(); } if((ctrlDown || cmdDown) && (e.keyCode == vKey || e.keyCode == cKey)){ console.log("Copy/Paste Detected..."); if(e.keyCode == vKey){ handleKeypress_Paste(); }else{ handleKeypress_Copy(); } return false; } if((ctrlDown || cmdDown) && (e.keyCode == sKey)){ console.log("SAVE via keyboard shortcut!"); save(); return false; } // we know that the focus is in the editable container area... console.log(e); if (e.keyCode == 37) { console.log("left pressed"); if(e.shiftKey){ $(".ui-selected").each(function(i,el){ var l = Math.max(0, $(el).position().left-10); $(el).css({left: l}); putActiveDivElementPropertiesIntoEditor(); }); }else{ $(".ui-selected").each(function(i,el){ var l = Math.max(0, $(el).position().left-1); $(el).css({left: l}); putActiveDivElementPropertiesIntoEditor(); }); } return false; } if (e.keyCode == 38) { console.log("up pressed"); if(e.shiftKey){ $(".ui-selected").each(function(i,el){ var t = Math.max(0, $(el).position().top-10); $(el).css({top: t}); putActiveDivElementPropertiesIntoEditor(); }); }else{ $(".ui-selected").each(function(i,el){ var t = Math.max(0, $(el).position().top-1); $(el).css({top: t}); putActiveDivElementPropertiesIntoEditor(); }); } return false; } if (e.keyCode == 39) { console.log("right pressed"); if(e.shiftKey){ $(".ui-selected").each(function(i,el){ var l = Math.max(0, $(el).position().left+10); $(el).css({left: l}); putActiveDivElementPropertiesIntoEditor(); }); }else{ $(".ui-selected").each(function(i,el){ var l = Math.max(0, $(el).position().left+1); $(el).css({left: l}); putActiveDivElementPropertiesIntoEditor(); }); } return false; } if (e.keyCode == 40) { console.log("down pressed"); if(e.shiftKey){ $(".ui-selected").each(function(i,el){ var t = Math.max(0, $(el).position().top+10); $(el).css({top: t}); putActiveDivElementPropertiesIntoEditor(); }); }else{ $(".ui-selected").each(function(i,el){ var t = Math.max(0, $(el).position().top+1); $(el).css({top: t}); putActiveDivElementPropertiesIntoEditor(); }); } return false; } if(e.keyCode == 46 || e.keyCode == 8){ console.log("backspace/delete pressed"); $(".bt_BG").find(".ui-selected").remove(); unselectAllDivs(); putAllBTDivsIntoTree(); return false; } // KEYBOARD SHORTCUTS! :) console.log(e.keyCode); if(e.keyCode == 78){ // 'n' // FIXME: Jump to naming... console.log("Naming"); if($(".ui-selected").length > 0 && $(".bt_treeNodeSelected").length > 0){ doubleClickedTreeNode(null, $(".bt_treeNodeSelected")[0]); //$("#bt_divName").focus(); //clicked(null, $("#bt_divName")[0]); return false; } } if(e.keyCode == 80){ // 'p' if($(".ui-selected").length > 0){ openNewPropertyDialog(); return false; } } if(e.keyCode == 67){ // 'c' if($(".ui-selected").length > 0){ openNewClassDialog(); return false; } } if(e.keyCode == 65){ // 'a' unselectAllDivs(); addNewDivToParentAndSelectIt($(".bt_BG")[0], 0, 0); } //if(e.keyCode == 32){ // ' ' (space) if(e.keyCode == 84){ // 't' selectElementStyleAsClass(); $("#bt_sidebarContentEditor").focus(); setFocusInMain(false); return false; } if(e.keyCode == 72){ // 'h' showHistory(); return false; } if(e.keyCode == 83){ // 's' flipPropertiesCard(); return false; } if(e.keyCode == 191){ // '?' console.log("showing help..."); showHelp(); } }); // ################################################################################################### // KEYDOWN / COPY & PASTE // ################################################################################################### function handleKeypress_Paste(){ console.log("*** PASTE"); if (localStorage) { var clipboardHTML = localStorage.getItem("boxesandtext_Clipboard"); console.log(clipboardHTML); if(clipboardHTML && clipboardHTML != ""){ var testDiv = document.createElement('div'); $(testDiv).append(clipboardHTML); $(testDiv).find(".bt_").each(function(index, el){ var initialID = $(el).attr("id"); if(!initialID){ // randomly assign an ID.. it had none. $(el).attr("id", getNextNewDivID()); }else{ if($(".bt_BG").find("#"+initialID).size() > 0){ // duplicateID! console.log("duplicate!"); var idCounter = 1; while($(".bt_BG").find("#"+initialID+"_"+idCounter).size() > 0 || $(testDiv).find("#"+initialID+"_"+idCounter).size()){ idCounter++; } $(el).attr("id", initialID+"_"+idCounter); }else{ // id is okay.. leave it alone } } }); var clipHTMLWithNewNames = $(testDiv).html(); console.log(clipHTMLWithNewNames); var pActive = null; if(activeDiv){ pActive = activeDiv; console.log("appending copy html to activeDiv."); $(activeDiv).append(clipHTMLWithNewNames); $(activeDiv).append("\n"); }else{ console.log("appending copy html to BG."); $(".bt_BG").append(clipHTMLWithNewNames); $(".bt_BG").append("\n"); } makeSureAllBTDivsAreSetupForInteraction(); if(viewModeIsLive){ setViewModeToLive(); }else{ setViewModeToBuild(); } putAllBTDivsIntoTree(); unselectAllDivs(); if(pActive){ selectDiv(pActive); } } } } function handleKeypress_Copy(){ console.log("*** COPY"); if(activeDiv){ console.log("Copying active div: " + $(activeDiv).attr("id")); if(localStorage){ var c = $(activeDiv).clone(true, true); removeInteractionFromDiv(c); localStorage.setItem("boxesandtext_Clipboard", $(c)[0].outerHTML); }else{ console.log("Can't copy.. browser doesn't seem to have local storage?!"); } var parentBT = $(activeDiv).parents(".bt_").first(); console.log(parentBT); if(parentBT && parentBT.length > 0){ unselectAllDivs(); selectDiv(parentBT[0]); }else{ unselectAllDivs(); } //selectDiv($(activeDiv).parents(".bt_").first()); }else{ console.log("Nothing to copy..."); } } var currentContentDiv = null; function putActiveDivContentIntoEditor(){ $("#bt_sidebarContentEditor").val($(activeDiv).children(".content").html()); currentContentDiv = $(activeDiv).children(".content")[0]; showActiveDivContentEditor(); // resize content editor to size of content. $("#bt_sidebarContentEditor").css({height: 50}); $("#bt_sidebarContentEditor").css({height: $("#bt_sidebarContentEditor").attr("scrollHeight")-10}); } function updateContentFromEditor(){ if(currentContentDiv != null){ $(currentContentDiv).html($("#bt_sidebarContentEditor").val()); } } function clearContentEditor(){ currentContentDiv = null; $("#bt_sidebarContentEditor").val(""); hideActiveDivContentEditor(); } function showActiveDivContentEditor(){ $("#bt_stylePanel_Content").show(); //$("#bt_sidebarPropEdit_Content").show(); //$("#bt_sidebarContentEditor").show(); } function hideActiveDivContentEditor(){ $("#bt_stylePanel_Content").hide(); //$("#bt_sidebarPropEdit_Content").hide(); } function contentEditorKeyDown(event){ console.log(event); if(event.keyCode == 27){ // Escape key! event.stopPropagation(); $(event.target).blur(); updateContentFromEditor(); setFocusInMain(true); return false; } event.cancelBubble = true; } $("#bt_sidebarContentEditor").keyup(function(e){ //console.log("changed!"); if(e.keyCode >= 37 && e.keyCode <= 40){ // arrow keys! don't worry about reloading the content. }else{ // resize the textarea to fit all content height. if(e.keyCode == 46 || e.keyCode == 8){ // content was deleted... $("#bt_sidebarContentEditor").css({height: 50}); } $("#bt_sidebarContentEditor").css({height: $("#bt_sidebarContentEditor").attr("scrollHeight")-10}); updateContentFromEditor(); } }); function unselectHighlightedPageContent(){ console.log("unselecting..."); var oTextRange = window.getSelection(); try{ if(!oTextRange.isCollapsed){ oTextRange.collapseToStart(); }else{ console.log("already collapsed. no need to unselect."); } }catch(ex){ console.log("Encountered error trying to unselect..."); console.log(oTextRange); console.log(ex); } } function clicked(event,el){ //console.log(event); //console.log(el); if($(el).attr("id") == "bt_divName"){ setFocusInMain(false); console.log("now editing Name... anything special to do?"); } } // ################################################################################################### // HANDLERS FOR DIV NAME MANIPULATION // ################################################################################################### /* function keypress_DivName(event, el){ console.log(event); if(event.which == 13){ //console.log("ENTER"); $(el).blur(); focusInMain = true; return false; } if(event.which == 32){ //console.log("SPACE"); return false; } if(event.which == 45 || event.which == 95 || (event.which >= 48 && event.which <= 57) || (event.which >= 65 && event.which <= 90) || (event.which >= 97 && event.which <= 122)){ // valid. (-, _, a-z, A-Z) }else{ return false; } } */ /* function blur_DivName(event, el){ console.log("divName: BLUR"); // TODO: Strip name of special chars that shouldn't exist (#, ., <, >, etc.) before trying to rename. tryToRenameElement($(".ui-selected")[0], $(el).text()); focusInMain = true; } */ function classNameIsValid(classname){ var matches = classname.match(/-?[_a-zA-Z]+[_a-zA-Z0-9-]*/); if(matches && matches.length > 0 && matches[0] == classname){ console.log("Match: " + matches[0]); return true; } return false; } function tryToRenameElement(div, newName){ if(!div){ showError("No div is selected."); return; } if(newName == $(div).attr("id")){ return; // name is the same; no change needed. } if(newName.length <= 0){ showError("Element names must have a length greater than zero."); return; } if($("#"+newName).length != 0){ showError("An element with the name '"+newName+"' already exists."); return; } if(!classNameIsValid(newName)){ showError("Invalid Name: '"+newName+"'"); return; } // Rename it! $(div).attr("id", newName); } // ################################################################################################### // HANDLERS FOR PROPERTY VALUE MANIPULATION // ################################################################################################### function keypress_PropVal(event, el){ if(event.which == 13){ // ENTER was pressed. //console.log("ENTER"); $(el).blur(); return false; } $(el).removeClass("bt_propValDefault").removeClass("bt_propValDefaultDash"); // editing it.. no longer default value event.cancelBubble = true; /* if(event.which == 9){ // TAB was pressed console.log("TAB"); $(el).blur(); var next = $(el).next(".bt_propVal")[0]; console.log("next: "); console.log(next); if(next){ $(next).focus(); clicked(null, next); } return false; } */ } function onchange_PropVal(event, el){ $(el).removeClass("bt_propValDefault").removeClass("bt_propValDefaultDash"); blur_PropVal(event, el); } function blur_PropVal(event, el){ console.log("propVal: BLUR"); // TODO: Make sure the new value can't totally break things. var newVal = $(el).text(); if($(el).hasClass("bt_editablePropDropdown") && el[el.selectedIndex]){ newVal = el[el.selectedIndex].value; } if(modifyElementNotClass){ tryToUpdateElementPropertyVal(activeDiv, $(el).attr("propName"), newVal, el); }else{ tryToUpdateClassPropertyVal(activeClass, $(el).attr("propName"), newVal, el); } setFocusInMain(true); } function tryToUpdateElementPropertyVal(div, propName, propVal, propEditorDiv){ //console.log("ELEMENT >> Update prop < " + propName + "> to " + propVal); $(div).css(propName, propVal); var updatedStyleVal = $(div).css(propName); if(propVal && propVal != "" && !isNaN(propVal) && propVal != updatedStyleVal){ // FIXME console.log("Number entry failed... Trying with 'px' suffix."); $(div).css(propName, propVal+"px"); updatedStyleVal = $(div).css(propName); } //if(propEditorDiv){ if($(propEditorDiv).hasClass("bt_editablePropDropdown")){ setSelectElementVal(propEditorDiv, updatedStyleVal); }else{ $(propEditorDiv).html(updatedStyleVal); } //} } function tryToUpdateClassPropertyVal(classname, propName, propVal, propEditorDiv){ //console.log("CLASS >> Update prop < " + propName + "> to " + propVal); setStyleForSelector("."+classname, propName, propVal); var updatedStyleVal = getStyleForSelector("."+classname, propName); if(propVal && propVal != "" && !isNaN(propVal) && propVal != updatedStyleVal){ // FIXME console.log("Number entry failed (class)... Trying with 'px' suffix."); setStyleForSelector("."+classname, propName, propVal+"px"); updatedStyleVal = getStyleForSelector("."+classname, propName); } //if(propEditorDiv){ if($(propEditorDiv).hasClass("bt_editablePropDropdown")){ setSelectElementVal(propEditorDiv, updatedStyleVal); }else{ $(propEditorDiv).html(updatedStyleVal); } //} } function setSelectElementVal(select, val){ var selIndex = -1; for(var i=0; i> " + val); } select.selectedIndex = selIndex; } // ################################################################################################### // RAW CSS TEXT EDITOR // ################################################################################################### var propCardIsFlipped = false; function flipPropertiesCard(){ console.log("Flip the CSS/Property editor!"); if(propCardIsFlipped){ $("#bt_sidebarPropertiesEditor").removeClass("bt_flipY180"); $("#bt_sidebardPropertiesRawText").removeClass("bt_flipY360"); }else{ $("#bt_sidebarPropertiesEditor").addClass("bt_flipY180"); $("#bt_sidebardPropertiesRawText").addClass("bt_flipY360"); } if(modifyElementNotClass){ putActiveDivElementPropertiesIntoEditor(); }else{ putActiveClassPropertiesIntoEditor(); } propCardIsFlipped = !propCardIsFlipped; } // ################################################################################################### // ERROR DIALOG... // ################################################################################################### function showError(msg){ alert(msg); // FIXME: Should be a nicer error message than an alert... /* if($(".ui-widget-overlay").length > 0){ console.log("dialog is already open. Not showing error: " + msg); return; } console.log("showing error: " + msg); $('#bt_dialogModal').html(msg); $('#bt_dialogModal').dialog({ autoOpen: true, width: 300, height: 80, draggable: false, resizable: false, modal: false, //true, closeOnEscape: true, title: "Error" }); */ } function closeErrorDialog(){ if($('#bt_dialogModal').dialog("isOpen")){ $('#bt_dialogModal').dialog("close"); } } // ################################################################################################### // HELP DIALOG... // ################################################################################################### var helpIsOpen = false; function showHelp(){ $("#bt_help").show(); helpIsOpen = true; } function closeHelp(){ $("#bt_help").fadeOut(150); setFocusInMain(true); helpIsOpen = false; } // ################################################################################################### // SAVING AND LOADING... // ################################################################################################### var versionHistory = []; function save(){ console.log("** Saving..."); var staticCSS = ""; var dynamicCSS = getDynamicCSS(); //console.log(dynamicCSS); var c = $(".bt_BG").clone(true,true); /* $(c).find(".ui-resizable-handle").remove(); $(c).find(".ui-draggable").removeClass("ui-draggable"); $(c).removeClass("ui-draggable"); $(c).find(".ui-resizable").removeClass("ui-resizable"); $(c).removeClass("ui-resizable"); $(c).find(".ui-selected").removeClass("ui-selected"); $(c).removeClass("ui-selected"); $(c).find(".ui-selected-parent").removeClass("ui-selected-parent"); $(c).removeClass("ui-selected-parent"); $(c).find(".bt_dev").removeClass("bt_dev"); $(c).removeClass("bt_dev"); $(c).find(".bt_devBG").removeClass("bt_devBG"); $(c).removeClass("bt_devBG"); */ removeInteractionFromDiv(c); $(c).css("right", "0px"); var dynamicHTML = $(c)[0].outerHTML; //console.log(dynamicHTML); var outputHTML = "\nB&T Page\n\n\n\n\n\n"; outputHTML += "\n\n\n"+dynamicHTML+"\n\n\n" } outputHTML += "
\n\n\n\n"; //console.log(outputHTML); //loadPage(outputHTML); // SAVE IT :) $.ajax({ type: "POST", url: "./php/save.php", processData: true, data: { "content": outputHTML }, success: function (msg) { var pageID = $(msg).find("savepoint").attr("pageID"); console.log("Saved >> PageID = " + pageID); versionHistory.push(pageID); // when done with save.. update the hash window.location.hash = pageID; updateHistoryList(); showSaveConfirmation(pageID); }, error: function (msg) { console.log("ERROR tring to save to server. " + msg); } }); } function removeInteractionFromDiv(c){ $(c).find(".ui-resizable-handle").remove(); $(c).removeClass(".ui-resizable-handle"); $(c).find(".ui-draggable").removeClass("ui-draggable"); $(c).removeClass("ui-draggable"); $(c).find(".ui-resizable").removeClass("ui-resizable"); $(c).removeClass("ui-resizable"); $(c).find(".ui-selected").removeClass("ui-selected"); $(c).removeClass("ui-selected"); $(c).find(".ui-selected-parent").removeClass("ui-selected-parent"); $(c).removeClass("ui-selected-parent"); $(c).find(".bt_dev").removeClass("bt_dev"); $(c).removeClass("bt_dev"); $(c).find(".bt_devBG").removeClass("bt_devBG"); $(c).removeClass("bt_devBG"); } function showSaveConfirmation(pageID){ // TODO: show a popup of the new URL to use... ? $("#bt_historySaveConfirm_chkpt").val(window.location); $("#bt_historySaveConfirm_rawHTML").attr("href", "../pages/"+pageID+".html"); showHistory(); $("#bt_historySaveConfirmation").show().css({opacity: .5}).animate({opacity: 1}, 250); } function hideSaveConfirmation(){ $("#bt_historySaveConfirmation").hide(); } function fork(){ console.log("TODO: Forking..."); //var html = "
"; //loadPage(html); } function loadCSSAndHTML(css, html){ var cssEl = document.getElementById("bt_css_editable"); //console.log(cssEl); cssEl.innerText = css; //console.log(cssEl); initEditableStylesheet(); $(".bt_BG").replaceWith(html); $(".bt_BG").find(".bt_").each(function(index, el){ setupDivForInteraction(el); if(!$(el).attr('id')){ $(el).attr('id', getNextNewDivID()); } }); setViewModeToBuild(); putAllBTDivsIntoTree(); unselectAllDivs(); } function loadPage(html){ var testDiv = document.createElement('html'); //console.log(html); testDiv.innerHTML = html; //console.log(testDiv); versionHistory = []; // rebuild version history. $(testDiv).find("#bt_metaInfo").find(".bt_versionInfo").each(function(index, el){ versionHistory.push($(el).text()) }); console.log("History:"); console.log(versionHistory); savedColorPalettes = []; // rebuild color palettes... $(testDiv).find("#bt_metaInfo").find(".bt_colorPalette").each(function(index, el){ var pName = $(el).attr("title"); if(!pName || pName == ""){ pName = "New Palette"; } var cArray = []; $(el).find(".bt_colorPaletteEntry").each(function(index2, el2){ var rgba = tryToGetRGBAColorFromValueAlone($(el2).text()); if(rgba){ cArray.push(rgba); }else{ console.log("Failed to load save color in palette: " + pName + ", val was: " + $(el2).text()); } }); savedColorPalettes.push(new ColorPalette(pName, cArray)); }); console.log("Color Palettes:"); console.log(savedColorPalettes); var css = $(testDiv).find("#bt_css_editable").html(); var htm = $(testDiv).find(".bt_BG")[0].outerHTML; //console.log(css); //console.log(htm); loadCSSAndHTML(css, htm); } function loadPageFromID(pageID){ $.ajax({ type: "GET", url: "./php/fetch.php?pageID="+pageID, success: function (msg) { console.log("Got page..."); // Process the page and update version history... loadPage(msg); versionHistory.push(pageID); updateHistoryList(); }, error: function (msg) { console.log("ERROR trying to fetch page by ID. " + msg); } }); } function tryToLoadPageUsingURLHash(){ var hash = window.location.hash; if(hash){ var hashID = hash.substring(1); if(versionHistory.length > 0 && hashID == versionHistory[versionHistory.length-1]){ console.log("No need to update.. just saved the latest copy."); }else{ //console.log(versionHistory[versionHistory.length-1]); console.log("Loading from hashed pageID: *" + hashID +"*"); loadPageFromID(hashID); } } } // ################################################################################################### // HISTORY... // ################################################################################################### function showHistory(){ historyIsOpen = true; console.log("TODO: Show history..."); // populate the history list... updateHistoryList(); $('#bt_dialogViewHistory').dialog({ autoOpen: true, width: 250, height: 400, draggable: false, resizable: false, modal: false, //true, closeOnEscape: true, title: "", close: function(event, ui) { setFocusInMain(true); } }); setFocusInMain(false); } function updateHistoryList(){ var historyHTML = ""; if(versionHistory.length <= 0){ // no history yet... historyHTML = "
No page history yet...
" }else{ var d = new Date(); var hourTZ = d.getTimezoneOffset()/60 - 4; console.log("TimeDiff: " + hourTZ); // go through versions in reverse order... for(var i=versionHistory.length-1; i>=0; i--){ var v = versionHistory[i]; var year = v.substr(0,4); var month = v.substr(4,2); var day = v.substr(6,2); var hour = (parseInt(v.substr(9,2))+24-hourTZ)%24; var min = v.substr(11,2); var mName = getMonthName(month); var ampm = "am"; var hour12 = hour; if(hour >= 12){ hour12 = hour-12; ampm = "pm"; } historyHTML += "
"; } } $("#bt_dialogHistoryList_B").html(historyHTML); } function closeHistoryDialog(){ if($('#bt_dialogViewHistory').dialog("isOpen")){ $('#bt_dialogViewHistory').dialog("close"); } } var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; function getMonthName(num){ var index = parseInt(num); if(index > 0 && index <= 12){ return monthNames[index-1]; }else{ return "???"; } } function signUpForNewsletter(){ var val = $("#bt_helpInputEmailNewsletter").val(); if(!val || val == "" || val.length < 5){ alert("Hmm.. It doesn't look like your email is quite complete."); } $.ajax({ type: "POST", url: "./php/tweet.php", processData: true, data: { "type": "newsletter", "content": val }, success: function (msg) { console.log("Email success. " + msg); alert("You're all signed up.\n\nWe'll keep you posted. Thanks. :)"); }, error: function (msg) { console.log("ERROR tring send to server. " + msg); } }); $("#bt_helpInputEmailNewsletter").val(""); } function showSubmitBugDialog(){ $('#bt_dialogSubmitBug').dialog({ autoOpen: true, width: 250, height: 400, draggable: false, resizable: false, modal: false, //true, closeOnEscape: true, title: "", close: function(event, ui) { setFocusInMain(true); } }); setFocusInMain(false); updateBugList(); } function closeSubmitBugDialog(){ if($('#bt_dialogSubmitBug').dialog("isOpen")){ $('#bt_dialogSubmitBug').dialog("close"); } } function submitBug(){ var val = $("#bt_dialogBugEntryText").val(); if(!val || val == "" || val.length < 10){ alert("Hmm.. It doesn't look like you there's quite enough detail.\n\nAdd a bit more information and try again."); } $.ajax({ type: "POST", url: "./php/tweet.php", processData: true, data: { "type": "bug", "content": val }, success: function (msg) { console.log("Bug success. " + msg); alert("Thanks for letting us know.\n\nWe'll get right on it!"); updateBugList(); }, error: function (msg) { console.log("ERROR tring send to server. " + msg); } }); //closeSubmitBugDialog(); $("#bt_dialogBugEntryText").val(""); } function updateBugList(){ $.ajax({ type: "GET", url: "./php/fetchbugs.php?rand="+Math.random(), success: function (msg) { //console.log("BugList success. " + msg); var lines = msg.split("\n"); var escapedHTML = ""; for(var i=lines.length-1; i>=0; i--){ var vals = lines[i].split("|"); //console.log(vals); if(vals.length == 4){ if(vals[2].indexOf("FIXED:") >= 0){ escapedHTML += "
"+vals[3].trim().replace("<", "<").replace(">", ">")+"
"; }else{ if(vals[2].indexOf("FIXING:") >= 0){ escapedHTML += "
"+vals[3].trim().replace("<", "<").replace(">", ">")+"
"; }else{ if(vals[2].indexOf("NOFIX:") >= 0){ escapedHTML += "
"+vals[3].trim().replace("<", "<").replace(">", ">")+"
"; }else{ escapedHTML += "
"+vals[3].trim().replace("<", "<").replace(">", ">")+"
"; } } } } } $("#bt_dialogBugList").html(escapedHTML); }, error: function (msg) { console.log("ERROR tring to fetch bug list. " + msg); } }); } // for variable watch debugging... //setInterval(function(){console.log("FocusInMail: " + focusInMain)}, 1000); // ##PHP ADD IN: JS Palettes. // --------------------------------- // COLOR PICKER... // (function ($) { var RGBAPicker = function () { var pickerHTML = "
"; pickerHTML += "
"; pickerHTML += "
"; pickerHTML += "
"; pickerHTML += "
"; pickerHTML += "
9){ var cTrim = c.substring(4, c.indexOf(")")); var cArr = cTrim.split(","); if(cArr.length == 3){ return new RGBAColor(parseInt(cArr[0],10), parseInt(cArr[1],10), parseInt(cArr[2],10), 1.0, elName, style); }else{ console.log("Error in RGB: " + c); } } if(c.indexOf("rgba(") == 0 && c.indexOf(")") >= 9){ var cTrim = c.substring(5, c.indexOf(")")); var cArr = cTrim.split(","); if(cArr.length == 4){ if(parseFloat(cArr[3]) >= 0.0){ return new RGBAColor(parseInt(cArr[0],10), parseInt(cArr[1],10), parseInt(cArr[2],10), parseFloat(cArr[3]), elName, style); } }else{ console.log("Error in RGBA: " + c); } } return null; } var defaults = { onChange: function (rgba) {}, color: 'rgba(128, 198, 128, 1)', }; var idCounter = 1; return { init: function(opt){ console.log("init RGBA..."); opt = $.extend({}, defaults, opt||{}); return this.each(function(index, el){ if($(el).data('rgbaPickerID')){ console.log("This element has already been initialized with the rgbaPicker. "); console.log(this); return; } var rootEl = el; $(el).data('rgbaPickerID', idCounter++); var activeRGBA = new RGBAColor(128, 128, 128, 1.0, "", ""); var options = $.extend({}, opt); var rgba = tryToGetRGBAColorFromValueAlone(options.color, "", ""); if(rgba){ activeRGBA = rgba; } var colorSatLum_MouseIsDown = false; var colorHueLum_MouseIsDown = false; $(document).mouseup(function(e){ colorSatLum_MouseIsDown = false; colorHueLum_MouseIsDown = false; }); var mouseMove_SatLum = function(e){ if(colorSatLum_MouseIsDown){ console.log("drag in satLum"); var x = e.pageX-$(this).offset().left; var y = e.pageY-$(this).offset().top; colorMouseEvent_SatLum(x, y); return false; } }; var mouseDown_SatLum = function(e){ colorSatLum_MouseIsDown = true; var x = e.pageX-$(this).offset().left; var y = e.pageY-$(this).offset().top; colorMouseEvent_SatLum(x, y); return false; }; var mouseMove_HueLum = function(e){ if(colorHueLum_MouseIsDown){ console.log("drag in hueLum"); var x = e.pageX-$(this).offset().left; var y = e.pageY-$(this).offset().top; colorMouseEvent_HueLum(x, y); return false; } } var mouseDown_HueLum = function(e){ colorHueLum_MouseIsDown = true; var x = e.pageX-$(this).offset().left; var y = e.pageY-$(this).offset().top; colorMouseEvent_HueLum(x, y); return false; } function colorMouseEvent_HueLum(x, y){ var newHue = Math.min(1.0, Math.max(0.0, ((x-4)/92.0))); var newLum = Math.min(1.0, Math.max(0.0, 1.0-((y-4)/92.0))); console.log("new Hue: " + newHue + ", new Lum: " + newLum); if(activeRGBA){ var savedSat = Math.max(0.01, activeRGBA.sat); var newRGB = hsvToRgb(newHue , savedSat, newLum); activeRGBA = new RGBAColor(parseInt(newRGB[0]), parseInt(newRGB[1]), parseInt(newRGB[2]), activeRGBA.a, activeRGBA.elName, activeRGBA.style); activeRGBA.sat = savedSat; activeRGBA.hue = newHue; update_ColorHue(newHue); update_ColorFromRGBA(activeRGBA); } } function colorMouseEvent_SatLum(x, y){ var newSat = Math.min(1.0, Math.max(0.0, ((x-4)/92.0))); var newLum = Math.min(1.0, Math.max(0.0, 1.0-((y-4)/92.0))); if(activeRGBA){ var savedHue = activeRGBA.hue; var newRGB = hsvToRgb(savedHue , newSat, newLum); activeRGBA = new RGBAColor(parseInt(newRGB[0]), parseInt(newRGB[1]), parseInt(newRGB[2]), activeRGBA.a, activeRGBA.elName, activeRGBA.style); activeRGBA.hue = savedHue; activeRGBA.sat = newSat; activeRGBA.lum = newLum; update_ColorFromRGBA(activeRGBA, true); } } function update_ColorHue(h){ var decH = h; var rgbLeft = hsvToRgb(decH, 1.0, 1.0); var bgGradients = "-webkit-gradient(linear, left top, left bottom, color-stop(2%,rgba(0,0,0,0)), color-stop(98%,rgba(0,0,0,1))), "; bgGradients += " -webkit-gradient(linear, left top, right top, color-stop(4%,rgba("; bgGradients += Math.floor(rgbLeft[0])+","+Math.floor(rgbLeft[1])+","+Math.floor(rgbLeft[2]); bgGradients += ",0)), color-stop(96%,rgba("; bgGradients += Math.floor(rgbLeft[0])+","+Math.floor(rgbLeft[1])+","+Math.floor(rgbLeft[2]); bgGradients += ",1))), "; bgGradients += "-webkit-gradient(linear, left top, left bottom, color-stop(2%,rgba(255,255,255,1)), color-stop(98%,rgba(0,0,0,1)))"; $(rootEl).find(".rgbaPicker_ColorSel_SatLum").css({"background": bgGradients}); if(activeRGBA){ var newRGB = hsvToRgb(decH, activeRGBA.sat, activeRGBA.lum); activeRGBA = new RGBAColor(parseInt(newRGB[0]), parseInt(newRGB[1]), parseInt(newRGB[2]), activeRGBA.a, activeRGBA.elName, activeRGBA.style); update_ColorFromRGBA(activeRGBA, true); } } var activeRGBAIsUnspecified = true; function update_ColorAlpha(alpha){ console.log("alpha: " + alpha); if(activeRGBA){ activeRGBA.a = alpha; update_ColorFromRGBA(activeRGBA, true); } } function update_ColorFromUserInput(cTextVal, explicitlySet){ var rgba = tryToGetRGBAColorFromValueAlone(cTextVal, "", ""); if(rgba && explicitlySet){ console.log("Update color picker with this rgba: " + cTextVal); console.log(rgba); }else{ console.log("TODO: uspecified color..." + cTextVal); if(activeRGBA){ rgba = activeRGBA; }else{ rgba = new RGBAColor(128, 128, 128, 1, "", ""); } } update_ColorHue(rgba.hue); update_ColorAlpha(rgba.a); activeRGBA = rgba; update_ColorFromRGBA(rgba, explicitlySet); } function colorKeyDown(event){ console.log(event); if(event.which == 13){ //console.log("ENTER"); activeRGBAIsUnspecified = false; $(rootEl).find(".rgbaPicker_ColorPickedInput").blur(); return false; } event.stopPropagation(); event.cancelBubble = true; } function colorBlur(){ console.log("FIXME: at colorBlur... activeRGBAIsUnspecified=" + activeRGBAIsUnspecified); if(!activeRGBAIsUnspecified){ update_ColorFromUserInput($(rootEl).find(".rgbaPicker_ColorPickedInput").html(), true); } } function update_ColorFromRGBA(rgba, explicitlySet){ if(explicitlySet){ activeRGBAIsUnspecified = false; }else{ activeRGBAIsUnspecified = true; } console.log("Updating with color: "); console.log(rgba); $(rootEl).find(".rgbaPicker_ColorPickedFG").css({background: rgba.cssText()}); var rgbTrip = activeRGBA.r+","+activeRGBA.g+","+activeRGBA.b; var bgGrad = "-webkit-gradient(linear, left top, left bottom, color-stop(10%,rgba("+rgbTrip+",1)), color-stop(100%,rgba("+rgbTrip+",0))),"; bgGrad += "url('../media/transBGGrid.png')"; $(rootEl).find(".rgbaPicker_ColorSelAlphaSlider").slider("value", rgba.a*100).css({background: bgGrad}); $(rootEl).find(".rgbaPicker_ColorSelDot_SatLum").css({"left": (4+rgba.sat*92), "top": (4+(92-rgba.lum*92)) }); $(rootEl).find(".rgbaPicker_ColorSelDot_HueLum").css({"left": (4+rgba.hue*92), "top": (4+(92-rgba.lum*92)) }); $(rootEl).find(".rgbaPicker_ColorPickedInput").html(rgba.cssText()); if(!activeRGBAIsUnspecified){ //console.log("Fire color onChange handler..."); options.onChange(rgba); } } function setActiveRGBA(rgba, explicitlySet){ activeRGBA = rgba; update_ColorHue(activeRGBA.hue); update_ColorAlpha(activeRGBA.a); update_ColorFromRGBA(rgba, explicitlySet); } function getActiveRGBA(){ return activeRGBA; } console.log(rootEl); $(rootEl).html(pickerHTML); $(rootEl).find(".rgbaPicker_ColorSel_SatLum").mousedown(mouseDown_SatLum).mousemove(mouseMove_SatLum); $(rootEl).find(".rgbaPicker_ColorSel_HueLum").mousedown(mouseDown_HueLum).mousemove(mouseMove_HueLum); $(rootEl).find(".rgbaPicker_ColorSelAlphaSlider").slider({orientation: 'vertical', min: 0, max: 100, slide: function(event, ui){ update_ColorAlpha(ui.value/100.0); }}); $(rootEl).find(".rgbaPicker_ColorPickedInput").keydown(colorKeyDown).blur(colorBlur); $(rootEl).data("rgbaSetColorFn", setActiveRGBA); $(rootEl).data("rgbaGetColorFn", getActiveRGBA); update_ColorHue(activeRGBA.hue); update_ColorAlpha(activeRGBA.a); update_ColorFromRGBA(activeRGBA, false); }); }, setColor: function(newColor, explicitlySet) { return this.each( function (index, el) { if ($(el).data('rgbaPickerID')) { var setColorFn = $(el).data("rgbaSetColorFn"); if(setColorFn){ var rgba = tryToGetRGBAColorFromValueAlone(newColor, "", ""); if(rgba != null){ setColorFn(rgba, explicitlySet); }else{ console.log("Invalid color: " + newColor); } }else{ console.log("No Color Set fn. "); } }else{ console.log("NO ID. :("); } }); }, getColor: function() { if(this.length > 0){ var el = this[0]; if ($(el).data('rgbaPickerID')) { var getColorFn = $(el).data("rgbaGetColorFn"); if(getColorFn){ console.log("got it...."); return getColorFn(); }else{ console.log("No Color Get fn. "); } }else{ console.log("NO ID. :("); } return null; } }, } }(); $.fn.extend({ rgbaPickerInit: RGBAPicker.init, rgbaPickerSetColor: RGBAPicker.setColor, rgbaPickerGetColor: RGBAPicker.getColor }); })(jQuery); // ------------------------------------------- // STYLE PANEL (PALETTES?) HELPERS... // function hideAllStylePanels(){ $("#bt_stylePanel_Position").hide(); $("#bt_stylePanel_Spacing").hide(); $("#bt_stylePanel_Background").hide(); $("#bt_stylePanel_Border").hide(); $("#bt_stylePanel_Other").hide(); $("#bt_stylePanel_Text").hide(); $("#bt_stylePanel_Content").hide(); } var cancelNextStylePanelToggle = false; function toggleStylePanelOpenState(el){ // FIXME: hack to keep from toggling on sorting... if(cancelNextStylePanelToggle){ cancelNextStylePanelToggle = false; return; } if($(el).children(".bt_panelHeaderContent").attr("paletteIsOpen") == "false"){ openStylePanel(el); }else{ closeStylePanel(el); } } function openStylePanel(el){ console.log("open style panel: " + el); $(el).children(".bt_panelHeaderContent").attr("paletteIsOpen", "true"); $(el).children(".bt_panelHeaderContent").find(".bt_prop").show(); $(el).children(".bt_panelHeaderContent").find("textarea").show(); $(el).children(".bt_panelHeader").removeClass("bt_panelHeaderCollapsed"); } function closeStylePanel(el){ console.log("close style panel: " + el); $(el).children(".bt_panelHeaderContent").attr("paletteIsOpen", "false"); $(el).children(".bt_panelHeaderContent").find(".bt_prop").hide(); $(el).children(".bt_panelHeaderContent").find("textarea").hide(); $(el).children(".bt_panelHeader").addClass("bt_panelHeaderCollapsed"); } // // PANELS! :) // function setStylePanelHTML_Positioning(styles, autoselectProp){ var stylesToUpdate = [ "position", "display", "left", "right", "top", "bottom", "width", "height", "max-width", "min-width", "max-height", "min-height"]; var styleHTML = ""; // read all of the styles we care about. var sPos = getStyleFromListAndMarkAsUsed("position", styles); var sDisp = getStyleFromListAndMarkAsUsed("display", styles); var sLeft = getStyleFromListAndMarkAsUsed("left", styles); var sRight = getStyleFromListAndMarkAsUsed("right", styles); var sWidth = getStyleFromListAndMarkAsUsed("width", styles); var sMaxW = getStyleFromListAndMarkAsUsed("max-width", styles); var sMinW = getStyleFromListAndMarkAsUsed("min-width", styles); var sTop = getStyleFromListAndMarkAsUsed("top", styles); var sBottom = getStyleFromListAndMarkAsUsed("bottom", styles); var sHeight = getStyleFromListAndMarkAsUsed("height", styles); var sMaxH = getStyleFromListAndMarkAsUsed("max-height", styles); var sMinH = getStyleFromListAndMarkAsUsed("min-height", styles); if(!(sPos || sDisp || sLeft || sRight || sWidth || sMaxW || sMinW || sTop || sBottom || sHeight || sMaxH || sMinH)){ // no text styles applied. return. // return ""; } // test for need to auto-open panel... if(autoselectProp && styleIsInSimpleArrayOfNames(autoselectProp, stylesToUpdate)){ console.log("Auto-opening Position Panel."); openStylePanel("#bt_stylePanel_Position"); } // line 1 styleHTML += "
"; styleHTML += "
Position
"; styleHTML += getPropValHTML("position", sPos, ["Static", "Absolute", "Fixed", "Inherit", "Relative"], "bt_propValMedium"); styleHTML += "
Display
"; styleHTML += getPropValHTML("display", sDisp, ["Block", "Inherit", "Inline", "Inline-Block", "None"], "bt_propValMedium"); styleHTML += "
"; // line 2 styleHTML += "
"; styleHTML += "
Left(x):
"; styleHTML += getPropValHTML("left", sLeft, null, "bt_propValSmall"); styleHTML += "
Top(y):
"; styleHTML += getPropValHTML("top", sTop, null, "bt_propValSmall"); styleHTML += "
Width
"; styleHTML += getPropValHTML("width", sWidth, null, "bt_propValSmall"); styleHTML += "
"; // line 3 styleHTML += "
"; styleHTML += "
Right
"; styleHTML += getPropValHTML("right", sRight, null, "bt_propValSmall"); styleHTML += "
Bottom
"; styleHTML += getPropValHTML("bottom", sBottom, null, "bt_propValSmall"); styleHTML += "
Height
"; styleHTML += getPropValHTML("height", sHeight, null, "bt_propValSmall"); styleHTML += "
"; //line 4 if(sMinW || sMaxW || sMinH || sMaxH){ styleHTML += "
"; styleHTML += "
Min/Max
"; styleHTML += "
W
"; styleHTML += getPropValHTML("min-width", sMinW, null, "bt_propValSmallest"); styleHTML += "/"; styleHTML += getPropValHTML("max-width", sMaxW, null, "bt_propValSmallest"); styleHTML += "  
H
" styleHTML += getPropValHTML("min-height", sMinH, null, "bt_propValSmallest"); styleHTML += "/"; styleHTML += getPropValHTML("max-height", sMaxH, null, "bt_propValSmallest"); styleHTML += "
"; } $("#bt_stylePanel_Position").show().children(".bt_panelHeaderContent").html(styleHTML); if($("#bt_stylePanel_Position").children(".bt_panelHeaderContent").attr("paletteIsOpen") == "false"){ $("#bt_stylePanel_Position").children(".bt_panelHeaderContent").find(".bt_prop").hide(); } return ""; } function setStylePanelHTML_Text(styles, autoselectProp){ var stylesToUpdate = [ "color", "font-family", "font-size", "font-weight", "font-style", "line-height", "letter-spacing", "word-spacing", "text-decoration", "text-shadow", "text-transform", "text-align", "text-wrap", "text-justify"]; var styleHTML = ""; // read all of the styles we care about. var sColor = getStyleFromListAndMarkAsUsed("color", styles); var sFamily = getStyleFromListAndMarkAsUsed("font-family", styles); var sSize = getStyleFromListAndMarkAsUsed("font-size", styles); var sWeight = getStyleFromListAndMarkAsUsed("font-weight", styles); var sStyle = getStyleFromListAndMarkAsUsed("font-style", styles); var sHeight = getStyleFromListAndMarkAsUsed("line-height", styles); var sLetter = getStyleFromListAndMarkAsUsed("letter-spacing", styles); var sWord = getStyleFromListAndMarkAsUsed("word-spacing", styles); var sDecor = getStyleFromListAndMarkAsUsed("text-decoration", styles); var sShadow = getStyleFromListAndMarkAsUsed("text-shadow", styles); var sXform = getStyleFromListAndMarkAsUsed("text-transform", styles); var sAlign = getStyleFromListAndMarkAsUsed("text-align", styles); var sWrap = getStyleFromListAndMarkAsUsed("text-wrap", styles); var sJustify = getStyleFromListAndMarkAsUsed("text-justify", styles); if(!(sColor || sFamily || sSize || sWeight || sStyle || sHeight || sLetter || sWord || sDecor || sShadow || sXform || sAlign || sWrap || sJustify)){ // no text styles applied. return. // return ""; } // test for need to auto-open panel... if(autoselectProp && styleIsInSimpleArrayOfNames(autoselectProp, stylesToUpdate)){ console.log("Auto-opening Text Panel."); openStylePanel("#bt_stylePanel_Text"); } // line 1 styleHTML += "
"; styleHTML += getPropValHTML("font-family", sFamily, ["Arial", "Arimo", "Arvo", "Cabin", "Cantarell", "Crushed", "Damion", "Helvetica", "Lato", "Molengo", "Monospace", "Oswald", "Pacifico", "Permanent Marker", "Puritan", "Raleway", "Sans-serif", "Serif", "Sniglet", "Sue Ellen Francisco", "Tangerine", "Terminal Dosis Light", "Ubuntu", "UnifrakturCook", "Verdana"], "bt_propValSA_half"); styleHTML += getPropValHTML("font-size", sSize, null, "bt_propValSA_quarter"); styleHTML += getPropValHTML("text-align", sAlign, ["Center", "End", "Justify", "Left", "Right", "Start"], "bt_propValSA_quarter"); styleHTML += "
"; // line 3 styleHTML += "
"; styleHTML += "
Color
"; styleHTML += getPropValHTML("color", sColor, null, "bt_propValMedium"); styleHTML += "
Style
"; styleHTML += getPropValHTML("font-style", sStyle, ["Normal", "Italic"], "bt_propValMedium"); styleHTML += "
"; // line 5 styleHTML += "
"; styleHTML += "
Xform
"; styleHTML += getPropValHTML("text-transform", sXform, ["None", "Capitalize", "Lowercase", "Uppercase"], "bt_propValMedium"); styleHTML += "
Shadow
" styleHTML += getPropValHTML("text-shadow", sShadow, null, "bt_propValMedium"); styleHTML += "
"; // line 4 styleHTML += "
"; styleHTML += "
Letter Spacing
"; styleHTML += getPropValHTML("letter-spacing", sLetter, null, "bt_propValSmall"); styleHTML += "
Word Spacing
" styleHTML += getPropValHTML("word-spacing", sWord, null, "bt_propValSmall"); styleHTML += "
"; // line 2 styleHTML += "
"; styleHTML += "
Weight
"; styleHTML += getPropValHTML("font-weight", sWeight, null, "bt_propValSmall"); styleHTML += "
Line H
"; styleHTML += getPropValHTML("line-height", sHeight, null, "bt_propValSmall"); styleHTML += "
Wrap
"; styleHTML += getPropValHTML("text-wrap", sWrap, ["Normal", "None", "Unrestricted", "Avoid"], "bt_propValSmall"); styleHTML += "
"; // line 2b styleHTML += "
"; styleHTML += "
Decorate
"; styleHTML += getPropValHTML("text-decoration", sDecor, ["None", "Line-Through", "Overline", "Underline"], "bt_propValMedium"); styleHTML += "
Justify
"; styleHTML += getPropValHTML("text-justify", sJustify, ["Auto", "Distribute", "Distribute-All-Lines", "Inter-Cluster", "Inter-Ideograph", "Inter-Word", "Newspaper"], "bt_propValSmall"); styleHTML += "
"; $("#bt_stylePanel_Text").show().children(".bt_panelHeaderContent").html(styleHTML); if($("#bt_stylePanel_Text").children(".bt_panelHeaderContent").attr("paletteIsOpen") == "false"){ $("#bt_stylePanel_Text").children(".bt_panelHeaderContent").find(".bt_prop").hide(); } return ""; } function setStylePanelHTML_BG(styles, autoselectProp){ var stylesToUpdate = [ "background-color", "background-image", "background-repeat-x", "background-repeat-y", "background-attachment", "background-position-x", "background-position-y", "background-size", "background-clip", "background-origin"]; var styleHTML = ""; // read all of the styles we care about. var sBGColor = getStyleFromListAndMarkAsUsed("background-color", styles); var sBGImage = getStyleFromListAndMarkAsUsed("background-image", styles); var sBGRepeatX = getStyleFromListAndMarkAsUsed("background-repeat-x", styles); var sBGRepeatY = getStyleFromListAndMarkAsUsed("background-repeat-y", styles); var sBGAttach = getStyleFromListAndMarkAsUsed("background-attachment", styles); var sBGPosX = getStyleFromListAndMarkAsUsed("background-position-x", styles); var sBGPosY = getStyleFromListAndMarkAsUsed("background-position-y", styles); var sBGSize = getStyleFromListAndMarkAsUsed("background-size", styles); var sBGClip = getStyleFromListAndMarkAsUsed("background-clip", styles); var sBGOrigin = getStyleFromListAndMarkAsUsed("background-origin", styles); if(!(sBGColor || sBGImage || sBGRepeatX || sBGRepeatY || sBGAttach || sBGPosX || sBGPosY || sBGSize || sBGClip || sBGOrigin )){ // no text styles applied. return. // return ""; } // test for need to auto-open panel... if(autoselectProp && styleIsInSimpleArrayOfNames(autoselectProp, stylesToUpdate)){ console.log("Auto-opening Background Panel."); openStylePanel("#bt_stylePanel_Background"); } // bundle similar terms... var sBGRepeat = sBGRepeatX + ", " + sBGRepeatY; if(sBGRepeat == "repeat, repeat"){ sBGRepeat = "repeat"; } if(sBGRepeat == "repeat, no-repeat"){ sBGRepeat = "repeat-x"; } if(sBGRepeat == "no-repeat, no-repeat"){ sBGRepeat = "no-repeat"; } if(sBGRepeat == "no-repeat, repeat"){ sBGRepeat = "repeat-y"; } if(sBGRepeat == "round, round"){ sBGRepeat = "round"; } if(sBGRepeat == "space, space"){ sBGRepeat = "space"; } var sBGPos = ""; if(sBGPosX){ sBGPos = sBGPosX; } if(sBGPosX && sBGPosY){ sBGPos += " "; } if(sBGPosY){ sBGPos += sBGPosY; } // line 1 styleHTML += "
"; styleHTML += "
Color:
"; styleHTML += getPropValHTML("background-color", sBGColor, null, "bt_propValMedium"); styleHTML += "
"; // line 2 styleHTML += "
"; styleHTML += "
Image:
"; styleHTML += getPropValHTML("background-image", sBGImage, null, "bt_propValMedium bt_propValTall"); styleHTML += "
"; // line 3 styleHTML += "
"; styleHTML += "
Repeat:
"; styleHTML += getPropValHTML("background-repeat", sBGRepeat, ["Repeat", "No-Repeat", "Repeat-X", "Repeat-Y", "Round", "Space"], "bt_propValMedium"); styleHTML += "
Attach:
"; styleHTML += getPropValHTML("background-attachment", sBGAttach, ["Scroll", "Fixed", "Local"], "bt_propValMedium"); styleHTML += "
"; // line 4 styleHTML += "
"; styleHTML += "
Position:
"; styleHTML += getPropValHTML("background-position", sBGPos, null, "bt_propValMedium"); styleHTML += "
Size:
"; styleHTML += getPropValHTML("background-size", sBGSize, null, "bt_propValMedium"); styleHTML += "
"; // line 5 styleHTML += "
"; styleHTML += "
Origin:
"; styleHTML += getPropValHTML("background-origin", sBGOrigin, ["Padding-Box", "Border-Box", "Content-Box"], "bt_propValMedium"); styleHTML += "
Clip:
"; styleHTML += getPropValHTML("background-clip", sBGClip, ["Border-Box", "Padding-Box", "Content-Box"], "bt_propValMedium"); styleHTML += "
"; $("#bt_stylePanel_Background").show().children(".bt_panelHeaderContent").html(styleHTML); // FIXME: This is a bit of a hack.. do we really need to add the filedrop listener each time!? setupDivForBGImageFileDrop($(".bt_propValSpecial_BGImageDropZone")[0], function(file, base64Data){ console.log("Reading dropped file (quick spot): " + file.name); var newBGImageCSS = "url(data:"+file.type+";base64,"+base64Data+")"; $("#bt_dValSpecial_BGImageSelTxt").html(newBGImageCSS); updateSpecialVal_BGImageFromUserInput(newBGImageCSS, true); }); if($("#bt_stylePanel_Background").children(".bt_panelHeaderContent").attr("paletteIsOpen") == "false"){ $("#bt_stylePanel_Background").children(".bt_panelHeaderContent").find(".bt_prop").hide(); } return ""; } function setStylePanelHTML_Spacing(styles, autoselectProp){ var stylesToUpdate = [ "margin-left", "margin-right", "margin-top", "margin-bottom", "margin", "padding-left", "padding-right", "padding-top", "padding-bottom", "padding"]; var styleHTML = ""; // read all of the styles we care about. var sMarginL = getStyleFromListAndMarkAsUsed("margin-left", styles); var sMarginR = getStyleFromListAndMarkAsUsed("margin-right", styles); var sMarginT = getStyleFromListAndMarkAsUsed("margin-top", styles); var sMarginB = getStyleFromListAndMarkAsUsed("margin-bottom", styles); var sMargin = getStyleFromListAndMarkAsUsed("margin", styles); var sPaddingL = getStyleFromListAndMarkAsUsed("padding-left", styles); var sPaddingR = getStyleFromListAndMarkAsUsed("padding-right", styles); var sPaddingT = getStyleFromListAndMarkAsUsed("padding-top", styles); var sPaddingB = getStyleFromListAndMarkAsUsed("padding-bottom", styles); var sPadding = getStyleFromListAndMarkAsUsed("padding", styles); if(!(sMarginL || sMarginR || sMarginT || sMarginB || sPaddingL || sPaddingR || sPaddingT || sPaddingB )){ // no text styles applied. return. // return ""; } // test for need to auto-open panel... if(autoselectProp && styleIsInSimpleArrayOfNames(autoselectProp, stylesToUpdate)){ console.log("Auto-opening Spacing Panel."); openStylePanel("#bt_stylePanel_Spacing"); } // bundle similar terms... if(sMarginL == sMarginR && sMarginL == sMarginT && sMarginL == sMarginB){ sMargin = sMarginL; } if(sPaddingL == sPaddingR && sPaddingL == sPaddingT && sPaddingL == sPaddingB){ sPadding = sPaddingL; } // line 1 styleHTML += "
"; styleHTML += "
Margin:
"; styleHTML += getPropValHTML("margin", sMargin, null, "bt_propValLarge"); styleHTML += "
"; // line 2 styleHTML += "
"; styleHTML += getPropValHTML("margin-top", sMarginT, null, "bt_propValSA_quarter", "Top"); styleHTML += getPropValHTML("margin-right", sMarginR, null, "bt_propValSA_quarter", "Right"); styleHTML += getPropValHTML("margin-bottom", sMarginB, null, "bt_propValSA_quarter", "Bottom"); styleHTML += getPropValHTML("margin-left", sMarginL, null, "bt_propValSA_quarter", "Left"); styleHTML += "
"; // line 3 styleHTML += "
"; styleHTML += "
Padding:
"; styleHTML += getPropValHTML("padding", sPadding, null, "bt_propValLarge"); styleHTML += "
"; // line 4 styleHTML += "
"; styleHTML += getPropValHTML("padding-top", sPaddingT, null, "bt_propValSA_quarter", "Top"); styleHTML += getPropValHTML("padding-right", sPaddingR, null, "bt_propValSA_quarter", "Right"); styleHTML += getPropValHTML("padding-bottom", sPaddingB, null, "bt_propValSA_quarter", "Bottom"); styleHTML += getPropValHTML("padding-left", sPaddingL, null, "bt_propValSA_quarter", "Left"); styleHTML += "
"; $("#bt_stylePanel_Spacing").show().children(".bt_panelHeaderContent").html(styleHTML); if($("#bt_stylePanel_Spacing").children(".bt_panelHeaderContent").attr("paletteIsOpen") == "false"){ $("#bt_stylePanel_Spacing").children(".bt_panelHeaderContent").find(".bt_prop").hide(); } return ""; } function setStylePanelHTML_Border(styles, autoselectProp){ var stylesToUpdate = [ "border-left-width", "border-right-width", "border-top-width", "border-bottom-width", "border-width", "border-left-style", "border-right-style", "border-top-style", "border-bottom-style", "border-style", "border-left-color", "border-right-color", "border-top-color", "border-bottom-color", "border-color", "border-top-left-radius", "border-top-right-radius", "border-bottom-right-radius", "border-bottom-left-radius", "border-radius"]; var styleHTML = ""; // read all of the styles we care about. var sBWidthL = getStyleFromListAndMarkAsUsed("border-left-width", styles); var sBWidthR = getStyleFromListAndMarkAsUsed("border-right-width", styles); var sBWidthT = getStyleFromListAndMarkAsUsed("border-top-width", styles); var sBWidthB = getStyleFromListAndMarkAsUsed("border-bottom-width", styles); var sBWidth = getStyleFromListAndMarkAsUsed("border-width", styles); var sBStyleL = getStyleFromListAndMarkAsUsed("border-left-style", styles); var sBStyleR = getStyleFromListAndMarkAsUsed("border-right-style", styles); var sBStyleT = getStyleFromListAndMarkAsUsed("border-top-style", styles); var sBStyleB = getStyleFromListAndMarkAsUsed("border-bottom-style", styles); var sBStyle = getStyleFromListAndMarkAsUsed("border-style", styles); var sBColorL = getStyleFromListAndMarkAsUsed("border-left-color", styles); var sBColorR = getStyleFromListAndMarkAsUsed("border-right-color", styles); var sBColorT = getStyleFromListAndMarkAsUsed("border-top-color", styles); var sBColorB = getStyleFromListAndMarkAsUsed("border-bottom-color", styles); var sBColor = getStyleFromListAndMarkAsUsed("border-color", styles); var sBRadTL = getStyleFromListAndMarkAsUsed("border-top-left-radius", styles); var sBRadTR = getStyleFromListAndMarkAsUsed("border-top-right-radius", styles); var sBRadBR = getStyleFromListAndMarkAsUsed("border-bottom-right-radius", styles); var sBRadBL = getStyleFromListAndMarkAsUsed("border-bottom-left-radius", styles); var sBRad = getStyleFromListAndMarkAsUsed("border-radius", styles); //top-left, top-right, bottom-right, bottom-left if(!(sBWidthL || sBWidthR || sBWidthT || sBWidthB || sBWidth || sBStyleL || sBStyleR || sBStyleT || sBStyleB || sBStyle || sBColorL || sBColorR || sBColorT || sBColorB || sBColor || sBRadTL || sBRadTR || sBRadBR || sBRadBL || sBRad )){ // no text styles applied. return. // return ""; } // test for need to auto-open panel... if(autoselectProp && styleIsInSimpleArrayOfNames(autoselectProp, stylesToUpdate)){ console.log("Auto-opening Border Panel."); openStylePanel("#bt_stylePanel_Border"); } // bundle similar terms... if(sBColorT == sBColorR && sBColorT == sBColorB && sBColorT == sBColorL){ sBColor = sBColorT; } if(sBStyleT == sBStyleR && sBStyleT == sBStyleB && sBStyleT == sBStyleL){ sBStyle = sBStyleT; } if(sBWidthT == sBWidthR && sBWidthT == sBWidthB && sBWidthT == sBWidthL){ sBWidth = sBWidthT; } if(sBRadTL == sBRadTR && sBRadTL == sBRadBR && sBRadTL == sBRadBL){ sBRad = sBRadTL; } var borderPossibleStyles = ["none", "solid", "dotted", "dashed", "double", "groove", "inset", "outset", "ridge"]; // line 1 styleHTML += "
"; styleHTML += "
Style:
"; styleHTML += getPropValHTML("border-style", sBStyle, borderPossibleStyles, "bt_propValLarge"); styleHTML += "
"; // line 2 styleHTML += "
"; styleHTML += getPropValHTML("border-top-style", sBStyleT, borderPossibleStyles, "bt_propValSA_quarter", "Top"); styleHTML += getPropValHTML("border-right-style", sBStyleR, borderPossibleStyles, "bt_propValSA_quarter", "Right"); styleHTML += getPropValHTML("border-bottom-style", sBStyleB, borderPossibleStyles, "bt_propValSA_quarter", "Bottom"); styleHTML += getPropValHTML("border-left-style", sBStyleL, borderPossibleStyles, "bt_propValSA_quarter", "Left"); styleHTML += "
"; // line 1 styleHTML += "
"; styleHTML += "
Width:
"; styleHTML += getPropValHTML("border-width", sBWidth, null, "bt_propValLarge"); styleHTML += "
"; // line 2 styleHTML += "
"; styleHTML += getPropValHTML("border-top-width", sBWidthT, null, "bt_propValSA_quarter", "Top"); styleHTML += getPropValHTML("border-right-width", sBWidthR, null, "bt_propValSA_quarter", "Right"); styleHTML += getPropValHTML("border-bottom-width", sBWidthB, null, "bt_propValSA_quarter", "Bottom"); styleHTML += getPropValHTML("border-left-width", sBWidthL, null, "bt_propValSA_quarter", "Left"); styleHTML += "
"; // line 1 styleHTML += "
"; styleHTML += "
Color:
"; styleHTML += getPropValHTML("border-color", sBColor, null, "bt_propValLarge"); styleHTML += "
"; // line 2 styleHTML += "
"; styleHTML += getPropValHTML("border-top-color", sBColorT, null, "bt_propValSA_quarter", "Top"); styleHTML += getPropValHTML("border-right-color", sBColorR, null, "bt_propValSA_quarter", "Right"); styleHTML += getPropValHTML("border-bottom-color", sBColorB, null, "bt_propValSA_quarter", "Bottom"); styleHTML += getPropValHTML("border-left-color", sBColorL, null, "bt_propValSA_quarter", "Left"); styleHTML += "
"; // line 1 styleHTML += "
"; styleHTML += "
Radius:
"; styleHTML += getPropValHTML("border-radius", sBRad, null, "bt_propValLarge"); styleHTML += "
"; // line 2 styleHTML += "
"; styleHTML += getPropValHTML("border-top-left-radius", sBRadTL, null, "bt_propValSA_quarter", "TopLeft"); styleHTML += getPropValHTML("border-top-right-radius", sBRadTR, null, "bt_propValSA_quarter", "TopRight"); styleHTML += getPropValHTML("border-bottom-right-radius", sBRadBR, null, "bt_propValSA_quarter", "BottomRight"); styleHTML += getPropValHTML("border-bottom-left-radius", sBRadBL, null, "bt_propValSA_quarter", "BottomLeft"); styleHTML += "
"; $("#bt_stylePanel_Border").show().children(".bt_panelHeaderContent").html(styleHTML); if($("#bt_stylePanel_Border").children(".bt_panelHeaderContent").attr("paletteIsOpen") == "false"){ $("#bt_stylePanel_Border").children(".bt_panelHeaderContent").find(".bt_prop").hide(); } return ""; } function setStylePanelHTML_Other(styles,autoselectProp){ var styleHTML = ""; var otherStylesPresent = false; for(var i=0; i 0){ // add root style for direct editing... var sName = activeStyleNode.style; var sVal = getStyleFromListAndMarkAsUsed(sName, styles); styleHTML += getPropStyleHTMLFromListIfPresent(sName, styles, null); // start grouped property div styleHTML += "
"; for(var b=0; b×
"; styleHTML += "
"+shortStyle.toUpperCaseFirst()+"
"; styleHTML += getPropValHTML(style, s, styleChoices); styleHTML += "
"; return styleHTML; } return ""; } // ---------------------------------------------------------------------------- // GET PROP VAL HTML... // function getPropValHTML(style, propVal, styleChoices, addedClasses, titleText){ var styleHTML = ""; var classesToAdd = ""; if(addedClasses != null){ classesToAdd = addedClasses; } var hasBeenChanged = true; if(propVal == null || propVal == "" || $.trim(propVal) == ""){ // no value given... show this as a default value.. hasBeenChanged = false; classesToAdd += " bt_propValDefault"; if(modifyElementNotClass){ //tryToUpdateElementPropertyVal(activeDiv, $(el).attr("propName"), newVal, el); propVal = $(activeDiv).css(style); }else{ //tryToUpdateClassPropertyVal(activeClass, $(el).attr("propName"), newVal, el); propVal = getStyleForSelector("."+activeClass, style); } if(!styleChoices && (propVal == null || propVal == "" || $.trim(propVal) == "")){ // no default value either, and it's a standard text entry... classesToAdd += " bt_propValDefaultDash"; } } switch(style.toLowerCase()){ case "background-color": case "border-color": case "border-top-color": case "border-left-color": case "border-right-color": case "border-bottom-color": case "column-rule-color": case "outline-color": case "color": { styleHTML += getPropValHTMLSpecial_Color(style, propVal, styleChoices, classesToAdd, hasBeenChanged, titleText); break; } case "background-image": { styleHTML += getPropValHTMLSpecial_BGImage(style, propVal, styleChoices, classesToAdd, hasBeenChanged, titleText); break; } default: { if(styleChoices != null && styleChoices.length > 0){ // value has a limited set of choices styleHTML += ""; }else{ // value can be any text styleHTML += "
"; }else{ styleHTML += "
?
"; } styleHTML += "
"; return styleHTML; } // EXAMPLE: // initialize new rgbaPicker, $("#bt_dValSpecial_BGImageCPicker").rgbaPickerInit({ onChange: function(rgba){ console.log("Outside fn seeing color change. " + rgba.cssText()); if(activeGradient != null){ var stopID = activeGradient.selectedStop; var safeID = Math.max(0, Math.min(activeGradient.colorStops.length-1, stopID)); var cStop = activeGradient.colorStops[safeID]; cStop.rgba = rgba; valSpecial_BGImageUpdateColorStopGrabHandleColors(); valSpecial_BGImageRedrawActiveGradient(); } } }); // $("#bt_dValSpecial_BGImageCPicker").rgbaPickerSetColor("#33A"); //console.log($("#bt_dValSpecial_BGImageCPicker").rgbaPickerGetColor()); var baseSpecialPropValDiv_BGImage = null; var bgImageFileDropHasBeenInitialized = false; function openSpecialVal_BGImage(bgDiv){ console.log("Open special BGImage dialog..."); baseSpecialPropValDiv_BGImage = $(bgDiv).parent()[0]; var style = $(bgDiv).parent().attr('propName'); $("#bt_dValTitle_BGImage").html(style.capitalize()); var fg = $(bgDiv).children(".bt_propValSpecial_ColorFG")[0]; updateSpecialVal_BGImageFromUserInput($(fg).css("background-image"), !$(fg).hasClass("bt_propValSpecial_BGImageDefault")); if(!bgImageFileDropHasBeenInitialized){ setupDivForBGImageFileDrop($("#bt_dValSpecial_BGImageSelBG")[0], function(file, base64Data){ console.log("Reading dropped file: " + file.name); var newBGImageCSS = "url(data:"+file.type+";base64,"+base64Data+")"; $("#bt_dValSpecial_BGImageSelTxt").html(newBGImageCSS); updateSpecialVal_BGImageFromUserInput(newBGImageCSS, true); $("#bt_dValSpecial_BGImageSelDropHelper").hide(); valSpecial_setupBGImageDialogForCorrectMode(); }); bgImageFileDropHasBeenInitialized = true; } closeAllSpecialValueDialogs(); valSpecial_setupBGImageDialogForCorrectMode(); $('#bt_dialogValSpecial_BGImage').dialog({ autoOpen: true, width: 250, height: 400, draggable: false, resizable: false, modal: false, //true, closeOnEscape: true, title: "", close: function(event, ui) { $("#bt_dValSpecial_BGImageSelTxt").blur(); setFocusInMain(true); } }); $("#bt_dValSpecial_BGImageSelTxt").focus(); setFocusInMain(false); } function valSpecial_setupBGImageDialogForCorrectMode(){ var css = $("#bt_dValSpecial_BGImageSelTxt").text(); if(css.indexOf("url(data") != -1){ valSpecial_BGImage_setMode_Base64Image(); return; } if(css.indexOf("url(") != -1){ valSpecial_BGImage_setMode_URL(); return; } if(css.trim().length == 0){ valSpecial_BGImage_setMode_None(); return; } valSpecial_BGImage_setMode_Gradient(); } function valSpecial_BGImage_setMode_Base64Image(){ console.log("MODE: Base64Image."); $("#bt_dValSpecial_BGImageGradMaker").hide(); $("#bt_dValSpecial_BGImageSetURL").hide(); var css = $("#bt_dValSpecial_BGImageSelTxt").text(); if(css.indexOf("url(data") == -1){ $("#bt_dValSpecial_BGImageSelDropHelper").show(); }else{ $("#bt_dValSpecial_BGImageSelDropHelper").hide(); } $("#bt_dValList_BGImage").css({top: "170px"}); $("#bt_dValSpecial_BGImageType").val("Base64Image"); } function valSpecial_BGImage_setMode_URL(){ console.log("MODE: URL"); $("#bt_dValSpecial_BGImageGradMaker").hide(); $("#bt_dValSpecial_BGImageSetURL").show(); $("#bt_dValSpecial_BGImageSelDropHelper").hide(); $("#bt_dValList_BGImage").css({top: "170px"}); $("#bt_dValSpecial_BGImageType").val("URL"); } function valSpecial_BGImage_setMode_None(){ console.log("MODE: None"); $("#bt_dValSpecial_BGImageGradMaker").hide(); $("#bt_dValSpecial_BGImageSetURL").hide(); $("#bt_dValSpecial_BGImageSelDropHelper").hide(); $("#bt_dValList_BGImage").css({top: "170px"}); $("#bt_dValSpecial_BGImageType").val("None"); } function valSpecial_BGImage_setMode_Gradient(){ console.log("MODE: Gradient"); $("#bt_dValSpecial_BGImageGradMaker").show(); $("#bt_dValSpecial_BGImageSetURL").hide(); $("#bt_dValSpecial_BGImageSelDropHelper").hide(); $("#bt_dValList_BGImage").css({top: "350px"}); $("#bt_dValSpecial_BGImageType").val("Gradient"); var css = $("#bt_dValSpecial_BGImageSelTxt").text(); valSpecial_BGImage_loadGradientFromCSS(css); } var activeGradient = null; function valSpecial_BGImage_loadGradientFromCSS(css){ // try to setup a gradient using the css (if it's blank or not the correct type, set a default). console.log("TODO: setup gradient from CSS"); if(css.indexOf("gradient") != -1){ // try to read the gradient! var isLinear = true; if(css.indexOf("radial") != -1){ isLinear = false; } var colorStops = []; var gradStart = "0% 0%"; var gradEnd = "0% 100%"; var cSplit = css.split(","); if(isLinear){ // parse header of linear. if(cSplit.length > 3){ gradStart = cSplit[1].trim(); gradEnd = cSplit[2].trim(); console.log("sart: " + gradStart + ", end: " + gradEnd); cSplit.splice(0,3); var justStops = cSplit.join(","); var splitColors = justStops.split("),"); for(var i=0; i 5){ gradStart = cSplit[1].trim()+", "+cSplit[2].trim(); gradEnd = cSplit[3].trim()+", "+cSplit[4].trim(); console.log("sart: " + gradStart + ", end: " + gradEnd); cSplit.splice(0,5); var justStops = cSplit.join(","); var splitColors = justStops.split("),"); for(var i=0; i> " + css + " >> STOP AT: " + stop + ", css = " + rgba.cssText()); return new ColorStop(rgba, stop); } function valSpecial_BGImageSetGradOrientation(el, type, start, end){ if(activeGradient){ activeGradient.gradType = type; activeGradient.gradStart = start; activeGradient.gradEnd = end; valSpecial_BGImageRedrawActiveGradient(); $(".bt_gradOrientSelActive").removeClass("bt_gradOrientSelActive"); $(el).addClass("bt_gradOrientSelActive"); } } function valSpecial_BGImageGradientAsRadial(el){ var r = parseInt(prompt("Enter radius of radial gradient (in pixels):", "100")); valSpecial_BGImageSetGradOrientation(el, 'radial', '50% 50%, 0', '50% 50%,' + r); } function valSpecial_BGImageAddGrabHandlesForColorStops(){ // now add grab handles for color stops... var grabHTML = ""; var stopMul = 2.0; for(var i=0; i"+cStop.stop+"
"; } $("#bt_dValSpecial_BGImageGradTrackStopContainer").html(grabHTML); $("#bt_dValSpecial_BGImageGradTrackStopContainer").find(".bt_GradientColorStop").draggable({ stack: ".bt_GradientColorStop", axis: 'x', containment: 'parent', drag: function(event, ui){ var percent = Math.floor(ui.position.left/2); var stopID = $(this).attr("stopID"); if(stopID !== undefined && activeGradient != null){ var safeID = Math.max(0, Math.min(activeGradient.colorStops.length-1, stopID)); console.log("stopID: " + stopID); $(this).html(percent); var cStop = activeGradient.colorStops[safeID]; cStop.stop = Math.max(0, Math.min(100, percent)); valSpecial_BGImageRedrawActiveGradient(); } } }).mousedown(function(e){ var el = e.target; if(e.shiftKey){ // user was holding down shift... remove it. valSpecial_BGImageRemoveColorStop(el); }else{ // select it. valSpecial_BGImageSelectColorStop(el); } }); valSpecial_BGImageSelectColorStop($("#bt_dValSpecial_BGImageGradTrackStopContainer").find(".bt_GradientColorStop").last()); } function valSpecial_BGImageUpdateColorStopGrabHandleColors(){ if(activeGradient){ for(var i=0; i"+cStop.stop+""; } } } function valSpecial_BGImageAddColorStop(e){ if(activeGradient){ console.log("Add Color Stop"); var stopPos = Math.max(0, Math.min(100, Math.floor((e.layerX-10)/2))); var rgba = $("#bt_dValSpecial_BGImageCPicker").rgbaPickerGetColor(); //console.log("stop pos: " + stopPos); activeGradient.colorStops.push(new ColorStop(rgba, stopPos)); valSpecial_BGImageAddGrabHandlesForColorStops(); } } function valSpecial_BGImageRemoveColorStop(el){ console.log("Remove Color Stop"); var stopID = $(el).attr("stopID"); if(stopID !== undefined && activeGradient != null && activeGradient.colorStops.length > 1){ var safeID = Math.max(0, Math.min(activeGradient.colorStops.length-1, stopID)); activeGradient.colorStops.splice(safeID, 1); valSpecial_BGImageAddGrabHandlesForColorStops(); } } function valSpecial_BGImageSelectColorStop(el){ $(el).parent().find(".bt_GradientColorStopSelected").removeClass("bt_GradientColorStopSelected"); $(el).addClass("bt_GradientColorStopSelected"); console.log("TODO: load in this color stop."); var stopID = $(el).attr("stopID"); if(stopID !== undefined && activeGradient != null){ var safeID = Math.max(0, Math.min(activeGradient.colorStops.length-1, stopID)); activeGradient.selectedStop = safeID; var cStop = activeGradient.colorStops[safeID]; $("#bt_dValSpecial_BGImageCPicker").rgbaPickerSetColor(cStop.rgba.cssText()); } } function valSpecial_BGImageRedrawActiveGradient(){ var gradCopy = new Gradient(activeGradient.colorStops); gradCopy.gradStart = "0% 0%"; gradCopy.gradEnd = "100% 0%"; gradCopy.gradType = "linear"; var trackGridBGImageCSS = "url('./media/transBGGrid.png')"; $("#bt_dValSpecial_BGImageGradTrack").css("background-image", gradCopy.cssText() + ", " + trackGridBGImageCSS); updateSpecialVal_BGImageFromUserInput(activeGradient.cssText(), true); } function Gradient(colorStops){ this.colorStops = colorStops; this.gradType = "linear"; this.gradStart = "0% 0%"; this.gradEnd = "100% 0%"; this.selectedStop = 0; this.cssText = function(){ var css = "-webkit-gradient("; css += this.gradType; css += ", " + this.gradStart + ", " + this.gradEnd; for(var i=0; i> " + file.name); break; default: console.log("Unknown file upload error."); break; } }, maxfiles: 1, maxfilesize: 0.5, // max file size in MBs dragOver: function () { $(rxDiv).addClass("fileDropzone"); }, dragLeave: function () { $(rxDiv).removeClass("fileDropzone"); }, docOver: function () { $(rxDiv).addClass("docDropzone"); }, docLeave: function () { $(rxDiv).removeClass("docDropzone"); }, drop: function () { console.log("DROP!"); }, uploadStarted: function (i, file, len) { console.log("Upload started!"); }, uploadFinished: function (i, file, xhr, time, filesRemaining) { var response = xhr.responseText; //immediatelyUpdateTicker(file.name + " — Upload complete."); console.log("Files remaining: " + filesRemaining); if (filesRemaining == 0) { //gracefullyUpdateTicker("Upload complete."); //loadProject(currentProject); } if (response.indexOf("FAIL") >= 0) { alert(response); } }, progressUpdated: function (i, file, progress) { // immediatelyUpdateTicker("Uploading [" + file.name + "] — " + progress + "%"); }, speedUpdated: function (i, file, speed) { // speed in kb/s }, readFileAndBase64: function(file, base64Data){ console.log("GOT IT! > " + file.name); $(".docDropzone").removeClass("docDropzone"); $(".fileDropzone").removeClass("fileDropzone"); dropFn(file, base64Data); } }); } // ---------------------------------------------------------------------------- // GET SPECIAL PROP VAL COLOR HTML... // function getPropValHTMLSpecial_Color(style, propVal, styleChoices, classesToAdd, hasBeenChanged, titleText){ //console.log("getPropValHTMLSpecial_color"); var styleHTML = ""; styleHTML += "
"; }else{ styleHTML += "
?
"; } styleHTML += ""; return styleHTML; } var savedColorPalettes = [new ColorPalette("Basic Grayscale", [ new RGBAColor(0, 0, 0), new RGBAColor(25, 25, 25), new RGBAColor(50, 50, 50), new RGBAColor(75, 75, 75), new RGBAColor(100, 100, 100), new RGBAColor(125, 125, 125), new RGBAColor(150, 150, 150), new RGBAColor(175, 175, 175), new RGBAColor(200, 200, 200), new RGBAColor(225, 225, 225), new RGBAColor(240, 240, 240), new RGBAColor(255, 255, 255) ])]; function ColorPalette(title, swatches){ this.title = title; this.swatches = []; if(swatches){ this.swatches = swatches; } } var baseSpecialPropValDiv_Color = null; function openSpecialVal_Color(bgDiv){ console.log("Open special color dialog..."); activeRGBA = null; baseSpecialPropValDiv_Color = $(bgDiv).parent()[0]; var style = $(bgDiv).parent().attr('propName'); $("#bt_dValTitle_Color").html(style.capitalize()); var fg = $(bgDiv).children(".bt_propValSpecial_ColorFG")[0]; updateSpecialVal_ColorFromUserInput($(fg).css("background-color"), !$(fg).hasClass("bt_propValSpecial_ColorDefault")); loadCustomColorPalettes(); var swatchesHTML = ""; // var build all colors used on page... swatchesHTML = ""; var allColorsUsed = getAllColorsUsedOnPage(); allColorsUsed.sort(hueSort); for(var i=0; i < allColorsUsed.length; i++){ swatchesHTML += "
"; swatchesHTML += "
"; swatchesHTML += "
"; } //bt_dValColorSquareBG $("#bt_dValColor_AllUsed").html(swatchesHTML); closeAllSpecialValueDialogs(); $('#bt_dialogValSpecial_Color').dialog({ autoOpen: true, width: 250, height: 400, draggable: false, resizable: false, modal: false, //true, closeOnEscape: true, title: "", close: function(event, ui) { $("#bt_dValSpecial_ColorPickedInput").blur(); setFocusInMain(true); } }); $("#bt_dValSpecial_ColorPickedInput").focus(); setFocusInMain(false); } function loadCustomColorPalettes(){ var swatchesHTML = ""; var allPalettesHTML = ""; // build custom palettes... for(var p=0; p"; swatchesHTML += ""; } allPalettesHTML += "
"; allPalettesHTML += "
"; allPalettesHTML += "
" + swatchesHTML + "
+
"; allPalettesHTML += "
"; } $("#bt_dValColor_AllPalettes").html(allPalettesHTML); } function doubleClickedCPaletteTitle(event, el){ $(el).attr("contenteditable", "true"); $(el).focus(); } function keypressCPaletteTitle(event,el){ console.log(event); if(event.which == 13){ //console.log("ENTER"); $(el).blur(); return false; } if(event.which == 32 || event.which == 45 || event.which == 95 || (event.which >= 48 && event.which <= 57) || (event.which >= 65 && event.which <= 90) || (event.which >= 97 && event.which <= 122)){ // valid. (-, _, a-z, A-Z, ,) }else{ return false; } } function blurCPaletteTitle(event, el){ if($(el).attr("contenteditable")){ $(el).attr("contenteditable", "false"); var id = parseInt($(el).attr("paletteID")); if(id>=0 && id < savedColorPalettes.length){ savedColorPalettes[id].title = $(el).text(); }else{ console.log("No PaletteID. Can't save the naming change!"); } } } function clickCPaletteAddNew(){ console.log("TODO: add new palette."); savedColorPalettes.push(new ColorPalette("New Palette", [])); loadCustomColorPalettes(); var newPaletteDiv = $(".bt_dValColor_PaletteTitle").last()[0]; console.log(newPaletteDiv); doubleClickedCPaletteTitle(null, newPaletteDiv); return false; } function addSelectedColorToPalette(p){ if(activeRGBA){ savedColorPalettes[p].swatches.push(activeRGBA); loadCustomColorPalettes(); } } function tryToGetRGBAColor(el, style){ var c = $(el).css(style); if(!c){ return null; } var elName = $(el).attr("id"); return tryToGetRGBAColorFromValueAlone(c, elName, style); } function tryToGetRGBAColorFromValueAlone(c, elName, style){ if(c.indexOf("#") == 0){ var el = document.createElement('div'); $(el).css("color", c); c = $(el).css("color"); } if(c.indexOf("rgb(") == 0 && c.indexOf(")") > 9){ var cTrim = c.substring(4, c.indexOf(")")); var cArr = cTrim.split(","); if(cArr.length == 3){ return new RGBAColor(parseInt(cArr[0],10), parseInt(cArr[1],10), parseInt(cArr[2],10), 1.0, elName, style); }else{ console.log("Error in RGB: " + c); } } if(c.indexOf("rgba(") == 0 && c.indexOf(")") > 9){ var cTrim = c.substring(5, c.indexOf(")")); var cArr = cTrim.split(","); if(cArr.length == 4){ if(parseFloat(cArr[3]) > 0.0){ // only keep the color if it's visible return new RGBAColor(parseInt(cArr[0],10), parseInt(cArr[1],10), parseInt(cArr[2],10), parseFloat(cArr[3]), elName, style); } }else{ console.log("Error in RGBA: " + c); } } return null; } var activeRGBA = null; function RGBAColor(r, g, b, a, elName, style){ this.r = Math.max(0, Math.min(255, r)); this.g = Math.max(0, Math.min(255, g)); this.b = Math.max(0, Math.min(255, b)); this.a = 1; //console.log("A: " + a); if(a !== undefined){ this.a = Math.max(0.0, Math.min(1.0, a)); } this.elName = ""; if(elName){ this.elName = elName; } this.style = ""; if(style){ this.style = style; } this.eqRGB = function(c2){ return (this.r == c2.r && this.g == c2.g && this.b == c2.b); }; this.eqRGBA = function(c2){ return (this.eqRGB(c2) && this.a == c2.a); }; // set hsl values. //var hsl = rgbToHsl(this.r, this.g, this.b); var hsl = rgbToHsv(this.r, this.g, this.b); this.hue = hsl[0]; this.sat = hsl[1]; this.lum = hsl[2]; this.cssText = function(){ return "rgba("+this.r+", "+this.g+", "+this.b+", "+this.a+")" }; } function hueSort(c1, c2){ if(c1.hue != c2.hue){ if(c1.hue > c2.hue){ return 1; } if(c1.hue < c2.hue){ return -1; } return 0; }else{ if(c1.lum != c2.lum){ if(c1.lum > c2.lum){ return 1; } if(c1.lum < c2.lum){ return -1; } return 0; }else{ if(c1.sat > c2.sat){ return 1; } if(c1.sat < c2.sat){ return -1; } return 0; } } } function tryToGetRGBAColorAndAddToList(el, style, list){ var rgba = tryToGetRGBAColor(el, style); if(rgba){ addColorToRGBAColorList(rgba, list) }; } function getAllColorsUsedOnPage(){ var allRGBA= []; $(".bt_BG").find(".bt_").each(function(index, el){ tryToGetRGBAColorAndAddToList(el, "background-color", allRGBA); tryToGetRGBAColorAndAddToList(el, "color", allRGBA); }); console.log(allRGBA); return allRGBA; } function addColorToRGBAColorList(rgba, list){ for(var i=0; i> " + rgbLeft[0]+","+rgbLeft[1]+","+rgbLeft[2]); if(activeRGBA){ //var newRGB = hslToRgb(decH, activeRGBA.sat, activeRGBA.lum); var newRGB = hsvToRgb(decH, activeRGBA.sat, activeRGBA.lum); activeRGBA = new RGBAColor(parseInt(newRGB[0]), parseInt(newRGB[1]), parseInt(newRGB[2]), activeRGBA.a, activeRGBA.elName, activeRGBA.style); updateSpecialVal_ColorFromRGBA(activeRGBA, true); //valSpecial_ColorBlur(); } } function updateSpecialVal_ColorAlpha(alpha){ console.log("alpha: " + alpha); if(activeRGBA){ activeRGBA.a = alpha; updateSpecialVal_ColorFromRGBA(activeRGBA, true); //valSpecial_ColorBlur(); } } var activeRGBAIsUnspecified = true; function updateSpecialVal_ColorFromUserInput(cTextVal, explicitlySet){ var rgba = tryToGetRGBAColorFromValueAlone(cTextVal, "", ""); if(rgba && explicitlySet){ console.log("Update color picker with this rgba: " + cTextVal); console.log(rgba); }else{ console.log("TODO: uspecified color..." + cTextVal); if(activeRGBA){ rgba = activeRGBA; }else{ rgba = new RGBAColor(128, 128, 128, 1, "", ""); } } updateSpecialVal_ColorHue(rgba.hue); updateSpecialVal_ColorAlpha(rgba.a); activeRGBA = rgba; updateSpecialVal_ColorFromRGBA(rgba, explicitlySet); } function updateSpecialVal_ColorFromRGBA(rgba, explicitlySet){ if(explicitlySet){ activeRGBAIsUnspecified = false; }else{ activeRGBAIsUnspecified = true; } $("#bt_dValSpecial_ColorPickedFG").css({background: rgba.cssText()}); //$("#bt_dValSpecial_ColorSelHueSlider").slider("value", rgba.hue*360); $("#bt_dValSpecial_ColorSelAlphaSlider").slider("value", rgba.a*100); $("#bt_dValSpecial_ColorSelDot_SatLum").css({"left": (4+rgba.sat*92), "top": (4+(92-rgba.lum*92)) }); $("#bt_dValSpecial_ColorSelDot_HueLum").css({"left": (4+rgba.hue*92), "top": (4+(92-rgba.lum*92)) }); $("#bt_dValSpecial_ColorPickedInput").html(rgba.cssText()); // update the main element! var propName = $("#bt_dValTitle_Color").html().toLowerCase(); var newVal = activeRGBA.cssText(); //console.log("Update color: style="+propName+", val="+newVal); if(!activeRGBAIsUnspecified){ //console.log("Setting Color to activeDiv..."); if(modifyElementNotClass){ tryToUpdateElementPropertyVal(activeDiv, propName, newVal, null ); }else{ tryToUpdateClassPropertyVal(activeClass, propName, newVal, null ); } } } function valSpecial_ColorKeyDown(event){ console.log(event); if(event.which == 13){ //console.log("ENTER"); activeRGBAIsUnspecified = false; $("#bt_dValSpecial_ColorPickedInput").blur(); return false; } event.cancelBubble = true; } function valSpecial_ColorBlur(){ console.log("FIXME: at colorBlur... activeRGBAIsUnspecified=" + activeRGBAIsUnspecified); if(!activeRGBAIsUnspecified){ updateSpecialVal_ColorFromUserInput($("#bt_dValSpecial_ColorPickedInput").html(), true); } } function putSwatchIntoColorPicker(el,event){ if(event && event.shiftKey){ // remove it. console.log(event); var swatchID = $(el).attr('swatchID'); if(swatchID){ console.log("swatchID: " + swatchID); var idPair = swatchID.split("_"); console.log(idPair); if(idPair.length == 2){ var pID = parseInt(idPair[0]); var sID = parseInt(idPair[1]); if(pID >= 0 && pID < savedColorPalettes.length){ console.log("Removing"); var pal = savedColorPalettes[pID]; if(sID >= 0 && sID < pal.swatches.length){ console.log("Removing swatch:"); console.log(pal.swatches.splice(sID,1)); loadCustomColorPalettes(); } } } } return; } console.log("put swatch into color picker! " + $(el).css("background-color")); updateSpecialVal_ColorFromUserInput($(el).css("background-color"), true); } function closeAllSpecialValueDialogs() { if($("#bt_dialogValSpecial_Color").dialog("isOpen")){ console.log("closing valSpecial_Color Dialog."); valSpecial_ColorBlur(); $('#bt_dialogValSpecial_Color').dialog("close"); } if($("#bt_dialogValSpecial_BGImage").dialog("isOpen")){ console.log("closing valSpecial_Color Dialog."); valSpecial_BGImageBlur(); $('#bt_dialogValSpecial_BGImage').dialog("close"); } } function valSpecial_ColorMouseDown_SatLum(event){ valSpecial_ColorMouseEvent_SatLum(event); return false; } function valSpecial_ColorMouseEvent_SatLum(x, y){ var newSat = Math.min(1.0, Math.max(0.0, ((x-4)/92.0))); var newLum = Math.min(1.0, Math.max(0.0, 1.0-((y-4)/92.0))); //console.log("new Sat: " + newSat + ", new Lum: " + newLum); if(activeRGBA){ var savedHue = activeRGBA.hue; var newRGB = hsvToRgb(savedHue , newSat, newLum); activeRGBA = new RGBAColor(parseInt(newRGB[0]), parseInt(newRGB[1]), parseInt(newRGB[2]), activeRGBA.a, activeRGBA.elName, activeRGBA.style); activeRGBA.hue = savedHue; activeRGBA.sat = newSat; activeRGBA.lum = newLum; updateSpecialVal_ColorFromRGBA(activeRGBA, true); } } var dVal_ColorSatLum_MouseIsDown = false; var dVal_ColorHueLum_MouseIsDown = false; $("#bt_dValSepcial_ColorSel_SatLum").mousemove(function(e){ if(dVal_ColorSatLum_MouseIsDown){ var x = e.pageX-$(this).offset().left; var y = e.pageY-$(this).offset().top; valSpecial_ColorMouseEvent_SatLum(x, y); return false; } }); $("#bt_dValSepcial_ColorSel_SatLum").mousedown(function(e){ dVal_ColorSatLum_MouseIsDown = true; var x = e.pageX-$(this).offset().left; var y = e.pageY-$(this).offset().top; valSpecial_ColorMouseEvent_SatLum(x, y); return false; }); $("#bt_dValSepcial_ColorSel_HueLum").mousemove(function(e){ if(dVal_ColorHueLum_MouseIsDown){ var x = e.pageX-$(this).offset().left; var y = e.pageY-$(this).offset().top; valSpecial_ColorMouseEvent_HueLum(x, y); return false; } }); $("#bt_dValSepcial_ColorSel_HueLum").mousedown(function(e){ dVal_ColorHueLum_MouseIsDown = true; var x = e.pageX-$(this).offset().left; var y = e.pageY-$(this).offset().top; valSpecial_ColorMouseEvent_HueLum(x, y); return false; }); function valSpecial_ColorMouseEvent_HueLum(x, y){ var newHue = Math.min(1.0, Math.max(0.0, ((x-4)/92.0))); var newLum = Math.min(1.0, Math.max(0.0, 1.0-((y-4)/92.0))); console.log("new Hue: " + newHue + ", new Lum: " + newLum); if(activeRGBA){ var savedSat = Math.max(0.01, activeRGBA.sat); var newRGB = hsvToRgb(newHue , savedSat, newLum); activeRGBA = new RGBAColor(parseInt(newRGB[0]), parseInt(newRGB[1]), parseInt(newRGB[2]), activeRGBA.a, activeRGBA.elName, activeRGBA.style); activeRGBA.sat = savedSat; activeRGBA.hue = newHue; updateSpecialVal_ColorHue(newHue); updateSpecialVal_ColorFromRGBA(activeRGBA); } } // ##PHP ADD IN: JS Color Conversion. // from: http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c /** * Converts an RGB color value to HSL. Conversion formula * adapted from http://en.wikipedia.org/wiki/HSL_color_space. * Assumes r, g, and b are contained in the set [0, 255] and * returns h, s, and l in the set [0, 1]. * * @param Number r The red color value * @param Number g The green color value * @param Number b The blue color value * @return Array The HSL representation */ function rgbToHsl(r, g, b){ r /= 255, g /= 255, b /= 255; var max = Math.max(r, g, b), min = Math.min(r, g, b); var h, s, l = (max + min) / 2; if(max == min){ h = s = 0; // achromatic }else{ var d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch(max){ case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return [h, s, l]; } /** * Converts an HSL color value to RGB. Conversion formula * adapted from http://en.wikipedia.org/wiki/HSL_color_space. * Assumes h, s, and l are contained in the set [0, 1] and * returns r, g, and b in the set [0, 255]. * * @param Number h The hue * @param Number s The saturation * @param Number l The lightness * @return Array The RGB representation */ function hslToRgb(h, s, l){ var r, g, b; if(s == 0){ r = g = b = l; // achromatic }else{ function hue2rgb(p, q, t){ if(t < 0) t += 1; if(t > 1) t -= 1; if(t < 1/6) return p + (q - p) * 6 * t; if(t < 1/2) return q; if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; return p; } var q = l < 0.5 ? l * (1 + s) : l + s - l * s; var p = 2 * l - q; r = hue2rgb(p, q, h + 1/3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1/3); } return [r * 255, g * 255, b * 255]; } /** * Converts an RGB color value to HSV. Conversion formula * adapted from http://en.wikipedia.org/wiki/HSV_color_space. * Assumes r, g, and b are contained in the set [0, 255] and * returns h, s, and v in the set [0, 1]. * * @param Number r The red color value * @param Number g The green color value * @param Number b The blue color value * @return Array The HSV representation */ function rgbToHsv(r, g, b){ r = r/255, g = g/255, b = b/255; var max = Math.max(r, g, b), min = Math.min(r, g, b); var h, s, v = max; var d = max - min; s = max == 0 ? 0 : d / max; if(max == min){ h = 0; // achromatic }else{ switch(max){ case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return [h, s, v]; } /** * Converts an HSV color value to RGB. Conversion formula * adapted from http://en.wikipedia.org/wiki/HSV_color_space. * Assumes h, s, and v are contained in the set [0, 1] and * returns r, g, and b in the set [0, 255]. * * @param Number h The hue * @param Number s The saturation * @param Number v The value * @return Array The RGB representation */ function hsvToRgb(h, s, v){ var r, g, b; var i = Math.floor(h * 6); var f = h * 6 - i; var p = v * (1 - s); var q = v * (1 - f * s); var t = v * (1 - (1 - f) * s); switch(i % 6){ case 0: r = v, g = t, b = p; break; case 1: r = q, g = v, b = p; break; case 2: r = p, g = v, b = t; break; case 3: r = p, g = q, b = v; break; case 4: r = t, g = p, b = v; break; case 5: r = v, g = p, b = q; break; } return [r * 255, g * 255, b * 255]; }