Anti-Aliased Curvy Corners


/ Published in: JavaScript
Save to your folder(s)

curvyCorners is a free JavaScript program that will create on-the-fly rounded corners for any HTML DIV element, that look as good as any graphically created corners.


Copy this code and paste it in your HTML
  1. /****************************************************************
  2.   * *
  3.   * curvyCorners *
  4.   * ------------ *
  5.   * *
  6.   * This script generates rounded corners for your divs. *
  7.   * *
  8.   * Version 1.2.9 *
  9.   * Copyright (c) 2006 Cameron Cooke *
  10.   * By: Cameron Cooke and Tim Hutchison. *
  11.   * *
  12.   * *
  13.   * Website: http://www.curvycorners.net *
  14.   * Email: [email protected] *
  15.   * Forum: http://www.curvycorners.net/forum/ *
  16.   * *
  17.   * *
  18.   * This library is free software; you can redistribute *
  19.   * it and/or modify it under the terms of the GNU *
  20.   * Lesser General Public License as published by the *
  21.   * Free Software Foundation; either version 2.1 of the *
  22.   * License, or (at your option) any later version. *
  23.   * *
  24.   * This library is distributed in the hope that it will *
  25.   * be useful, but WITHOUT ANY WARRANTY; without even the *
  26.   * implied warranty of MERCHANTABILITY or FITNESS FOR A *
  27.   * PARTICULAR PURPOSE. See the GNU Lesser General Public *
  28.   * License for more details. *
  29.   * *
  30.   * You should have received a copy of the GNU Lesser *
  31.   * General Public License along with this library; *
  32.   * Inc., 59 Temple Place, Suite 330, Boston, *
  33.   * MA 02111-1307 USA *
  34.   * *
  35.   ****************************************************************/
  36.  
  37. // Browser detection
  38. var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1;
  39. var isMoz = document.implementation && document.implementation.createDocument;
  40. var isSafari = ((navigator.userAgent.toLowerCase().indexOf('safari')!=-1)&&(navigator.userAgent.toLowerCase().indexOf('mac')!=-1))?true:false;
  41.  
  42. /*
  43.   Usage:
  44.  
  45.   newCornersObj = new curvyCorners(settingsObj, "classNameStr");
  46.   newCornersObj = new curvyCorners(settingsObj, divObj1[, divObj2[, divObj3[, . . . [, divObjN]]]]);
  47.   */
  48. function curvyCorners()
  49. {
  50. // Check parameters
  51. if(typeof(arguments[0]) != "object") throw newCurvyError("First parameter of curvyCorners() must be an object.");
  52. if(typeof(arguments[1]) != "object" && typeof(arguments[1]) != "string") throw newCurvyError("Second parameter of curvyCorners() must be an object or a class name.");
  53.  
  54. // Get object(s)
  55. if(typeof(arguments[1]) == "string")
  56. {
  57. // Get elements by class name
  58. var startIndex = 0;
  59. var boxCol = getElementsByClass(arguments[1]);
  60. }
  61. else
  62. {
  63. // Get objects
  64. var startIndex = 1;
  65. var boxCol = arguments;
  66. }
  67.  
  68. // Create return collection/object
  69. var curvyCornersCol = new Array();
  70.  
  71. // Create array of html elements that can have rounded corners
  72. if(arguments[0].validTags)
  73. var validElements = arguments[0].validTags;
  74. else
  75. var validElements = ["div"]; // Default
  76.  
  77. // Loop through each argument
  78. for(var i = startIndex, j = boxCol.length; i < j; i++)
  79. {
  80. // Current element tag name
  81. var currentTag = boxCol[i].tagName.toLowerCase();
  82.  
  83. if(inArray(validElements, currentTag) !== false)
  84. {
  85. curvyCornersCol[curvyCornersCol.length] = new curvyObject(arguments[0], boxCol[i]);
  86. }
  87. }
  88.  
  89. this.objects = curvyCornersCol;
  90.  
  91. // Applys the curvyCorners to all objects
  92. this.applyCornersToAll = function()
  93. {
  94. for(var x = 0, k = this.objects.length; x < k; x++)
  95. {
  96. this.objects[x].applyCorners();
  97. }
  98. }
  99. }
  100.  
  101. // curvyCorners object (can be called directly)
  102. function curvyObject()
  103. {
  104. // Setup Globals
  105. this.box = arguments[1];
  106. this.settings = arguments[0];
  107. this.topContainer = null;
  108. this.bottomContainer = null;
  109. this.masterCorners = new Array();
  110. this.contentDIV = null;
  111.  
  112. // Get box formatting details
  113. var boxHeight = get_style(this.box, "height", "height");
  114. var boxWidth = get_style(this.box, "width", "width");
  115. var borderWidth = get_style(this.box, "borderTopWidth", "border-top-width");
  116. var borderColour = get_style(this.box, "borderTopColor", "border-top-color");
  117. var boxColour = get_style(this.box, "backgroundColor", "background-color");
  118. var backgroundImage = get_style(this.box, "backgroundImage", "background-image");
  119. var boxPosition = get_style(this.box, "position", "position");
  120. var boxPadding = get_style(this.box, "paddingTop", "padding-top");
  121.  
  122. // Set formatting propertes
  123. this.boxHeight = parseInt(((boxHeight != "" && boxHeight != "auto" && boxHeight.indexOf("%") == -1)? boxHeight.substring(0, boxHeight.indexOf("px")) : this.box.scrollHeight));
  124. this.boxWidth = parseInt(((boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1)? boxWidth.substring(0, boxWidth.indexOf("px")) : this.box.scrollWidth));
  125. this.borderWidth = parseInt(((borderWidth != "" && borderWidth.indexOf("px") !== -1)? borderWidth.slice(0, borderWidth.indexOf("px")) : 0));
  126. this.boxColour = format_colour(boxColour);
  127. this.boxPadding = parseInt(((boxPadding != "" && boxPadding.indexOf("px") !== -1)? boxPadding.slice(0, boxPadding.indexOf("px")) : 0));
  128. this.borderColour = format_colour(borderColour);
  129. this.borderString = this.borderWidth + "px" + " solid " + this.borderColour;
  130. this.backgroundImage = ((backgroundImage != "none")? backgroundImage : "");
  131. this.boxContent = this.box.innerHTML;
  132.  
  133. // Make box relative if not already absolute and remove any padding
  134. if(boxPosition != "absolute") this.box.style.position = "relative";
  135. this.box.style.padding = "0px";
  136.  
  137. // If IE and height and width are not set, we need to set width so that we get positioning
  138. if(isIE && boxWidth == "auto" && boxHeight == "auto") this.box.style.width = "100%";
  139.  
  140. // Resize box so that it stays to the orignal height
  141.  
  142.  
  143. // Remove content if box is using autoPad
  144. if(this.settings.autoPad == true && this.boxPadding > 0)
  145. this.box.innerHTML = "";
  146.  
  147. /*
  148.   This method creates the corners and
  149.   applies them to the div element.
  150.   */
  151. this.applyCorners = function()
  152. {
  153. /*
  154.   Create top and bottom containers.
  155.   These will be used as a parent for the corners and bars.
  156.   */
  157. for(var t = 0; t < 2; t++)
  158. {
  159. switch(t)
  160. {
  161. // Top
  162. case 0:
  163.  
  164. // Only build top bar if a top corner is to be draw
  165. if(this.settings.tl || this.settings.tr)
  166. {
  167. var newMainContainer = document.createElement("DIV");
  168. newMainContainer.style.width = "100%";
  169. newMainContainer.style.fontSize = "1px";
  170. newMainContainer.style.overflow = "hidden";
  171. newMainContainer.style.position = "absolute";
  172. newMainContainer.style.paddingLeft = this.borderWidth + "px";
  173. newMainContainer.style.paddingRight = this.borderWidth + "px";
  174. var topMaxRadius = Math.max(this.settings.tl ? this.settings.tl.radius : 0, this.settings.tr ? this.settings.tr.radius : 0);
  175. newMainContainer.style.height = topMaxRadius + "px";
  176. newMainContainer.style.top = 0 - topMaxRadius + "px";
  177. newMainContainer.style.left = 0 - this.borderWidth + "px";
  178. this.topContainer = this.box.appendChild(newMainContainer);
  179. }
  180. break;
  181.  
  182. // Bottom
  183. case 1:
  184.  
  185. // Only build bottom bar if a top corner is to be draw
  186. if(this.settings.bl || this.settings.br)
  187. {
  188. var newMainContainer = document.createElement("DIV");
  189. newMainContainer.style.width = "100%";
  190. newMainContainer.style.fontSize = "1px";
  191. newMainContainer.style.overflow = "hidden";
  192. newMainContainer.style.position = "absolute";
  193. newMainContainer.style.paddingLeft = this.borderWidth + "px";
  194. newMainContainer.style.paddingRight = this.borderWidth + "px";
  195. var botMaxRadius = Math.max(this.settings.bl ? this.settings.bl.radius : 0, this.settings.br ? this.settings.br.radius : 0);
  196. newMainContainer.style.height = botMaxRadius + "px";
  197. newMainContainer.style.bottom = 0 - botMaxRadius + "px";
  198. newMainContainer.style.left = 0 - this.borderWidth + "px";
  199. this.bottomContainer = this.box.appendChild(newMainContainer);
  200. }
  201. break;
  202. }
  203. }
  204.  
  205. // Turn off current borders
  206. if(this.topContainer) this.box.style.borderTopWidth = "0px";
  207. if(this.bottomContainer) this.box.style.borderBottomWidth = "0px";
  208.  
  209. // Create array of available corners
  210. var corners = ["tr", "tl", "br", "bl"];
  211.  
  212. /*
  213.   Loop for each corner
  214.   */
  215. for(var i in corners)
  216. {
  217. // FIX for prototype lib
  218. if(i > -1 < 4)
  219. {
  220. // Get current corner type from array
  221. var cc = corners[i];
  222.  
  223. // Has the user requested the currentCorner be round?
  224. if(!this.settings[cc])
  225. {
  226. // No
  227. if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null))
  228. {
  229. // We need to create a filler div to fill the space upto the next horzontal corner.
  230. var newCorner = document.createElement("DIV");
  231.  
  232. // Setup corners properties
  233. newCorner.style.position = "relative";
  234. newCorner.style.fontSize = "1px";
  235. newCorner.style.overflow = "hidden";
  236.  
  237. // Add background image?
  238. if(this.backgroundImage == "")
  239. newCorner.style.backgroundColor = this.boxColour;
  240. else
  241. newCorner.style.backgroundImage = this.backgroundImage;
  242.  
  243. switch(cc)
  244. {
  245. case "tl":
  246. newCorner.style.height = topMaxRadius - this.borderWidth + "px";
  247. newCorner.style.marginRight = this.settings.tr.radius - (this.borderWidth*2) + "px";
  248. newCorner.style.borderLeft = this.borderString;
  249. newCorner.style.borderTop = this.borderString;
  250. newCorner.style.left = -this.borderWidth + "px";
  251. break;
  252.  
  253. case "tr":
  254. newCorner.style.height = topMaxRadius - this.borderWidth + "px";
  255. newCorner.style.marginLeft = this.settings.tl.radius - (this.borderWidth*2) + "px";
  256. newCorner.style.borderRight = this.borderString;
  257. newCorner.style.borderTop = this.borderString;
  258. newCorner.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px";
  259. newCorner.style.left = this.borderWidth + "px";
  260. break;
  261.  
  262. case "bl":
  263. newCorner.style.height = botMaxRadius - this.borderWidth + "px";
  264. newCorner.style.marginRight = this.settings.br.radius - (this.borderWidth*2) + "px";
  265. newCorner.style.borderLeft = this.borderString;
  266. newCorner.style.borderBottom = this.borderString;
  267. newCorner.style.left = -this.borderWidth + "px";
  268. newCorner.style.backgroundPosition = "-" + (this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px";
  269. break;
  270.  
  271. case "br":
  272. newCorner.style.height = botMaxRadius - this.borderWidth + "px";
  273. newCorner.style.marginLeft = this.settings.bl.radius - (this.borderWidth*2) + "px";
  274. newCorner.style.borderRight = this.borderString;
  275. newCorner.style.borderBottom = this.borderString;
  276. newCorner.style.left = this.borderWidth + "px"
  277. newCorner.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px";
  278. break;
  279. }
  280. }
  281. }
  282. else
  283. {
  284. /*
  285.   PERFORMANCE NOTE:
  286.  
  287.   If more than one corner is requested and a corner has been already
  288.   created for the same radius then that corner will be used as a master and cloned.
  289.   The pixel bars will then be repositioned to form the new corner type.
  290.   All new corners start as a bottom right corner.
  291.   */
  292. if(this.masterCorners[this.settings[cc].radius])
  293. {
  294. // Create clone of the master corner
  295. var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);
  296. }
  297. else
  298. {
  299. // Yes, we need to create a new corner
  300. var newCorner = document.createElement("DIV");
  301. newCorner.style.height = this.settings[cc].radius + "px";
  302. newCorner.style.width = this.settings[cc].radius + "px";
  303. newCorner.style.position = "absolute";
  304. newCorner.style.fontSize = "1px";
  305. newCorner.style.overflow = "hidden";
  306.  
  307. // THE FOLLOWING BLOCK OF CODE CREATES A ROUNDED CORNER
  308. // ---------------------------------------------------- TOP
  309.  
  310. // Get border radius
  311. var borderRadius = parseInt(this.settings[cc].radius - this.borderWidth);
  312.  
  313. // Cycle the x-axis
  314. for(var intx = 0, j = this.settings[cc].radius; intx < j; intx++)
  315. {
  316. // Calculate the value of y1 which identifies the pixels inside the border
  317. if((intx +1) >= borderRadius)
  318. var y1 = -1;
  319. else
  320. var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1);
  321.  
  322. // Only calculate y2 and y3 if there is a border defined
  323. if(borderRadius != j)
  324. {
  325. if((intx) >= borderRadius)
  326. var y2 = -1;
  327. else
  328. var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2)));
  329.  
  330. if((intx+1) >= j)
  331. var y3 = -1;
  332. else
  333. var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);
  334. }
  335.  
  336. // Calculate y4
  337. if((intx) >= j)
  338. var y4 = -1;
  339. else
  340. var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2)));
  341.  
  342. // Draw bar on inside of the border with foreground colour
  343. if(y1 > -1) this.drawPixel(intx, 0, this.boxColour, 100, (y1+1), newCorner, -1, this.settings[cc].radius);
  344.  
  345. // Only draw border/foreground antialiased pixels and border if there is a border defined
  346. if(borderRadius != j)
  347. {
  348. // Cycle the y-axis
  349. for(var inty = (y1 + 1); inty < y2; inty++)
  350. {
  351. // Draw anti-alias pixels
  352. if(this.settings.antiAlias)
  353. {
  354. // For each of the pixels that need anti aliasing between the foreground and border colour draw single pixel divs
  355. if(this.backgroundImage != "")
  356. {
  357. var borderFract = (pixelFraction(intx, inty, borderRadius) * 100);
  358.  
  359. if(borderFract < 30)
  360. {
  361. this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);
  362. }
  363. else
  364. {
  365. this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);
  366. }
  367. }
  368. else
  369. {
  370. var pixelcolour = BlendColour(this.boxColour, this.borderColour, pixelFraction(intx, inty, borderRadius));
  371. this.drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, this.settings[cc].radius, cc);
  372. }
  373. }
  374. }
  375.  
  376. // Draw bar for the border
  377. if(this.settings.antiAlias)
  378. {
  379. if(y3 >= y2)
  380. {
  381. if (y2 == -1) y2 = 0;
  382. this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, 0);
  383. }
  384. }
  385. else
  386. {
  387. if(y3 >= y1)
  388. {
  389. this.drawPixel(intx, (y1 + 1), this.borderColour, 100, (y3 - y1), newCorner, 0, 0);
  390. }
  391. }
  392.  
  393. // Set the colour for the outside curve
  394. var outsideColour = this.borderColour;
  395. }
  396. else
  397. {
  398. // Set the coour for the outside curve
  399. var outsideColour = this.boxColour;
  400. var y3 = y1;
  401. }
  402.  
  403. // Draw aa pixels?
  404. if(this.settings.antiAlias)
  405. {
  406. // Cycle the y-axis and draw the anti aliased pixels on the outside of the curve
  407. for(var inty = (y3 + 1); inty < y4; inty++)
  408. {
  409. // For each of the pixels that need anti aliasing between the foreground/border colour & background draw single pixel divs
  410. this.drawPixel(intx, inty, outsideColour, (pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);
  411. }
  412. }
  413. }
  414.  
  415. // END OF CORNER CREATION
  416. // ---------------------------------------------------- END
  417.  
  418. // We now need to store the current corner in the masterConers array
  419. this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);
  420. }
  421.  
  422. /*
  423.   Now we have a new corner we need to reposition all the pixels unless
  424.   the current corner is the bottom right.
  425.   */
  426. if(cc != "br")
  427. {
  428. // Loop through all children (pixel bars)
  429. for(var t = 0, k = newCorner.childNodes.length; t < k; t++)
  430. {
  431. // Get current pixel bar
  432. var pixelBar = newCorner.childNodes[t];
  433.  
  434. // Get current top and left properties
  435. var pixelBarTop = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px")));
  436. var pixelBarLeft = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px")));
  437. var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px")));
  438.  
  439. // Reposition pixels
  440. if(cc == "tl" || cc == "bl"){
  441. pixelBar.style.left = this.settings[cc].radius -pixelBarLeft -1 + "px"; // Left
  442. }
  443. if(cc == "tr" || cc == "tl"){
  444. pixelBar.style.top = this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px"; // Top
  445. }
  446.  
  447. switch(cc)
  448. {
  449. case "tr":
  450. pixelBar.style.backgroundPosition = "-" + Math.abs((this.boxWidth - this.settings[cc].radius + this.borderWidth) + pixelBarLeft) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px";
  451. break;
  452.  
  453. case "tl":
  454. pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px";
  455. break;
  456.  
  457. case "bl":
  458. pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs((this.boxHeight + this.settings[cc].radius + pixelBarTop) -this.borderWidth) + "px";
  459. break;
  460. }
  461. }
  462. }
  463. }
  464.  
  465. if(newCorner)
  466. {
  467. // Position the container
  468. switch(cc)
  469. {
  470. case "tl":
  471. if(newCorner.style.position == "absolute") newCorner.style.top = "0px";
  472. if(newCorner.style.position == "absolute") newCorner.style.left = "0px";
  473. if(this.topContainer) this.topContainer.appendChild(newCorner);
  474. break;
  475.  
  476. case "tr":
  477. if(newCorner.style.position == "absolute") newCorner.style.top = "0px";
  478. if(newCorner.style.position == "absolute") newCorner.style.right = "0px";
  479. if(this.topContainer) this.topContainer.appendChild(newCorner);
  480. break;
  481.  
  482. case "bl":
  483. if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px";
  484. if(newCorner.style.position == "absolute") newCorner.style.left = "0px";
  485. if(this.bottomContainer) this.bottomContainer.appendChild(newCorner);
  486. break;
  487.  
  488. case "br":
  489. if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px";
  490. if(newCorner.style.position == "absolute") newCorner.style.right = "0px";
  491. if(this.bottomContainer) this.bottomContainer.appendChild(newCorner);
  492. break;
  493. }
  494. }
  495. }
  496. }
  497.  
  498. /*
  499.   The last thing to do is draw the rest of the filler DIVs.
  500.   We only need to create a filler DIVs when two corners have
  501.   diffrent radiuses in either the top or bottom container.
  502.   */
  503.  
  504. // Find out which corner has the biiger radius and get the difference amount
  505. var radiusDiff = new Array();
  506. radiusDiff["t"] = Math.abs(this.settings.tl.radius - this.settings.tr.radius)
  507. radiusDiff["b"] = Math.abs(this.settings.bl.radius - this.settings.br.radius);
  508.  
  509. for(z in radiusDiff)
  510. {
  511. // FIX for prototype lib
  512. if(z == "t" || z == "b")
  513. {
  514. if(radiusDiff[z])
  515. {
  516. // Get the type of corner that is the smaller one
  517. var smallerCornerType = ((this.settings[z + "l"].radius < this.settings[z + "r"].radius)? z +"l" : z +"r");
  518.  
  519. // First we need to create a DIV for the space under the smaller corner
  520. var newFiller = document.createElement("DIV");
  521. newFiller.style.height = radiusDiff[z] + "px";
  522. newFiller.style.width = this.settings[smallerCornerType].radius+ "px"
  523. newFiller.style.position = "absolute";
  524. newFiller.style.fontSize = "1px";
  525. newFiller.style.overflow = "hidden";
  526. newFiller.style.backgroundColor = this.boxColour;
  527. //newFiller.style.backgroundColor = get_random_color();
  528.  
  529. // Position filler
  530. switch(smallerCornerType)
  531. {
  532. case "tl":
  533. newFiller.style.bottom = "0px";
  534. newFiller.style.left = "0px";
  535. newFiller.style.borderLeft = this.borderString;
  536. this.topContainer.appendChild(newFiller);
  537. break;
  538.  
  539. case "tr":
  540. newFiller.style.bottom = "0px";
  541. newFiller.style.right = "0px";
  542. newFiller.style.borderRight = this.borderString;
  543. this.topContainer.appendChild(newFiller);
  544. break;
  545.  
  546. case "bl":
  547. newFiller.style.top = "0px";
  548. newFiller.style.left = "0px";
  549. newFiller.style.borderLeft = this.borderString;
  550. this.bottomContainer.appendChild(newFiller);
  551. break;
  552.  
  553. case "br":
  554. newFiller.style.top = "0px";
  555. newFiller.style.right = "0px";
  556. newFiller.style.borderRight = this.borderString;
  557. this.bottomContainer.appendChild(newFiller);
  558. break;
  559. }
  560. }
  561.  
  562. // Create the bar to fill the gap between each corner horizontally
  563. var newFillerBar = document.createElement("DIV");
  564. newFillerBar.style.position = "relative";
  565. newFillerBar.style.fontSize = "1px";
  566. newFillerBar.style.overflow = "hidden";
  567. newFillerBar.style.backgroundColor = this.boxColour;
  568. newFillerBar.style.backgroundImage = this.backgroundImage;
  569.  
  570. switch(z)
  571. {
  572. case "t":
  573. // Top Bar
  574. if(this.topContainer)
  575. {
  576. // Edit by Asger Hallas: Check if settings.xx.radius is not false
  577. if(this.settings.tl.radius && this.settings.tr.radius)
  578. {
  579. newFillerBar.style.height = topMaxRadius - this.borderWidth + "px";
  580. newFillerBar.style.marginLeft = this.settings.tl.radius - this.borderWidth + "px";
  581. newFillerBar.style.marginRight = this.settings.tr.radius - this.borderWidth + "px";
  582. newFillerBar.style.borderTop = this.borderString;
  583.  
  584. if(this.backgroundImage != "")
  585. newFillerBar.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px";
  586.  
  587. this.topContainer.appendChild(newFillerBar);
  588. }
  589.  
  590. // Repos the boxes background image
  591. this.box.style.backgroundPosition = "0px -" + (topMaxRadius - this.borderWidth) + "px";
  592. }
  593. break;
  594.  
  595. case "b":
  596. if(this.bottomContainer)
  597. {
  598. // Edit by Asger Hallas: Check if settings.xx.radius is not false
  599. if(this.settings.bl.radius && this.settings.br.radius)
  600. {
  601. // Bottom Bar
  602. newFillerBar.style.height = botMaxRadius - this.borderWidth + "px";
  603. newFillerBar.style.marginLeft = this.settings.bl.radius - this.borderWidth + "px";
  604. newFillerBar.style.marginRight = this.settings.br.radius - this.borderWidth + "px";
  605. newFillerBar.style.borderBottom = this.borderString;
  606.  
  607. if(this.backgroundImage != "")
  608. newFillerBar.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (topMaxRadius + this.borderWidth)) + "px";
  609.  
  610. this.bottomContainer.appendChild(newFillerBar);
  611. }
  612. }
  613. break;
  614. }
  615. }
  616. }
  617.  
  618. /*
  619.   AutoPad! apply padding if set.
  620.   */
  621. if(this.settings.autoPad == true && this.boxPadding > 0)
  622. {
  623. // Create content container
  624. var contentContainer = document.createElement("DIV");
  625.  
  626. // Set contentContainer's properties
  627. contentContainer.style.position = "relative";
  628. contentContainer.innerHTML = this.boxContent;
  629. contentContainer.className = "autoPadDiv";
  630.  
  631. // Get padding amounts
  632. var topPadding = Math.abs(topMaxRadius - this.boxPadding);
  633. var botPadding = Math.abs(botMaxRadius - this.boxPadding);
  634.  
  635. // Apply top padding
  636. if(topMaxRadius < this.boxPadding)
  637. contentContainer.style.paddingTop = topPadding + "px";
  638.  
  639. // Apply Bottom padding
  640. if(botMaxRadius < this.boxPadding)
  641. contentContainer.style.paddingBottom = botMaxRadius + "px";
  642.  
  643. // Apply left and right padding
  644. contentContainer.style.paddingLeft = this.boxPadding + "px";
  645. contentContainer.style.paddingRight = this.boxPadding + "px";
  646.  
  647. // Append contentContainer
  648. this.contentDIV = this.box.appendChild(contentContainer);
  649. }
  650. }
  651.  
  652. /*
  653.   This function draws the pixles
  654.   */
  655. this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius)
  656. {
  657. // Create pixel
  658. var pixel = document.createElement("DIV");
  659. pixel.style.height = height + "px";
  660. pixel.style.width = "1px";
  661. pixel.style.position = "absolute";
  662. pixel.style.fontSize = "1px";
  663. pixel.style.overflow = "hidden";
  664.  
  665. // Max Top Radius
  666. var topMaxRadius = Math.max(this.settings["tr"].radius, this.settings["tl"].radius);
  667.  
  668. // Dont apply background image to border pixels
  669. if(image == -1 && this.backgroundImage != "")
  670. {
  671. pixel.style.backgroundImage = this.backgroundImage;
  672. pixel.style.backgroundPosition = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + topMaxRadius + inty) -this.borderWidth) + "px";
  673. }
  674. else
  675. {
  676. pixel.style.backgroundColor = colour;
  677. }
  678.  
  679. // Set opacity if the transparency is anything other than 100
  680. if (transAmount != 100)
  681. setOpacity(pixel, transAmount);
  682.  
  683. // Set the pixels position
  684. pixel.style.top = inty + "px";
  685. pixel.style.left = intx + "px";
  686.  
  687. newCorner.appendChild(pixel);
  688. }
  689. }
  690.  
  691. // ------------- UTILITY FUNCTIONS
  692.  
  693. // Inserts a element after another
  694. function insertAfter(parent, node, referenceNode)
  695. {
  696. parent.insertBefore(node, referenceNode.nextSibling);
  697. }
  698.  
  699. /*
  700.   Blends the two colours by the fraction
  701.   returns the resulting colour as a string in the format "#FFFFFF"
  702.   */
  703. function BlendColour(Col1, Col2, Col1Fraction)
  704. {
  705. var red1 = parseInt(Col1.substr(1,2),16);
  706. var green1 = parseInt(Col1.substr(3,2),16);
  707. var blue1 = parseInt(Col1.substr(5,2),16);
  708. var red2 = parseInt(Col2.substr(1,2),16);
  709. var green2 = parseInt(Col2.substr(3,2),16);
  710. var blue2 = parseInt(Col2.substr(5,2),16);
  711.  
  712. if(Col1Fraction > 1 || Col1Fraction < 0) Col1Fraction = 1;
  713.  
  714. var endRed = Math.round((red1 * Col1Fraction) + (red2 * (1 - Col1Fraction)));
  715. if(endRed > 255) endRed = 255;
  716. if(endRed < 0) endRed = 0;
  717.  
  718. var endGreen = Math.round((green1 * Col1Fraction) + (green2 * (1 - Col1Fraction)));
  719. if(endGreen > 255) endGreen = 255;
  720. if(endGreen < 0) endGreen = 0;
  721.  
  722. var endBlue = Math.round((blue1 * Col1Fraction) + (blue2 * (1 - Col1Fraction)));
  723. if(endBlue > 255) endBlue = 255;
  724. if(endBlue < 0) endBlue = 0;
  725.  
  726. return "#" + IntToHex(endRed)+ IntToHex(endGreen)+ IntToHex(endBlue);
  727. }
  728.  
  729. /*
  730.   Converts a number to hexadecimal format
  731.   */
  732. function IntToHex(strNum)
  733. {
  734. base = strNum / 16;
  735. rem = strNum % 16;
  736. base = base - (rem / 16);
  737. baseS = MakeHex(base);
  738. remS = MakeHex(rem);
  739.  
  740. return baseS + '' + remS;
  741. }
  742.  
  743.  
  744. /*
  745.   gets the hex bits of a number
  746.   */
  747. function MakeHex(x)
  748. {
  749. if((x >= 0) && (x <= 9))
  750. {
  751. return x;
  752. }
  753. else
  754. {
  755. switch(x)
  756. {
  757. case 10: return "A";
  758. case 11: return "B";
  759. case 12: return "C";
  760. case 13: return "D";
  761. case 14: return "E";
  762. case 15: return "F";
  763. }
  764. }
  765. }
  766.  
  767.  
  768. /*
  769.   For a pixel cut by the line determines the fraction of the pixel on the 'inside' of the
  770.   line. Returns a number between 0 and 1
  771.   */
  772. function pixelFraction(x, y, r)
  773. {
  774. var pixelfraction = 0;
  775.  
  776. /*
  777.   determine the co-ordinates of the two points on the perimeter of the pixel that the
  778.   circle crosses
  779.   */
  780. var xvalues = new Array(1);
  781. var yvalues = new Array(1);
  782. var point = 0;
  783. var whatsides = "";
  784.  
  785. // x + 0 = Left
  786. var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2)));
  787.  
  788. if ((intersect >= y) && (intersect < (y+1)))
  789. {
  790. whatsides = "Left";
  791. xvalues[point] = 0;
  792. yvalues[point] = intersect - y;
  793. point = point + 1;
  794. }
  795. // y + 1 = Top
  796. var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2)));
  797.  
  798. if ((intersect >= x) && (intersect < (x+1)))
  799. {
  800. whatsides = whatsides + "Top";
  801. xvalues[point] = intersect - x;
  802. yvalues[point] = 1;
  803. point = point + 1;
  804. }
  805. // x + 1 = Right
  806. var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2)));
  807.  
  808. if ((intersect >= y) && (intersect < (y+1)))
  809. {
  810. whatsides = whatsides + "Right";
  811. xvalues[point] = 1;
  812. yvalues[point] = intersect - y;
  813. point = point + 1;
  814. }
  815. // y + 0 = Bottom
  816. var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2)));
  817.  
  818. if ((intersect >= x) && (intersect < (x+1)))
  819. {
  820. whatsides = whatsides + "Bottom";
  821. xvalues[point] = intersect - x;
  822. yvalues[point] = 0;
  823. }
  824.  
  825. /*
  826.   depending on which sides of the perimeter of the pixel the circle crosses calculate the
  827.   fraction of the pixel inside the circle
  828.   */
  829. switch (whatsides)
  830. {
  831. case "LeftRight":
  832. pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2);
  833. break;
  834.  
  835. case "TopRight":
  836. pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2);
  837. break;
  838.  
  839. case "TopBottom":
  840. pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2);
  841. break;
  842.  
  843. case "LeftBottom":
  844. pixelfraction = (yvalues[0]*xvalues[1])/2;
  845. break;
  846.  
  847. default:
  848. pixelfraction = 1;
  849. }
  850.  
  851. return pixelfraction;
  852. }
  853.  
  854.  
  855. // This function converts CSS rgb(x, x, x) to hexadecimal
  856. function rgb2Hex(rgbColour)
  857. {
  858. try{
  859.  
  860. // Get array of RGB values
  861. var rgbArray = rgb2Array(rgbColour);
  862.  
  863. // Get RGB values
  864. var red = parseInt(rgbArray[0]);
  865. var green = parseInt(rgbArray[1]);
  866. var blue = parseInt(rgbArray[2]);
  867.  
  868. // Build hex colour code
  869. var hexColour = "#" + IntToHex(red) + IntToHex(green) + IntToHex(blue);
  870. }
  871. catch(e){
  872.  
  873. alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");
  874. }
  875.  
  876. return hexColour;
  877. }
  878.  
  879. // Returns an array of rbg values
  880. function rgb2Array(rgbColour)
  881. {
  882. // Remove rgb()
  883. var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")"));
  884.  
  885. // Split RGB into array
  886. var rgbArray = rgbValues.split(", ");
  887.  
  888. return rgbArray;
  889. }
  890.  
  891. /*
  892.   Function by Simon Willison from sitepoint.com
  893.   Modified by Cameron Cooke adding Safari's rgba support
  894.   */
  895. function setOpacity(obj, opacity)
  896. {
  897. opacity = (opacity == 100)?99.999:opacity;
  898.  
  899. if(isSafari && obj.tagName != "IFRAME")
  900. {
  901. // Get array of RGB values
  902. var rgbArray = rgb2Array(obj.style.backgroundColor);
  903.  
  904. // Get RGB values
  905. var red = parseInt(rgbArray[0]);
  906. var green = parseInt(rgbArray[1]);
  907. var blue = parseInt(rgbArray[2]);
  908.  
  909. // Safari using RGBA support
  910. obj.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity/100 + ")";
  911. }
  912. else if(typeof(obj.style.opacity) != "undefined")
  913. {
  914. // W3C
  915. obj.style.opacity = opacity/100;
  916. }
  917. else if(typeof(obj.style.MozOpacity) != "undefined")
  918. {
  919. // Older Mozilla
  920. obj.style.MozOpacity = opacity/100;
  921. }
  922. else if(typeof(obj.style.filter) != "undefined")
  923. {
  924. // IE
  925. obj.style.filter = "alpha(opacity:" + opacity + ")";
  926. }
  927. else if(typeof(obj.style.KHTMLOpacity) != "undefined")
  928. {
  929. // Older KHTML Based Browsers
  930. obj.style.KHTMLOpacity = opacity/100;
  931. }
  932. }
  933.  
  934. /*
  935.   Returns index if the passed value is found in the
  936.   array otherwise returns false.
  937.   */
  938. function inArray(array, value)
  939. {
  940. for(var i = 0; i < array.length; i++){
  941.  
  942. // Matches identical (===), not just similar (==).
  943. if (array[i] === value) return i;
  944. }
  945.  
  946. return false;
  947. }
  948.  
  949. /*
  950.   Returns true if the passed value is found as a key
  951.   in the array otherwise returns false.
  952.   */
  953. function inArrayKey(array, value)
  954. {
  955. for(key in array){
  956.  
  957. // Matches identical (===), not just similar (==).
  958. if(key === value) return true;
  959. }
  960.  
  961. return false;
  962. }
  963.  
  964. // Cross browser add event wrapper
  965. function addEvent(elm, evType, fn, useCapture) {
  966. if (elm.addEventListener) {
  967. elm.addEventListener(evType, fn, useCapture);
  968. return true;
  969. }
  970. else if (elm.attachEvent) {
  971. var r = elm.attachEvent('on' + evType, fn);
  972. return r;
  973. }
  974. else {
  975. elm['on' + evType] = fn;
  976. }
  977. }
  978.  
  979. // Cross browser remove event wrapper
  980. function removeEvent(obj, evType, fn, useCapture){
  981. if (obj.removeEventListener){
  982. obj.removeEventListener(evType, fn, useCapture);
  983. return true;
  984. } else if (obj.detachEvent){
  985. var r = obj.detachEvent("on"+evType, fn);
  986. return r;
  987. } else {
  988. alert("Handler could not be removed");
  989. }
  990. }
  991.  
  992. // Formats colours
  993. function format_colour(colour)
  994. {
  995. var returnColour = "#ffffff";
  996.  
  997. // Make sure colour is set and not transparent
  998. if(colour != "" && colour != "transparent")
  999. {
  1000. // RGB Value?
  1001. if(colour.substr(0, 3) == "rgb")
  1002. {
  1003. // Get HEX aquiv.
  1004. returnColour = rgb2Hex(colour);
  1005. }
  1006. else if(colour.length == 4)
  1007. {
  1008. // 3 chr colour code add remainder
  1009. returnColour = "#" + colour.substring(1, 2) + colour.substring(1, 2) + colour.substring(2, 3) + colour.substring(2, 3) + colour.substring(3, 4) + colour.substring(3, 4);
  1010. }
  1011. else
  1012. {
  1013. // Normal valid hex colour
  1014. returnColour = colour;
  1015. }
  1016. }
  1017.  
  1018. return returnColour;
  1019. }
  1020.  
  1021. // Returns the style value for the property specfied
  1022. function get_style(obj, property, propertyNS)
  1023. {
  1024. try
  1025. {
  1026. if(obj.currentStyle)
  1027. {
  1028. var returnVal = eval("obj.currentStyle." + property);
  1029. }
  1030. else
  1031. {
  1032. /*
  1033.   Safari does not expose any information for the object if display is
  1034.   set to none is set so we temporally enable it.
  1035.   */
  1036. if(isSafari && obj.style.display == "none")
  1037. {
  1038. obj.style.display = "";
  1039. var wasHidden = true;
  1040. }
  1041.  
  1042. var returnVal = document.defaultView.getComputedStyle(obj, '').getPropertyValue(propertyNS);
  1043.  
  1044. // Rehide the object
  1045. if(isSafari && wasHidden)
  1046. {
  1047. obj.style.display = "none";
  1048. }
  1049. }
  1050. }
  1051. catch(e)
  1052. {
  1053. // Do nothing
  1054. }
  1055.  
  1056. return returnVal;
  1057. }
  1058.  
  1059. // Get elements by class by Dustin Diaz.
  1060. function getElementsByClass(searchClass, node, tag)
  1061. {
  1062. var classElements = new Array();
  1063.  
  1064. if(node == null)
  1065. node = document;
  1066. if(tag == null)
  1067. tag = '*';
  1068.  
  1069. var els = node.getElementsByTagName(tag);
  1070. var elsLen = els.length;
  1071. var pattern = new RegExp("(^|\s)"+searchClass+"(\s|$)");
  1072.  
  1073. for (i = 0, j = 0; i < elsLen; i++)
  1074. {
  1075. if(pattern.test(els[i].className))
  1076. {
  1077. classElements[j] = els[i];
  1078. j++;
  1079. }
  1080. }
  1081.  
  1082. return classElements;
  1083. }
  1084.  
  1085. // Displays error message
  1086. function newCurvyError(errorMessage)
  1087. {
  1088. return new Error("curvyCorners Error:\n" + errorMessage)
  1089. }

URL: http://www.curvycorners.net/

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.