--- /dev/null
+<?php\r
+header("Content-type: text/javascript");\r
+?>\r
+\r
+if (!window.Node) {\r
+ var Node = {\r
+ ELEMENT_NODE : 1,\r
+ ATTRIBUTE_NODE : 2,\r
+ TEXT_NODE : 3,\r
+ CDATA_SECTION_NODE : 4,\r
+ ENTITY_REFERENCE_NODE : 5,\r
+ ENTITY_NODE : 6,\r
+ PROCESSING_INSTRUCTIONS_NODE : 7,\r
+ COMMENT_NODE : 8,\r
+ DOCUMENT_NODE : 9,\r
+ DOCUMENT_TYPE_NODE : 10,\r
+ DOCUMENT_FRAGMENT_NODE : 11,\r
+ NOTATION_NODE : 12\r
+ };\r
+}\r
+\r
+\r
+\r
+String.prototype.trim = function() {\r
+ return this.replace(/^\s+|\s+$/g, '');\r
+};\r
+\r
+<?php\r
+\r
+$chameleon_theme_root = explode('/', $_SERVER['PHP_SELF']);\r
+array_pop($chameleon_theme_root);\r
+array_pop($chameleon_theme_root);\r
+$chameleon_theme_root = implode('/', $chameleon_theme_root);\r
+\r
+?>\r
+\r
+(function() {\r
+ \r
+ var struct = [];\r
+ var hotspotMode = null;\r
+ \r
+ var Config = {\r
+ THEME_ROOT: '<?php echo $chameleon_theme_root; ?>',\r
+ REMOTE_URI: '<?php echo substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/')); ?>/css.php?id=<?php echo (isset($_GET['id'])) ? (int) $_GET['id'] : 0; ?>',\r
+ FONTS_LIST: ['verdana, arial, helvetica, sans-serif', '"trebuchet ms", verdana, sans-serif', 'georgia, "trebuchet ms", times, serif', 'Other'],\r
+ FONT_WEIGHTS: ['normal', 'bold'],\r
+ FONT_STYLES: ['normal', 'italic'],\r
+ TEXT_DECORATION: ['none', 'underline', 'overline', 'line-through'],\r
+ TEXT_ALIGN: ['left', 'right', 'center', 'justify'],\r
+ REPEAT_LIST: ['repeat', 'repeat-x', 'repeat-y', 'no-repeat'],\r
+ POSITION_LIST: ['left top', 'left center', 'left bottom', 'center top', 'center center', 'center bottom', 'right top', 'right center', 'right bottom'],\r
+ BORDER_LIST: ['solid', 'dotted', 'dashed', 'none'],\r
+ UNITS: ['px', 'pt', 'em', '%']\r
+ };\r
+ \r
+\r
+\r
+ var Util = {\r
+ __registry: {},\r
+ __uniqueId: 0,\r
+\r
+ createElement: function(tag, id) {\r
+ if (!id) var id = 'chameleon-element-' + ++Util.__uniqueId;\r
+ var obj = document.createElement(tag);\r
+ obj.setAttribute('id', id);\r
+ return obj;\r
+ },\r
+ removeElement: function(obj) {\r
+ if (!obj || !obj.parentNode) return false;\r
+\r
+ var kids = obj.getElementsByTagName('*');\r
+ var n = kids.length;\r
+ while (n--) {\r
+ if (kids[n].id && Util.__registry[kids[n].id]) {\r
+ Util.__removeAllEvents(kids[n]);\r
+ }\r
+ }\r
+ if (Util.__registry[obj.id]) {\r
+ Util.__removeAllEvents(obj);\r
+ }\r
+ obj.parentNode.removeChild(obj); \r
+ },\r
+\r
+ addEvent: function(obj, ev, fn) {\r
+ if (!Util.__addToRegistry(obj, ev, fn)) return;\r
+ \r
+ if (obj.addEventListener) {\r
+ obj.addEventListener(ev, fn, false);\r
+ } else if (obj.attachEvent) {\r
+ obj['e' + ev + fn] = fn;\r
+ obj[ev + fn] = function() { \r
+ obj['e' + ev + fn](window.event);\r
+ };\r
+ obj.attachEvent('on' + ev, obj[ev + fn]);\r
+ }\r
+ },\r
+ removeEvent: function(obj, ev, fn) {\r
+ if (!Util.__removeFromRegistry(obj, ev, fn)) return;\r
+\r
+ if (obj.removeEventListener) {\r
+ obj.removeEventListener(ev, fn, false);\r
+ } else if (obj.detachEvent) {\r
+ obj.detachEvent('on' + ev, obj[ev + fn]);\r
+ obj[ev + fn] = null; \r
+ }\r
+ },\r
+\r
+ __getEventId: function(obj) {\r
+ if (obj == document) return 'chameleon-doc';\r
+ if (obj == window) return 'chameleon-win';\r
+ if (obj.id) return obj.id;\r
+ return false;\r
+ },\r
+ __findEvent: function(id, ev, fn) {\r
+ var i = Util.__registry[id][ev].length;\r
+ while (i--) {\r
+ if (Util.__registry[id][ev][i] == fn) {\r
+ return i;\r
+ }\r
+ }\r
+ return -1;\r
+ },\r
+ __addToRegistry: function(obj, ev, fn) {\r
+ var id = Util.__getEventId(obj);\r
+\r
+ if (!id) return false;\r
+\r
+ if (!Util.__registry[id]) {\r
+ Util.__registry[id] = {};\r
+ }\r
+ if (!Util.__registry[id][ev]) {\r
+ Util.__registry[id][ev] = [];\r
+ }\r
+ if (Util.__findEvent(id, ev, fn) == -1) {\r
+ Util.__registry[id][ev].push(fn);\r
+ return true;\r
+ }\r
+ return false;\r
+ },\r
+ __removeFromRegistry: function(obj, ev, fn) {\r
+ var id = Util.__getEventId(obj);\r
+ \r
+ if (!id) return false;\r
+ \r
+ var pos = Util.__findEvent(id, ev, fn);\r
+ if (pos != -1) {\r
+ Util.__registry[id][ev].splice(pos, 1);\r
+ return true;\r
+ }\r
+ return false;\r
+ },\r
+ __removeAllEvents: function(obj) {\r
+ for (var event in Util.__registry[obj.id]) {\r
+ var n = Util.__registry[obj.id][event].length;\r
+ while (n--) {\r
+ Util.removeEvent(obj, event, Util.__registry[obj.id][event][n]);\r
+ }\r
+ }\r
+ },\r
+\r
+ cleanUp: function() {\r
+ UI.closeAllBoxes();\r
+ }\r
+ };\r
+\r
+\r
+\r
+\r
+\r
+ var Pos = {\r
+ getElement: function(obj) {\r
+ var x = 0; var y = 0;\r
+ if (obj.offsetParent) {\r
+ while (obj.offsetParent) {\r
+ x += obj.offsetLeft;\r
+ y += obj.offsetTop;\r
+ obj = obj.offsetParent;\r
+ }\r
+ }\r
+ return {x: x, y: y};\r
+ },\r
+ getMouse: function(e) {\r
+ var x = 0; var y = 0;\r
+ if (e.pageX || e.pageY) {\r
+ x = e.pageX;\r
+ y = e.pageY;\r
+ } else if (e.clientX || e.clientY) {\r
+ x = e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);\r
+ y = e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);\r
+ }\r
+ return {x: x, y: y};\r
+ }\r
+ };\r
+ \r
+ \r
+ \r
+\r
+\r
+\r
+\r
+ var CSS = {\r
+ \r
+ __localCSS: {},\r
+ __remoteCSS: {},\r
+ \r
+ __localSaveRequired: false,\r
+ __remoteSaveRequired: false,\r
+ \r
+\r
+ loadRemote: function(doSetup) {\r
+ if (!Sarissa.IS_ENABLED_XMLHTTP) {\r
+ return false;\r
+ }\r
+ var xmlhttp = new XMLHttpRequest();\r
+ xmlhttp.onreadystatechange = function() {\r
+ if (xmlhttp.readyState == 4) {\r
+ if (xmlhttp.responseText.indexOf('CHAMELEON_ERROR') != -1) {\r
+ alert('There was an error loading from the server:\n' + xmlhttp.responseText.replace(/CHAMELEON_ERROR /, '') + '.');\r
+ return;\r
+ }\r
+ CSS.__remoteCSS = CSS.toObject(xmlhttp.responseText);\r
+ CSS.__localCSS = CSS.__clone(CSS.__remoteCSS);\r
+ CSS.preview();\r
+ if (doSetup) {\r
+ setup();\r
+ }\r
+ xmlhttp = null;\r
+ }\r
+ };\r
+ xmlhttp.open('GET', Config.REMOTE_URI + '&nc=' + new Date().getTime(), true);\r
+ xmlhttp.send(null);\r
+ return true;\r
+ },\r
+ \r
+ \r
+ updateTemp: function(e, reset) {\r
+ if (!CSS.__localSaveRequired && !reset) {\r
+ UI.statusMsg('There are no changes that need saving!', 'chameleon-notice');\r
+ return;\r
+ }\r
+ \r
+ if (!reset) {\r
+ UI.statusMsg('Updating temporary styles on the server...', 'chameleon-working');\r
+ } else {\r
+ UI.statusMsg('Deleting temporary styles from the server...', 'chameleon-working');\r
+ }\r
+ \r
+ var css = CSS.toString();\r
+ var xmlhttp = new XMLHttpRequest();\r
+ xmlhttp.onreadystatechange = function() {\r
+ if (xmlhttp.readyState == 4) {\r
+ if (xmlhttp.responseText.indexOf('CHAMELEON_ERROR') != -1) {\r
+ UI.statusMsg('There was an error saving to the server:\n' + xmlhttp.responseText.replace(/CHAMELEON_ERROR /, '') + '.', 'chameleon-error');\r
+ \r
+ } else {\r
+ CSS.__localSaveRequired = false;\r
+ if (!reset) {\r
+ UI.statusMsg('Temporary styles have been updated.', 'chameleon-ok');\r
+ } else {\r
+ UI.statusMsg('Temporary styles have been cleared.', 'chameleon-ok');\r
+ } \r
+ }\r
+ xmlhttp = null;\r
+ }\r
+ };\r
+ xmlhttp.open('POST', Config.REMOTE_URI + '&temp=1', true);\r
+ xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\r
+ xmlhttp.send('css=' + css);\r
+ },\r
+ \r
+\r
+ updateRemote: function() {\r
+ if (!CSS.__remoteSaveRequired) {\r
+ UI.statusMsg('There are no changes that need saving!', 'chameleon-notice');\r
+ return;\r
+ } \r
+ \r
+ var css = CSS.toString(CSS.__localCSS);\r
+\r
+ UI.statusMsg('Updating styles on the server...', 'chameleon-working');\r
+ var xmlhttp = new XMLHttpRequest();\r
+ xmlhttp.onreadystatechange = function() {\r
+ if (xmlhttp.readyState == 4) {\r
+ if (xmlhttp.responseText.indexOf('CHAMELEON_ERROR') != -1) {\r
+ UI.statusMsg('There was an error saving to the server:\n' + xmlhttp.responseText.replace(/CHAMELEON_ERROR /, '') + '.', 'chameleon-error');\r
+ } else {\r
+ CSS.__remoteCSS = CSS.toObject(css);\r
+ CSS.__localSaveRequired = false;\r
+ CSS.__remoteSaveRequired = false;\r
+ UI.statusMsg('Styles have been saved to the server.', 'chameleon-ok');\r
+ }\r
+ xmlhttp = null;\r
+ }\r
+ };\r
+ xmlhttp.open('POST', Config.REMOTE_URI, true);\r
+ xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\r
+ xmlhttp.send('css=' + css);\r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ \r
+ hardReset: function(e, noPrompt) {\r
+ if (noPrompt || confirm('Are you sure? This will erase all styles that have not been permanently saved to the server.')) {\r
+ CSS.__localCSS = {};\r
+ CSS.updateTemp(null, true);\r
+ \r
+ CSS.__localCSS = CSS.__clone(CSS.__remoteCSS);\r
+ CSS.__localSaveRequired = false;\r
+ CSS.__remoteSaveRequired = false;\r
+ CSS.preview();\r
+ }\r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ setPropValue: function(prop, value, selector) {\r
+ if (!selector) var selector = CSS.Selector.get();\r
+\r
+ if (!CSS.__localCSS[selector]) {\r
+ CSS.__localCSS[selector] = {};\r
+ }\r
+ \r
+ var matches = prop.match(/^border\-([^\-]+)$/);\r
+ if (value) {\r
+ var func = CSS.__requiresFunction(prop);\r
+ if (func && value != 'none') {\r
+ CSS.__localCSS[selector][prop] = func + '(' + value + ')';\r
+ } else if (matches) {\r
+ CSS.__localCSS[selector]['border-left-' + matches[1]] = value;\r
+ CSS.__localCSS[selector]['border-right-' + matches[1]] = value;\r
+ CSS.__localCSS[selector]['border-top-' + matches[1]] = value;\r
+ CSS.__localCSS[selector]['border-bottom-' + matches[1]] = value;\r
+ } else {\r
+ CSS.__localCSS[selector][prop] = value;\r
+ }\r
+ } else {\r
+ if (matches) {\r
+ CSS.unsetProp('border-left-' + matches[1], selector);\r
+ CSS.unsetProp('border-right-' + matches[1], selector);\r
+ CSS.unsetProp('border-top-' + matches[1], selector);\r
+ CSS.unsetProp('border-bottom-' + matches[1], selector);\r
+ } else {\r
+ CSS.unsetProp(prop, selector);\r
+ }\r
+ }\r
+ \r
+ CSS.__localSaveRequired = true;\r
+ CSS.__remoteSaveRequired = true;\r
+ CSS.preview(selector);\r
+ },\r
+ \r
+ getPropValue: function(prop, selector) {\r
+ if (!selector) var selector = CSS.Selector.get();\r
+\r
+ if (!CSS.__localCSS[selector] || !CSS.__localCSS[selector][prop]) {\r
+ return '';\r
+ }\r
+ return CSS.__cleanFunctions(CSS.__localCSS[selector][prop]);\r
+ },\r
+\r
+ unsetProp: function(prop, selector) {\r
+ if (!selector) var selector = CSS.Selector.get();\r
+\r
+ if (!CSS.__localCSS[selector] || !CSS.__localCSS[selector][prop]) return;\r
+\r
+ CSS.__localCSS[selector][prop] = null;\r
+ delete CSS.__localCSS[selector][prop];\r
+\r
+ if (!CSS.__hasProps(selector)) {\r
+ CSS.__localCSS[selector] = null;\r
+ delete CSS.__localCSS[selector];\r
+ }\r
+ },\r
+ \r
+ \r
+ __hasProps: function(selector) {\r
+ for (var prop in CSS.__localCSS[selector]) {\r
+ if (prop) {\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ },\r
+ \r
+ \r
+\r
+\r
+ __cleanFunctions: function(val) {\r
+ var toClean = ['url'];\r
+ for (var i = 0; i < toClean.length; ++i) {\r
+ var start = val.indexOf(toClean[i] + '(');\r
+ var end = val.indexOf(')', start);\r
+ if (start == -1 || end == -1) {\r
+ continue;\r
+ }\r
+ val = val.slice(start + toClean[i].length + 1, end);\r
+ }\r
+ return val;\r
+ },\r
+\r
+ __requiresFunction: function(prop) {\r
+ var fnProps = {};\r
+ fnProps['background-image'] = 'url';\r
+ if (fnProps[prop]) {\r
+ return fnProps[prop];\r
+ }\r
+ return false;\r
+ },\r
+\r
+\r
+\r
+\r
+ fixPath: function(val) {\r
+ if (val == 'none') return val;\r
+ \r
+ var tmp = val.split('(');\r
+ if (tmp.length > 1) {\r
+ tmp[1] = Config.THEME_ROOT + '/' + tmp[1];\r
+ return tmp.join('(');\r
+ }\r
+ return Config.THEME_ROOT + '/' + val;\r
+ },\r
+ \r
+ \r
+ \r
+ preview: function(sel) {\r
+ var styleId = 'chameleon-preview-styles';\r
+\r
+ var h = document.getElementsByTagName('head')[0];\r
+ var s = document.getElementById(styleId);\r
+ \r
+ if (!s) {\r
+ var s = Util.createElement('style', styleId);\r
+ s.setAttribute('type', 'text/css');\r
+ h.appendChild(s);\r
+ }\r
+ \r
+ if (navigator.userAgent.toLowerCase().indexOf('msie') != -1 && !window.opera && document.styleSheets && document.styleSheets.length > 0) {\r
+ var lastStyle = document.styleSheets[document.styleSheets.length - 1];\r
+ \r
+ if (sel) {\r
+ var matchedSelectors = [];\r
+ if (typeof sel == 'string') {\r
+ sel = [sel];\r
+ }\r
+ var n = lastStyle.rules.length;\r
+ while (n--) {\r
+ var ns = sel.length;\r
+ if (ns == 0) {\r
+ break;\r
+ }\r
+ while (ns--) {\r
+ if (lastStyle.rules[n].selectorText.toLowerCase() == sel[ns].toLowerCase()) {\r
+ matchedSelectors.push(sel[ns]);\r
+ sel.splice(ns, 1);\r
+ lastStyle.removeRule(n);\r
+ break;\r
+ }\r
+ }\r
+\r
+ }\r
+ matchedSelectors = matchedSelectors.concat(sel);\r
+ var sl = matchedSelectors.length;\r
+ while (sl--) {\r
+ lastStyle.addRule(matchedSelectors[sl], CSS.__propsToString(CSS.__localCSS[matchedSelectors[sl]], true));\r
+ }\r
+ } else {\r
+ for (var sel in CSS.__localCSS) {\r
+ var dec = CSS.__propsToString(CSS.__localCSS[sel], true);\r
+ lastStyle.addRule(sel, dec);\r
+ }\r
+ }\r
+ \r
+ } else {\r
+ s.innerHTML = CSS.toString(CSS.__localCSS, true);\r
+ }\r
+ },\r
+ \r
+ \r
+\r
+ __merge: function() {\r
+ var merged = {};\r
+ for (var i = 0; i < arguments.length; ++i) {\r
+ for (var sel in arguments[i]) {\r
+ var newSelector = false;\r
+ if (!merged[sel]) {\r
+ merged[sel] = {};\r
+ newSelector = true;\r
+ }\r
+ for (var prop in arguments[i][sel]) {\r
+ merged[sel][prop] = arguments[i][sel][prop];\r
+ }\r
+\r
+ if (i > 0 && !newSelector) {\r
+ for (var prop in merged[sel]) {\r
+ if (!arguments[i][sel][prop]) {\r
+ merged[sel][prop] = null;\r
+ delete merged[sel][prop];\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (i > 0) {\r
+ for (var sel in merged) {\r
+ if (!arguments[i][sel]) {\r
+ merged[sel] = null;\r
+ delete merged[sel];\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return merged;\r
+ },\r
+ \r
+ __clone: function(src) {\r
+ var cloned = {};\r
+ for (var sel in src) {\r
+ if (!cloned[sel]) {\r
+ cloned[sel] = {};\r
+ }\r
+ for (var prop in src[sel]) {\r
+ cloned[sel][prop] = src[sel][prop];\r
+ }\r
+ }\r
+ return cloned;\r
+ },\r
+ \r
+ \r
+ toString: function(css, fixpath) {\r
+ if (!css) var css = CSS.__localCSS;\r
+ \r
+ var dec = '';\r
+ for (var sel in css) {\r
+ dec += sel + ' ' + CSS.__propsToString(css[sel], fixpath, sel);\r
+ }\r
+ return dec;\r
+ },\r
+ \r
+ __propsToString: function(css, fixpath) {\r
+ CSS.__Shorthand.border = {};\r
+ \r
+ var hasBorder = false;\r
+ var col = false;\r
+ \r
+ var dec = '{\n';\r
+ for (var prop in css) {\r
+ \r
+ if (prop.indexOf('border') != -1 && prop.indexOf('spacing') == -1 && prop.indexOf('collapse') == -1) {\r
+ CSS.__Shorthand.recordBorder(prop, css[prop]);\r
+ hasBorder = true;\r
+ }\r
+ \r
+ if (prop == 'color') {\r
+ col = css[prop];\r
+ }\r
+\r
+ if (fixpath && (CSS.__requiresFunction(prop) == 'url') && css[prop] != 'none') {\r
+ dec += ' ' + prop + ': ' + CSS.fixPath(css[prop]) + ';\n';\r
+ } else {\r
+ dec += ' ' + prop + ': ' + css[prop] + ';\n';\r
+ }\r
+ }\r
+ \r
+ if (hasBorder) {\r
+ dec += CSS.__Shorthand.getBorderString(col);\r
+ }\r
+\r
+ dec += '}\n';\r
+ return dec;\r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ toObject: function(css) {\r
+ var cssObj = {};\r
+ var end;\r
+\r
+ while (end = css.indexOf('}'), end != -1) {\r
+ var cssRule = css.substr(0, end);\r
+ var parts = cssRule.split('{');\r
+ var selector = parts.shift()\r
+ if (selector.indexOf(',') != -1) {\r
+ var selectorArr = selector.split(',');\r
+ } else {\r
+ var selectorArr = [selector];\r
+ }\r
+ \r
+ var rules = parts.pop().trim();\r
+ rules = rules.split(';');\r
+ for (var i = 0; i < rules.length; ++i) {\r
+ if (rules[i].indexOf(':') == -1) {\r
+ break;\r
+ }\r
+ var rule = rules[i].split(':');\r
+ var prop = rule.shift().trim();\r
+ var val = rule.pop().trim();\r
+ \r
+ for (var j = 0; j < selectorArr.length; ++j) {\r
+ var noFontPropReset = {};\r
+ \r
+ selector = selectorArr[j].trim();\r
+ if (!cssObj[selector]) {\r
+ cssObj[selector] = {};\r
+ }\r
+ \r
+ if (prop != 'font' && (prop.indexOf('font') != -1 || prop == 'line-height')) {\r
+ noFontPropReset[prop] = true;\r
+ }\r
+ \r
+ if (prop == 'background') {\r
+ CSS.__Shorthand.setBackground(cssObj, selector, val);\r
+ } else if (prop == 'font') { \r
+ CSS.__Shorthand.setFont(cssObj, selector, val, noFontPropReset);\r
+ } else if ((prop == 'border' || prop.match(/^border\-([^-]+)$/)) && prop.indexOf('spacing') == -1 && prop.indexOf('collapse') == -1) {\r
+ CSS.__Shorthand.setBorder(cssObj, selector, val, prop);\r
+ } else {\r
+ cssObj[selector][prop] = val;\r
+ }\r
+ }\r
+ }\r
+ css = css.substring(end + 1);\r
+ }\r
+ return cssObj;\r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ getSelectorCSS: function(selector, asObject) {\r
+ if (!selector) var selector = CSS.Selector.get();\r
+\r
+ var css = (CSS.__localCSS[selector]) ? CSS.__localCSS[selector] : {};\r
+ if (asObject) {\r
+ return css;\r
+ }\r
+ return selector + ' ' + CSS.__propsToString(css);\r
+ },\r
+ \r
+ \r
+ \r
+ saveRequired: function() {\r
+ return CSS.__localSaveRequired || CSS.__serverSaveRequired;\r
+ },\r
+ \r
+ \r
+ checkSpec: function(e, selector) {\r
+ var canMatchAny = function(str) {\r
+ var classPos = str.indexOf('.');\r
+ var idPos = str.indexOf('#');\r
+ if (classPos == 0 || idPos == 0) {\r
+ return true;\r
+ }\r
+ return false;\r
+ };\r
+ \r
+ if (!selector) var selector = CSS.Selector.get();\r
+ if (selector == '') {\r
+ UI.statusMsg('First you have to choose which item to style!', 'chameleon-notice');\r
+ return;\r
+ }\r
+ var similarSelectors = [];\r
+ \r
+ var thisMatches = selector.split(' ').pop();\r
+ var matchAnyTag = canMatchAny(thisMatches);\r
+ if (matchAnyTag) {\r
+ var curRegExp = new RegExp('([\. ]?)' + thisMatches.split('.').join('\\.') + '([\.:]|$)');\r
+ }\r
+ \r
+ \r
+ for (var sel in CSS.__localCSS) {\r
+ var selMatches = sel.split(' ').pop();\r
+ if (thisMatches == selMatches) {\r
+ similarSelectors.push(sel);\r
+ } else if (matchAnyTag && selMatches.match(curRegExp)) {\r
+ similarSelectors.push(sel);\r
+ } else if (canMatchAny(selMatches)) {\r
+ var selRegExp = new RegExp('([ ]?)' + selMatches.split('.').join('\\.') + '([\.:]|$)');\r
+ if (thisMatches.match(selRegExp)) {\r
+ similarSelectors.push(sel);\r
+ }\r
+ }\r
+ }\r
+\r
+ \r
+ if (similarSelectors.length) {\r
+ UI.Selector.__displayOverview(null, similarSelectors, selector);\r
+ } else {\r
+ UI.statusMsg('You file currently contains no selectors that appear similar to "' + selector + '"', 'chameleon-notice');\r
+ } \r
+ },\r
+ \r
+ unloadPrompt: function() {\r
+ if (CSS.__localSaveRequired) {\r
+ if (confirm('You have made changes to the CSS on this page since the last time it was saved, these changes will be lost unless you save them now.\nSelect OK to save a temporary copy or Cancel to continue and discard the unsaved CSS.')) {\r
+ CSS.updateTemp();\r
+ }\r
+ }\r
+ }\r
+\r
+ };\r
+ \r
+ \r
+ \r
+ CSS.Selector = {\r
+ \r
+ trimmed: [],\r
+ full: [],\r
+ selector: '',\r
+ \r
+ create: function() {\r
+ CSS.Selector.trimmed = [];\r
+ \r
+ var n = struct.length;\r
+ while (n--) {\r
+ if (CSS.Selector.full[n]) {\r
+ CSS.Selector.trimmed.push(CSS.Selector.full[n].val);\r
+ }\r
+ }\r
+ CSS.Selector.set(CSS.Selector.trimmed.join(' '));\r
+ },\r
+ \r
+ modify: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ var p = target.position;\r
+ \r
+ var sel = CSS.Selector.full;\r
+\r
+ if (!sel[p]) {\r
+ UI.Selector.highlight(target);\r
+ sel[p] = {val: target.selectorValue, id: target.id};\r
+ } else if (sel[p].val != target.selectorValue) {\r
+ UI.Selector.highlight(target);\r
+ UI.Selector.unhighlight(document.getElementById(sel[p].id));\r
+ sel[p] = {val: target.selectorValue, id: target.id};\r
+ } else {\r
+ UI.Selector.unhighlight(target);\r
+ sel[p] = null;\r
+ }\r
+\r
+ CSS.Selector.create();\r
+ UI.Selector.displaySelector(CSS.Selector.trimmed);\r
+ },\r
+ \r
+ set: function(sel) {\r
+ CSS.Selector.selector = sel;\r
+ },\r
+ \r
+ get: function() {\r
+ return CSS.Selector.selector; \r
+ },\r
+\r
+ reset: function() {\r
+ CSS.Selector.trimmed = [];\r
+ CSS.Selector.full = [];\r
+ CSS.Selector.set('');\r
+ } \r
+ };\r
+ \r
+ \r
+ \r
+ CSS.__Shorthand = {\r
+ border: {},\r
+ \r
+ recordBorder: function(prop, value) {\r
+ var pr = prop.split('-')\r
+ var p = pr.pop();\r
+ var s = pr.pop();\r
+ if (!CSS.__Shorthand.border[p]) {\r
+ CSS.__Shorthand.border[p] = [];\r
+ }\r
+ if (!CSS.__Shorthand.border[s]) {\r
+ CSS.__Shorthand.border[s] = {};\r
+ }\r
+ if (!CSS.__Shorthand.border[s][p]) {\r
+ CSS.__Shorthand.border[s][p] = [];\r
+ }\r
+ CSS.__Shorthand.border[p].push({prop: prop, value: value});\r
+ CSS.__Shorthand.border[s][p] = value;\r
+ },\r
+ \r
+ getBorderString: function(col) {\r
+ var cb = CSS.__Shorthand.border;\r
+ \r
+ var useHowManyProps = function(prop) {\r
+ if (!cb['top'] || !cb['right'] || !cb['bottom'] || !cb['left']) {\r
+ return false;\r
+ }\r
+ \r
+ if (!(cb['top'][prop] && cb['right'][prop] && cb['bottom'][prop] && cb['left'][prop])) {\r
+ return false;\r
+ }\r
+ \r
+ if (cb['top'][prop] == cb['right'][prop] && cb['top'][prop] == cb['bottom'][prop] && cb['top'][prop] == cb['left'][prop]) {\r
+ return 1;\r
+ }\r
+ if (cb['top'][prop] == cb['bottom'][prop] && cb['right'][prop] == cb['left'][prop]) {\r
+ return 2;\r
+ }\r
+ if (cb['right'][prop] == cb['left'][prop]) {\r
+ return 3;\r
+ }\r
+ return 4;\r
+ };\r
+ \r
+ var getPropShorthand = function(prop) {\r
+ var num = useHowManyProps(prop);\r
+ if (!num) {\r
+ return '';\r
+ }\r
+ \r
+ if (prop.indexOf('color') != -1) {\r
+ var l = inheritColor(cb['left'][prop]);\r
+ var r = inheritColor(cb['right'][prop]);\r
+ var t = inheritColor(cb['top'][prop]);\r
+ var b = inheritColor(cb['bottom'][prop]);\r
+ } else {\r
+ var l = cb['left'][prop];\r
+ var r = cb['right'][prop];\r
+ var t = cb['top'][prop];\r
+ var b = cb['bottom'][prop];\r
+ }\r
+ \r
+ var propShorthand = '';\r
+ if (num == 1) {\r
+ propShorthand += ' border-' + prop + ': ' + l;\r
+ } else if (num == 2) {\r
+ propShorthand += ' border-' + prop + ': ' + t + ' ' + l;\r
+ } else if (num == 3) {\r
+ propShorthand += ' border-' + prop + ': ' + t + ' ' + l + ' ' + b;\r
+ } else {\r
+ propShorthand += ' border-' + prop + ': ' + t + ' ' + r + ' ' + b + ' ' + l;\r
+ }\r
+ return propShorthand + ';\n';\r
+ };\r
+ \r
+ var propsStr = function(props) {\r
+ var str = '';\r
+ for (var i = 0; i < props.length; ++i) {\r
+ str += ' ' + props[i].prop + ': ' + ((props[i].prop.indexOf('color') != -1) ? inheritColor(props[i].value) : props[i].value) + ';\n';\r
+ }\r
+ return str;\r
+ };\r
+ \r
+ var inheritColor = function(val) {\r
+ if (!col || val != 'inherit') return val; \r
+ return col;\r
+ };\r
+ \r
+ var setImportant = function(str) {\r
+ if (!str) return '';\r
+ if (str.indexOf('!important') == -1) return str;\r
+ str = str.replace(/ *\!important */g, ' ');\r
+ return str.substr(0, str.lastIndexOf(';')) + ' !important;\n';\r
+ };\r
+ \r
+ var widthEqual = (cb['width']) ? CSS.__Shorthand.__allPropsEqual(cb['width']) : false;\r
+ var styleEqual = (cb['style']) ? CSS.__Shorthand.__allPropsEqual(cb['style']) : false;\r
+ var colorEqual = (cb['color']) ? CSS.__Shorthand.__allPropsEqual(cb['color']) : false;\r
+ \r
+ if (widthEqual && styleEqual && colorEqual) {\r
+ var propStr = setImportant(cb['width'][0].value + ' ' + cb['style'][0].value + ' ' + inheritColor(cb['color'][0].value) + ';\n'); \r
+ if (cb['left'] && cb['top'] && cb['right'] && cb['bottom']) {\r
+ return ' border: ' + propStr;\r
+ }\r
+ \r
+ var sideShorthand = '';\r
+ if (cb['top']) {\r
+ sideShorthand += ' border-top: ' + propStr;\r
+ }\r
+ if (cb['right']) {\r
+ sideShorthand += ' border-right: ' + propStr;\r
+ }\r
+ if (cb['bottom']) {\r
+ sideShorthand += ' border-bottom: ' + propStr;\r
+ }\r
+ if (cb['left']) {\r
+ sideShorthand += ' border-left: ' + propStr;\r
+ }\r
+ return sideShorthand;\r
+ }\r
+\r
+ var widthProps = getPropShorthand('width');\r
+ if (!widthProps) {\r
+ widthProps = (cb['width']) ? propsStr(cb['width']) : '';\r
+ }\r
+ var styleProps = getPropShorthand('style');\r
+ if (!styleProps) {\r
+ styleProps = (cb['style']) ? propsStr(cb['style']) : '';\r
+ }\r
+ var colorProps = getPropShorthand('color');\r
+ if (!colorProps) {\r
+ colorProps = (cb['color']) ? propsStr(cb['color']) : '';\r
+ }\r
+ \r
+ return setImportant(widthProps) + setImportant(styleProps) + setImportant(colorProps);\r
+\r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ setBorder: function(css, selector, value, prop) {\r
+ var props = {};\r
+ props['width'] = {\r
+ regexp: /^(thin|medium|thick|0|(\d+(([^%\d]+)|%)))$/,\r
+ def: 'medium'\r
+ };\r
+ props['style'] = {\r
+ regexp: /none|dotted|dashed|solid|double|groove|ridge|inset|outset/,\r
+ def: 'none'\r
+ };\r
+ props['color'] = {\r
+ regexp: /^((rgb\(\d{1,3} *, *\d{1,3} *, *\d{1,3} *\))|(#[A-F0-9]{3}([A-F0-9]{3})?)|([a-z]+))$/i,\r
+ def: 'inherit'\r
+ };\r
+ \r
+ var bits = value.split(' ');\r
+ var imp = (bits[bits.length - 1] == '!important') ? ' ' + bits.pop() : '';\r
+ \r
+ if (prop == 'border') {\r
+ for (var i in props) {\r
+ css[selector]['border-top-' + i] = props[i].def;\r
+ css[selector]['border-right-' + i] = props[i].def;\r
+ css[selector]['border-bottom-' + i] = props[i].def;\r
+ css[selector]['border-left-' + i] = props[i].def;\r
+ var j = bits.length;\r
+ while (j--) {\r
+ if (bits[j].match(props[i].regexp)) {\r
+ css[selector]['border-top-' + i] = bits[j];\r
+ css[selector]['border-right-' + i] = bits[j];\r
+ css[selector]['border-bottom-' + i] = bits[j];\r
+ css[selector]['border-left-' + i] = bits[j];\r
+ bits.splice(j, 1);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ } else if (prop == 'border-left' || prop == 'border-right' || prop == 'border-top' || prop == 'border-bottom') {\r
+ for (var i in props) {\r
+ css[selector][prop + '-' + i] = props[i].def;\r
+ var j = bits.length;\r
+ while (j--) {\r
+ if (bits[j].match(props[i].regexp)) {\r
+ css[selector][prop + '-' + i] = bits[j];\r
+ bits.splice(j, 1);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ } else if (prop == 'border-width' || prop == 'border-style' || prop == 'border-color') {\r
+ var p = prop.split('-').pop();\r
+ var num = bits.length;\r
+ if (num == 1) {\r
+ css[selector]['border-top-' + p] = bits[0];\r
+ css[selector]['border-right-' + p] = bits[0];\r
+ css[selector]['border-bottom-' + p] = bits[0];\r
+ css[selector]['border-left-' + p] = bits[0];\r
+ } else if (num == 2) {\r
+ css[selector]['border-top-' + p] = bits[0];\r
+ css[selector]['border-right-' + p] = bits[1];\r
+ css[selector]['border-bottom-' + p] = bits[0];\r
+ css[selector]['border-left-' + p] = bits[1];\r
+ } else if (num == 3) {\r
+ css[selector]['border-top-' + p] = bits[0];\r
+ css[selector]['border-right-' + p] = bits[1];\r
+ css[selector]['border-bottom-' + p] = bits[2];\r
+ css[selector]['border-left-' + p] = bits[1];\r
+ } else if (num == 4) {\r
+ css[selector]['border-top-' + p] = bits[0];\r
+ css[selector]['border-right-' + p] = bits[1];\r
+ css[selector]['border-bottom-' + p] = bits[2];\r
+ css[selector]['border-left-' + p] = bits[3];\r
+ }\r
+ }\r
+ \r
+ if (imp != '') {\r
+ var sides = ['top', 'right', 'bottom', 'left'];\r
+ for (var i = 0; i < 4; ++i) {\r
+ for (var j in props) {\r
+ if (css[selector]['border-' + sides[i] + '-' + j]) {\r
+ css[selector]['border-' + sides[i] + '-' + j] += imp;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ setBackground: function(css, selector, value) {\r
+ var imp = (value.indexOf('!important') != -1) ? ' !important' : '';\r
+ if (imp != '') {\r
+ value = value.replace(/ *\!important */g, '');\r
+ }\r
+ //value = value.replace(/[ ]{2, }/, ' ');\r
+ \r
+ var urlPos = value.indexOf('url(');\r
+ if (urlPos == -1 && value.indexOf('none') == -1) {\r
+ css[selector]['background-color'] = value + imp;\r
+ return;\r
+ } else if (urlPos == -1 && value.indexOf(' none') != -1) {\r
+ var bits = value.split(' ');\r
+ css[selector]['background-color'] = bits[0] + imp;\r
+ css[selector]['background-image'] = bits[1] + imp;\r
+ return;\r
+ } else if (value == 'none') {\r
+ css[selector]['background-image'] = value + imp;\r
+ return;\r
+ }\r
+ var bits = value.split('url(');\r
+ var endImg = bits[1].indexOf(')');\r
+ if (endImg == -1) {\r
+ return;\r
+ }\r
+ css[selector]['background-image'] = 'url(' + bits[1].substr(0, endImg).replace(/["']+/g, '') + ')' + imp; //"\r
+ \r
+ var pos = [];\r
+ \r
+ var bgOptions = bits[1].substring(endImg + 1).split(' ');\r
+ var n = bgOptions.length;\r
+ \r
+ for (var i = 0; i < n; ++i) {\r
+ var opt = bgOptions[i].trim();\r
+ if (opt.indexOf('repeat') != -1) {\r
+ css[selector]['background-repeat'] = opt + imp;\r
+ } else if (opt == 'fixed' || opt == 'scroll') {\r
+ css[selector]['background-attachment'] = opt + imp;\r
+ } else if (opt != '') {\r
+ pos.push(opt);\r
+ }\r
+ }\r
+ if (pos.length == 2) {\r
+ css[selector]['background-position'] = pos.join(' ') + imp;\r
+ }\r
+ var col = bits[0].trim();\r
+ if (col != '') {\r
+ css[selector]['background-color'] = col + imp;\r
+ }\r
+ },\r
+ \r
+ setFont: function(css, selector, value, noreset) {\r
+ var imp = (value.indexOf('!important') != -1) ? ' !important' : '';\r
+ if (imp != '') {\r
+ value = value.replace(/ *\!important */g, '');\r
+ }\r
+ \r
+ var order = ['font-style', 'font-variant', 'font-weight', 'font-size', 'font-family'];\r
+ var numProps = order.length;\r
+ var allowedVals = {};\r
+ allowedVals['font-style'] = /(normal|italic|oblique|inherit)/;\r
+ allowedVals['font-variant'] = /(normal|small\-caps|inherit)/;\r
+ allowedVals['font-weight'] = /(normal|bold|bolder|lighter|100|200|300|400|500|600|700|800|900|inherit)/;\r
+ allowedVals['font-size'] = /([^ ]+)/;\r
+ allowedVals['font-family'] = /(.+$)/;\r
+ \r
+ if (!noreset['font-style']) css[selector]['font-style'] = 'normal';\r
+ if (!noreset['font-variant']) css[selector]['font-variant'] = 'normal';\r
+ if (!noreset['font-weight']) css[selector]['font-weight'] = 'normal';\r
+ if (!noreset['font-size']) css[selector]['font-size'] = 'medium';\r
+ if (!noreset['line-height']) css[selector]['line-height'] = 'normal';\r
+ \r
+ var expandShorthand = function(bits) {\r
+ var numBits = bits.length;\r
+ var startProp = 0;\r
+ for (var i = 0; i < numBits; ++i) {\r
+ if (i > numProps - 1) {\r
+ return;\r
+ }\r
+ for (var j = startProp; j < numProps; ++j) {\r
+ if (bits[i].match(allowedVals[order[j]])) {\r
+ if (order[j] == 'font-size' && bits[i].indexOf('/') != -1) {\r
+ var fsLh = bits[i].split('/');\r
+ css[selector]['font-size'] = fsLh[0] + imp;\r
+ css[selector]['line-height'] = fsLh[1] + imp;\r
+ } else {\r
+ css[selector][order[j]] = bits[i] + imp;\r
+ }\r
+ startProp = j + 1;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ };\r
+ \r
+ var removeCommaListSpaces = function(str) {\r
+ var comma = str.indexOf(',');\r
+ if (comma != -1) {\r
+ return str.substr(0, comma) + str.substring(comma).replace(/ +/g, '');\r
+ }\r
+ return str;\r
+ };\r
+ \r
+ var hasQuote = value.match(/(["'])/); //"\r
+ if (hasQuote) {\r
+ var tmp = value.split(hasQuote[1]);\r
+ var bits = removeCommaListSpaces(tmp.shift()).split(' ');\r
+ var startFont = bits.pop();\r
+ \r
+ expandShorthand(bits);\r
+ \r
+ css[selector]['font-family'] = startFont + hasQuote[1] + tmp.join(hasQuote[1]) + imp; \r
+ } else {\r
+ value = removeCommaListSpaces(value); \r
+ expandShorthand(value.split(' '));\r
+ }\r
+ },\r
+ \r
+ \r
+ \r
+\r
+ __allPropsEqual: function(props) {\r
+ var num = props.length - 1;\r
+ if (num < 4) return false;\r
+ \r
+ for (var i = 0; i < num; ++i) {\r
+ if (props[i].value != props[i + 1].value) {\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+ \r
+ };\r
+ \r
+ \r
+ \r
+ CSS.FreeEdit = {\r
+ \r
+ __initial: {},\r
+ \r
+ setInitial: function(e) {\r
+ var target = e.target || e.srcElement;\r
+\r
+ CSS.FreeEdit.__initial = CSS.toObject(target.value);\r
+ },\r
+ \r
+ saveComplete: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ target.value = CSS.FreeEdit.__stripComments(target.value);\r
+\r
+ CSS.__localCSS = CSS.__merge(CSS.__localCSS, CSS.toObject(target.value));\r
+\r
+ CSS.__localSaveRequired = true;\r
+ CSS.__remoteSaveRequired = true;\r
+\r
+ CSS.preview();\r
+ },\r
+ \r
+ saveSelector: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ target.value = CSS.FreeEdit.__stripComments(target.value);\r
+ \r
+ if (target.value.indexOf('{') != target.value.lastIndexOf('{')) {\r
+ UI.statusMsg('Please note: when you return to this window only the styles for "' + CSS.Selector.get() + '" will be displayed here. Don\'t worry, your other styles aren\'t lost - they can be edited from the overview option.', 'chameleon-notice'); \r
+ }\r
+ \r
+ var changedSelectors = [];\r
+ \r
+\r
+ var css = CSS.toObject(target.value);\r
+ for (var sel in css) {\r
+ changedSelectors.push(sel);\r
+ if (!CSS.__localCSS[sel]) {\r
+ CSS.__localCSS[sel] = {};\r
+ }\r
+ for (var prop in css[sel]) {\r
+ CSS.__localCSS[sel][prop] = css[sel][prop];\r
+ }\r
+ }\r
+\r
+ for (var sel in CSS.FreeEdit.__initial) {\r
+ if (!css[sel] && CSS.__localCSS[sel]) {\r
+ changedSelectors.push(sel);\r
+ CSS.__localCSS[sel] = null;\r
+ delete CSS.__localCSS[sel];\r
+ continue;\r
+ }\r
+ for (var prop in CSS.FreeEdit.__initial[sel]) {\r
+ if (!css[sel][prop] && CSS.__localCSS[sel][prop]) {\r
+ CSS.__localCSS[sel][prop] = null;\r
+ delete CSS.__localCSS[sel][prop];\r
+ }\r
+ }\r
+ }\r
+ \r
+ CSS.__localSaveRequired = true;\r
+ CSS.__remoteSaveRequired = true;\r
+ CSS.preview(changedSelectors);\r
+ },\r
+ \r
+ __stripComments: function(str) {\r
+ return str.replace(/\/\*([\s\S])*?\*\//g, '');\r
+ }\r
+ \r
+ };\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ \r
+ var FileHandler = {\r
+ \r
+ getFiles: function(path) {\r
+ if (!path) path = '';\r
+ var xmlhttp = new XMLHttpRequest();\r
+ xmlhttp.onreadystatechange = function() {\r
+ if (xmlhttp.readyState == 4) {\r
+ UI.CSS.displayImagePicker(xmlhttp.responseXML);\r
+ xmlhttp = null;\r
+ }\r
+ };\r
+ xmlhttp.open('GET', Config.REMOTE_URI + '&path=' + escape(path) + '&nc=' + new Date().getTime(), true);\r
+ xmlhttp.send(null);\r
+ return true;\r
+ }\r
+ };\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ var UI = {\r
+ boxes: [],\r
+ boxOffsetX: 35,\r
+ boxOffsetY: 30,\r
+ zIndex: 9999,\r
+\r
+ __dragTargetId: null,\r
+\r
+ statusMsg: function(msg, cls) {\r
+ UI.clearStatusMsg();\r
+ \r
+ var target = UI.__getBox();\r
+ if (!target) {\r
+ var box = Util.createElement('div', 'chameleon-status-msg');\r
+ box.appendChild(document.createTextNode(msg));\r
+ box.style.zIndex = ++UI.zIndex;\r
+ UI.addToDoc(box);\r
+ } else {\r
+ \r
+ var statusTable = Util.createElement('table', 'chameleon-status-msg');\r
+ var statusTableBody = Util.createElement('tbody');\r
+ var statusRow = Util.createElement('tr');\r
+ var statusIconCell = Util.createElement('td');\r
+ var statusMsgCell = Util.createElement('td');\r
+ var statusBtnCell = Util.createElement('td');\r
+ \r
+ if (cls) {\r
+ statusIconCell.className = cls;\r
+ }\r
+ statusMsgCell.appendChild(document.createTextNode(msg));\r
+ statusBtnCell.appendChild(UI.createButton('chameleon-status-msg-btn', 'OK', 'Clear this message', UI.clearStatusMsg));\r
+ \r
+ statusRow.appendChild(statusIconCell);\r
+ statusRow.appendChild(statusMsgCell);\r
+ statusRow.appendChild(statusBtnCell);\r
+ statusTableBody.appendChild(statusRow);\r
+ statusTable.appendChild(statusTableBody);\r
+ \r
+ target.appendChild(statusTable);\r
+ }\r
+ },\r
+\r
+ clearStatusMsg: function() {\r
+ var obj = document.getElementById('chameleon-status-msg');\r
+ if (obj) {\r
+ Util.removeElement(obj);\r
+ }\r
+ },\r
+\r
+ addToDoc: function(content) {\r
+ document.getElementsByTagName('body')[0].appendChild(content);\r
+ },\r
+\r
+ makeDraggableBox: function(id, x, y) {\r
+ if ((x + 500) > screen.width) {\r
+ var offset = x + 525 - screen.width;\r
+ x -= offset;\r
+ }\r
+ \r
+ var box = Util.createElement('div', id);\r
+ box.style.left = x + 'px';\r
+ box.style.top = y + 'px';\r
+ box.style.zIndex = ++UI.zIndex;\r
+\r
+ var topBar = Util.createElement('div', id + '-handle');\r
+ var closeBtn = Util.createElement('div', id + '-close');\r
+ closeBtn.appendChild(document.createTextNode('x'));\r
+ closeBtn.setAttribute('title', 'Close');\r
+ topBar.setAttribute('title', 'Drag me!');\r
+ \r
+ UI.__dragTargetId = id + '-handle';\r
+\r
+ Util.addEvent(closeBtn, 'click', UI.closeBoxes);\r
+ Util.addEvent(topBar, 'mousedown', UI.__startDrag);\r
+ Util.addEvent(topBar, 'mousedown', UI.__bringToFront);\r
+ Util.addEvent(topBar, 'mouseup', UI.__stopDrag);\r
+\r
+ topBar.appendChild(closeBtn);\r
+ box.appendChild(topBar);\r
+ \r
+ UI.boxes.push(id);\r
+\r
+ return box;\r
+ },\r
+ \r
+ closeAllBoxes: function() {\r
+ var n = UI.boxes.length;\r
+ while (n--) {\r
+ Util.removeElement(document.getElementById(UI.boxes[n]));\r
+ UI.boxes.splice(n, 1);\r
+ }\r
+ UI.__dragTargetId = null;\r
+ },\r
+\r
+ closeBoxes: function(e, box) {\r
+ if (!box) {\r
+ var target = e.target || e.srcElement;\r
+ var box = target.parentNode.parentNode;\r
+ }\r
+ var n = UI.boxes.length;\r
+ while (n--) {\r
+ if (UI.boxes[n] == box.id) {\r
+ break;\r
+ }\r
+ Util.removeElement(document.getElementById(UI.boxes[n]));\r
+ UI.boxes.splice(n, 1);\r
+ }\r
+ Util.removeElement(box);\r
+ UI.boxes.splice(n, 1);\r
+ UI.__dragTargetId = (UI.boxes.length) ? UI.boxes[UI.boxes.length - 1] + '-handle' : null;\r
+ },\r
+\r
+ __startDrag: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ var mouseCoords = Pos.getMouse(e);\r
+ var elementCoords = Pos.getElement(target);\r
+ target.mouseX = mouseCoords.x - elementCoords.x;\r
+ target.mouseY = mouseCoords.y - elementCoords.y; \r
+\r
+ UI.__dragTargetId = target.id;\r
+\r
+ Util.addEvent(document, 'mousemove', UI.__drag);\r
+ },\r
+\r
+ __stopDrag: function(e) {\r
+ Util.removeEvent(document, 'mousemove', UI.__drag);\r
+ },\r
+\r
+ __drag: function(e) {\r
+ var target = document.getElementById(UI.__dragTargetId);\r
+\r
+ var mouseCoords = Pos.getMouse(e);\r
+ target.parentNode.style.left = (mouseCoords.x - target.mouseX) + 'px';\r
+ target.parentNode.style.top = (mouseCoords.y - target.mouseY) + 'px';\r
+ },\r
+\r
+ __bringToFront: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ target.parentNode.style.zIndex = ++UI.zIndex;\r
+ },\r
+ \r
+ __getBox: function() {\r
+ var obj = document.getElementById(UI.__dragTargetId);\r
+ if (obj && obj.parentNode) {\r
+ return obj.parentNode;\r
+ }\r
+ return false;\r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ setupPane: function(tabs, parentId, tabId, active) {\r
+ for (var i = 0; i < tabs.length; ++i) {\r
+ var obj = document.getElementById(tabId + '-tab-' + tabs[i]);\r
+ if (obj) {\r
+ obj.className = tabId + ((active == tabs[i]) ? '-tab-active' : '-tab');\r
+ }\r
+ }\r
+\r
+ var parent = document.getElementById(parentId);\r
+ if (parent && parent.firstChild) {\r
+ Util.removeElement(parent.firstChild);\r
+ }\r
+ return parent;\r
+ },\r
+ \r
+ setupButtons: function() {\r
+ var parentId = arguments[0];\r
+ var parent = document.getElementById(parentId);\r
+ if (!parent) return;\r
+\r
+ var btns = parent.getElementsByTagName('input');\r
+ for (var i = 0; i < btns.length; ++i) {\r
+ btns[i].style.display = 'none';\r
+ }\r
+\r
+ for (var i = 1; i < arguments.length; ++i) {\r
+ var id = parentId + '-' + arguments[i];\r
+ var btn = document.getElementById(id);\r
+ if (btn) {\r
+ btn.style.display = 'inline';\r
+ }\r
+ }\r
+ },\r
+ \r
+ createButton: function(id, value, title, fn, hidden) {\r
+ var btn = Util.createElement('input', id);\r
+ btn.setAttribute('type', 'submit');\r
+ btn.setAttribute('value', value);\r
+ btn.setAttribute('title', title);\r
+ btn.className = 'chameleon-btn';\r
+ if (hidden) {\r
+ btn.style.display = 'none';\r
+ }\r
+\r
+ Util.addEvent(btn, 'click', fn);\r
+ return btn;\r
+ },\r
+\r
+ setOverflow: function(obj, height, forced) {\r
+ if (obj.offsetHeight > height || forced) {\r
+ obj.style.height = height + 'px';\r
+ obj.style.overflow = 'scroll';\r
+ }\r
+ }\r
+ };\r
+ \r
+ \r
+ UI.Selector = {\r
+ controlsId: 'chameleon-selector-controls',\r
+ sections: ['selector', 'overview', 'free-edit'],\r
+ \r
+ \r
+ editWindow: function(e) {\r
+ if (!e.shiftKey) {\r
+ return;\r
+ }\r
+\r
+ var target = e.target || e.srcElement;\r
+ var tmpStruct = climbTree(target);\r
+ if (typeof tmpStruct == 'string') {\r
+ return;\r
+ }\r
+ \r
+ hotspotMode = false;\r
+\r
+ var box = document.getElementById('chameleon-selector-box');\r
+ if (box) UI.closeBoxes(true, box);\r
+\r
+ struct = tmpStruct;\r
+ CSS.Selector.reset();\r
+\r
+ var coords = Pos.getMouse(e);\r
+ var box = UI.makeDraggableBox('chameleon-selector-box', coords.x, coords.y);\r
+\r
+\r
+ var instructions = Util.createElement('p');\r
+ instructions.appendChild(document.createTextNode('Create a CSS selector to edit, browse an overview of your edited styles or edit your complete stylesheet by hand.'));\r
+ instructions.className = 'chameleon-instructions';\r
+ box.appendChild(instructions);\r
+\r
+ var tabsContainer = Util.createElement('table', 'chameleon-selector-tabs');\r
+ var tabsBody = Util.createElement('tbody');\r
+ var tabs = Util.createElement('tr');\r
+ \r
+ tabs.appendChild(UI.Selector.__createTab('Selector', UI.Selector.__editSelector, true));\r
+ tabs.appendChild(UI.Selector.__createTab('Overview', UI.Selector.__displayOverview));\r
+ tabs.appendChild(UI.Selector.__createTab('Free Edit', UI.Selector.__editCode));\r
+\r
+ tabsBody.appendChild(tabs);\r
+ tabsContainer.appendChild(tabsBody);\r
+\r
+ box.appendChild(tabsContainer);\r
+\r
+ var styleControls = Util.createElement('div', UI.Selector.controlsId);\r
+ box.appendChild(styleControls);\r
+ box.appendChild(UI.Selector.__addButtons());\r
+\r
+ UI.addToDoc(box);\r
+\r
+ UI.Selector.__editSelector();\r
+ \r
+ if (e.preventDefault) {\r
+ e.preventDefault();\r
+ } else if (window.event) {\r
+ window.event.returnValue = false;\r
+ }\r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ __editSelector: function() {\r
+ var parent = UI.setupPane(UI.Selector.sections, UI.Selector.controlsId, 'chameleon-selector', 'selector');\r
+ UI.setupButtons('chameleon-selector-buttons', 'edit', 'check');\r
+\r
+ var container = Util.createElement('div');\r
+\r
+ var instructions = Util.createElement('p');\r
+ instructions.appendChild(document.createTextNode('Choose the element you would like to style.'));\r
+ container.appendChild(instructions);\r
+ container.appendChild(UI.Selector.__elementList());\r
+\r
+ parent.appendChild(container);\r
+\r
+ UI.Selector.displaySelector(CSS.Selector.trimmed);\r
+ },\r
+ \r
+ __displayOverview: function(e, selectors, selector) {\r
+ var parent = UI.setupPane(UI.Selector.sections, UI.Selector.controlsId, 'chameleon-selector', 'overview');\r
+ UI.setupButtons('chameleon-selector-buttons');\r
+ \r
+ var container = Util.createElement('div', 'chameleon-style-overview-container');\r
+ parent.appendChild(container); // much faster to insert the container and apply the overflow before creating the table\r
+ UI.setOverflow(container, 350, true);\r
+ \r
+ var overviewTable = Util.createElement('table', 'chameleon-style-overview');\r
+ var overviewTableBody = Util.createElement('tbody');\r
+ \r
+ if (!selectors) {\r
+\r
+ for (var sel in CSS.__localCSS) {\r
+ var overviewTableRow = Util.createElement('tr');\r
+ \r
+ var overviewTableCell = Util.createElement('th');\r
+ overviewTableCell.className = 'selector';\r
+ overviewTableCell.appendChild(document.createTextNode(sel));\r
+ overviewTableRow.appendChild(overviewTableCell);\r
+ overviewTableCell = Util.createElement('td');\r
+\r
+ var overviewEditLink = Util.createElement('a');\r
+ overviewEditLink.value = sel;\r
+ overviewEditLink.appendChild(document.createTextNode('[edit]'));\r
+ Util.addEvent(overviewEditLink, 'click', UI.CSS.launchEditWindow);\r
+ overviewTableCell.className = 'selector';\r
+ overviewTableCell.appendChild(overviewEditLink);\r
+\r
+ overviewTableRow.appendChild(overviewTableCell);\r
+ overviewTableBody.appendChild(overviewTableRow);\r
+ for (var prop in CSS.__localCSS[sel]) {\r
+ overviewTableRow = Util.createElement('tr');\r
+ overviewTableCell = Util.createElement('td');\r
+ overviewTableCell.className = 'prop';\r
+ overviewTableCell.appendChild(document.createTextNode(prop));\r
+ overviewTableRow.appendChild(overviewTableCell);\r
+ overviewTableCell = Util.createElement('td');\r
+ overviewTableCell.className = 'value';\r
+ overviewTableCell.appendChild(document.createTextNode(CSS.__localCSS[sel][prop]));\r
+ overviewTableRow.appendChild(overviewTableCell);\r
+ overviewTableBody.appendChild(overviewTableRow);\r
+ }\r
+ }\r
+ } else {\r
+ \r
+ var n = selectors.length;\r
+ \r
+ if (!CSS.__localCSS[selector]) {\r
+ var overviewTableRow = Util.createElement('tr');\r
+ \r
+ var overviewTableCell = Util.createElement('th');\r
+ overviewTableCell.className = 'current-selector';\r
+ overviewTableCell.appendChild(document.createTextNode(selector));\r
+ overviewTableRow.appendChild(overviewTableCell);\r
+ overviewTableCell = Util.createElement('td');\r
+\r
+ var overviewEditLink = Util.createElement('a');\r
+ overviewEditLink.value = selector;\r
+ overviewEditLink.appendChild(document.createTextNode('[edit]'));\r
+ Util.addEvent(overviewEditLink, 'click', UI.CSS.launchEditWindow);\r
+ overviewTableCell.className = 'current-selector';\r
+ overviewTableCell.appendChild(overviewEditLink);\r
+\r
+ overviewTableRow.appendChild(overviewTableCell);\r
+ overviewTableBody.appendChild(overviewTableRow);\r
+ }\r
+ \r
+ for (var i = 0; i < n; ++i) {\r
+ var sel = selectors[i];\r
+ \r
+ var overviewTableRow = Util.createElement('tr');\r
+ \r
+ var overviewTableCell = Util.createElement('th');\r
+ overviewTableCell.className = (sel == selector) ? 'current-selector' : 'selector';\r
+ overviewTableCell.appendChild(document.createTextNode(sel));\r
+ overviewTableRow.appendChild(overviewTableCell);\r
+ overviewTableCell = Util.createElement('td');\r
+\r
+ var overviewEditLink = Util.createElement('a');\r
+ overviewEditLink.value = sel;\r
+ overviewEditLink.appendChild(document.createTextNode('[edit]'));\r
+ Util.addEvent(overviewEditLink, 'click', UI.CSS.launchEditWindow);\r
+ overviewTableCell.className = (sel == selector) ? 'current-selector' : 'selector';\r
+ overviewTableCell.appendChild(overviewEditLink);\r
+\r
+ overviewTableRow.appendChild(overviewTableCell);\r
+ overviewTableBody.appendChild(overviewTableRow);\r
+ for (var prop in CSS.__localCSS[sel]) {\r
+ overviewTableRow = Util.createElement('tr');\r
+ overviewTableCell = Util.createElement('td');\r
+ overviewTableCell.className = 'prop';\r
+ overviewTableCell.appendChild(document.createTextNode(prop));\r
+ overviewTableRow.appendChild(overviewTableCell);\r
+ overviewTableCell = Util.createElement('td');\r
+ overviewTableCell.className = 'value';\r
+ overviewTableCell.appendChild(document.createTextNode(CSS.__localCSS[sel][prop]));\r
+ overviewTableRow.appendChild(overviewTableCell);\r
+ overviewTableBody.appendChild(overviewTableRow);\r
+ }\r
+ }\r
+ \r
+ }\r
+\r
+ overviewTable.appendChild(overviewTableBody); \r
+ container.appendChild(overviewTable);\r
+ },\r
+ \r
+ __elementList: function() {\r
+ var list = Util.createElement('ol');\r
+ var n = struct.length;\r
+ var classStr = '';\r
+ var idStr = '';\r
+\r
+ var pseudoClasses = ['active', 'visited', 'hover', 'focus'];\r
+\r
+ while (n--) {\r
+ var item = Util.createElement('li');\r
+ var tag = Util.createElement('span', 'chameleon-tag-name-' + n);\r
+ tag.appendChild(document.createTextNode(struct[n].tagname));\r
+ tag.selectorValue = struct[n].tagname;\r
+ tag.position = n;\r
+ \r
+ UI.Selector.__autoHighlight(tag);\r
+\r
+ Util.addEvent(tag, 'click', CSS.Selector.modify);\r
+\r
+ item.appendChild(tag);\r
+\r
+ if (idStr = struct[n].id) {\r
+ var id = Util.createElement('span', 'chameleon-id-attr-' + n);\r
+ id.selectorValue = struct[n].tagname + '#' + idStr; \r
+ id.position = n; \r
+ id.appendChild(document.createTextNode('#' + idStr));\r
+\r
+ UI.Selector.__autoHighlight(id);\r
+\r
+ Util.addEvent(id, 'click', CSS.Selector.modify);\r
+ item.appendChild(id);\r
+ }\r
+\r
+ if (struct[n].classname) {\r
+ var classArr = struct[n].classname.split(' ');\r
+ for (var i = 0; i < classArr.length; ++i) {\r
+ var cn = Util.createElement('span', 'chameleon-class-attr-' + n + '-' + i);\r
+ cn.selectorValue = struct[n].tagname + '.' + classArr[i];\r
+ cn.position = n; \r
+ cn.appendChild(document.createTextNode('.' + classArr[i]));\r
+\r
+ UI.Selector.__autoHighlight(cn);\r
+\r
+ Util.addEvent(cn, 'click', CSS.Selector.modify);\r
+ item.appendChild(cn);\r
+ }\r
+ }\r
+ if (struct[n].tagname == 'a') {\r
+ for (var i = 0; i < pseudoClasses.length; ++i) {\r
+ var pc = Util.createElement('span', 'chameleon-pseudo-class' + n + '-' + i);\r
+ pc.selectorValue = struct[n].tagname + ':' + pseudoClasses[i];\r
+\r
+ pc.position = n; \r
+ pc.appendChild(document.createTextNode(':' + pseudoClasses[i]));\r
+\r
+ UI.Selector.__autoHighlight(pc);\r
+\r
+ Util.addEvent(pc, 'click', CSS.Selector.modify);\r
+ item.appendChild(pc);\r
+ }\r
+ }\r
+ list.appendChild(item);\r
+ }\r
+ \r
+ return list;\r
+ },\r
+ \r
+ \r
+ __editCode: function() {\r
+ var parent = UI.setupPane(UI.Selector.sections, UI.Selector.controlsId, 'chameleon-selector', 'free-edit');\r
+ UI.setupButtons('chameleon-selector-buttons', 'revert', 'save-local', 'save-server');\r
+\r
+ var container = Util.createElement('div');\r
+ var textarea = Util.createElement('textarea', 'chameleon-free-edit-all-field');\r
+ textarea.value = CSS.toString();\r
+ textarea.style.width = '100%';\r
+ textarea.style.height = '350px';\r
+ Util.addEvent(textarea, 'blur', CSS.FreeEdit.saveComplete);\r
+\r
+ container.appendChild(textarea);\r
+\r
+ parent.appendChild(container);\r
+\r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ __selectorList: function() {\r
+ return Util.createElement('ol', 'chameleon-selector-list');\r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ __createTab: function(str, fn, active) {\r
+ var id = 'chameleon-selector-tab-' + str.replace(/ +/, '-').toLowerCase();\r
+ var tab = Util.createElement('td', id);\r
+ tab.appendChild(document.createTextNode(str));\r
+ tab.className = (active) ? 'chameleon-selector-tab-active' : 'chameleon-selector-tab';\r
+ Util.addEvent(tab, 'click', fn);\r
+ return tab;\r
+ },\r
+\r
+ __addButtons: function() {\r
+ var p = Util.createElement('p', 'chameleon-selector-buttons');\r
+ p.style.textAlign = 'right';\r
+\r
+ p.appendChild(UI.createButton('chameleon-selector-buttons-check', 'Compare', 'Check for other similar selectors already in your styles', CSS.checkSpec));\r
+ p.appendChild(UI.createButton('chameleon-selector-buttons-revert', 'Revert', 'Revert to the version currently on the server', CSS.hardReset));\r
+ p.appendChild(UI.createButton('chameleon-selector-buttons-save-local', 'Save Temp', 'Save these changes to a temporary file on the server', CSS.updateTemp));\r
+ p.appendChild(UI.createButton('chameleon-selector-buttons-save-server', 'Save Server', 'Save these changes to the server', CSS.updateRemote))\r
+ p.appendChild(UI.createButton('chameleon-selector-buttons-edit', 'Set Styles', 'Create and edit styles for this CSS selector', UI.CSS.editWindow));\r
+\r
+ return p;\r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ __autoHighlight: function(el) {\r
+ if (CSS.Selector.full[el.position] && CSS.Selector.full[el.position].val == el.selectorValue) {\r
+ UI.Selector.highlight(el);\r
+ } else {\r
+ UI.Selector.unhighlight(el);\r
+ }\r
+ },\r
+ \r
+ highlight: function(el) {\r
+ UI.Selector.unhighlight(el);\r
+ el.className += 'active-selector';\r
+ },\r
+\r
+ unhighlight: function(el) {\r
+ el.className = el.className.replace(/\bactive-selector\b/, '');\r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ displaySelector: function(selector) {\r
+ var n = selector.length;\r
+\r
+ var list = document.getElementById('chameleon-selector-list');\r
+ if (!list && n != 0) {\r
+ var parent = document.getElementById(UI.Selector.controlsId).firstChild;\r
+ list = UI.Selector.__selectorList();\r
+ parent.appendChild(list);\r
+ } else if (list && n == 0) {\r
+ Util.removeElement(list);\r
+ } else if (list) {\r
+ while (list.hasChildNodes()) {\r
+ Util.removeElement(list.firstChild);\r
+ }\r
+ }\r
+\r
+ if (n == 0) return;\r
+\r
+ var item = Util.createElement('li');\r
+ item.appendChild(document.createTextNode('Style ' + UI.Selector.__describe(selector[--n])));\r
+ list.appendChild(item);\r
+ while (n--) {\r
+ item = Util.createElement('li');\r
+ item.appendChild(document.createTextNode('That are descended from ' + UI.Selector.__describe(selector[n])));\r
+ list.appendChild(item);\r
+ }\r
+ },\r
+\r
+ __describe: function(txt) {\r
+ if (!txt) return '';\r
+ \r
+ if (txt.indexOf(':') != -1) {\r
+ var parts = txt.split(':');\r
+ var pc = ' the "' + parts.pop() + '" state of ';\r
+ txt = parts.shift();\r
+ } else {\r
+ var pc = '';\r
+ }\r
+\r
+ if (txt.indexOf('#') != -1) {\r
+ var parts = txt.split('#');\r
+ return pc + parts[0] + ' tags with the id "' + parts[1] + '"';\r
+ }\r
+ if (txt.indexOf('.') != -1) {\r
+ var parts = txt.split('.');\r
+ return pc + parts[0] + ' tags with the class "' + parts[1] + '"';\r
+ }\r
+ return pc + txt + ' tags';\r
+ }\r
+ };\r
+ \r
+ \r
+ \r
+ UI.CSS = {\r
+ redraw: null,\r
+ colorType: null,\r
+ controlsId: 'chameleon-style-controls',\r
+ sections: ['text', 'backgrounds', 'borders-all', 'borders-separate', 'free-edit'],\r
+ \r
+ __borderEditGroup: true,\r
+ \r
+ editWindow: function(e) {\r
+ if (CSS.Selector.get() == '') {\r
+ UI.statusMsg('First you have to choose which item to style!', 'chameleon-notice');\r
+ return;\r
+ }\r
+ \r
+ var box = document.getElementById('chameleon-style-box');\r
+ if (box) UI.closeBoxes(true, box);\r
+\r
+ var coords = Pos.getElement(document.getElementById('chameleon-selector-box'));\r
+ var box = UI.makeDraggableBox('chameleon-style-box', coords.x + UI.boxOffsetX, coords.y + UI.boxOffsetY);\r
+\r
+ var instructions = Util.createElement('p');\r
+ if (!hotspotMode) {\r
+ instructions.appendChild(document.createTextNode('Add/Edit styles for the CSS selector "' + CSS.Selector.get() + '"'));\r
+ //UI.CSS.sections = ['text', 'backgrounds', 'borders-all', 'borders-separate', 'free-edit'];\r
+ } else {\r
+ instructions.appendChild(document.createTextNode('Add/Edit styles for ' + UI.HotSpots.getString()));\r
+ //UI.CSS.sections = ['text', 'backgrounds', 'borders-all', 'borders-separate'];\r
+ }\r
+ instructions.className = 'chameleon-instructions';\r
+ box.appendChild(instructions);\r
+\r
+ var tabsContainer = Util.createElement('table', 'chameleon-style-tabs');\r
+ var tabsBody = Util.createElement('tbody');\r
+ var tabs = Util.createElement('tr');\r
+ \r
+ tabs.appendChild(UI.CSS.__createTab('Text', UI.CSS.__editText, true));\r
+ tabs.appendChild(UI.CSS.__createTab('Backgrounds', UI.CSS.__editBackgrounds));\r
+ tabs.appendChild(UI.CSS.__createTab('Borders (All)', UI.CSS.__editBordersAll));\r
+ tabs.appendChild(UI.CSS.__createTab('Borders (Separate)', UI.CSS.__editBordersSeparate));\r
+ //if (!hotspotMode) {\r
+ tabs.appendChild(UI.CSS.__createTab('Free Edit', UI.CSS.__editCode));\r
+ //}\r
+\r
+ tabsBody.appendChild(tabs);\r
+ tabsContainer.appendChild(tabsBody);\r
+\r
+ box.appendChild(tabsContainer);\r
+\r
+ var styleControls = Util.createElement('div', UI.CSS.controlsId);\r
+ box.appendChild(styleControls);\r
+ box.appendChild(UI.CSS.__addButtons());\r
+\r
+ UI.addToDoc(box);\r
+ \r
+ UI.CSS.__editText();\r
+ },\r
+ \r
+ \r
+ \r
+ launchEditWindow: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ CSS.Selector.set(target.value);\r
+ UI.CSS.editWindow(e);\r
+ },\r
+ \r
+ \r
+ __editText: function(e, redraw) {\r
+ UI.CSS.redraw = arguments.callee;\r
+ UI.CSS.colorType = 'color';\r
+\r
+ var containerTable = document.getElementById('chameleon-style-edit-text-container');\r
+ if (!containerTable) {\r
+ var parent = UI.setupPane(UI.CSS.sections, UI.CSS.controlsId, 'chameleon-style', 'text');\r
+ containerTable = Util.createElement('table', 'chameleon-style-edit-text-container');\r
+ var container = Util.createElement('tbody');\r
+\r
+ var row = UI.CSS.__inputField('color', '-input-color', Check.color);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__selectBox('font-family', '-select-font-family', Check.fontFamily, Config.FONTS_LIST);\r
+ container.appendChild(row.node); \r
+\r
+ row = UI.CSS.__inputField('font-family', '-input-font-family', Check.fontFamily, !row.meta.sel);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__inputField('font-size', '-input-font-size', Check.fontSize);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__inputField('line-height', '-input-line-height', Check.lineHeight);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__selectBox('font-weight', '-select-font-weight', Check.fontWeight, Config.FONT_WEIGHTS);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__selectBox('font-style', '-select-font-style', Check.fontStyle, Config.FONT_STYLES);\r
+ container.appendChild(row.node);\r
+ \r
+ row = UI.CSS.__selectBox('text-align', '-select-text-align', Check.textAlign, Config.TEXT_ALIGN);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__selectBox('text-decoration', '-select-text-decoration', Check.textDecoration, Config.TEXT_DECORATION);\r
+ container.appendChild(row.node);\r
+\r
+ containerTable.appendChild(container);\r
+ parent.appendChild(containerTable);\r
+ } else {\r
+ if (redraw == 'color') {\r
+ UI.CSS.__setColorDisplay(UI.CSS.colorType, UI.CSS.__getPropValue(UI.CSS.colorType));\r
+ }\r
+ }\r
+ },\r
+ \r
+ __editBackgrounds: function(e, redraw) {\r
+ UI.CSS.redraw = arguments.callee;\r
+ UI.CSS.colorType = 'background-color';\r
+\r
+ var containerTable = document.getElementById('chameleon-style-edit-backgrounds-container');\r
+ if (!containerTable) {\r
+ var parent = UI.setupPane(UI.CSS.sections, UI.CSS.controlsId, 'chameleon-style', 'backgrounds');\r
+ containerTable = Util.createElement('table', 'chameleon-style-edit-backgrounds-container');\r
+ var container = Util.createElement('tbody');\r
+\r
+ var row = UI.CSS.__inputField('background-color', '-input-background-color', Check.color);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__inputField('background-image', '-input-background-image', Check.backgroundImage);\r
+ container.appendChild(row.node);\r
+\r
+ var extraFields = row.meta;\r
+ \r
+ row = UI.CSS.__selectBox('background-repeat', '-select-background-repeat', Check.backgroundRepeat, Config.REPEAT_LIST, !extraFields);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__selectBox('background-position', '-select-background-position', Check.backgroundPosition, Config.POSITION_LIST, !extraFields);\r
+ container.appendChild(row.node); \r
+\r
+ containerTable.appendChild(container);\r
+ parent.appendChild(containerTable);\r
+ } else {\r
+ if (redraw == 'color') {\r
+ UI.CSS.__setColorDisplay(UI.CSS.colorType, UI.CSS.__getPropValue(UI.CSS.colorType));\r
+ } else if (redraw == 'image') {\r
+ var val = UI.CSS.__getPropValue('background-image');\r
+ UI.CSS.__setImageDisplay(val);\r
+ if (val == 'none' || val == '') {\r
+ document.getElementById(UI.CSS.controlsId + '-row-select-background-repeat').style.display = 'none';\r
+ document.getElementById(UI.CSS.controlsId + '-row-select-background-position').style.display = 'none';\r
+ } else {\r
+ try {\r
+ document.getElementById(UI.CSS.controlsId + '-row-select-background-repeat').style.display = 'table-row';\r
+ document.getElementById(UI.CSS.controlsId + '-row-select-background-position').style.display = 'table-row';\r
+ } catch(e) {\r
+ document.getElementById(UI.CSS.controlsId + '-row-select-background-repeat').style.display = 'block';\r
+ document.getElementById(UI.CSS.controlsId + '-row-select-background-position').style.display = 'block';\r
+ }\r
+ }\r
+ }\r
+ }\r
+ var imgPreview = document.getElementById('chameleon-image-preview');\r
+ if (imgPreview) {\r
+ imgPreview.setAttribute('width', '20');\r
+ imgPreview.setAttribute('height', '20');\r
+ }\r
+ },\r
+ \r
+ __editBordersAll: function(e, redraw) {\r
+ UI.CSS.redraw = arguments.callee;\r
+ UI.CSS.colorType = 'border-color';\r
+ \r
+ var containerTable = document.getElementById('chameleon-style-edit-borders-all-container');\r
+ if (!containerTable) {\r
+ \r
+ var parent = UI.setupPane(UI.CSS.sections, UI.CSS.controlsId, 'chameleon-style', 'borders-all');\r
+ containerTable = Util.createElement('table', 'chameleon-style-edit-borders-all-container');\r
+ var container = Util.createElement('tbody');\r
+\r
+ var row = UI.CSS.__inputField('border-width', '-input-border-width', Check.borderWidth);\r
+ container.appendChild(row.node);\r
+ \r
+ row = UI.CSS.__inputField('border-color', '-input-border-color', Check.color);\r
+ container.appendChild(row.node);\r
+ \r
+ row = UI.CSS.__selectBox('border-style', '-select-border-style', Check.borderStyle, Config.BORDER_LIST);\r
+ container.appendChild(row.node);\r
+\r
+ containerTable.appendChild(container);\r
+ parent.appendChild(containerTable);\r
+ } else {\r
+ if (redraw == 'color') {\r
+ UI.CSS.__setColorDisplay(UI.CSS.colorType, UI.CSS.__getPropValue(UI.CSS.colorType));\r
+ }\r
+ }\r
+ },\r
+ \r
+ __editBordersSeparate: function(e, redraw) {\r
+ UI.CSS.redraw = arguments.callee;\r
+ \r
+ var containerTable = document.getElementById('chameleon-style-edit-borders-separate-container');\r
+ if (!containerTable) {\r
+ var parent = UI.setupPane(UI.CSS.sections, UI.CSS.controlsId, 'chameleon-style', 'borders-separate');\r
+ containerTable = Util.createElement('table', 'chameleon-style-edit-borders-separate-container');\r
+ var container = Util.createElement('tbody');\r
+\r
+ var row = UI.CSS.__inputField('border-top-width', '-input-border-top-width', Check.borderWidth);\r
+ container.appendChild(row.node);\r
+ \r
+ row = UI.CSS.__inputField('border-top-color', '-input-border-top-color', Check.color, false, UI.CSS.__setColorType);\r
+ container.appendChild(row.node);\r
+ \r
+ row = UI.CSS.__selectBox('border-top-style', '-select-border-top-style', Check.borderStyle, Config.BORDER_LIST);\r
+ container.appendChild(row.node); \r
+\r
+\r
+ row = UI.CSS.__inputField('border-right-width', '-input-border-right-width', Check.borderWidth);\r
+ container.appendChild(row.node);\r
+ \r
+ row = UI.CSS.__inputField('border-right-color', '-input-border-right-color', Check.color, false, UI.CSS.__setColorType);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__selectBox('border-right-style', '-select-border-right-style', Check.borderStyle, Config.BORDER_LIST);\r
+ container.appendChild(row.node); \r
+\r
+ \r
+ row = UI.CSS.__inputField('border-bottom-width', '-input-border-bottom-width', Check.borderWidth);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__inputField('border-bottom-color', '-input-border-bottom-color', Check.color, false, UI.CSS.__setColorType);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__selectBox('border-bottom-style', '-select-border-bottom-style', Check.borderStyle, Config.BORDER_LIST);\r
+ container.appendChild(row.node); \r
+\r
+ \r
+ row = UI.CSS.__inputField('border-left-width', '-input-border-left-width', Check.borderWidth);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__inputField('border-left-color', '-input-border-left-color', Check.color, false, UI.CSS.__setColorType);\r
+ container.appendChild(row.node);\r
+\r
+ row = UI.CSS.__selectBox('border-left-style', '-select-border-left-style', Check.borderStyle, Config.BORDER_LIST);\r
+ container.appendChild(row.node);\r
+ \r
+ containerTable.appendChild(container);\r
+ parent.appendChild(containerTable);\r
+ } else {\r
+ if (redraw == 'color') {\r
+ UI.CSS.__setColorDisplay(UI.CSS.colorType, UI.CSS.__getPropValue(UI.CSS.colorType));\r
+ }\r
+ }\r
+ },\r
+ \r
+ __editCode: function(e) {\r
+ UI.CSS.redraw = arguments.callee;\r
+\r
+ var parent = UI.setupPane(UI.CSS.sections, UI.CSS.controlsId, 'chameleon-style', 'free-edit');\r
+\r
+ var container = Util.createElement('div');\r
+ var textarea = Util.createElement('textarea', 'chameleon-free-edit-field');\r
+ textarea.value = CSS.getSelectorCSS();\r
+ textarea.style.width = '100%';\r
+ textarea.style.height = '350px';\r
+\r
+ Util.addEvent(textarea, 'focus', CSS.FreeEdit.setInitial);\r
+ Util.addEvent(textarea, 'blur', CSS.FreeEdit.saveSelector);\r
+\r
+ container.appendChild(textarea);\r
+ parent.appendChild(container); \r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ \r
+ \r
+ __getPropValue: function(prop) {\r
+ var val = UI.CSS.__getBorderPropValue(prop);\r
+ if (val === '') {\r
+ return false;\r
+ }\r
+ \r
+ if (val === false) {\r
+ val = CSS.getPropValue(prop);\r
+ }\r
+ return val;\r
+ },\r
+ \r
+ \r
+ __setColorDisplay: function(prop, value, field, picker) {\r
+ if (!field) var field = document.getElementById(UI.CSS.controlsId + '-input-' + prop);\r
+ if (!picker) var picker = document.getElementById(UI.CSS.controlsId + '-color-picker-' + prop);\r
+ \r
+ if (!field || !picker) return;\r
+ \r
+ field.value = value;\r
+ try {\r
+ picker.style.backgroundColor = (value != '') ? value.replace(/[ ]*\!important/, '') : '#000';\r
+ if (!picker.style.backgroundColor) {\r
+ UI.statusMsg(value + ' is an Invalid color!', 'chameleon-error');\r
+ }\r
+ } catch(e) {\r
+ UI.statusMsg(value + ' is an Invalid color!', 'chameleon-error');\r
+ }\r
+ },\r
+ \r
+ __setImageDisplay: function(value, field, picker) {\r
+ if (!field) var field = document.getElementById(UI.CSS.controlsId + '-input-background-image');\r
+ if (!picker) var picker = document.getElementById(UI.CSS.controlsId + '-background-image-picker');\r
+ \r
+ var preview = document.getElementById('chameleon-image-preview');\r
+ \r
+ if (!field || !picker) return;\r
+ \r
+ field.value = value;\r
+ if (value != '') {\r
+ if (!preview) {\r
+ preview = Util.createElement('img', 'chameleon-image-preview');\r
+ picker.appendChild(preview);\r
+ }\r
+ \r
+ if (field.value != 'none') {\r
+ preview.setAttribute('src', CSS.fixPath(value.replace(/[ ]*\!important/, '')));\r
+ } else {\r
+ preview.setAttribute('src', CSS.fixPath('ui/images/none.gif'));\r
+ }\r
+ preview.setAttribute('title', 'Open image picker');\r
+ Util.addEvent(preview, 'click', UI.CSS.__loadImagePicker);\r
+\r
+ picker.style.backgroundColor = 'transparent';\r
+ } else {\r
+ if (preview) {\r
+ Util.removeElement(preview);\r
+ }\r
+ picker.style.backgroundColor = '#000';\r
+ picker.setAttribute('title', 'Open image picker');\r
+ Util.addEvent(picker, 'click', UI.CSS.__loadImagePicker);\r
+ }\r
+ \r
+ \r
+ },\r
+ \r
+ __shorthandWarningIcon: function() {\r
+ var img = Util.createElement('img');\r
+ img.setAttribute('src', CSS.fixPath('ui/images/notice.gif'));\r
+ img.style.margin = '0 2px -5px 0';\r
+ img.setAttribute('title', 'You currently have set values of this property for one or more individual sides. Updating the value here will set the property for all sides, overwriting the individual values.'); \r
+ return img;\r
+ },\r
+ \r
+ __inputField: function(prop, id, validate, hidden, init) {\r
+ var row = Util.createElement('tr', UI.CSS.controlsId + '-row' + id);\r
+ id = UI.CSS.controlsId + id;\r
+ \r
+ var labelCell = Util.createElement('td');\r
+ var fieldCell = Util.createElement('td');\r
+\r
+ var field = Util.createElement('input', id);\r
+ field.setAttribute('type', 'text');\r
+ field.className = 'chameleon-input-text';\r
+ \r
+ \r
+ var val = UI.CSS.__getPropValue(prop);\r
+ if (val !== false) {\r
+ field.value = val;\r
+ } else {\r
+ //field.className = 'longhand-warning';\r
+ labelCell.appendChild(UI.CSS.__shorthandWarningIcon());\r
+ }\r
+ \r
+ Util.addEvent(field, 'blur', validate);\r
+ if (init) {\r
+ Util.addEvent(field, 'focus', init);\r
+ }\r
+ \r
+ labelCell.appendChild(document.createTextNode(UI.CSS.__formatProp(prop) + ': '));\r
+ labelCell.className = 'label';\r
+\r
+ fieldCell.appendChild(field);\r
+ \r
+ row.appendChild(labelCell);\r
+ row.appendChild(fieldCell);\r
+ \r
+ if (prop == 'color' || prop.indexOf('-color') != -1) {\r
+ var colorCell = Util.createElement('td');\r
+ var colorPicker = Util.createElement('div', UI.CSS.controlsId + '-color-picker-' + prop);\r
+\r
+ colorPicker.setAttribute('title', 'Open color picker');\r
+ UI.CSS.__setColorDisplay(prop, field.value, field, colorPicker);\r
+ \r
+ Util.addEvent(colorPicker, 'click', UI.CSS.__displayColorPicker);\r
+ if (init) {\r
+ Util.addEvent(colorPicker, 'click', init);\r
+ }\r
+\r
+ colorCell.appendChild(colorPicker);\r
+ row.appendChild(colorCell);\r
+ } else if (prop.indexOf('-image') != -1) {\r
+ var imgCell = Util.createElement('td');\r
+ var imgPicker = Util.createElement('div', UI.CSS.controlsId + '-background-image-picker');\r
+ \r
+ UI.CSS.__setImageDisplay(field.value, field, imgPicker);\r
+\r
+ imgCell.appendChild(imgPicker);\r
+ row.appendChild(imgCell);\r
+ \r
+ } else {\r
+ fieldCell.setAttribute('colspan', '2');\r
+ }\r
+ if (hidden) {\r
+ row.style.display = 'none';\r
+ }\r
+ return {node: row, meta: (field.value == 'none') ? false : field.value};\r
+ },\r
+ \r
+ \r
+ __selectBox: function(prop, id, validate, src, hidden) {\r
+ var row = Util.createElement('tr', UI.CSS.controlsId + '-row' + id);\r
+ id = UI.CSS.controlsId + id;\r
+\r
+ var labelCell = Util.createElement('td');\r
+ var fieldCell = Util.createElement('td');\r
+ fieldCell.setAttribute('colspan', '2');\r
+ \r
+ var currentValue = UI.CSS.__getPropValue(prop);\r
+ if (currentValue === false) {\r
+ labelCell.appendChild(UI.CSS.__shorthandWarningIcon());\r
+ currentValue = '';\r
+ }\r
+\r
+ labelCell.appendChild(document.createTextNode(UI.CSS.__formatProp(prop) + ': '));\r
+ labelCell.className = 'label';\r
+\r
+ var field = Util.createElement('select', id);\r
+ var op = Util.createElement('option');\r
+ op.setAttribute('value', '');\r
+ op.appendChild(document.createTextNode('Please select'));\r
+ field.appendChild(op);\r
+\r
+ var selected = false;\r
+ var otherSelected = false;\r
+ \r
+ for (var i = 0; i < src.length; ++i) {\r
+ op = Util.createElement('option');\r
+ op.setAttribute('value', src[i]);\r
+ op.appendChild(document.createTextNode(src[i]));\r
+ if (src[i] != 'other' && src[i] == currentValue) {\r
+ op.setAttribute('selected', 'selected');\r
+ selected = true;\r
+ } else if (src[i].toLowerCase() == 'other' && currentValue != '' && !selected) {\r
+ op.setAttribute('selected', 'selected');\r
+ selected = true;\r
+ otherSelected = true;\r
+ }\r
+ field.appendChild(op);\r
+ }\r
+\r
+ Util.addEvent(field, 'change', validate);\r
+\r
+ fieldCell.appendChild(field);\r
+ row.appendChild(labelCell);\r
+ row.appendChild(fieldCell);\r
+\r
+ if (hidden) {\r
+ row.style.display = 'none';\r
+ }\r
+\r
+ return {node: row, meta: {sel: otherSelected, value: currentValue}};\r
+ },\r
+ \r
+ \r
+ \r
+ __createTab: function(str, fn, active) {\r
+ var id = 'chameleon-style-tab-' + str.replace(/[\( ]+/, '-').replace(/[\)]+/, '').toLowerCase();\r
+ var tab = Util.createElement('td', id);\r
+ tab.appendChild(document.createTextNode(str));\r
+ tab.className = (active) ? 'chameleon-style-tab-active' : 'chameleon-style-tab';\r
+ Util.addEvent(tab, 'click', fn);\r
+ return tab;\r
+ },\r
+ \r
+ __addButtons: function() {\r
+ var p = Util.createElement('p', 'chameleon-style-buttons');\r
+ p.style.textAlign = 'right';\r
+\r
+ p.appendChild(UI.createButton('chameleon-style-buttons-revert', 'Revert', 'Discard all temporarily saved changes', CSS.hardReset));\r
+ p.appendChild(UI.createButton('chameleon-style-buttons-save-local', 'Save Temp', 'Save these changes in a temporary file on the server', CSS.updateTemp));\r
+ p.appendChild(UI.createButton('chameleon-style-buttons-save-server', 'Save Server', 'Save these changes to the server', CSS.updateRemote));\r
+\r
+ return p;\r
+ },\r
+ \r
+ __formatProp: function(txt) {\r
+ if (txt.length > 15 && txt.indexOf('-') != -1) {\r
+ return txt.split('-').slice(1).join('-');\r
+ }\r
+ return txt;\r
+ },\r
+\r
+\r
+\r
+\r
+ __loadImagePicker: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ \r
+ if (target.value) {\r
+ UI.statusMsg('Loading file list for ' + target.value + '...', 'chameleon-working');\r
+ FileHandler.getFiles(target.value);\r
+ } else {\r
+ UI.statusMsg('Loading file list...', 'chameleon-working');\r
+ FileHandler.getFiles('root');\r
+ }\r
+ },\r
+ \r
+ displayImagePicker: function(xmldata) {\r
+ UI.clearStatusMsg();\r
+\r
+ var box = document.getElementById('chameleon-file-box');\r
+ if (box) UI.closeBoxes(true, box);\r
+\r
+ var coords = Pos.getElement(document.getElementById('chameleon-style-box'));\r
+ box = UI.makeDraggableBox('chameleon-file-box', coords.x + UI.boxOffsetX, coords.y + UI.boxOffsetY);\r
+ \r
+ if (xmldata.firstChild.nodeName.toLowerCase() == 'chameleon_error') {\r
+ UI.statusMsg('There was an error reading files from the server:\n' + xmldata.firstChild.firstChild.nodeValue + '.', 'chameleon-error');\r
+ return;\r
+ }\r
+ \r
+ var files = xmldata.firstChild;\r
+ var hasFiles = false;\r
+ \r
+ var infoTable = Util.createElement('table');\r
+ var infoTableBody = Util.createElement('tbody');\r
+ var infoTableRow = Util.createElement('tr');\r
+\r
+ var path = files.getAttribute('path');\r
+ if (path.indexOf('/') != -1) {\r
+ var parentPath = path.substring(0, path.lastIndexOf('/'));\r
+ var parentCell = Util.createElement('td');\r
+ var parentLink = Util.createElement('p', 'chameleon-files-parent');\r
+ parentLink.value = parentPath;\r
+ parentLink.className = 'chameleon-image-folder';\r
+ parentLink.appendChild(document.createTextNode('Parent folder'));\r
+ Util.addEvent(parentLink, 'click', UI.CSS.__loadImagePicker);\r
+ parentCell.appendChild(parentLink);\r
+ infoTableRow.appendChild(parentCell);\r
+ } \r
+\r
+ var location = Util.createElement('td', 'chameleon-files-location');\r
+ var locationPara = Util.createElement('p');\r
+ var locationTxt = Util.createElement('span');\r
+ locationTxt.appendChild(document.createTextNode('Location: '));\r
+ locationPara.appendChild(locationTxt);\r
+ locationPara.appendChild(document.createTextNode(path));\r
+ location.appendChild(locationPara);\r
+\r
+ infoTableRow.appendChild(location);\r
+ infoTableBody.appendChild(infoTableRow);\r
+ infoTable.appendChild(infoTableBody);\r
+ box.appendChild(infoTable);\r
+ \r
+ var fileList = Util.createElement('div');\r
+\r
+ for (var i = 0; i < files.childNodes.length; ++i) {\r
+ if (files.childNodes[i].nodeType != Node.ELEMENT_NODE) {\r
+ continue;\r
+ }\r
+ hasFiles = true;\r
+\r
+ var fileItemContainer = Util.createElement('p');\r
+ var fileItem = Util.createElement('span');\r
+ fileItem.value = files.childNodes[i].firstChild.nodeValue;\r
+ fileItem.appendChild(document.createTextNode(fileItem.value.split('/').pop()));\r
+ if (files.childNodes[i].getAttribute('type') == 'img') {\r
+ Util.addEvent(fileItem, 'click', Check.backgroundImage);\r
+ } else {\r
+ fileItemContainer.className = 'chameleon-image-folder';\r
+ Util.addEvent(fileItem, 'click', UI.CSS.__loadImagePicker);\r
+ }\r
+ fileItemContainer.appendChild(fileItem);\r
+ fileList.appendChild(fileItemContainer);\r
+ }\r
+\r
+ if (!hasFiles) {\r
+ var fileItem = Util.createElement('p');\r
+ fileItem.appendChild(document.createTextNode('No images were found in this folder'));\r
+ fileList.appendChild(fileItem);\r
+ }\r
+\r
+ box.appendChild(fileList);\r
+ UI.addToDoc(box);\r
+\r
+ UI.setOverflow(fileList, 350);\r
+ },\r
+ \r
+ \r
+ \r
+ \r
+ __displayColorPicker: function(e) {\r
+ var box = document.getElementById('chameleon-color-box');\r
+ if (box) UI.closeBoxes(true, box);\r
+ \r
+ var extraColors = ['000000', '333333', '666666', '999999', 'cccccc', 'ffffff', 'ff0000', '00ff00', '0000ff', 'ffff00', 'ff00ff', '00ffff'];\r
+\r
+ var coords = Pos.getElement(document.getElementById('chameleon-style-box'));\r
+ box = UI.makeDraggableBox('chameleon-color-box', coords.x + UI.boxOffsetX, coords.y + UI.boxOffsetY);\r
+\r
+ var container = Util.createElement('div', 'chameleon-color-palette');\r
+ box.appendChild(container);\r
+\r
+ var x = 0; var y = 0; var xx = 0; var yi = 0;\r
+ for (var r = 0; r < 256; r += 51) {\r
+ for (var g = 0; g < 256; g += 51) {\r
+ for (var b = 0; b < 256; b += 51) {\r
+ var col = (r << 16 | g << 8 | b).toString(16);\r
+ while (col.length < 6) {\r
+ col = '0' + col;\r
+ }\r
+ \r
+ yi = (xx > 17) ? 5 : 0;\r
+ \r
+ var colorTab = Util.createElement('div');\r
+ colorTab.style.position = 'absolute';\r
+ colorTab.style.left = ((15 * x) + 17) + 'px';\r
+ colorTab.style.top = (15 * (yi + y)) + 'px';\r
+ colorTab.style.width = colorTab.style.height = '15px';\r
+ colorTab.style.backgroundColor = colorTab.value = '#' + col;\r
+\r
+ colorTab.setAttribute('title', '#' + col);\r
+\r
+ container.appendChild(colorTab);\r
+ \r
+ if (x == 17) {\r
+ x = 0;\r
+ if (xx == 35) {\r
+ xx = 0;\r
+ } else {\r
+ ++xx;\r
+ ++y;\r
+ }\r
+ } else {\r
+ ++x;\r
+ ++xx;\r
+ }\r
+ } \r
+ }\r
+ }\r
+ \r
+ for (var i = 0; i < extraColors.length; ++i) {\r
+ var colorTab = Util.createElement('div');\r
+ colorTab.style.position = 'absolute';\r
+ colorTab.style.left = '0px';\r
+ colorTab.style.top = (15 * i) + 'px';\r
+ colorTab.style.width = colorTab.style.height = '15px';\r
+ colorTab.style.backgroundColor = colorTab.value = '#' + extraColors[i];\r
+\r
+ colorTab.setAttribute('title', '#' + extraColors[i]);\r
+\r
+ container.appendChild(colorTab);\r
+ }\r
+ \r
+ Util.addEvent(container, 'click', Check.color);\r
+\r
+ container.style.height = (((y + yi) * 15) + 20) + 'px';\r
+\r
+ UI.addToDoc(box);\r
+ },\r
+ \r
+ \r
+ \r
+ __setColorType: function(e) {\r
+ var target = e.target || e.srcElement;\r
+\r
+ UI.CSS.colorType = UI.CSS.getBorderProp(target.id);\r
+ },\r
+ \r
+ \r
+ getBorderProp: function(id) {\r
+ var separators = ['color-picker', 'input', 'select'];\r
+ for (var i = 0; i < separators.length; ++i) {\r
+ if (id.indexOf('-' + separators[i] + '-') != -1) {\r
+ return id.split('-' + separators[i] + '-').pop();\r
+ }\r
+ }\r
+ return '';\r
+ },\r
+\r
+ __getBorderPropValue: function(prop) {\r
+ var matches = prop.match(/^border\-([^\-]+)$/);\r
+ if (matches) {\r
+ var p1 = CSS.getPropValue('border-left-' + matches[1]);\r
+ var p2 = CSS.getPropValue('border-right-' + matches[1]);\r
+ var p3 = CSS.getPropValue('border-top-' + matches[1]);\r
+ var p4 = CSS.getPropValue('border-bottom-' + matches[1]);\r
+ if (!p1 && !p2 && !p3 && !p4) {\r
+ return false;\r
+ }\r
+ \r
+ if (!(p1 && p2 && p3 && p4)) {\r
+ return '';\r
+ }\r
+ \r
+ return (p1 == p2 && p2 == p3 && p3 == p4) ? p1 : ''; \r
+ }\r
+ return false;\r
+ }\r
+ \r
+ };\r
+ \r
+ \r
+ \r
+ UI.HotSpots = {\r
+ __selectors: null,\r
+ __counter: 0,\r
+ \r
+ init: function() {\r
+ var box = Util.createElement('div', 'chameleon-launch-hotspots');\r
+ box.appendChild(document.createTextNode('Load hotspots'));\r
+ box.style.zIndex = ++UI.zIndex;\r
+ box.hotSpotsOn = false;\r
+ Util.addEvent(box, 'click', UI.HotSpots.__load);\r
+ \r
+ UI.addToDoc(box);\r
+ },\r
+ \r
+ getString: function() {\r
+ var sel = CSS.Selector.get();\r
+ if (UI.HotSpots.__selectors[sel]) {\r
+ return UI.HotSpots.__selectors[sel] + '.';\r
+ }\r
+ return '"' + sel + '"';\r
+ },\r
+ \r
+ __load: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ target.hotSpotsOn = !target.hotSpotsOn;\r
+ \r
+ UI.HotSpots.__counter = 0;\r
+ \r
+ if (!target.hotSpotsOn) {\r
+ target.firstChild.nodeValue = 'Show hotspots';\r
+ UI.HotSpots.__clear();\r
+ return;\r
+ }\r
+ target.firstChild.nodeValue = 'Hide hotspots';\r
+ \r
+ if (!UI.HotSpots.__selectors) {\r
+ UI.HotSpots.__selectors = {};\r
+ UI.HotSpots.__selectors['div#header'] = 'Header bar';\r
+ UI.HotSpots.__selectors['div#header-home'] = 'Header bar on the homepage';\r
+ UI.HotSpots.__selectors['div#header-home div.headermain'] = 'The header text on the homepage';\r
+ UI.HotSpots.__selectors['div#header div.headermain'] = 'The header text';\r
+ UI.HotSpots.__selectors['td#right-column div.sideblock div.header'] = 'The block headings in the right hand column';\r
+ UI.HotSpots.__selectors['div.sideblock div.title'] = 'The text in the block headings';\r
+ }\r
+ \r
+ UI.HotSpots.__parse();\r
+ },\r
+ \r
+ __parse: function() {\r
+ for (var sel in UI.HotSpots.__selectors) {\r
+ var matches = cssQuery(sel);\r
+ var nm = matches.length;\r
+ if (!nm) {\r
+ continue;\r
+ }\r
+ \r
+ for (var j = 0; j < nm; ++j) {\r
+ if (matches[j].hasAttribute && matches[j].hasAttribute('id') && matches[j].getAttribute('id').indexOf('chameleon') != -1) {\r
+ continue;\r
+ }\r
+ if (!matches[j].mySelectors) {\r
+ matches[j].appendChild(UI.HotSpots.__makeButton(UI.HotSpots.__selectors[sel]));\r
+ matches[j].mySelectors = sel;\r
+ } else {\r
+ matches[j].mySelectors += '|' + sel;\r
+ }\r
+ }\r
+ }\r
+ },\r
+ \r
+ \r
+ __clear: function() {\r
+ var i = 0;\r
+ var obj;\r
+ while (obj = document.getElementById('chameleon-hotspot-' + ++i)) {\r
+ obj.parentNode.mySelectors = null;\r
+ Util.removeElement(obj);\r
+ } \r
+ },\r
+ \r
+ \r
+ __makeButton: function(title) {\r
+ var d = Util.createElement('img', 'chameleon-hotspot-' + ++UI.HotSpots.__counter);\r
+ d.style.width = d.style.height = '20px'; d.style.cssFloat = 'left'; d.style.cursor = 'pointer';\r
+ d.setAttribute('src', CSS.fixPath('ui/images/hotspot.gif'));\r
+ d.setAttribute('title', title);\r
+ Util.addEvent(d, 'click', UI.HotSpots.__launch);\r
+ return d;\r
+ },\r
+ \r
+ __launch: function(e) {\r
+ var target = (e.target || e.srcElement).parentNode;\r
+ var selectors = target.mySelectors.split('|');\r
+ \r
+ var coords = Pos.getMouse(e);\r
+ \r
+ hotspotMode = true;\r
+ \r
+ var box = document.getElementById('chameleon-selector-box');\r
+ if (box) UI.closeBoxes(true, box);\r
+ \r
+ var box = UI.makeDraggableBox('chameleon-selector-box', coords.x, coords.y);\r
+ \r
+ if (selectors.length > 1) {\r
+ var instructions = Util.createElement('p');\r
+ instructions.appendChild(document.createTextNode('This element matches more than one selector, please choose which you would like to style.'));\r
+ instructions.className = 'chameleon-instructions';\r
+ box.appendChild(instructions);\r
+ }\r
+ \r
+ var selList = Util.createElement('ul');\r
+ for (var i = 0; i < selectors.length; ++i) {\r
+ var item = Util.createElement('li');\r
+ var itemLink = Util.createElement('a');\r
+ itemLink.appendChild(document.createTextNode('Add/Edit styles for ' + UI.HotSpots.__selectors[selectors[i]]));\r
+ itemLink.value = selectors[i];\r
+ Util.addEvent(itemLink, 'click', UI.HotSpots.__launchCSSEditor);\r
+ \r
+ item.appendChild(itemLink);\r
+ \r
+ selList.appendChild(item);\r
+ \r
+ box.appendChild(selList); \r
+ }\r
+ UI.addToDoc(box);\r
+ },\r
+ \r
+ __launchCSSEditor: function(e, value) {\r
+ var target = e.target || e.srcElement;\r
+ \r
+ if (!value) {\r
+ var value = target.value;\r
+ }\r
+ CSS.Selector.set(value);\r
+ UI.CSS.editWindow(e);\r
+ }\r
+ \r
+ };\r
+ \r
+\r
+ \r
+ \r
+ \r
+ \r
+ var Check = {\r
+ color: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ if (e.type == 'click' && !target.value) return;\r
+ \r
+ var originalColor = UI.CSS.__getPropValue(UI.CSS.colorType);\r
+ if (originalColor != target.value) {\r
+ CSS.setPropValue(UI.CSS.colorType, target.value);\r
+ UI.CSS.redraw.call(null, null, 'color');\r
+ }\r
+ if (e.type == 'click') {\r
+ UI.closeBoxes(true, target.parentNode.parentNode);\r
+ }\r
+ },\r
+ \r
+ backgroundImage: function(e) {\r
+ var target = e.target || e.srcElement;\r
+\r
+ CSS.setPropValue('background-image', target.value);\r
+ UI.CSS.redraw.call(null, null, 'image');\r
+ if (e.type == 'click') {\r
+ UI.closeBoxes(true, document.getElementById('chameleon-file-box'));\r
+ }\r
+ }, \r
+ \r
+ backgroundRepeat: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ var value = target.options[target.options.selectedIndex].value.toLowerCase();\r
+ CSS.setPropValue('background-repeat', value);\r
+ },\r
+ \r
+ backgroundPosition: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ var value = target.options[target.options.selectedIndex].value.toLowerCase();\r
+ CSS.setPropValue('background-position', value);\r
+ },\r
+ \r
+ borderWidth: function(e) {\r
+ var target = e.target || e.srcElement;\r
+\r
+ var hasUnits = false;\r
+ for (var i = 0; i < Config.UNITS.length; ++i) {\r
+ if (target.value.indexOf(Config.UNITS[i]) > 0) {\r
+ hasUnits = true;\r
+ break;\r
+ }\r
+ }\r
+\r
+ var val = parseInt(target.value);\r
+ if (isNaN(val)) {\r
+ if (!target.value.match(/thin|medium|thick/)) {\r
+ target.value = '';\r
+ }\r
+ } else if (!hasUnits) {\r
+ target.value = val + 'px';\r
+ }\r
+ CSS.setPropValue(UI.CSS.getBorderProp(target.id), target.value); \r
+ },\r
+ \r
+ borderStyle: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ var value = target.options[target.options.selectedIndex].value.toLowerCase();\r
+ CSS.setPropValue(UI.CSS.getBorderProp(target.id), value);\r
+ },\r
+ \r
+ fontStyle: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ var value = target.options[target.options.selectedIndex].value.toLowerCase();\r
+ CSS.setPropValue('font-style', value);\r
+ },\r
+ \r
+ fontWeight: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ var value = target.options[target.options.selectedIndex].value.toLowerCase();\r
+ CSS.setPropValue('font-weight', value);\r
+ },\r
+ \r
+ fontSize: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ CSS.setPropValue('font-size', target.value);\r
+ },\r
+ \r
+ lineHeight: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ CSS.setPropValue('line-height', target.value);\r
+ },\r
+ \r
+ fontFamily: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ var n = target.nodeName.toLowerCase();\r
+ \r
+ if (n == 'select') {\r
+ var value = target.options[target.options.selectedIndex].value.toLowerCase();\r
+ var fontFamilyInputRow = target.parentNode.parentNode.nextSibling;\r
+ if (value == 'other') {\r
+ try {\r
+ fontFamilyInputRow.style.display = 'table-row';\r
+ } catch(e) {\r
+ fontFamilyInputRow.style.display = 'block';\r
+ }\r
+ } else {\r
+ if (value != '') {\r
+ fontFamilyInputRow.style.display = 'none';\r
+ }\r
+ CSS.setPropValue('font-family', value);\r
+ }\r
+ } else {\r
+ CSS.setPropValue('font-family', target.value);\r
+ }\r
+ },\r
+ \r
+ textDecoration: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ var value = target.options[target.options.selectedIndex].value.toLowerCase();\r
+ CSS.setPropValue('text-decoration', value);\r
+ },\r
+ \r
+ textAlign: function(e) {\r
+ var target = e.target || e.srcElement;\r
+ var value = target.options[target.options.selectedIndex].value.toLowerCase();\r
+ CSS.setPropValue('text-align', value);\r
+ }\r
+ };\r
+ \r
+ \r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+ var debugMsg = function(msg) {\r
+ //if (window.opera) window.opera.postError(msg);\r
+ };\r
+\r
+\r
+\r
+\r
+ var climbTree = function(src) {\r
+ var struct = [];\r
+ while (src.nodeName.toLowerCase() != 'html') {\r
+ if (src.nodeType == Node.ELEMENT_NODE) {\r
+ if (src.hasAttribute && src.hasAttribute('id') && src.getAttribute('id').indexOf('chameleon-') != -1) {\r
+ return src.getAttribute('id');\r
+ }\r
+ var elementObj = {tagname: src.nodeName.toLowerCase()};\r
+ if (src.hasAttribute && src.hasAttribute('id')) {\r
+ elementObj.id = src.getAttribute('id');\r
+ }\r
+ if (src.className) {\r
+ elementObj.classname = src.className;\r
+ }\r
+ struct.push(elementObj);\r
+ }\r
+ src = src.parentNode;\r
+ }\r
+ return struct;\r
+ };\r
+\r
+\r
+\r
+ var setup = function() {\r
+ UI.clearStatusMsg();\r
+ \r
+ //UI.HotSpots.init();\r
+ \r
+ Util.addEvent(window, 'unload', CSS.unloadPrompt);\r
+ Util.addEvent(window, 'unload', Util.cleanUp);\r
+ Util.addEvent(document, 'mousedown', UI.Selector.editWindow);\r
+ };\r
+\r
+ var startSetup = function() {\r
+ UI.statusMsg('Chameleon is loading...');\r
+\r
+ if (!CSS.loadRemote(true)) {\r
+ alert('Your browser must support XMLHttpRequest! Supported browsers include Internet Explorer 6, Mozilla Firefox and Opera 8.01+');\r
+ }\r
+ };\r
+\r
+ Util.addEvent(window, 'load', startSetup);\r
+\r
+})();\r
--- /dev/null
+\r
+/**\r
+ * ====================================================================\r
+ * About\r
+ * ====================================================================\r
+ * Sarissa is an ECMAScript library acting as a cross-browser wrapper for native XML APIs.\r
+ * The library supports Gecko based browsers like Mozilla and Firefox,\r
+ * Internet Explorer (5.5+ with MSXML3.0+), Konqueror, Safari and a little of Opera\r
+ * @version 0.9.6.1\r
+ * @author: Manos Batsis, mailto: mbatsis at users full stop sourceforge full stop net\r
+ * ====================================================================\r
+ * Licence\r
+ * ====================================================================\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License version 2 or\r
+ * the GNU Lesser General Public License version 2.1 as published by\r
+ * the Free Software Foundation (your choice between the two).\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License or GNU Lesser General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * or GNU Lesser General Public License along with this program; if not,\r
+ * write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+ * or visit http://www.gnu.org\r
+ *\r
+ */\r
+/**\r
+ * <p>Sarissa is a utility class. Provides "static" methods for DOMDocument and \r
+ * XMLHTTP objects, DOM Node serializatrion to XML strings and other goodies.</p>\r
+ * @constructor\r
+ */\r
+function Sarissa(){};\r
+/** @private */\r
+Sarissa.PARSED_OK = "Document contains no parsing errors";\r
+/**\r
+ * Tells you whether transformNode and transformNodeToObject are available. This functionality\r
+ * is contained in sarissa_ieemu_xslt.js and is deprecated. If you want to control XSLT transformations\r
+ * use the XSLTProcessor\r
+ * @deprecated\r
+ * @type boolean\r
+ */\r
+Sarissa.IS_ENABLED_TRANSFORM_NODE = false;\r
+/**\r
+ * tells you whether XMLHttpRequest (or equivalent) is available\r
+ * @type boolean\r
+ */\r
+Sarissa.IS_ENABLED_XMLHTTP = false;\r
+/**\r
+ * tells you whether selectNodes/selectSingleNode is available\r
+ * @type boolean\r
+ */\r
+Sarissa.IS_ENABLED_SELECT_NODES = false;\r
+var _sarissa_iNsCounter = 0;\r
+var _SARISSA_IEPREFIX4XSLPARAM = "";\r
+var _SARISSA_HAS_DOM_IMPLEMENTATION = document.implementation && true;\r
+var _SARISSA_HAS_DOM_CREATE_DOCUMENT = _SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.createDocument;\r
+var _SARISSA_HAS_DOM_FEATURE = _SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.hasFeature;\r
+var _SARISSA_IS_MOZ = _SARISSA_HAS_DOM_CREATE_DOCUMENT && _SARISSA_HAS_DOM_FEATURE;\r
+var _SARISSA_IS_SAFARI = (navigator.userAgent && navigator.vendor && (navigator.userAgent.toLowerCase().indexOf("applewebkit") != -1 || navigator.vendor.indexOf("Apple") != -1));\r
+var _SARISSA_IS_IE = document.all && window.ActiveXObject && navigator.userAgent.toLowerCase().indexOf("msie") > -1 && navigator.userAgent.toLowerCase().indexOf("opera") == -1;\r
+if(!window.Node || !window.Node.ELEMENT_NODE){\r
+ var Node = {ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5, ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12};\r
+};\r
+\r
+// IE initialization\r
+if(_SARISSA_IS_IE){\r
+ // for XSLT parameter names, prefix needed by IE\r
+ _SARISSA_IEPREFIX4XSLPARAM = "xsl:";\r
+ // used to store the most recent ProgID available out of the above\r
+ var _SARISSA_DOM_PROGID = "";\r
+ var _SARISSA_XMLHTTP_PROGID = "";\r
+ /**\r
+ * Called when the Sarissa_xx.js file is parsed, to pick most recent\r
+ * ProgIDs for IE, then gets destroyed.\r
+ * @param idList an array of MSXML PROGIDs from which the most recent will be picked for a given object\r
+ * @param enabledList an array of arrays where each array has two items; the index of the PROGID for which a certain feature is enabled\r
+ */\r
+ pickRecentProgID = function (idList, enabledList){\r
+ // found progID flag\r
+ var bFound = false;\r
+ for(var i=0; i < idList.length && !bFound; i++){\r
+ try{\r
+ var oDoc = new ActiveXObject(idList[i]);\r
+ o2Store = idList[i];\r
+ bFound = true;\r
+ for(var j=0;j<enabledList.length;j++)\r
+ if(i <= enabledList[j][1])\r
+ Sarissa["IS_ENABLED_"+enabledList[j][0]] = true;\r
+ }catch (objException){\r
+ // trap; try next progID\r
+ };\r
+ };\r
+ if (!bFound)\r
+ throw "Could not retreive a valid progID of Class: " + idList[idList.length-1]+". (original exception: "+e+")";\r
+ idList = null;\r
+ return o2Store;\r
+ };\r
+ // pick best available MSXML progIDs\r
+ _SARISSA_DOM_PROGID = pickRecentProgID(["Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"], [["SELECT_NODES", 2],["TRANSFORM_NODE", 2]]);\r
+ _SARISSA_XMLHTTP_PROGID = pickRecentProgID(["Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"], [["XMLHTTP", 4]]);\r
+ _SARISSA_THREADEDDOM_PROGID = pickRecentProgID(["Msxml2.FreeThreadedDOMDocument.5.0", "MSXML2.FreeThreadedDOMDocument.4.0", "MSXML2.FreeThreadedDOMDocument.3.0"]);\r
+ _SARISSA_XSLTEMPLATE_PROGID = pickRecentProgID(["Msxml2.XSLTemplate.5.0", "Msxml2.XSLTemplate.4.0", "MSXML2.XSLTemplate.3.0"], [["XSLTPROC", 2]]);\r
+ // we dont need this anymore\r
+ pickRecentProgID = null;\r
+ //============================================\r
+ // Factory methods (IE)\r
+ //============================================\r
+ // see non-IE version\r
+ Sarissa.getDomDocument = function(sUri, sName){\r
+ var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID);\r
+ // if a root tag name was provided, we need to load it in the DOM\r
+ // object\r
+ if (sName){\r
+ // if needed, create an artifical namespace prefix the way Moz\r
+ // does\r
+ if (sUri){\r
+ oDoc.loadXML("<a" + _sarissa_iNsCounter + ":" + sName + " xmlns:a" + _sarissa_iNsCounter + "=\"" + sUri + "\" />");\r
+ // don't use the same prefix again\r
+ ++_sarissa_iNsCounter;\r
+ }\r
+ else\r
+ oDoc.loadXML("<" + sName + "/>");\r
+ };\r
+ return oDoc;\r
+ };\r
+ // see non-IE version \r
+ Sarissa.getParseErrorText = function (oDoc) {\r
+ var parseErrorText = Sarissa.PARSED_OK;\r
+ if(oDoc.parseError != 0){\r
+ parseErrorText = "XML Parsing Error: " + oDoc.parseError.reason + \r
+ "\nLocation: " + oDoc.parseError.url + \r
+ "\nLine Number " + oDoc.parseError.line + ", Column " + \r
+ oDoc.parseError.linepos + \r
+ ":\n" + oDoc.parseError.srcText +\r
+ "\n";\r
+ for(var i = 0; i < oDoc.parseError.linepos;i++){\r
+ parseErrorText += "-";\r
+ };\r
+ parseErrorText += "^\n";\r
+ };\r
+ return parseErrorText;\r
+ };\r
+ // see non-IE version\r
+ Sarissa.setXpathNamespaces = function(oDoc, sNsSet) {\r
+ oDoc.setProperty("SelectionLanguage", "XPath");\r
+ oDoc.setProperty("SelectionNamespaces", sNsSet);\r
+ }; \r
+ /**\r
+ * Basic implementation of Mozilla's XSLTProcessor for IE. \r
+ * Reuses the same XSLT stylesheet for multiple transforms\r
+ * @constructor\r
+ */\r
+ XSLTProcessor = function(){\r
+ this.template = new ActiveXObject(_SARISSA_XSLTEMPLATE_PROGID);\r
+ this.processor = null;\r
+ };\r
+ /**\r
+ * Impoprts the given XSLT DOM and compiles it to a reusable transform\r
+ * @argument xslDoc The XSLT DOMDocument to import\r
+ */\r
+ XSLTProcessor.prototype.importStylesheet = function(xslDoc){\r
+ // convert stylesheet to free threaded\r
+ var converted = new ActiveXObject(_SARISSA_THREADEDDOM_PROGID); \r
+ converted.loadXML(xslDoc.xml);\r
+ this.template.stylesheet = converted;\r
+ this.processor = this.template.createProcessor();\r
+ // (re)set default param values\r
+ this.paramsSet = new Array();\r
+ };\r
+ /**\r
+ * Transform the given XML DOM\r
+ * @argument sourceDoc The XML DOMDocument to transform\r
+ * @return The transformation result as a DOM Document\r
+ */\r
+ XSLTProcessor.prototype.transformToDocument = function(sourceDoc){\r
+ this.processor.input = sourceDoc;\r
+ var outDoc = new ActiveXObject(_SARISSA_DOM_PROGID);\r
+ this.processor.output = outDoc; \r
+ this.processor.transform();\r
+ return outDoc;\r
+ };\r
+ /**\r
+ * Set global XSLT parameter of the imported stylesheet\r
+ * @argument nsURI The parameter namespace URI\r
+ * @argument name The parameter base name\r
+ * @argument value The new parameter value\r
+ */\r
+ XSLTProcessor.prototype.setParameter = function(nsURI, name, value){\r
+ /* nsURI is optional but cannot be null */\r
+ if(nsURI){\r
+ this.processor.addParameter(name, value, nsURI);\r
+ }else{\r
+ this.processor.addParameter(name, value);\r
+ };\r
+ /* update updated params for getParameter */\r
+ if(!this.paramsSet[""+nsURI]){\r
+ this.paramsSet[""+nsURI] = new Array();\r
+ };\r
+ this.paramsSet[""+nsURI][name] = value;\r
+ };\r
+ /**\r
+ * Gets a parameter if previously set by setParameter. Returns null\r
+ * otherwise\r
+ * @argument name The parameter base name\r
+ * @argument value The new parameter value\r
+ * @return The parameter value if reviously set by setParameter, null otherwise\r
+ */\r
+ XSLTProcessor.prototype.getParameter = function(nsURI, name){\r
+ nsURI = nsURI || "";\r
+ if(nsURI in this.paramsSet && name in this.paramsSet[nsURI]){\r
+ return this.paramsSet[nsURI][name];\r
+ }else{\r
+ return null;\r
+ };\r
+ };\r
+}\r
+else{ /* end IE initialization, try to deal with real browsers now ;-) */\r
+ if(_SARISSA_HAS_DOM_CREATE_DOCUMENT){\r
+ /**\r
+ * <p>Ensures the document was loaded correctly, otherwise sets the\r
+ * parseError to -1 to indicate something went wrong. Internal use</p>\r
+ * @private\r
+ */\r
+ Sarissa.__handleLoad__ = function(oDoc){\r
+ if (!oDoc.documentElement || oDoc.documentElement.tagName == "parsererror")\r
+ oDoc.parseError = -1;\r
+ Sarissa.__setReadyState__(oDoc, 4);\r
+ };\r
+ /**\r
+ * <p>Attached by an event handler to the load event. Internal use.</p>\r
+ * @private\r
+ */\r
+ _sarissa_XMLDocument_onload = function(){\r
+ Sarissa.__handleLoad__(this);\r
+ };\r
+ /**\r
+ * <p>Sets the readyState property of the given DOM Document object.\r
+ * Internal use.</p>\r
+ * @private\r
+ * @argument oDoc the DOM Document object to fire the\r
+ * readystatechange event\r
+ * @argument iReadyState the number to change the readystate property to\r
+ */\r
+ Sarissa.__setReadyState__ = function(oDoc, iReadyState){\r
+ oDoc.readyState = iReadyState;\r
+ if (oDoc.onreadystatechange != null && typeof oDoc.onreadystatechange == "function")\r
+ oDoc.onreadystatechange();\r
+ };\r
+ Sarissa.getDomDocument = function(sUri, sName){\r
+ var oDoc = document.implementation.createDocument(sUri?sUri:"", sName?sName:"", null);\r
+ oDoc.addEventListener("load", _sarissa_XMLDocument_onload, false);\r
+ return oDoc;\r
+ };\r
+ if(window.XMLDocument){\r
+ /**\r
+ * <p>Emulate IE's onreadystatechange attribute</p>\r
+ */\r
+ XMLDocument.prototype.onreadystatechange = null;\r
+ /**\r
+ * <p>Emulates IE's readyState property, which always gives an integer from 0 to 4:</p>\r
+ * <ul><li>1 == LOADING,</li>\r
+ * <li>2 == LOADED,</li>\r
+ * <li>3 == INTERACTIVE,</li>\r
+ * <li>4 == COMPLETED</li></ul>\r
+ */\r
+ XMLDocument.prototype.readyState = 0;\r
+ /**\r
+ * <p>Emulate IE's parseError attribute</p>\r
+ */\r
+ XMLDocument.prototype.parseError = 0;\r
+\r
+ // NOTE: setting async to false will only work with documents\r
+ // called over HTTP (meaning a server), not the local file system,\r
+ // unless you are using Moz 1.4+.\r
+ // BTW the try>catch block is for 1.4; I haven't found a way to check if\r
+ // the property is implemented without\r
+ // causing an error and I dont want to use user agent stuff for that...\r
+ var _SARISSA_SYNC_NON_IMPLEMENTED = false;// ("async" in XMLDocument.prototype) ? false: true;\r
+ /**\r
+ * <p>Keeps a handle to the original load() method. Internal use and only\r
+ * if Mozilla version is lower than 1.4</p>\r
+ * @private\r
+ */\r
+ XMLDocument.prototype._sarissa_load = XMLDocument.prototype.load;\r
+\r
+ /**\r
+ * <p>Overrides the original load method to provide synchronous loading for\r
+ * Mozilla versions prior to 1.4, using an XMLHttpRequest object (if\r
+ * async is set to false)</p>\r
+ * @returns the DOM Object as it was before the load() call (may be empty)\r
+ */\r
+ XMLDocument.prototype.load = function(sURI) {\r
+ var oDoc = document.implementation.createDocument("", "", null);\r
+ Sarissa.copyChildNodes(this, oDoc);\r
+ this.parseError = 0;\r
+ Sarissa.__setReadyState__(this, 1);\r
+ try {\r
+ if(this.async == false && _SARISSA_SYNC_NON_IMPLEMENTED) {\r
+ var tmp = new XMLHttpRequest();\r
+ tmp.open("GET", sURI, false);\r
+ tmp.send(null);\r
+ Sarissa.__setReadyState__(this, 2);\r
+ Sarissa.copyChildNodes(tmp.responseXML, this);\r
+ Sarissa.__setReadyState__(this, 3);\r
+ }\r
+ else {\r
+ this._sarissa_load(sURI);\r
+ };\r
+ }\r
+ catch (objException) {\r
+ this.parseError = -1;\r
+ }\r
+ finally {\r
+ if(this.async == false){\r
+ Sarissa.__handleLoad__(this);\r
+ };\r
+ };\r
+ return oDoc;\r
+ };\r
+ \r
+ \r
+ }//if(window.XMLDocument)\r
+ else if(document.implementation && document.implementation.hasFeature && document.implementation.hasFeature('LS', '3.0')){\r
+ Document.prototype.async = true;\r
+ Document.prototype.onreadystatechange = null;\r
+ Document.prototype.parseError = 0;\r
+ Document.prototype.load = function(sURI) {\r
+ var parser = document.implementation.createLSParser(this.async ? document.implementation.MODE_ASYNCHRONOUS : document.implementation.MODE_SYNCHRONOUS, null);\r
+ if(this.async){\r
+ var self = this;\r
+ parser.addEventListener("load", \r
+ function(e) { \r
+ self.readyState = 4;\r
+ Sarissa.copyChildNodes(e.newDocument, self.documentElement, false);\r
+ self.onreadystatechange.call(); \r
+ }, \r
+ false); \r
+ };\r
+ try {\r
+ var oDoc = parser.parseURI(sURI);\r
+ }\r
+ catch(e){\r
+ this.parseError = -1;\r
+ };\r
+ if(!this.async)\r
+ Sarissa.copyChildNodes(oDoc, this.documentElement, false);\r
+ return oDoc;\r
+ };\r
+ /**\r
+ * <p>Factory method to obtain a new DOM Document object</p>\r
+ * @argument sUri the namespace of the root node (if any)\r
+ * @argument sUri the local name of the root node (if any)\r
+ * @returns a new DOM Document\r
+ */\r
+ Sarissa.getDomDocument = function(sUri, sName){\r
+ return document.implementation.createDocument(sUri?sUri:"", sName?sName:"", null);\r
+ }; \r
+ };\r
+ };//if(_SARISSA_HAS_DOM_CREATE_DOCUMENT)\r
+};\r
+//==========================================\r
+// Common stuff\r
+//==========================================\r
+if(!window.DOMParser){\r
+ /*\r
+ * DOMParser is a utility class, used to construct DOMDocuments from XML strings\r
+ * @constructor\r
+ */\r
+ DOMParser = function() {\r
+ };\r
+ if(_SARISSA_IS_SAFARI){\r
+ /** \r
+ * Construct a new DOM Document from the given XMLstring\r
+ * @param sXml the given XML string\r
+ * @param contentType the content type of the document the given string represents (one of text/xml, application/xml, application/xhtml+xml). \r
+ * @return a new DOM Document from the given XML string\r
+ */\r
+ DOMParser.prototype.parseFromString = function(sXml, contentType){\r
+ if(contentType.toLowerCase() != "application/xml"){\r
+ throw "Cannot handle content type: \"" + contentType + "\"";\r
+ };\r
+ var xmlhttp = new XMLHttpRequest();\r
+ xmlhttp.open("GET", "data:text/xml;charset=utf-8," + encodeURIComponent(str), false);\r
+ xmlhttp.send(null);\r
+ return xmlhttp.responseXML;\r
+ };\r
+ }else if(Sarissa.getDomDocument && Sarissa.getDomDocument() && "loadXML" in Sarissa.getDomDocument()){\r
+ DOMParser.prototype.parseFromString = function(sXml, contentType){\r
+ var doc = Sarissa.getDomDocument();\r
+ doc.loadXML(sXml);\r
+ return doc;\r
+ };\r
+ };\r
+};\r
+\r
+if(window.XMLHttpRequest){\r
+ Sarissa.IS_ENABLED_XMLHTTP = true;\r
+}\r
+else if(_SARISSA_IS_IE){\r
+ /**\r
+ * Emulate XMLHttpRequest\r
+ * @constructor\r
+ */\r
+ XMLHttpRequest = function() {\r
+ return new ActiveXObject(_SARISSA_XMLHTTP_PROGID);\r
+ };\r
+ Sarissa.IS_ENABLED_XMLHTTP = true;\r
+};\r
+\r
+if(!window.document.importNode && _SARISSA_IS_IE){\r
+ try{\r
+ /**\r
+ * Implements importNode for the current window document in IE using innerHTML.\r
+ * Testing showed that DOM was multiple times slower than innerHTML for this,\r
+ * sorry folks. If you encounter trouble (who knows what IE does behind innerHTML)\r
+ * please gimme a call.\r
+ * @param oNode the Node to import\r
+ * @param bChildren whether to include the children of oNode\r
+ * @returns the imported node for further use\r
+ */\r
+ window.document.importNode = function(oNode, bChildren){\r
+ var importNode = document.createElement("div");\r
+ if(bChildren)\r
+ importNode.innerHTML = Sarissa.serialize(oNode);\r
+ else\r
+ importNode.innerHTML = Sarissa.serialize(oNode.cloneNode(false));\r
+ return importNode.firstChild;\r
+ };\r
+ }catch(e){};\r
+};\r
+if(!Sarissa.getParseErrorText){\r
+ /**\r
+ * <p>Returns a human readable description of the parsing error. Usefull\r
+ * for debugging. Tip: append the returned error string in a <pre>\r
+ * element if you want to render it.</p>\r
+ * <p>Many thanks to Christian Stocker for the initial patch.</p>\r
+ * @argument oDoc The target DOM document\r
+ * @returns The parsing error description of the target Document in\r
+ * human readable form (preformated text)\r
+ */\r
+ Sarissa.getParseErrorText = function (oDoc){\r
+ var parseErrorText = Sarissa.PARSED_OK;\r
+ if(oDoc && oDoc.parseError && oDoc.parseError != 0){\r
+ /*moz*/\r
+ if(oDoc.documentElement.tagName == "parsererror"){\r
+ parseErrorText = oDoc.documentElement.firstChild.data;\r
+ parseErrorText += "\n" + oDoc.documentElement.firstChild.nextSibling.firstChild.data;\r
+ }/*konq*/\r
+ else{\r
+ parseErrorText = Sarissa.getText(oDoc.documentElement);/*.getElementsByTagName("h1")[0], false) + "\n";\r
+ parseErrorText += Sarissa.getText(oDoc.documentElement.getElementsByTagName("body")[0], false) + "\n";\r
+ parseErrorText += Sarissa.getText(oDoc.documentElement.getElementsByTagName("pre")[0], false);*/\r
+ };\r
+ };\r
+ return parseErrorText;\r
+ };\r
+};\r
+Sarissa.getText = function(oNode, deep){\r
+ var s = "";\r
+ var nodes = oNode.childNodes;\r
+ for(var i=0; i < nodes.length; i++){\r
+ var node = nodes[i];\r
+ var nodeType = node.nodeType;\r
+ if(nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE){\r
+ s += node.data;\r
+ }else if(deep == true\r
+ && (nodeType == Node.ELEMENT_NODE\r
+ || nodeType == Node.DOCUMENT_NODE\r
+ || nodeType == Node.DOCUMENT_FRAGMENT_NODE)){\r
+ s += Sarissa.getText(node, true);\r
+ };\r
+ };\r
+ return s;\r
+};\r
+if(window.XMLSerializer){\r
+ /**\r
+ * <p>Factory method to obtain the serialization of a DOM Node</p>\r
+ * @returns the serialized Node as an XML string\r
+ */\r
+ Sarissa.serialize = function(oDoc){\r
+ var s = null;\r
+ if(oDoc){\r
+ s = oDoc.innerHTML?oDoc.innerHTML:(new XMLSerializer()).serializeToString(oDoc);\r
+ };\r
+ return s;\r
+ };\r
+}else{\r
+ if(Sarissa.getDomDocument && (Sarissa.getDomDocument("","foo", null)).xml){\r
+ // see non-IE version\r
+ Sarissa.serialize = function(oDoc) {\r
+ var s = null;\r
+ if(oDoc){\r
+ s = oDoc.innerHTML?oDoc.innerHTML:oDoc.xml;\r
+ };\r
+ return s;\r
+ };\r
+ /**\r
+ * Utility class to serialize DOM Node objects to XML strings\r
+ * @constructor\r
+ */\r
+ XMLSerializer = function(){};\r
+ /**\r
+ * Serialize the given DOM Node to an XML string\r
+ * @param oNode the DOM Node to serialize\r
+ */\r
+ XMLSerializer.prototype.serializeToString = function(oNode) {\r
+ return oNode.xml;\r
+ };\r
+ };\r
+};\r
+\r
+/**\r
+ * strips tags from a markup string\r
+ */\r
+Sarissa.stripTags = function (s) {\r
+ return s.replace(/<[^>]+>/g,"");\r
+};\r
+/**\r
+ * <p>Deletes all child nodes of the given node</p>\r
+ * @argument oNode the Node to empty\r
+ */\r
+Sarissa.clearChildNodes = function(oNode) {\r
+ // need to check for firstChild due to opera 8 bug with hasChildNodes\r
+ while(oNode.firstChild){\r
+ oNode.removeChild(oNode.firstChild);\r
+ };\r
+};\r
+/**\r
+ * <p> Copies the childNodes of nodeFrom to nodeTo</p>\r
+ * <p> <b>Note:</b> The second object's original content is deleted before \r
+ * the copy operation, unless you supply a true third parameter</p>\r
+ * @argument nodeFrom the Node to copy the childNodes from\r
+ * @argument nodeTo the Node to copy the childNodes to\r
+ * @argument bPreserveExisting whether to preserve the original content of nodeTo, default is false\r
+ */\r
+Sarissa.copyChildNodes = function(nodeFrom, nodeTo, bPreserveExisting) {\r
+ if((!nodeFrom) || (!nodeTo)){\r
+ throw "Both source and destination nodes must be provided";\r
+ };\r
+ if(!bPreserveExisting){\r
+ Sarissa.clearChildNodes(nodeTo);\r
+ };\r
+ var ownerDoc = nodeTo.nodeType == Node.DOCUMENT_NODE ? nodeTo : nodeTo.ownerDocument;\r
+ var nodes = nodeFrom.childNodes;\r
+ if(ownerDoc.importNode && (!_SARISSA_IS_IE)) {\r
+ for(var i=0;i < nodes.length;i++) {\r
+ nodeTo.appendChild(ownerDoc.importNode(nodes[i], true));\r
+ };\r
+ }\r
+ else{\r
+ for(var i=0;i < nodes.length;i++) {\r
+ nodeTo.appendChild(nodes[i].cloneNode(true));\r
+ };\r
+ };\r
+};\r
+\r
+/**\r
+ * <p> Moves the childNodes of nodeFrom to nodeTo</p>\r
+ * <p> <b>Note:</b> The second object's original content is deleted before \r
+ * the move operation, unless you supply a true third parameter</p>\r
+ * @argument nodeFrom the Node to copy the childNodes from\r
+ * @argument nodeTo the Node to copy the childNodes to\r
+ * @argument bPreserveExisting whether to preserve the original content of nodeTo, default is\r
+ */ \r
+Sarissa.moveChildNodes = function(nodeFrom, nodeTo, bPreserveExisting) {\r
+ if((!nodeFrom) || (!nodeTo)){\r
+ throw "Both source and destination nodes must be provided";\r
+ };\r
+ if(!bPreserveExisting){\r
+ Sarissa.clearChildNodes(nodeTo);\r
+ };\r
+ var nodes = nodeFrom.childNodes;\r
+ // if within the same doc, just move, else copy and delete\r
+ if(nodeFrom.ownerDocument == nodeTo.ownerDocument){\r
+ while(nodeFrom.firstChild){\r
+ nodeTo.appendChild(nodeFrom.firstChild);\r
+ };\r
+ }else{\r
+ var ownerDoc = nodeTo.nodeType == Node.DOCUMENT_NODE ? nodeTo : nodeTo.ownerDocument;\r
+ if(ownerDoc.importNode && (!_SARISSA_IS_IE)) {\r
+ for(var i=0;i < nodes.length;i++) {\r
+ nodeTo.appendChild(ownerDoc.importNode(nodes[i], true));\r
+ };\r
+ }else{\r
+ for(var i=0;i < nodes.length;i++) {\r
+ nodeTo.appendChild(nodes[i].cloneNode(true));\r
+ };\r
+ };\r
+ Sarissa.clearChildNodes(nodeFrom);\r
+ };\r
+};\r
+\r
+/** \r
+ * <p>Serialize any object to an XML string. All properties are serialized using the property name\r
+ * as the XML element name. Array elements are rendered as <code>array-item</code> elements, \r
+ * using their index/key as the value of the <code>key</code> attribute.</p>\r
+ * @argument anyObject the object to serialize\r
+ * @argument objectName a name for that object\r
+ * @return the XML serializationj of the given object as a string\r
+ */\r
+Sarissa.xmlize = function(anyObject, objectName, indentSpace){\r
+ indentSpace = indentSpace?indentSpace:'';\r
+ var s = indentSpace + '<' + objectName + '>';\r
+ var isLeaf = false;\r
+ if(!(anyObject instanceof Object) || anyObject instanceof Number || anyObject instanceof String \r
+ || anyObject instanceof Boolean || anyObject instanceof Date){\r
+ s += Sarissa.escape(""+anyObject);\r
+ isLeaf = true;\r
+ }else{\r
+ s += "\n";\r
+ var itemKey = '';\r
+ var isArrayItem = anyObject instanceof Array;\r
+ for(var name in anyObject){\r
+ s += Sarissa.xmlize(anyObject[name], (isArrayItem?"array-item key=\""+name+"\"":name), indentSpace + " ");\r
+ };\r
+ s += indentSpace;\r
+ };\r
+ return s += (objectName.indexOf(' ')!=-1?"</array-item>\n":"</" + objectName + ">\n");\r
+};\r
+\r
+/** \r
+ * Escape the given string chacters that correspond to the five predefined XML entities\r
+ * @param sXml the string to escape\r
+ */\r
+Sarissa.escape = function(sXml){\r
+ return sXml.replace(/&/g, "&")\r
+ .replace(/</g, "<")\r
+ .replace(/>/g, ">")\r
+ .replace(/"/g, """)\r
+ .replace(/'/g, "'");\r
+};\r
+\r
+/** \r
+ * Unescape the given string. This turns the occurences of the predefined XML \r
+ * entities to become the characters they represent correspond to the five predefined XML entities\r
+ * @param sXml the string to unescape\r
+ */\r
+Sarissa.unescape = function(sXml){\r
+ return sXml.replace(/'/g,"'")\r
+ .replace(/"/g,"\"")\r
+ .replace(/>/g,">")\r
+ .replace(/</g,"<")\r
+ .replace(/&/g,"&");\r
+};\r
+//
\ No newline at end of file