cssSandpaper.js 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395
  1. /*******************************************************************************
  2. * This notice must be untouched at all times.
  3. *
  4. * CSS Sandpaper: smooths out differences between CSS implementations.
  5. *
  6. * This javascript library contains routines to implement the CSS transform,
  7. * box-shadow and gradient in IE. It also provides a common syntax for other
  8. * browsers that support vendor-specific methods.
  9. *
  10. * Written by: Zoltan Hawryluk. Version 1.0 beta 1 completed on March 8, 2010.
  11. *
  12. * Some routines are based on code from CSS Gradients via Canvas v1.2
  13. * by Weston Ruter <http://weston.ruter.net/projects/css-gradients-via-canvas/>
  14. *
  15. * Requires sylvester.js by James Coglan http://sylvester.jcoglan.com/
  16. *
  17. * cssSandpaper.js v.1.0 beta 1 available at http://www.useragentman.com/
  18. *
  19. * released under the MIT License:
  20. * http://www.opensource.org/licenses/mit-license.php
  21. *
  22. ******************************************************************************/
  23. if (!document.querySelectorAll) {
  24. document.querySelectorAll = cssQuery;
  25. }
  26. var cssSandpaper = new function(){
  27. var me = this;
  28. var styleNodes, styleSheets = new Array();
  29. var ruleSetRe = /[^\{]*{[^\}]*}/g;
  30. var ruleSplitRe = /[\{\}]/g;
  31. var reGradient = /gradient\([\s\S]*\)/g;
  32. var reHSL = /hsl\([\s\S]*\)/g;
  33. // This regexp from the article
  34. // http://james.padolsey.com/javascript/javascript-comment-removal-revisted/
  35. var reMultiLineComment = /\/\/.+?(?=\n|\r|$)|\/\*[\s\S]+?\*\//g;
  36. var reAtRule = /@[^\{\};]*;|@[^\{\};]*\{[^\}]*\}/g;
  37. var reFunctionSpaces = /\(\s*/g
  38. var ruleLists = new Array();
  39. var styleNode;
  40. var tempObj;
  41. var body;
  42. me.init = function(reinit){
  43. if (EventHelpers.hasPageLoadHappened(arguments) && !reinit) {
  44. return;
  45. }
  46. body = document.body;
  47. tempObj = document.createElement('div');
  48. getStyleSheets();
  49. indexRules();
  50. fixTransforms();
  51. fixBoxShadow();
  52. fixLinearGradients();
  53. fixBackgrounds();
  54. fixColors();
  55. fixOpacity();
  56. setClasses();
  57. //fixBorderRadius();
  58. }
  59. me.setOpacity = function(obj, value){
  60. var property = CSS3Helpers.findProperty(document.body, 'opacity');
  61. if (property == "filter") {
  62. // IE must have layout, see
  63. // http://jszen.blogspot.com/2005/04/ie6-opacity-filter-caveat.html
  64. // for details.
  65. obj.style.zoom = "100%";
  66. var filter = CSS3Helpers.addFilter(obj, 'DXImageTransform.Microsoft.Alpha', StringHelpers.sprintf("opacity=%d", ((value) * 100)));
  67. filter.opacity = value * 100;
  68. } else if (obj.style[property] != null) {
  69. obj.style[property] = value;
  70. }
  71. }
  72. function fixOpacity(){
  73. var transformRules = getRuleList('opacity').values;
  74. for (var i in transformRules) {
  75. var rule = transformRules[i];
  76. var nodes = document.querySelectorAll(rule.selector);
  77. for (var j = 0; j < nodes.length; j++) {
  78. me.setOpacity(nodes[j], rule.value)
  79. }
  80. }
  81. }
  82. me.setTransform = function(obj, transformString){
  83. var property = CSS3Helpers.findProperty(obj, 'transform');
  84. if (property == "filter") {
  85. var matrix = CSS3Helpers.getTransformationMatrix(transformString);
  86. CSS3Helpers.setMatrixFilter(obj, matrix)
  87. } else if (obj.style[property] != null) {
  88. obj.style[property] = transformString;
  89. }
  90. }
  91. function fixTransforms(){
  92. var transformRules = getRuleList('-sand-transform').values;
  93. var property = CSS3Helpers.findProperty(document.body, 'transform');
  94. for (var i in transformRules) {
  95. var rule = transformRules[i];
  96. var nodes = document.querySelectorAll(rule.selector);
  97. for (var j = 0; j < nodes.length; j++) {
  98. me.setTransform(nodes[j], rule.value)
  99. }
  100. }
  101. }
  102. me.setBoxShadow = function(obj, value){
  103. var property = CSS3Helpers.findProperty(obj, 'boxShadow');
  104. var values = CSS3Helpers.getBoxShadowValues(value);
  105. if (property == "filter") {
  106. var filter = CSS3Helpers.addFilter(obj, 'DXImageTransform.Microsoft.DropShadow', StringHelpers.sprintf("color=%s,offX=%d,offY=%d", values.color, values.offsetX, values.offsetY));
  107. filter.color = values.color;
  108. filter.offX = values.offsetX;
  109. filter.offY = values.offsetY;
  110. } else if (obj.style[property] != null) {
  111. obj.style[property] = value;
  112. }
  113. }
  114. function fixBoxShadow(){
  115. var transformRules = getRuleList('-sand-box-shadow').values;
  116. //var matrices = new Array();
  117. for (var i in transformRules) {
  118. var rule = transformRules[i];
  119. var nodes = document.querySelectorAll(rule.selector);
  120. for (var j = 0; j < nodes.length; j++) {
  121. me.setBoxShadow(nodes[j], rule.value)
  122. }
  123. }
  124. }
  125. function setGradientFilter(node, values){
  126. if (values.colorStops.length == 2 &&
  127. values.colorStops[0].stop == 0.0 &&
  128. values.colorStops[1].stop == 1.0) {
  129. var startColor = new RGBColor(values.colorStops[0].color);
  130. var endColor = new RGBColor(values.colorStops[1].color);
  131. startColor = startColor.toHex();
  132. endColor = endColor.toHex();
  133. var filter = CSS3Helpers.addFilter(node, 'DXImageTransform.Microsoft.Gradient', StringHelpers.sprintf("GradientType = %s, StartColorStr = '%s', EndColorStr = '%s'", values.IEdir, startColor, endColor));
  134. filter.GradientType = values.IEdir;
  135. filter.StartColorStr = startColor;
  136. filter.EndColorStr = endColor;
  137. node.style.zoom = 1;
  138. }
  139. }
  140. me.setGradient = function(node, value){
  141. var support = CSS3Helpers.reportGradientSupport();
  142. var values = CSS3Helpers.getGradient(value);
  143. if (values == null) {
  144. return;
  145. }
  146. if (node.filters) {
  147. setGradientFilter(node, values);
  148. } else if (support == implementation.MOZILLA) {
  149. node.style.backgroundImage = StringHelpers.sprintf('-moz-gradient( %s, %s, from(%s), to(%s))', values.dirBegin, values.dirEnd, values.colorStops[0].color, values.colorStops[1].color);
  150. } else if (support == implementation.WEBKIT) {
  151. var tmp = StringHelpers.sprintf('-webkit-gradient(%s, %s, %s %s, %s %s)', values.type, values.dirBegin, values.r0 ? values.r0 + ", " : "", values.dirEnd, values.r1 ? values.r1 + ", " : "", listColorStops(values.colorStops));
  152. node.style.backgroundImage = tmp;
  153. } else if (support == implementation.CANVAS_WORKAROUND) {
  154. try {
  155. CSS3Helpers.applyCanvasGradient(node, values);
  156. }
  157. catch (ex) {
  158. // do nothing (for now).
  159. }
  160. }
  161. }
  162. me.setRGBABackground = function(node, value){
  163. var support = CSS3Helpers.reportColorSpaceSupport('RGBA', colorType.BACKGROUND);
  164. switch (support) {
  165. case implementation.NATIVE:
  166. node.style.value = value;
  167. break;
  168. case implementation.FILTER_WORKAROUND:
  169. setGradientFilter(node, {
  170. IEdir: 0,
  171. colorStops: [{
  172. stop: 0.0,
  173. color: value
  174. }, {
  175. stop: 1.0,
  176. color: value
  177. }]
  178. });
  179. break;
  180. }
  181. }
  182. me.setHSLABackground = function(node, value) {
  183. var support = CSS3Helpers.reportColorSpaceSupport('HSLA', colorType.BACKGROUND);
  184. switch (support) {
  185. case implementation.NATIVE:
  186. /* node.style.value = value;
  187. break; */
  188. case implementation.FILTER_WORKAROUND:
  189. var rgbColor = new RGBColor(value);
  190. if (rgbColor.a == 1) {
  191. node.style.backgroundColor = rgbColor.toHex();
  192. } else {
  193. var rgba = rgbColor.toRGBA();
  194. setGradientFilter(node, {
  195. IEdir: 0,
  196. colorStops: [{
  197. stop: 0.0,
  198. color: rgba
  199. }, {
  200. stop: 1.0,
  201. color: rgba
  202. }]
  203. });
  204. }
  205. break;
  206. }
  207. }
  208. /**
  209. * Convert a hyphenated string to camelized text. For example, the string "font-type" will be converted
  210. * to "fontType".
  211. *
  212. * @param {Object} s - the string that needs to be camelized.
  213. * @return {String} - the camelized text.
  214. */
  215. me.camelize = function (s) {
  216. var r="";
  217. for (var i=0; i<s.length; i++) {
  218. if (s.substring(i, i+1) == '-') {
  219. i++;
  220. r+= s.substring(i, i+1).toUpperCase();
  221. } else {
  222. r+= s.substring(i, i+1);
  223. }
  224. }
  225. return r;
  226. }
  227. me.setHSLColor = function (node, property, value) {
  228. var support = CSS3Helpers.reportColorSpaceSupport('HSL', colorType.FOREGROUND);
  229. switch (support) {
  230. case implementation.NATIVE:
  231. /* node.style.value = value;
  232. break; */
  233. case implementation.HEX_WORKAROUND:
  234. var hslColor = value.match(reHSL)[0];
  235. var hexColor = new RGBColor(hslColor).toHex()
  236. var newPropertyValue = value.replace(reHSL, hexColor);
  237. node.style[me.camelize(property)] = newPropertyValue;
  238. break;
  239. }
  240. }
  241. function fixLinearGradients(){
  242. var backgroundRules = getRuleList('background').values.concat(getRuleList('background-image').values);
  243. for (var i in backgroundRules) {
  244. var rule = backgroundRules[i];
  245. var nodes = document.querySelectorAll(rule.selector);
  246. for (var j = 0; j < nodes.length; j++) {
  247. me.setGradient(nodes[j], rule.value)
  248. }
  249. }
  250. }
  251. function fixBackgrounds(){
  252. var support = CSS3Helpers.reportColorSpaceSupport('RGBA', colorType.BACKGROUND);
  253. if (support == implementation.NATIVE) {
  254. return;
  255. }
  256. var backgroundRules = getRuleList('background').values.concat(getRuleList('background-color').values);
  257. for (var i in backgroundRules) {
  258. var rule = backgroundRules[i];
  259. var nodes = document.querySelectorAll(rule.selector);
  260. for (var j = 0; j < nodes.length; j++) {
  261. if (rule.value.indexOf('rgba(') == 0) {
  262. me.setRGBABackground(nodes[j], rule.value);
  263. } else if (rule.value.indexOf('hsla(') == 0 || rule.value.indexOf('hsl(') == 0) {
  264. me.setHSLABackground(nodes[j], rule.value);
  265. }
  266. }
  267. }
  268. }
  269. me.getProperties = function (obj, objName)
  270. {
  271. var result = ""
  272. if (!obj) {
  273. return result;
  274. }
  275. for (var i in obj)
  276. {
  277. try {
  278. result += objName + "." + i.toString() + " = " + obj[i] + ", ";
  279. } catch (ex) {
  280. // nothing
  281. }
  282. }
  283. return result
  284. }
  285. function fixColors() {
  286. var support = CSS3Helpers.reportColorSpaceSupport('HSL', colorType.FOREGROUND);
  287. if (support == implementation.NATIVE) {
  288. return;
  289. }
  290. var colorRules = getRuleList('color').values;
  291. var properties = ['color', 'border',
  292. 'border-left', 'border-right', 'border-bottom', 'border-top',
  293. 'border-left-color', 'border-right-color', 'border-bottom-color', 'border-top-color'];
  294. for (var i=0; i<properties.length; i++) {
  295. var rules = getRuleList(properties[i]).values;
  296. colorRules = colorRules.concat(rules);
  297. }
  298. for (var i in colorRules) {
  299. var rule = colorRules[i];
  300. var nodes = document.querySelectorAll(rule.selector);
  301. for (var j = 0; j < nodes.length; j++) {
  302. var isBorder = (rule.name.indexOf('border') == 0);
  303. var ruleMatch = rule.value.match(reHSL);
  304. if (ruleMatch) {
  305. var cssProperty;
  306. if (isBorder && rule.name.indexOf('-color') < 0) {
  307. cssProperty = rule.name;
  308. } else {
  309. cssProperty = rule.name;
  310. }
  311. me.setHSLColor(nodes[j], cssProperty, rule.value);
  312. }
  313. }
  314. }
  315. }
  316. function listColorStops(colorStops){
  317. var sb = new StringBuffer();
  318. for (var i = 0; i < colorStops.length; i++) {
  319. sb.append(StringHelpers.sprintf("color-stop(%s, %s)", colorStops[i].stop, colorStops[i].color));
  320. if (i < colorStops.length - 1) {
  321. sb.append(', ');
  322. }
  323. }
  324. return sb.toString();
  325. }
  326. function getStyleSheet(node){
  327. var sheetCssText;
  328. switch (node.nodeName.toLowerCase()) {
  329. case 'style':
  330. sheetCssText = StringHelpers.uncommentHTML(node.innerHTML); //does not work with inline styles because IE doesn't allow you to get the text content of a STYLE element
  331. break;
  332. case 'link':
  333. var xhr = XMLHelpers.getXMLHttpRequest(node.href, null, "GET", null, false);
  334. sheetCssText = xhr.responseText;
  335. break;
  336. }
  337. sheetCssText = sheetCssText.replace(reMultiLineComment, '').replace(reAtRule, '');
  338. return sheetCssText;
  339. }
  340. function getStyleSheets(){
  341. styleNodes = document.querySelectorAll('style, link[rel="stylesheet"]');
  342. for (var i = 0; i < styleNodes.length; i++) {
  343. if (!CSSHelpers.isMemberOfClass(styleNodes[i], 'cssSandpaper-noIndex')) {
  344. styleSheets.push(getStyleSheet(styleNodes[i]))
  345. }
  346. }
  347. }
  348. function indexRules(){
  349. for (var i = 0; i < styleSheets.length; i++) {
  350. var sheet = styleSheets[i];
  351. rules = sheet.match(ruleSetRe);
  352. if (rules) {
  353. for (var j = 0; j < rules.length; j++) {
  354. var parsedRule = rules[j].split(ruleSplitRe);
  355. var selector = parsedRule[0].trim();
  356. var propertiesStr = parsedRule[1];
  357. var properties = propertiesStr.split(';');
  358. for (var k = 0; k < properties.length; k++) {
  359. if (properties[k].trim() != '') {
  360. var splitProperty = properties[k].split(':')
  361. var name = splitProperty[0].trim().toLowerCase();
  362. var value = splitProperty[1];
  363. if (!ruleLists[name]) {
  364. ruleLists[name] = new RuleList(name);
  365. }
  366. if (value && typeof(ruleLists[name]) == 'object') {
  367. ruleLists[name].add(selector, value.trim());
  368. }
  369. }
  370. }
  371. }
  372. }
  373. }
  374. }
  375. function getRuleList(name){
  376. var list = ruleLists[name];
  377. if (!list) {
  378. list = new RuleList(name);
  379. }
  380. return list;
  381. }
  382. function setClasses(){
  383. var htmlNode = document.getElementsByTagName('html')[0];
  384. var properties = ['transform', 'opacity'];
  385. for (var i = 0; i < properties.length; i++) {
  386. var prop = properties[i];
  387. if (CSS3Helpers.supports(prop)) {
  388. CSSHelpers.addClass(htmlNode, 'cssSandpaper-' + prop);
  389. }
  390. }
  391. // Now .. remove the initially hidden classes
  392. var hiddenNodes = CSSHelpers.getElementsByClassName(document, 'cssSandpaper-initiallyHidden');
  393. for (var i=0; i<hiddenNodes.length; i++){
  394. CSSHelpers.removeClass(hiddenNodes[i], 'cssSandpaper-initiallyHidden');
  395. }
  396. }
  397. }
  398. function RuleList(propertyName){
  399. var me = this;
  400. me.values = new Array();
  401. me.propertyName = propertyName;
  402. me.add = function(selector, value){
  403. me.values.push(new CSSRule(selector, me.propertyName, value));
  404. }
  405. }
  406. function CSSRule(selector, name, value){
  407. var me = this;
  408. me.selector = selector;
  409. me.name = name;
  410. me.value = value;
  411. me.toString = function(){
  412. return StringHelpers.sprintf("%s { %s: %s}", me.selector, me.name, me.value);
  413. }
  414. }
  415. var MatrixGenerator = new function(){
  416. var me = this;
  417. var reUnit = /[a-z]+$/;
  418. me.identity = $M([[1, 0, 0], [0, 1, 0], [0, 0, 1]]);
  419. function degreesToRadians(degrees){
  420. return (degrees - 360) * Math.PI / 180;
  421. }
  422. function getRadianScalar(angleStr){
  423. var num = parseFloat(angleStr);
  424. var unit = angleStr.match(reUnit);
  425. if (angleStr.trim() == '0') {
  426. num = 0;
  427. unit = 'rad';
  428. }
  429. if (unit.length != 1 || num == 0) {
  430. return 0;
  431. }
  432. unit = unit[0];
  433. var rad;
  434. switch (unit) {
  435. case "deg":
  436. rad = degreesToRadians(num);
  437. break;
  438. case "rad":
  439. rad = num;
  440. break;
  441. default:
  442. throw "Not an angle: " + angleStr;
  443. }
  444. return rad;
  445. }
  446. me.prettyPrint = function(m){
  447. return StringHelpers.sprintf('| %s %s %s | - | %s %s %s | - |%s %s %s|', m.e(1, 1), m.e(1, 2), m.e(1, 3), m.e(2, 1), m.e(2, 2), m.e(2, 3), m.e(3, 1), m.e(3, 2), m.e(3, 3))
  448. }
  449. me.rotate = function(angleStr){
  450. var num = getRadianScalar(angleStr);
  451. return Matrix.RotationZ(num);
  452. }
  453. me.scale = function(sx, sy){
  454. sx = parseFloat(sx)
  455. if (!sy) {
  456. sy = sx;
  457. } else {
  458. sy = parseFloat(sy)
  459. }
  460. return $M([[sx, 0, 0], [0, sy, 0], [0, 0, 1]]);
  461. }
  462. me.scaleX = function(sx){
  463. return me.scale(sx, 1);
  464. }
  465. me.scaleY = function(sy){
  466. return me.scale(1, sy);
  467. }
  468. me.skew = function(ax, ay){
  469. var xRad = getRadianScalar(ax);
  470. var yRad;
  471. if (ay != null) {
  472. yRad = getRadianScalar(ay)
  473. } else {
  474. yRad = xRad
  475. }
  476. if (xRad != null && yRad != null) {
  477. return $M([[1, Math.tan(xRad), 0], [Math.tan(yRad), 1, 0], [0, 0, 1]]);
  478. } else {
  479. return null;
  480. }
  481. }
  482. me.skewX = function(ax){
  483. return me.skew(ax, "0");
  484. }
  485. me.skewY = function(ay){
  486. return me.skew("0", ay);
  487. }
  488. me.translate = function(tx, ty){
  489. var TX = parseInt(tx);
  490. var TY = parseInt(ty)
  491. //jslog.debug(StringHelpers.sprintf('translate %f %f', TX, TY));
  492. return $M([[1, 0, TX], [0, 1, TY], [0, 0, 1]]);
  493. }
  494. me.translateX = function(tx){
  495. return me.translate(tx, 0);
  496. }
  497. me.translateY = function(ty){
  498. return me.translate(0, ty);
  499. }
  500. me.matrix = function(a, b, c, d, e, f){
  501. // for now, e and f are ignored
  502. return $M([[a, c, parseInt(e)], [b, d, parseInt(f)], [0, 0, 1]])
  503. }
  504. }
  505. var CSS3Helpers = new function(){
  506. var me = this;
  507. var reTransformListSplitter = /[a-zA-Z]+\([^\)]*\)\s*/g;
  508. var reLeftBracket = /\(/g;
  509. var reRightBracket = /\)/g;
  510. var reComma = /,/g;
  511. var reSpaces = /\s+/g
  512. var reFilterNameSplitter = /progid:([^\(]*)/g;
  513. var reLinearGradient
  514. var canvas;
  515. var cache = new Array();
  516. me.supports = function(cssProperty){
  517. if (CSS3Helpers.findProperty(document.body, cssProperty) != null) {
  518. return true;
  519. } else {
  520. return false;
  521. }
  522. }
  523. me.getCanvas = function(){
  524. if (canvas) {
  525. return canvas;
  526. } else {
  527. canvas = document.createElement('canvas');
  528. return canvas;
  529. }
  530. }
  531. me.getTransformationMatrix = function(CSS3TransformProperty, doThrowIfError){
  532. var transforms = CSS3TransformProperty.match(reTransformListSplitter);
  533. /*
  534. * Do a check here to see if there is anything in the transformation
  535. * besides legit transforms
  536. */
  537. if (doThrowIfError) {
  538. var checkString = transforms.join(" ").replace(/\s*/g, ' ');
  539. var normalizedCSSProp = CSS3TransformProperty.replace(/\s*/g, ' ');
  540. if (checkString != normalizedCSSProp) {
  541. throw ("An invalid transform was given.")
  542. }
  543. }
  544. var resultantMatrix = MatrixGenerator.identity;
  545. for (var j = 0; j < transforms.length; j++) {
  546. var transform = transforms[j];
  547. transform = transform.replace(reLeftBracket, '("').replace(reComma, '", "').replace(reRightBracket, '")');
  548. try {
  549. var matrix = eval('MatrixGenerator.' + transform);
  550. //jslog.debug( transform + ': ' + MatrixGenerator.prettyPrint(matrix))
  551. resultantMatrix = resultantMatrix.x(matrix);
  552. }
  553. catch (ex) {
  554. if (doThrowIfError) {
  555. var method = transform.split('(')[0];
  556. var funcCall = transform.replace(/\"/g, '');
  557. if (MatrixGenerator[method] == undefined) {
  558. throw "Error: invalid tranform function: " + funcCall;
  559. } else {
  560. throw "Error: Invalid or missing parameters in function call: " + funcCall;
  561. }
  562. }
  563. // do nothing;
  564. }
  565. }
  566. return resultantMatrix;
  567. }
  568. me.getBoxShadowValues = function(propertyValue){
  569. var r = new Object();
  570. var values = propertyValue.split(reSpaces);
  571. if (values[0] == 'inset') {
  572. r.inset = true;
  573. values = values.reverse().pop().reverse();
  574. } else {
  575. r.inset = false;
  576. }
  577. r.offsetX = parseInt(values[0]);
  578. r.offsetY = parseInt(values[1]);
  579. if (values.length > 3) {
  580. r.blurRadius = values[2];
  581. if (values.length > 4) {
  582. r.spreadRadius = values[3]
  583. }
  584. }
  585. r.color = values[values.length - 1];
  586. return r;
  587. }
  588. me.getGradient = function(propertyValue){
  589. var r = new Object();
  590. r.colorStops = new Array();
  591. var substring = me.getBracketedSubstring(propertyValue, '-sand-gradient');
  592. if (substring == undefined) {
  593. return null;
  594. }
  595. var parameters = substring.match(/[^\(,]+(\([^\)]*\))?[^,]*/g); //substring.split(reComma);
  596. r.type = parameters[0].trim();
  597. if (r.type == 'linear') {
  598. r.dirBegin = parameters[1].trim();
  599. r.dirEnd = parameters[2].trim();
  600. var beginCoord = r.dirBegin.split(reSpaces);
  601. var endCoord = r.dirEnd.split(reSpaces);
  602. for (var i = 3; i < parameters.length; i++) {
  603. r.colorStops.push(parseColorStop(parameters[i].trim(), i - 3));
  604. }
  605. /* The following logic only applies to IE */
  606. if (document.body.filters) {
  607. if (r.x0 == r.x1) {
  608. /* IE only supports "center top", "center bottom", "top left" and "top right" */
  609. switch (beginCoord[1]) {
  610. case 'top':
  611. r.IEdir = 0;
  612. break;
  613. case 'bottom':
  614. swapIndices(r.colorStops, 0, 1);
  615. r.IEdir = 0;
  616. /* r.from = parameters[4].trim();
  617. r.to = parameters[3].trim(); */
  618. break;
  619. }
  620. }
  621. if (r.y0 == r.y1) {
  622. switch (beginCoord[0]) {
  623. case 'left':
  624. r.IEdir = 1;
  625. break;
  626. case 'right':
  627. r.IEdir = 1;
  628. swapIndices(r.colorStops, 0, 1);
  629. break;
  630. }
  631. }
  632. }
  633. } else {
  634. // don't even bother with IE
  635. if (document.body.filters) {
  636. return null;
  637. }
  638. r.dirBegin = parameters[1].trim();
  639. r.r0 = parameters[2].trim();
  640. r.dirEnd = parameters[3].trim();
  641. r.r1 = parameters[4].trim();
  642. var beginCoord = r.dirBegin.split(reSpaces);
  643. var endCoord = r.dirEnd.split(reSpaces);
  644. for (var i = 5; i < parameters.length; i++) {
  645. r.colorStops.push(parseColorStop(parameters[i].trim(), i - 5));
  646. }
  647. }
  648. r.x0 = beginCoord[0];
  649. r.y0 = beginCoord[1];
  650. r.x1 = endCoord[0];
  651. r.y1 = endCoord[1];
  652. return r;
  653. }
  654. function swapIndices(array, index1, index2){
  655. var tmp = array[index1];
  656. array[index1] = array[index2];
  657. array[index2] = tmp;
  658. }
  659. function parseColorStop(colorStop, index){
  660. var r = new Object();
  661. var substring = me.getBracketedSubstring(colorStop, 'color-stop');
  662. var from = me.getBracketedSubstring(colorStop, 'from');
  663. var to = me.getBracketedSubstring(colorStop, 'to');
  664. if (substring) {
  665. //color-stop
  666. var parameters = substring.split(',')
  667. r.stop = normalizePercentage(parameters[0].trim());
  668. r.color = parameters[1].trim();
  669. } else if (from) {
  670. r.stop = 0.0;
  671. r.color = from.trim();
  672. } else if (to) {
  673. r.stop = 1.0;
  674. r.color = to.trim();
  675. } else {
  676. if (index <= 1) {
  677. r.color = colorStop;
  678. if (index == 0) {
  679. r.stop = 0.0;
  680. } else {
  681. r.stop = 1.0;
  682. }
  683. } else {
  684. throw (StringHelpers.sprintf('invalid argument "%s"', colorStop));
  685. }
  686. }
  687. return r;
  688. }
  689. function normalizePercentage(s){
  690. if (s.substring(s.length - 1, s.length) == '%') {
  691. return parseFloat(s) / 100 + "";
  692. } else {
  693. return s;
  694. }
  695. }
  696. me.reportGradientSupport = function(){
  697. if (!cache["gradientSupport"]) {
  698. var r;
  699. var div = document.createElement('div');
  700. div.style.cssText = "background-image:-webkit-gradient(linear, 0% 0%, 0% 100%, from(red), to(blue));";
  701. if (div.style.backgroundImage) {
  702. r = implementation.WEBKIT;
  703. } else {
  704. /* div.style.cssText = "background-image:-moz-linear-gradient(top, blue, white 80%, orange);";
  705. if (div.style.backgroundImage) {
  706. r = implementation.MOZILLA;
  707. } else { */
  708. var canvas = CSS3Helpers.getCanvas();
  709. if (canvas.getContext && canvas.toDataURL) {
  710. r = implementation.CANVAS_WORKAROUND;
  711. } else {
  712. r = implementation.NONE;
  713. }
  714. /* } */
  715. }
  716. cache["gradientSupport"] = r;
  717. }
  718. return cache["gradientSupport"];
  719. }
  720. me.reportColorSpaceSupport = function(colorSpace, type){
  721. if (!cache[colorSpace + type]) {
  722. var r;
  723. var div = document.createElement('div');
  724. switch (type) {
  725. case colorType.BACKGROUND:
  726. switch(colorSpace) {
  727. case 'RGBA':
  728. div.style.cssText = "background-color: rgba(255, 32, 34, 0.5)";
  729. break;
  730. case 'HSL':
  731. div.style.cssText = "background-color: hsl(0,0%,100%)";
  732. break;
  733. case 'HSLA':
  734. div.style.cssText = "background-color: hsla(0,0%,100%,.5)";
  735. break;
  736. default:
  737. break;
  738. }
  739. var body = document.body;
  740. if (div.style.backgroundColor) {
  741. r = implementation.NATIVE;
  742. } else if (body.filters && body.filters != undefined) {
  743. r = implementation.FILTER_WORKAROUND;
  744. } else {
  745. r = implementation.NONE;
  746. }
  747. break;
  748. case colorType.FOREGROUND:
  749. switch(colorSpace) {
  750. case 'RGBA':
  751. div.style.cssText = "color: rgba(255, 32, 34, 0.5)";
  752. break;
  753. case 'HSL':
  754. div.style.cssText = "color: hsl(0,0%,100%)";
  755. break;
  756. case 'HSLA':
  757. div.style.cssText = "color: hsla(0,0%,100%,.5)";
  758. break;
  759. default:
  760. break;
  761. }
  762. if (div.style.color) {
  763. r = implementation.NATIVE;
  764. } else if (colorSpace == 'HSL') {
  765. r = implementation.HEX_WORKAROUND;
  766. } else {
  767. r = implementation.NONE;
  768. }
  769. break
  770. }
  771. cache[colorSpace] = r;
  772. }
  773. return cache[colorSpace];
  774. }
  775. me.getBracketedSubstring = function(s, header){
  776. var gradientIndex = s.indexOf(header + '(')
  777. if (gradientIndex != -1) {
  778. var substring = s.substring(gradientIndex);
  779. var openBrackets = 1;
  780. for (var i = header.length + 1; i < 100 || i < substring.length; i++) {
  781. var c = substring.substring(i, i + 1);
  782. switch (c) {
  783. case "(":
  784. openBrackets++;
  785. break;
  786. case ")":
  787. openBrackets--;
  788. break;
  789. }
  790. if (openBrackets == 0) {
  791. break;
  792. }
  793. }
  794. return substring.substring(gradientIndex + header.length + 1, i);
  795. }
  796. }
  797. me.setMatrixFilter = function(obj, matrix){
  798. if (!hasIETransformWorkaround(obj)) {
  799. addIETransformWorkaround(obj)
  800. }
  801. var container = obj.parentNode;
  802. //container.xTransform = degrees;
  803. filter = obj.filters.item('DXImageTransform.Microsoft.Matrix');
  804. //jslog.debug(MatrixGenerator.prettyPrint(matrix))
  805. filter.M11 = matrix.e(1, 1);
  806. filter.M12 = matrix.e(1, 2);
  807. filter.M21 = matrix.e(2, 1);
  808. filter.M22 = matrix.e(2, 2);
  809. // Now, adjust the margins of the parent object
  810. var offsets = me.getIEMatrixOffsets(obj, matrix, container.xOriginalWidth, container.xOriginalHeight);
  811. container.style.marginLeft = offsets.x;
  812. container.style.marginTop = offsets.y;
  813. container.style.marginRight = 0;
  814. container.style.marginBottom = 0;
  815. }
  816. me.getTransformedDimensions = function (obj, matrix) {
  817. var r = {};
  818. if (hasIETransformWorkaround(obj)) {
  819. r.width = obj.offsetWidth;
  820. r.height = obj.offsetHeight;
  821. } else {
  822. var pts = [
  823. matrix.x($V([0, 0, 1])) ,
  824. matrix.x($V([0, obj.offsetHeight, 1])),
  825. matrix.x($V([obj.offsetWidth, 0, 1])),
  826. matrix.x($V([obj.offsetWidth, obj.offsetHeight, 1]))
  827. ];
  828. var maxX = 0, maxY =0, minX=0, minY=0;
  829. for (var i = 0; i < pts.length; i++) {
  830. var pt = pts[i];
  831. var x = pt.e(1), y = pt.e(2);
  832. var minX = Math.min(minX, x);
  833. var maxX = Math.max(maxX, x);
  834. var minY = Math.min(minY, y);
  835. var maxY = Math.max(maxY, y);
  836. }
  837. r.width = maxX - minX;
  838. r.height = maxY - minY;
  839. }
  840. return r;
  841. }
  842. me.getIEMatrixOffsets = function (obj, matrix, width, height) {
  843. var r = {};
  844. var originalWidth = parseFloat(width);
  845. var originalHeight = parseFloat(height);
  846. var offset;
  847. if (CSSHelpers.getComputedStyle(obj, 'display') == 'inline') {
  848. offset = 0;
  849. } else {
  850. offset = 13; // This works ... don't know why.
  851. }
  852. var transformedDimensions = me.getTransformedDimensions(obj, matrix);
  853. r.x = (((originalWidth - transformedDimensions.width) / 2) - offset + matrix.e(1, 3)) + 'px';
  854. r.y = (((originalHeight - transformedDimensions.height) / 2) - offset + matrix.e(2, 3)) + 'px';
  855. return r;
  856. }
  857. function hasIETransformWorkaround(obj){
  858. return CSSHelpers.isMemberOfClass(obj.parentNode, 'IETransformContainer');
  859. }
  860. function addIETransformWorkaround(obj){
  861. if (!hasIETransformWorkaround(obj)) {
  862. var parentNode = obj.parentNode;
  863. var filter;
  864. // This is the container to offset the strange rotation behavior
  865. var container = document.createElement('div');
  866. CSSHelpers.addClass(container, 'IETransformContainer');
  867. container.style.width = obj.offsetWidth + 'px';
  868. container.style.height = obj.offsetHeight + 'px';
  869. container.xOriginalWidth = obj.offsetWidth;
  870. container.xOriginalHeight = obj.offsetHeight;
  871. container.style.position = 'absolute'
  872. container.style.zIndex = obj.currentStyle.zIndex;
  873. var horizPaddingFactor = 0; //parseInt(obj.currentStyle.paddingLeft);
  874. var vertPaddingFactor = 0; //parseInt(obj.currentStyle.paddingTop);
  875. if (obj.currentStyle.display == 'block') {
  876. container.style.left = obj.offsetLeft + 13 - horizPaddingFactor + "px";
  877. container.style.top = obj.offsetTop + 13 + -vertPaddingFactor + 'px';
  878. } else {
  879. container.style.left = obj.offsetLeft + "px";
  880. container.style.top = obj.offsetTop + 'px';
  881. }
  882. //container.style.float = obj.currentStyle.float;
  883. obj.style.top = "auto";
  884. obj.style.left = "auto"
  885. obj.style.bottom = "auto";
  886. obj.style.right = "auto";
  887. // This is what we need in order to insert to keep the document
  888. // flow ok
  889. var replacement = obj.cloneNode(true);
  890. replacement.style.visibility = 'hidden';
  891. obj.replaceNode(replacement);
  892. // now, wrap container around the original node ...
  893. obj.style.position = 'absolute';
  894. container.appendChild(obj);
  895. parentNode.insertBefore(container, replacement);
  896. container.style.backgroundColor = 'transparent';
  897. container.style.padding = '0';
  898. filter = me.addFilter(obj, 'DXImageTransform.Microsoft.Matrix', "M11=1, M12=0, M21=0, M22=1, sizingMethod='auto expand'")
  899. var bgImage = obj.currentStyle.backgroundImage.split("\"")[1];
  900. /*
  901. if (bgImage) {
  902. var alphaFilter = me.addFilter(obj, "DXImageTransform.Microsoft.AlphaImageLoader", "src='" + bgImage + "', sizingMethod='scale'");
  903. alert(bgImage)
  904. alphaFilter.src = bgImage;
  905. sizingMethod = 'scale';
  906. obj.style.background = 'none';
  907. obj.style.backgroundImage = 'none';
  908. }
  909. */
  910. }
  911. }
  912. me.addFilter = function(obj, filterName, filterValue){
  913. // now ... insert the filter so we can exploit its wonders
  914. var filter;
  915. try {
  916. filter = obj.filters.item(filterName);
  917. }
  918. catch (ex) {
  919. // dang! We have to go through all of them and make sure filter
  920. // is set right before we add the new one.
  921. var filterList = new MSFilterList(obj)
  922. filterList.fixFilterStyle();
  923. var comma = ", ";
  924. if (obj.filters.length == 0) {
  925. comma = "";
  926. }
  927. obj.style.filter += StringHelpers.sprintf("%sprogid:%s(%s)", comma, filterName, filterValue);
  928. filter = obj.filters.item(filterName);
  929. }
  930. return filter;
  931. }
  932. function degreesToRadians(degrees){
  933. return (degrees - 360) * Math.PI / 180;
  934. }
  935. me.findProperty = function(obj, type){
  936. capType = type.capitalize();
  937. var r = cache[type]
  938. if (!r) {
  939. var style = obj.style;
  940. var properties = [type, 'Moz' + capType, 'Webkit' + capType, 'O' + capType, 'filter'];
  941. for (var i = 0; i < properties.length; i++) {
  942. if (style[properties[i]] != null) {
  943. r = properties[i];
  944. break;
  945. }
  946. }
  947. if (r == 'filter' && document.body.filters == undefined) {
  948. r = null;
  949. }
  950. cache[type] = r;
  951. }
  952. return r;
  953. }
  954. /*
  955. * "A point is a pair of space-separated values. The syntax supports numbers,
  956. * percentages or the keywords top, bottom, left and right for point values."
  957. * This keywords and percentages into pixel equivalents
  958. */
  959. me.parseCoordinate = function(value, max){
  960. //Convert keywords
  961. switch (value) {
  962. case 'top':
  963. case 'left':
  964. return 0;
  965. case 'bottom':
  966. case 'right':
  967. return max;
  968. case 'center':
  969. return max / 2;
  970. }
  971. //Convert percentage
  972. if (value.indexOf('%') != -1)
  973. value = parseFloat(value.substr(0, value.length - 1)) / 100 * max;
  974. //Convert bare number (a pixel value)
  975. else
  976. value = parseFloat(value);
  977. if (isNaN(value))
  978. throw Error("Unable to parse coordinate: " + value);
  979. return value;
  980. }
  981. me.applyCanvasGradient = function(el, gradient){
  982. var canvas = me.getCanvas();
  983. var computedStyle = document.defaultView.getComputedStyle(el, null);
  984. canvas.width = parseInt(computedStyle.width) + parseInt(computedStyle.paddingLeft) + parseInt(computedStyle.paddingRight) + 1; // inserted by Zoltan
  985. canvas.height = parseInt(computedStyle.height) + parseInt(computedStyle.paddingTop) + parseInt(computedStyle.paddingBottom) + 2; // 1 inserted by Zoltan
  986. var ctx = canvas.getContext('2d');
  987. //Iterate over the gradients and build them up
  988. var canvasGradient;
  989. // Linear gradient
  990. if (gradient.type == 'linear') {
  991. canvasGradient = ctx.createLinearGradient(me.parseCoordinate(gradient.x0, canvas.width), me.parseCoordinate(gradient.y0, canvas.height), me.parseCoordinate(gradient.x1, canvas.width), me.parseCoordinate(gradient.y1, canvas.height));
  992. } // Radial gradient
  993. else /*if(gradient.type == 'radial')*/ {
  994. canvasGradient = ctx.createRadialGradient(me.parseCoordinate(gradient.x0, canvas.width), me.parseCoordinate(gradient.y0, canvas.height), gradient.r0, me.parseCoordinate(gradient.x1, canvas.width), me.parseCoordinate(gradient.y1, canvas.height), gradient.r1);
  995. }
  996. //Add each of the color stops to the gradient
  997. for (var i = 0; i < gradient.colorStops.length; i++) {
  998. var cs = gradient.colorStops[i];
  999. canvasGradient.addColorStop(cs.stop, cs.color);
  1000. };
  1001. //Paint the gradient
  1002. ctx.fillStyle = canvasGradient;
  1003. ctx.fillRect(0, 0, canvas.width, canvas.height);
  1004. //Apply the gradient to the selectedElement
  1005. el.style.backgroundImage = "url('" + canvas.toDataURL() + "')";
  1006. }
  1007. }
  1008. function MSFilterList(node){
  1009. var me = this;
  1010. me.list = new Array();
  1011. me.node = node;
  1012. var reFilterListSplitter = /[\s\S]*\([\s\S]*\)/g;
  1013. var styleAttr = node.style;
  1014. function init(){
  1015. var filterCalls = styleAttr.filter.match(reFilterListSplitter);
  1016. if (filterCalls != null) {
  1017. for (var i = 0; i < filterCalls.length; i++) {
  1018. var call = filterCalls[i];
  1019. me.list.push(new MSFilter(node, call));
  1020. }
  1021. }
  1022. }
  1023. me.toString = function(){
  1024. var sb = new StringBuffer();
  1025. for (var i = 0; i < me.list.length; i++) {
  1026. sb.append(me.list[i].toString());
  1027. if (i < me.list.length - 1) {
  1028. sb.append(',')
  1029. }
  1030. }
  1031. return sb.toString();
  1032. }
  1033. me.fixFilterStyle = function(){
  1034. try {
  1035. me.node.style.filter = me.toString();
  1036. }
  1037. catch (ex) {
  1038. // do nothing.
  1039. }
  1040. }
  1041. init();
  1042. }
  1043. function MSFilter(node, filterCall){
  1044. var me = this;
  1045. me.node = node;
  1046. me.filterCall = filterCall;
  1047. var reFilterNameSplitter = /progid:([^\(]*)/g;
  1048. var reParameterName = /([a-zA-Z0-9]+\s*)=/g;
  1049. function init(){
  1050. me.name = me.filterCall.match(reFilterNameSplitter)[0].replace('progid:', '');
  1051. //This may not be the best way to do this.
  1052. var parameterString = filterCall.split('(')[1].replace(')', '');
  1053. me.parameters = parameterString.match(reParameterName);
  1054. for (var i = 0; i < me.parameters.length; i++) {
  1055. me.parameters[i] = me.parameters[i].replace('=', '');
  1056. }
  1057. }
  1058. me.toString = function(){
  1059. var sb = new StringBuffer();
  1060. sb.append(StringHelpers.sprintf('progid:%s(', me.name));
  1061. for (var i = 0; i < me.parameters.length; i++) {
  1062. var param = me.parameters[i];
  1063. var filterObj = me.node.filters.item(me.name);
  1064. var paramValue = filterObj[param];
  1065. if (typeof(paramValue) == 'string') {
  1066. sb.append(StringHelpers.sprintf('%s="%s"', param, filterObj[param]));
  1067. } else {
  1068. sb.append(StringHelpers.sprintf('%s=%s', param, filterObj[param]));
  1069. }
  1070. if (i != me.parameters.length - 1) {
  1071. sb.append(', ')
  1072. }
  1073. }
  1074. sb.append(')');
  1075. return sb.toString();
  1076. }
  1077. init();
  1078. }
  1079. var implementation = new function(){
  1080. this.NONE = 0;
  1081. // Native Support.
  1082. this.NATIVE = 1;
  1083. // Vendor specific prefix implementations
  1084. this.MOZILLA = 2;
  1085. this.WEBKIT = 3;
  1086. this.IE = 4;
  1087. this.OPERA = 5;
  1088. // Non CSS3 Workarounds
  1089. this.CANVAS_WORKAROUND = 6;
  1090. this.FILTER_WORKAROUND = 7;
  1091. this.HEX_WORKAROUND = 8;
  1092. }
  1093. var colorType = new function () {
  1094. this.BACKGROUND = 0;
  1095. this.FOREGROUND = 1;
  1096. }
  1097. /*
  1098. * Extra helper routines
  1099. */
  1100. if (!window.StringHelpers) {
  1101. StringHelpers = new function(){
  1102. var me = this;
  1103. // used by the String.prototype.trim()
  1104. me.initWhitespaceRe = /^\s\s*/;
  1105. me.endWhitespaceRe = /\s\s*$/;
  1106. me.whitespaceRe = /\s/;
  1107. /*******************************************************************************
  1108. * Function sprintf(format_string,arguments...) Javascript emulation of the C
  1109. * printf function (modifiers and argument types "p" and "n" are not supported
  1110. * due to language restrictions)
  1111. *
  1112. * Copyright 2003 K&L Productions. All rights reserved
  1113. * http://www.klproductions.com
  1114. *
  1115. * Terms of use: This function can be used free of charge IF this header is not
  1116. * modified and remains with the function code.
  1117. *
  1118. * Legal: Use this code at your own risk. K&L Productions assumes NO
  1119. * resposibility for anything.
  1120. ******************************************************************************/
  1121. me.sprintf = function(fstring){
  1122. var pad = function(str, ch, len){
  1123. var ps = '';
  1124. for (var i = 0; i < Math.abs(len); i++)
  1125. ps += ch;
  1126. return len > 0 ? str + ps : ps + str;
  1127. }
  1128. var processFlags = function(flags, width, rs, arg){
  1129. var pn = function(flags, arg, rs){
  1130. if (arg >= 0) {
  1131. if (flags.indexOf(' ') >= 0)
  1132. rs = ' ' + rs;
  1133. else if (flags.indexOf('+') >= 0)
  1134. rs = '+' + rs;
  1135. } else
  1136. rs = '-' + rs;
  1137. return rs;
  1138. }
  1139. var iWidth = parseInt(width, 10);
  1140. if (width.charAt(0) == '0') {
  1141. var ec = 0;
  1142. if (flags.indexOf(' ') >= 0 || flags.indexOf('+') >= 0)
  1143. ec++;
  1144. if (rs.length < (iWidth - ec))
  1145. rs = pad(rs, '0', rs.length - (iWidth - ec));
  1146. return pn(flags, arg, rs);
  1147. }
  1148. rs = pn(flags, arg, rs);
  1149. if (rs.length < iWidth) {
  1150. if (flags.indexOf('-') < 0)
  1151. rs = pad(rs, ' ', rs.length - iWidth);
  1152. else
  1153. rs = pad(rs, ' ', iWidth - rs.length);
  1154. }
  1155. return rs;
  1156. }
  1157. var converters = new Array();
  1158. converters['c'] = function(flags, width, precision, arg){
  1159. if (typeof(arg) == 'number')
  1160. return String.fromCharCode(arg);
  1161. if (typeof(arg) == 'string')
  1162. return arg.charAt(0);
  1163. return '';
  1164. }
  1165. converters['d'] = function(flags, width, precision, arg){
  1166. return converters['i'](flags, width, precision, arg);
  1167. }
  1168. converters['u'] = function(flags, width, precision, arg){
  1169. return converters['i'](flags, width, precision, Math.abs(arg));
  1170. }
  1171. converters['i'] = function(flags, width, precision, arg){
  1172. var iPrecision = parseInt(precision);
  1173. var rs = ((Math.abs(arg)).toString().split('.'))[0];
  1174. if (rs.length < iPrecision)
  1175. rs = pad(rs, ' ', iPrecision - rs.length);
  1176. return processFlags(flags, width, rs, arg);
  1177. }
  1178. converters['E'] = function(flags, width, precision, arg){
  1179. return (converters['e'](flags, width, precision, arg)).toUpperCase();
  1180. }
  1181. converters['e'] = function(flags, width, precision, arg){
  1182. iPrecision = parseInt(precision);
  1183. if (isNaN(iPrecision))
  1184. iPrecision = 6;
  1185. rs = (Math.abs(arg)).toExponential(iPrecision);
  1186. if (rs.indexOf('.') < 0 && flags.indexOf('#') >= 0)
  1187. rs = rs.replace(/^(.*)(e.*)$/, '$1.$2');
  1188. return processFlags(flags, width, rs, arg);
  1189. }
  1190. converters['f'] = function(flags, width, precision, arg){
  1191. iPrecision = parseInt(precision);
  1192. if (isNaN(iPrecision))
  1193. iPrecision = 6;
  1194. rs = (Math.abs(arg)).toFixed(iPrecision);
  1195. if (rs.indexOf('.') < 0 && flags.indexOf('#') >= 0)
  1196. rs = rs + '.';
  1197. return processFlags(flags, width, rs, arg);
  1198. }
  1199. converters['G'] = function(flags, width, precision, arg){
  1200. return (converters['g'](flags, width, precision, arg)).toUpperCase();
  1201. }
  1202. converters['g'] = function(flags, width, precision, arg){
  1203. iPrecision = parseInt(precision);
  1204. absArg = Math.abs(arg);
  1205. rse = absArg.toExponential();
  1206. rsf = absArg.toFixed(6);
  1207. if (!isNaN(iPrecision)) {
  1208. rsep = absArg.toExponential(iPrecision);
  1209. rse = rsep.length < rse.length ? rsep : rse;
  1210. rsfp = absArg.toFixed(iPrecision);
  1211. rsf = rsfp.length < rsf.length ? rsfp : rsf;
  1212. }
  1213. if (rse.indexOf('.') < 0 && flags.indexOf('#') >= 0)
  1214. rse = rse.replace(/^(.*)(e.*)$/, '$1.$2');
  1215. if (rsf.indexOf('.') < 0 && flags.indexOf('#') >= 0)
  1216. rsf = rsf + '.';
  1217. rs = rse.length < rsf.length ? rse : rsf;
  1218. return processFlags(flags, width, rs, arg);
  1219. }
  1220. converters['o'] = function(flags, width, precision, arg){
  1221. var iPrecision = parseInt(precision);
  1222. var rs = Math.round(Math.abs(arg)).toString(8);
  1223. if (rs.length < iPrecision)
  1224. rs = pad(rs, ' ', iPrecision - rs.length);
  1225. if (flags.indexOf('#') >= 0)
  1226. rs = '0' + rs;
  1227. return processFlags(flags, width, rs, arg);
  1228. }
  1229. converters['X'] = function(flags, width, precision, arg){
  1230. return (converters['x'](flags, width, precision, arg)).toUpperCase();
  1231. }
  1232. converters['x'] = function(flags, width, precision, arg){
  1233. var iPrecision = parseInt(precision);
  1234. arg = Math.abs(arg);
  1235. var rs = Math.round(arg).toString(16);
  1236. if (rs.length < iPrecision)
  1237. rs = pad(rs, ' ', iPrecision - rs.length);
  1238. if (flags.indexOf('#') >= 0)
  1239. rs = '0x' + rs;
  1240. return processFlags(flags, width, rs, arg);
  1241. }
  1242. converters['s'] = function(flags, width, precision, arg){
  1243. var iPrecision = parseInt(precision);
  1244. var rs = arg;
  1245. if (rs.length > iPrecision)
  1246. rs = rs.substring(0, iPrecision);
  1247. return processFlags(flags, width, rs, 0);
  1248. }
  1249. farr = fstring.split('%');
  1250. retstr = farr[0];
  1251. fpRE = /^([-+ #]*)(\d*)\.?(\d*)([cdieEfFgGosuxX])(.*)$/;
  1252. for (var i = 1; i < farr.length; i++) {
  1253. fps = fpRE.exec(farr[i]);
  1254. if (!fps)
  1255. continue;
  1256. if (arguments[i] != null)
  1257. retstr += converters[fps[4]](fps[1], fps[2], fps[3], arguments[i]);
  1258. retstr += fps[5];
  1259. }
  1260. return retstr;
  1261. }
  1262. /**
  1263. * Take out the first comment inside a block of HTML
  1264. *
  1265. * @param {String} s - an HTML block
  1266. * @return {String} s - the HTML block uncommented.
  1267. */
  1268. me.uncommentHTML = function(s){
  1269. if (s.indexOf('-->') != -1 && s.indexOf('<!--') != -1) {
  1270. return s.replace("<!--", "").replace("-->", "");
  1271. } else {
  1272. return s;
  1273. }
  1274. }
  1275. }
  1276. }
  1277. if (!window.XMLHelpers) {
  1278. XMLHelpers = new function(){
  1279. var me = this;
  1280. /**
  1281. * Wrapper for XMLHttpRequest Object. Grabbing data (XML and/or text) from a URL.
  1282. * Grabbing data from a URL. Input is one parameter, url. It returns a request
  1283. * object. Based on code from
  1284. * http://www.xml.com/pub/a/2005/02/09/xml-http-request.html. IE caching problem
  1285. * fix from Wikipedia article http://en.wikipedia.org/wiki/XMLHttpRequest
  1286. *
  1287. * @param {String} url - the URL to retrieve
  1288. * @param {Function} processReqChange - the function/method to call at key events of the URL retrieval.
  1289. * @param {String} method - (optional) "GET" or "POST" (default "GET")
  1290. * @param {String} data - (optional) the CGI data to pass. Default null.
  1291. * @param {boolean} isAsync - (optional) is this call asyncronous. Default true.
  1292. *
  1293. * @return {Object} a XML request object.
  1294. */
  1295. me.getXMLHttpRequest = function(url, processReqChange) //, method, data, isAsync)
  1296. {
  1297. var argv = me.getXMLHttpRequest.arguments;
  1298. var argc = me.getXMLHttpRequest.arguments.length;
  1299. var httpMethod = (argc > 2) ? argv[2] : 'GET';
  1300. var data = (argc > 3) ? argv[3] : "";
  1301. var isAsync = (argc > 4) ? argv[4] : true;
  1302. var req;
  1303. // branch for native XMLHttpRequest object
  1304. if (window.XMLHttpRequest) {
  1305. req = new XMLHttpRequest();
  1306. // branch for IE/Windows ActiveX version
  1307. } else if (window.ActiveXObject) {
  1308. try {
  1309. req = new ActiveXObject('Msxml2.XMLHTTP');
  1310. }
  1311. catch (ex) {
  1312. req = new ActiveXObject("Microsoft.XMLHTTP");
  1313. }
  1314. // the browser doesn't support XML HttpRequest. Return null;
  1315. } else {
  1316. return null;
  1317. }
  1318. if (isAsync) {
  1319. req.onreadystatechange = processReqChange;
  1320. }
  1321. if (httpMethod == "GET" && data != "") {
  1322. url += "?" + data;
  1323. }
  1324. req.open(httpMethod, url, isAsync);
  1325. //Fixes IE Caching problem
  1326. req.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
  1327. req.send(data);
  1328. return req;
  1329. }
  1330. }
  1331. }
  1332. if (!window.CSSHelpers) {
  1333. CSSHelpers = new function(){
  1334. var me = this;
  1335. var blankRe = new RegExp('\\s');
  1336. /*
  1337. * getComputedStyle: code from http://blog.stchur.com/2006/06/21/css-computed-style/
  1338. */
  1339. me.getComputedStyle = function(elem, style)
  1340. {
  1341. var computedStyle;
  1342. if (typeof elem.currentStyle != 'undefined')
  1343. { computedStyle = elem.currentStyle; }
  1344. else
  1345. { computedStyle = document.defaultView.getComputedStyle(elem, null); }
  1346. return computedStyle[style];
  1347. }
  1348. /**
  1349. * Determines if an HTML object is a member of a specific class.
  1350. * @param {Object} obj - an HTML object.
  1351. * @param {Object} className - the CSS class name.
  1352. */
  1353. me.isMemberOfClass = function(obj, className){
  1354. if (blankRe.test(className))
  1355. return false;
  1356. var re = new RegExp(getClassReString(className), "g");
  1357. return (re.test(obj.className));
  1358. }
  1359. /**
  1360. * Make an HTML object be a member of a certain class.
  1361. *
  1362. * @param {Object} obj - an HTML object
  1363. * @param {String} className - a CSS class name.
  1364. */
  1365. me.addClass = function(obj, className){
  1366. if (blankRe.test(className)) {
  1367. return;
  1368. }
  1369. // only add class if the object is not a member of it yet.
  1370. if (!me.isMemberOfClass(obj, className)) {
  1371. obj.className += " " + className;
  1372. }
  1373. }
  1374. /**
  1375. * Make an HTML object *not* be a member of a certain class.
  1376. *
  1377. * @param {Object} obj - an HTML object
  1378. * @param {Object} className - a CSS class name.
  1379. */
  1380. me.removeClass = function(obj, className){
  1381. if (blankRe.test(className)) {
  1382. return;
  1383. }
  1384. var re = new RegExp(getClassReString(className), "g");
  1385. var oldClassName = obj.className;
  1386. if (obj.className) {
  1387. obj.className = oldClassName.replace(re, '');
  1388. }
  1389. }
  1390. function getClassReString(className) {
  1391. return '\\s'+className+'\\s|^' + className + '\\s|\\s' + className + '$|' + '^' + className +'$';
  1392. }
  1393. /**
  1394. * Given an HTML element, find all child nodes of a specific class.
  1395. *
  1396. * With ideas from Jonathan Snook
  1397. * (http://snook.ca/archives/javascript/your_favourite_1/)
  1398. * Since this was presented within a post on this site, it is for the
  1399. * public domain according to the site's copyright statement.
  1400. *
  1401. * @param {Object} obj - an HTML element. If you want to search a whole document, set
  1402. * this to the document object.
  1403. * @param {String} className - the class name of the objects to return
  1404. * @return {Array} - the list of objects of class cls.
  1405. */
  1406. me.getElementsByClassName = function (obj, className)
  1407. {
  1408. if (obj.getElementsByClassName) {
  1409. return DOMHelpers.nodeListToArray(obj.getElementsByClassName(className))
  1410. }
  1411. else {
  1412. var a = [];
  1413. var re = new RegExp(getClassReString(className));
  1414. var els = DOMHelpers.getAllDescendants(obj);
  1415. for (var i = 0, j = els.length; i < j; i++) {
  1416. if (re.test(els[i].className)) {
  1417. a.push(els[i]);
  1418. }
  1419. }
  1420. return a;
  1421. }
  1422. }
  1423. /**
  1424. * Generates a regular expression string that can be used to detect a class name
  1425. * in a tag's class attribute. It is used by a few methods, so I
  1426. * centralized it.
  1427. *
  1428. * @param {String} className - a name of a CSS class.
  1429. */
  1430. function getClassReString(className){
  1431. return '\\s' + className + '\\s|^' + className + '\\s|\\s' + className + '$|' + '^' + className + '$';
  1432. }
  1433. }
  1434. }
  1435. /*
  1436. * Adding trim method to String Object. Ideas from
  1437. * http://www.faqts.com/knowledge_base/view.phtml/aid/1678/fid/1 and
  1438. * http://blog.stevenlevithan.com/archives/faster-trim-javascript
  1439. */
  1440. String.prototype.trim = function(){
  1441. var str = this;
  1442. // The first method is faster on long strings than the second and
  1443. // vice-versa.
  1444. if (this.length > 6000) {
  1445. str = this.replace(StringHelpers.initWhitespaceRe, '');
  1446. var i = str.length;
  1447. while (StringHelpers.whitespaceRe.test(str.charAt(--i)))
  1448. ;
  1449. return str.slice(0, i + 1);
  1450. } else {
  1451. return this.replace(StringHelpers.initWhitespaceRe, '').replace(StringHelpers.endWhitespaceRe, '');
  1452. }
  1453. };
  1454. if (!window.DOMHelpers) {
  1455. DOMHelpers = new function () {
  1456. var me = this;
  1457. /**
  1458. * Returns all children of an element. Needed if it is necessary to do
  1459. * the equivalent of getElementsByTagName('*') for IE5 for Windows.
  1460. *
  1461. * @param {Object} e - an HTML object.
  1462. */
  1463. me.getAllDescendants = function(obj) {
  1464. return obj.all ? obj.all : obj.getElementsByTagName('*');
  1465. }
  1466. /******
  1467. * Converts a DOM live node list to a static/dead array. Good when you don't
  1468. * want the thing you are iterating in a for loop changing as the DOM changes.
  1469. *
  1470. * @param {Object} nodeList - a node list (like one returned by document.getElementsByTagName)
  1471. * @return {Array} - an array of nodes.
  1472. *
  1473. *******/
  1474. me.nodeListToArray = function (nodeList)
  1475. {
  1476. var ary = [];
  1477. for(var i=0, len = nodeList.length; i < len; i++)
  1478. {
  1479. ary.push(nodeList[i]);
  1480. }
  1481. return ary;
  1482. }
  1483. }
  1484. }
  1485. //+ Jonas Raoni Soares Silva
  1486. //@ http://jsfromhell.com/string/capitalize [v1.0]
  1487. String.prototype.capitalize = function(){ //v1.0
  1488. return this.charAt(0).toUpperCase() + this.substr(1);
  1489. };
  1490. /*
  1491. * stringBuffer.js - ideas from
  1492. * http://www.multitask.com.au/people/dion/archives/000354.html
  1493. */
  1494. function StringBuffer(){
  1495. var me = this;
  1496. var buffer = [];
  1497. me.append = function(string){
  1498. buffer.push(string);
  1499. return me;
  1500. }
  1501. me.appendBuffer = function(bufferToAppend){
  1502. buffer = buffer.concat(bufferToAppend);
  1503. }
  1504. me.toString = function(){
  1505. return buffer.join("");
  1506. }
  1507. me.getLength = function(){
  1508. return buffer.length;
  1509. }
  1510. me.flush = function(){
  1511. buffer.length = 0;
  1512. }
  1513. }
  1514. /**
  1515. * A class to parse color values
  1516. * @author Stoyan Stefanov <sstoo@gmail.com> (with modifications)
  1517. * @link http://www.phpied.com/rgb-color-parser-in-javascript/
  1518. * @license Use it if you like it
  1519. */
  1520. function RGBColor(color_string){
  1521. var me = this;
  1522. me.ok = false;
  1523. // strip any leading #
  1524. if (color_string.charAt(0) == '#') { // remove # if any
  1525. color_string = color_string.substr(1, 6);
  1526. }
  1527. color_string = color_string.replace(/ /g, '');
  1528. color_string = color_string.toLowerCase();
  1529. // before getting into regexps, try simple matches
  1530. // and overwrite the input
  1531. var simple_colors = {
  1532. aliceblue: 'f0f8ff',
  1533. antiquewhite: 'faebd7',
  1534. aqua: '00ffff',
  1535. aquamarine: '7fffd4',
  1536. azure: 'f0ffff',
  1537. beige: 'f5f5dc',
  1538. bisque: 'ffe4c4',
  1539. black: '000000',
  1540. blanchedalmond: 'ffebcd',
  1541. blue: '0000ff',
  1542. blueviolet: '8a2be2',
  1543. brown: 'a52a2a',
  1544. burlywood: 'deb887',
  1545. cadetblue: '5f9ea0',
  1546. chartreuse: '7fff00',
  1547. chocolate: 'd2691e',
  1548. coral: 'ff7f50',
  1549. cornflowerblue: '6495ed',
  1550. cornsilk: 'fff8dc',
  1551. crimson: 'dc143c',
  1552. cyan: '00ffff',
  1553. darkblue: '00008b',
  1554. darkcyan: '008b8b',
  1555. darkgoldenrod: 'b8860b',
  1556. darkgray: 'a9a9a9',
  1557. darkgreen: '006400',
  1558. darkkhaki: 'bdb76b',
  1559. darkmagenta: '8b008b',
  1560. darkolivegreen: '556b2f',
  1561. darkorange: 'ff8c00',
  1562. darkorchid: '9932cc',
  1563. darkred: '8b0000',
  1564. darksalmon: 'e9967a',
  1565. darkseagreen: '8fbc8f',
  1566. darkslateblue: '483d8b',
  1567. darkslategray: '2f4f4f',
  1568. darkturquoise: '00ced1',
  1569. darkviolet: '9400d3',
  1570. deeppink: 'ff1493',
  1571. deepskyblue: '00bfff',
  1572. dimgray: '696969',
  1573. dodgerblue: '1e90ff',
  1574. feldspar: 'd19275',
  1575. firebrick: 'b22222',
  1576. floralwhite: 'fffaf0',
  1577. forestgreen: '228b22',
  1578. fuchsia: 'ff00ff',
  1579. gainsboro: 'dcdcdc',
  1580. ghostwhite: 'f8f8ff',
  1581. gold: 'ffd700',
  1582. goldenrod: 'daa520',
  1583. gray: '808080',
  1584. green: '008000',
  1585. greenyellow: 'adff2f',
  1586. honeydew: 'f0fff0',
  1587. hotpink: 'ff69b4',
  1588. indianred: 'cd5c5c',
  1589. indigo: '4b0082',
  1590. ivory: 'fffff0',
  1591. khaki: 'f0e68c',
  1592. lavender: 'e6e6fa',
  1593. lavenderblush: 'fff0f5',
  1594. lawngreen: '7cfc00',
  1595. lemonchiffon: 'fffacd',
  1596. lightblue: 'add8e6',
  1597. lightcoral: 'f08080',
  1598. lightcyan: 'e0ffff',
  1599. lightgoldenrodyellow: 'fafad2',
  1600. lightgrey: 'd3d3d3',
  1601. lightgreen: '90ee90',
  1602. lightpink: 'ffb6c1',
  1603. lightsalmon: 'ffa07a',
  1604. lightseagreen: '20b2aa',
  1605. lightskyblue: '87cefa',
  1606. lightslateblue: '8470ff',
  1607. lightslategray: '778899',
  1608. lightsteelblue: 'b0c4de',
  1609. lightyellow: 'ffffe0',
  1610. lime: '00ff00',
  1611. limegreen: '32cd32',
  1612. linen: 'faf0e6',
  1613. magenta: 'ff00ff',
  1614. maroon: '800000',
  1615. mediumaquamarine: '66cdaa',
  1616. mediumblue: '0000cd',
  1617. mediumorchid: 'ba55d3',
  1618. mediumpurple: '9370d8',
  1619. mediumseagreen: '3cb371',
  1620. mediumslateblue: '7b68ee',
  1621. mediumspringgreen: '00fa9a',
  1622. mediumturquoise: '48d1cc',
  1623. mediumvioletred: 'c71585',
  1624. midnightblue: '191970',
  1625. mintcream: 'f5fffa',
  1626. mistyrose: 'ffe4e1',
  1627. moccasin: 'ffe4b5',
  1628. navajowhite: 'ffdead',
  1629. navy: '000080',
  1630. oldlace: 'fdf5e6',
  1631. olive: '808000',
  1632. olivedrab: '6b8e23',
  1633. orange: 'ffa500',
  1634. orangered: 'ff4500',
  1635. orchid: 'da70d6',
  1636. palegoldenrod: 'eee8aa',
  1637. palegreen: '98fb98',
  1638. paleturquoise: 'afeeee',
  1639. palevioletred: 'd87093',
  1640. papayawhip: 'ffefd5',
  1641. peachpuff: 'ffdab9',
  1642. peru: 'cd853f',
  1643. pink: 'ffc0cb',
  1644. plum: 'dda0dd',
  1645. powderblue: 'b0e0e6',
  1646. purple: '800080',
  1647. red: 'ff0000',
  1648. rosybrown: 'bc8f8f',
  1649. royalblue: '4169e1',
  1650. saddlebrown: '8b4513',
  1651. salmon: 'fa8072',
  1652. sandybrown: 'f4a460',
  1653. seagreen: '2e8b57',
  1654. seashell: 'fff5ee',
  1655. sienna: 'a0522d',
  1656. silver: 'c0c0c0',
  1657. skyblue: '87ceeb',
  1658. slateblue: '6a5acd',
  1659. slategray: '708090',
  1660. snow: 'fffafa',
  1661. springgreen: '00ff7f',
  1662. steelblue: '4682b4',
  1663. tan: 'd2b48c',
  1664. teal: '008080',
  1665. metle: 'd8bfd8',
  1666. tomato: 'ff6347',
  1667. turquoise: '40e0d0',
  1668. violet: 'ee82ee',
  1669. violetred: 'd02090',
  1670. wheat: 'f5deb3',
  1671. white: 'ffffff',
  1672. whitesmoke: 'f5f5f5',
  1673. yellow: 'ffff00',
  1674. yellowgreen: '9acd32'
  1675. };
  1676. for (var key in simple_colors) {
  1677. if (color_string == key) {
  1678. color_string = simple_colors[key];
  1679. }
  1680. }
  1681. // emd of simple type-in colors
  1682. // array of color definition objects
  1683. var color_defs = [{
  1684. re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
  1685. example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
  1686. process: function(bits){
  1687. return [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3])];
  1688. }
  1689. }, {
  1690. re: /^(\w{2})(\w{2})(\w{2})$/,
  1691. example: ['#00ff00', '336699'],
  1692. process: function(bits){
  1693. return [parseInt(bits[1], 16), parseInt(bits[2], 16), parseInt(bits[3], 16)];
  1694. }
  1695. }, {
  1696. re: /^(\w{1})(\w{1})(\w{1})$/,
  1697. example: ['#fb0', 'f0f'],
  1698. process: function(bits){
  1699. return [parseInt(bits[1] + bits[1], 16), parseInt(bits[2] + bits[2], 16), parseInt(bits[3] + bits[3], 16)];
  1700. }
  1701. }, {
  1702. re: /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(0{0,1}\.\d{1,}|0\.{0,}0*|1\.{0,}0*)\)$/,
  1703. example: ['rgba(123, 234, 45, 22)', 'rgba(255, 234,245, 34)'],
  1704. process: function(bits){
  1705. return [parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]), parseFloat(bits[4])];
  1706. }
  1707. }, {
  1708. re: /^hsla\((\d{1,3}),\s*(\d{1,3}%),\s*(\d{1,3}%),\s*(0{0,1}\.\d{1,}|0\.{0,}0*|1\.{0,}0*)\)$/,
  1709. example: ['hsla(0,100%,50%,0.2)'],
  1710. process: function(bits){
  1711. var result = hsl2rgb(parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]), parseFloat(bits[4]));
  1712. return [result.r, result.g, result.b, parseFloat(bits[4])];
  1713. }
  1714. }, {
  1715. re: /^hsl\((\d{1,3}),\s*(\d{1,3}%),\s*(\d{1,3}%)\)$/,
  1716. example: ['hsl(0,100%,50%)'],
  1717. process: function(bits){
  1718. var result = hsl2rgb(parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]), 1);
  1719. return [result.r, result.g, result.b, 1];
  1720. }
  1721. }];
  1722. // search through the definitions to find a match
  1723. for (var i = 0; i < color_defs.length; i++) {
  1724. var re = color_defs[i].re;
  1725. var processor = color_defs[i].process;
  1726. var bits = re.exec(color_string);
  1727. if (bits) {
  1728. channels = processor(bits);
  1729. me.r = channels[0];
  1730. me.g = channels[1];
  1731. me.b = channels[2];
  1732. me.a = channels[3];
  1733. me.ok = true;
  1734. }
  1735. }
  1736. // validate/cleanup values
  1737. me.r = (me.r < 0 || isNaN(me.r)) ? 0 : ((me.r > 255) ? 255 : me.r);
  1738. me.g = (me.g < 0 || isNaN(me.g)) ? 0 : ((me.g > 255) ? 255 : me.g);
  1739. me.b = (me.b < 0 || isNaN(me.b)) ? 0 : ((me.b > 255) ? 255 : me.b);
  1740. me.a = (isNaN(me.a)) ? 1 : ((me.a > 255) ? 255 : (me.a < 0) ? 0 : me.a);
  1741. // some getters
  1742. me.toRGB = function(){
  1743. return 'rgb(' + me.r + ', ' + me.g + ', ' + me.b + ')';
  1744. }
  1745. // some getters
  1746. me.toRGBA = function(){
  1747. return 'rgba(' + me.r + ', ' + me.g + ', ' + me.b + ', ' + me.a + ')';
  1748. }
  1749. /**
  1750. * Converts an RGB color value to HSV. Conversion formula
  1751. * adapted from http://en.wikipedia.org/wiki/HSV_color_space.
  1752. * Assumes r, g, and b are contained in the set [0, 255] and
  1753. * returns h, s, and v in the set [0, 1].
  1754. *
  1755. * This routine by Michael Jackson (not *that* one),
  1756. * from http://www.mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
  1757. *
  1758. * @param Number r The red color value
  1759. * @param Number g The green color value
  1760. * @param Number b The blue color value
  1761. * @return Array The HSV representation
  1762. */
  1763. me.toHSV = function(){
  1764. var r = me.r / 255, g = me.g / 255, b = me.b / 255;
  1765. var max = Math.max(r, g, b), min = Math.min(r, g, b);
  1766. var h, s, v = max;
  1767. var d = max - min;
  1768. s = max == 0 ? 0 : d / max;
  1769. if (max == min) {
  1770. h = 0; // achromatic
  1771. } else {
  1772. switch (max) {
  1773. case r:
  1774. h = (g - b) / d + (g < b ? 6 : 0);
  1775. break;
  1776. case g:
  1777. h = (b - r) / d + 2;
  1778. break;
  1779. case b:
  1780. h = (r - g) / d + 4;
  1781. break;
  1782. }
  1783. h /= 6;
  1784. }
  1785. return {
  1786. h: h,
  1787. s: s,
  1788. v: v
  1789. };
  1790. }
  1791. /*
  1792. * hsl2rgb from http://codingforums.com/showthread.php?t=11156
  1793. * code by Jason Karl Davis (http://www.jasonkarldavis.com)
  1794. */
  1795. function hsl2rgb(h, s, l) {
  1796. var m1, m2, hue;
  1797. var r, g, b
  1798. s /=100;
  1799. l /= 100;
  1800. if (s == 0)
  1801. r = g = b = (l * 255);
  1802. else {
  1803. if (l <= 0.5)
  1804. m2 = l * (s + 1);
  1805. else
  1806. m2 = l + s - l * s;
  1807. m1 = l * 2 - m2;
  1808. hue = h / 360;
  1809. r = HueToRgb(m1, m2, hue + 1/3);
  1810. g = HueToRgb(m1, m2, hue);
  1811. b = HueToRgb(m1, m2, hue - 1/3);
  1812. }
  1813. return {r: Math.round(r), g: Math.round(g), b: Math.round(b)};
  1814. }
  1815. function HueToRgb(m1, m2, hue) {
  1816. var v;
  1817. if (hue < 0)
  1818. hue += 1;
  1819. else if (hue > 1)
  1820. hue -= 1;
  1821. if (6 * hue < 1)
  1822. v = m1 + (m2 - m1) * hue * 6;
  1823. else if (2 * hue < 1)
  1824. v = m2;
  1825. else if (3 * hue < 2)
  1826. v = m1 + (m2 - m1) * (2/3 - hue) * 6;
  1827. else
  1828. v = m1;
  1829. return 255 * v;
  1830. }
  1831. me.toHex = function(){
  1832. var r = me.r.toString(16);
  1833. var g = me.g.toString(16);
  1834. var b = me.b.toString(16);
  1835. var a = Math.floor((me.a * 255)).toString(16);
  1836. if (r.length == 1)
  1837. r = '0' + r;
  1838. if (g.length == 1)
  1839. g = '0' + g;
  1840. if (b.length == 1)
  1841. b = '0' + b;
  1842. if (a == 'ff') {
  1843. a = '';
  1844. } else if (a.length == 1) {
  1845. a = '0' + a;
  1846. }
  1847. return '#' + a + r + g + b;
  1848. }
  1849. }
  1850. document.write('<style type="text/css">.cssSandpaper-initiallyHidden { visibility: hidden;} </style>');
  1851. EventHelpers.addPageLoadEvent('cssSandpaper.init')