PageSourceSearch

http://video-znanie.ru/templates/video-znanie/css/js/curvycorners.js

js video-znanie.ru collected 2026-10-06 17:54:04 UTC 55,834 bytes, 1,372 lines download raw bytes

1function browserdetect() {
2  var agent = navigator.userAgent.toLowerCase();
3  this.isIE = agent.indexOf("msie") > -1;
4  if (this.isIE) {
5    this.ieVer = /msie\s(\d\.\d)/.exec(agent)[1];
6    this.quirksMode = !document.compatMode || document.compatMode.indexOf("BackCompat") > -1;
7    this.get_style = function(obj, prop) {
8      if (!(prop in obj.currentStyle)) return "";
9      var matches = /^([\d.]+)(\w*)/.exec(obj.currentStyle[prop]);
10      if (!matches) return obj.currentStyle[prop];
11      if (matches[1] == 0) return '0';
12      // now convert to pixels if necessary
13      if (matches[2] && matches[2] !== 'px') {
14        var style = obj.style.left;
15        var rtStyle = obj.runtimeStyle.left;
16        obj.runtimeStyle.left = obj.currentStyle.left;
17        obj.style.left = matches[1] + matches[2];
18        matches[0] = obj.style.pixelLeft;
19        obj.style.left = style;
20        obj.runtimeStyle.left = rtStyle;
21      }
22      return matches[0];
23    };
24  }
25  else {
26    this.ieVer = this.quirksMode = 0;
27    this.isMoz     = agent.indexOf('firefox') !== -1 || ('style' in document.childNodes[1] && 'MozBorderRadius' in document.childNodes[1].style);
28    this.isSafari  = agent.indexOf('safari') != -1;
29    this.isOp      = 'opera' in window;
30    this.isWebKit  = agent.indexOf('webkit') != -1;
31    this.get_style = function(obj, prop) {
32      prop = prop.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
33      return document.defaultView.getComputedStyle(obj, '').getPropertyValue(prop);
34    };
35  }
36}
37var curvyBrowser = new browserdetect;
38
39/* Force caching of bg images in IE6 */
40if (curvyBrowser.isIE) {
41  try {
42    document.execCommand("BackgroundImageCache", false, true);
43  }
44  catch(e) {};
45}
46
47// object that parses border-radius properties for a box
48
49function curvyCnrSpec(selText) {
50  this.selectorText = selText;
51  this.tlR = this.trR = this.blR = this.brR = 0;
52  this.tlu = this.tru = this.blu = this.bru = "";
53  this.antiAlias = true; // default true
54}
55curvyCnrSpec.prototype.setcorner = function(tb, lr, radius, unit) {
56  if (!tb) { // no corner specified
57    this.tlR = this.trR = this.blR = this.brR = parseInt(radius);
58    this.tlu = this.tru = this.blu = this.bru = unit;
59  }
60  else { // corner specified
61    propname = tb.charAt(0) + lr.charAt(0);
62    this[propname + 'R'] = parseInt(radius);
63    this[propname + 'u'] = unit;
64  }
65}
66/*
67  get(propstring)
68  where propstring is:
69  - 'tR' or 'bR' : returns top or bottom radius.
70  - 'tlR', 'trR', 'blR' or 'brR' : returns top/bottom left/right radius.
71  - 'tlu', 'tru', 'blr' or 'bru' : returns t/b l/r unit (px, em...)
72  - 'tRu' or 'bRu' : returns top/bottom radius+unit
73  - 'tlRu', 'trRu', 'blRu', 'brRu' : returns t/b l/r radius+unit
74*/
75curvyCnrSpec.prototype.get = function(prop) {
76  if (/^(t|b)(l|r)(R|u)$/.test(prop)) return this[prop];
77  if (/^(t|b)(l|r)Ru$/.test(prop)) {
78    var pname = prop.charAt(0) + prop.charAt(1);
79    return this[pname + 'R'] + this[pname + 'u'];
80  }
81  if (/^(t|b)Ru?$/.test(prop)) {
82    var tb = prop.charAt(0);
83    tb += this[tb + 'lR'] > this[tb + 'rR'] ? 'l' : 'r';
84    var retval = this[tb + 'R'];
85    if (prop.length === 3 && prop.charAt(2) === 'u')
86      retval += this[tb = 'u'];
87    return retval;
88  }
89  throw new Error('Don\'t recognize property ' + prop);
90}
91curvyCnrSpec.prototype.radiusdiff = function(tb) {
92  if (tb !== 't' && tb !== 'b') throw new Error("Param must be 't' or 'b'");
93  return Math.abs(this[tb + 'lR'] - this[tb + 'rR']);
94}
95curvyCnrSpec.prototype.setfrom = function(obj) {
96  this.tlu = this.tru = this.blu = this.bru = 'px'; // default to px
97  if ('tl' in obj) this.tlR = obj.tl.radius;
98  if ('tr' in obj) this.trR = obj.tr.radius;
99  if ('bl' in obj) this.blR = obj.bl.radius;
100  if ('br' in obj) this.brR = obj.br.radius;
101  if ('antiAlias' in obj) this.antiAlias = obj.antiAlias;
102};
103curvyCnrSpec.prototype.cloneOn = function(box) { // not needed by IE
104  var props = ['tl', 'tr', 'bl', 'br'];
105  var converted = 0;
106  var i, propu;
107
108  for (i in props) if (!isNaN(i)) {
109    propu = this[props[i] + 'u'];
110    if (propu !== '' && propu !== 'px') {
111      converted = new curvyCnrSpec;
112      break;
113    }
114  }
115  if (!converted)
116    converted = this; // no need to clone
117  else {
118    var propi, propR, save = curvyBrowser.get_style(box, 'left');
119    for (i in props) if (!isNaN(i)) {
120      propi = props[i];
121      propu = this[propi + 'u'];
122      propR = this[propi + 'R'];
123      if (propu !== 'px') {
124        var save = box.style.left;
125        box.style.left = propR + propu;
126        propR = box.style.pixelLeft;
127        box.style.left = save;
128      }
129      converted[propi + 'R'] = propR;
130      converted[propi + 'u'] = 'px';
131    }
132    box.style.left = save;
133  }
134  return converted;
135}
136curvyCnrSpec.prototype.radiusSum = function(tb) {
137  if (tb !== 't' && tb !== 'b') throw new Error("Param must be 't' or 'b'");
138  return this[tb + 'lR'] + this[tb + 'rR'];
139}
140curvyCnrSpec.prototype.radiusCount = function(tb) {
141  var count = 0;
142  if (this[tb + 'lR']) ++count;
143  if (this[tb + 'rR']) ++count;
144  return count;
145}
146curvyCnrSpec.prototype.cornerNames = function() {
147  var ret = [];
148  if (this.tlR) ret.push('tl');
149  if (this.trR) ret.push('tr');
150  if (this.blR) ret.push('bl');
151  if (this.brR) ret.push('br');
152  return ret;
153}
154
155
156/*
157  Object that parses Opera CSS
158*/
159function operasheet(sheetnumber) {
160  var txt = document.styleSheets.item(sheetnumber).ownerNode.text;
161  txt = txt.replace(/\/\*(\n|\r|.)*?\*\//g, ''); // strip comments
162  // this pattern extracts all border-radius-containing rulesets
163  // matches will be:
164  // [0] = the whole lot
165  // [1] = the selector text
166  // [2] = all the rule text between braces
167  // [3] = top/bottom and left/right parts if present (only if webkit/CSS3)
168  // [4] = top|bottom
169  // [5] = left|right
170  // .. but 3..5 are useless as they're only the first match.
171  var pat = new RegExp("^\\s*([\\w.#][-\\w.#, ]+)[\\n\\s]*\\{([^}]+border-((top|bottom)-(left|right)-)?radius[^}]*)\\}", "mg");
172  var matches;
173  this.rules = [];
174  while ((matches = pat.exec(txt)) !== null) {
175    var pat2 = new RegExp("(..)border-((top|bottom)-(left|right)-)?radius:\\s*([\\d.]+)(in|em|px|ex|pt)", "g");
176    var submatches, cornerspec = new curvyCnrSpec(matches[1]);
177    while ((submatches = pat2.exec(matches[2])) !== null)
178      if (submatches[1] !== "z-")
179        cornerspec.setcorner(submatches[3], submatches[4], submatches[5], submatches[6]);
180    this.rules.push(cornerspec);
181  }
182}
183// static class function to determine if the sheet is worth parsing
184operasheet.contains_border_radius = function(sheetnumber) {
185  return /border-((top|bottom)-(left|right)-)?radius/.test(document.styleSheets.item(sheetnumber).ownerNode.text);
186}
187
188/*
189Usage:
190
191  curvyCorners(settingsObj, "selectorStr");
192  curvyCorners(settingsObj, domObj1[, domObj2[, domObj3[, . . . [, domObjN]]]]);
193  selectorStr::= "<complexSelector>[, <complexSelector>]..."
194  complexSelector::= <selector>[ <selector]
195  selector::= "[<elementname>].classname" | "#id"
196*/
197
198function curvyCorners() {
199  var i, j, boxCol, settings, startIndex;
200  // Check parameters
201  if (typeof arguments[0] !== "object") throw curvyCorners.newError("First parameter of curvyCorners() must be an object.");
202  if (arguments[0] instanceof curvyCnrSpec) {
203    settings = arguments[0];
204    if (!settings.selectorText && typeof arguments[1] === 'string')
205      settings.selectorText = arguments[1];
206  }
207  else {
208    if (typeof arguments[1] !== "object" && typeof arguments[1] !== "string") throw curvyCorners.newError("Second parameter of curvyCorners() must be an object or a class name.");
209    j = arguments[1];
210    if (typeof j !== 'string') j = '';
211    if (j !== '' && j.charAt(0) !== '.' && 'autoPad' in arguments[0]) j = '.' + j; // for compatibility, prefix with dot
212    settings = new curvyCnrSpec(j);
213    settings.setfrom(arguments[0]);
214  }
215
216  // Get object(s)
217  if (settings.selectorText) {
218    startIndex = 0;
219    var args = settings.selectorText.replace(/\s+$/,'').split(/,\s*/); // handle comma-separated selector list
220    boxCol = new Array;
221
222    // converts div#mybox to #mybox
223    function idof(str) {
224      var ret = str.split('#');
225      return (ret.length === 2 ? "#" : "") + ret.pop();
226    }
227
228    for (i = 0; i < args.length; ++i) {
229      var arg = idof(args[i]);
230      var argbits = arg.split(' ');
231      switch (arg.charAt(0)) {
232        case '#' : // id
233          j = argbits.length === 1 ? arg : argbits[0];
234          j = document.getElementById(j.substr(1));
235          if (j === null)
236            curvyCorners.alert("No object with ID " + arg + " exists yet.\nCall curvyCorners(settings, obj) when it is created.");
237          else if (argbits.length === 1)
238            boxCol.push(j);
239          else
240            boxCol = boxCol.concat(curvyCorners.getElementsByClass(argbits[1], j));
241        break;
242        default :
243          if (argbits.length === 1)
244            boxCol = boxCol.concat(curvyCorners.getElementsByClass(arg));
245          else {
246            var encloser = curvyCorners.getElementsByClass(argbits[0]);
247            for (j = 0; j < encloser.length; ++j) {
248              boxCol = boxCol.concat(curvyCorners.getElementsByClass(argbits[1], encloser[j]));
249            }
250          }
251        //break;
252      }
253    }
254  }
255  else {
256    // Get objects
257    startIndex = 1;
258    boxCol = arguments;
259  }
260
261  // Loop through each argument
262  for (i = startIndex, j = boxCol.length; i < j; ++i) {
263    if (boxCol[i] && (!('IEborderRadius' in boxCol[i].style) || boxCol[i].style.IEborderRadius != 'set')) {
264      if (boxCol[i].className && boxCol[i].className.indexOf('curvyRedraw') !== -1) {
265        if (typeof curvyCorners.redrawList === 'undefined') curvyCorners.redrawList = new Array;
266        curvyCorners.redrawList.push({
267          node : boxCol[i],
268          spec : settings,
269          copy : boxCol[i].cloneNode(false)
270        });
271      }
272      boxCol[i].style.IEborderRadius = 'set';
273      var obj = new curvyObject(settings, boxCol[i]);
274      obj.applyCorners();
275    }
276  }
277}
278curvyCorners.prototype.applyCornersToAll = function () { // now redundant
279  throw curvyCorners.newError('This function is now redundant. Just call curvyCorners(). See documentation.');
280};
281
282curvyCorners.redraw = function() {
283  if (!curvyBrowser.isOp && !curvyBrowser.isIE) return;
284  if (!curvyCorners.redrawList) throw curvyCorners.newError('curvyCorners.redraw() has nothing to redraw.');
285  var old_block_value = curvyCorners.block_redraw;
286  curvyCorners.block_redraw = true;
287  for (var i in curvyCorners.redrawList) {
288    if (isNaN(i)) continue; // in case of added prototype methods
289    var o = curvyCorners.redrawList[i];
290    if (!o.node.clientWidth) continue; // don't resize hidden boxes
291    var newchild = o.copy.cloneNode(false);
292    for (var contents = o.node.firstChild; contents != null; contents = contents.nextSibling)
293      if (contents.className === 'autoPadDiv') break;
294    if (!contents) {
295      curvyCorners.alert('Couldn\'t find autoPad DIV');
296      break;
297    }
298    o.node.parentNode.replaceChild(newchild, o.node);
299    // remove script elements, if any
300    var scripts = contents.getElementsByTagName('script');
301    for (var j = scripts.length - 1; j >= 0; --j)
302      scripts[j].parentNode.removeChild(scripts[j]);
303    while (contents.firstChild) newchild.appendChild(contents.removeChild(contents.firstChild));
304    o = new curvyObject(o.spec, o.node = newchild);
305    o.applyCorners();
306  }
307  curvyCorners.block_redraw = old_block_value;
308}
309curvyCorners.adjust = function(obj, prop, newval) {
310  if (curvyBrowser.isOp || curvyBrowser.isIE) {
311    if (!curvyCorners.redrawList) throw curvyCorners.newError('curvyCorners.adjust() has nothing to adjust.');
312    var i, j = curvyCorners.redrawList.length;
313    for (i = 0; i < j; ++i) if (curvyCorners.redrawList[i].node === obj) break;
314    if (i === j) throw curvyCorners.newError('Object not redrawable');
315    obj = curvyCorners.redrawList[i].copy;
316  }
317  if (prop.indexOf('.') === -1)
318    obj[prop] = newval;
319  else eval('obj.' + prop + "='" + newval + "'");
320}
321curvyCorners.handleWinResize = function() {
322  if (!curvyCorners.block_redraw) curvyCorners.redraw();
323}
324curvyCorners.setWinResize = function(onoff) {
325  curvyCorners.block_redraw = !onoff;
326}
327curvyCorners.newError = function(errorMessage) {
328  return new Error("curvyCorners Error:\n" + errorMessage)
329}
330curvyCorners.alert = function(errorMessage) {
331  if (typeof curvyCornersVerbose === 'undefined' || curvyCornersVerbose) alert(errorMessage);
332}
333
334// curvyCorners object (can be called directly)
335
336function curvyObject() {
337  var boxDisp;
338  this.box              = arguments[1];
339  this.settings         = arguments[0];
340  this.topContainer = this.bottomContainer = this.shell = boxDisp = null;
341  var boxWidth = this.box.clientWidth; // browser-independent IE-emulation (NB includes padding)
342
343  if (('canHaveChildren' in this.box && !this.box.canHaveChildren) || this.box.tagName === 'TABLE')
344    throw new Error(this.errmsg("You cannot apply corners to " + this.box.tagName + " elements.", "Error"));
345  if (!boxWidth && curvyBrowser.isIE) {
346    this.box.style.zoom = 1; // can force IE to calculate width
347    boxWidth = this.box.clientWidth;
348  }
349
350  // try to handle attempts to style inline elements
351
352  if (!boxWidth && curvyBrowser.get_style(this.box, 'display') === 'inline') {
353    this.box.style.display = 'inline-block';
354    curvyCorners.alert(this.errmsg("Converting inline element to inline-block", "warning"));
355    boxWidth = this.box.clientWidth;
356  }
357
358
359  // if still no clientWidth, maybe the box or a parent has 'display:none'.
360
361  if (!boxWidth) {
362    if (!this.box.parentNode) throw this.newError("box has no parent!"); // unlikely...
363    for (boxDisp = this.box; ; boxDisp = boxDisp.parentNode) {
364      if (!boxDisp || boxDisp.tagName === 'BODY') { // we've hit the buffers
365        this.applyCorners = function() {} // make the error benign
366        curvyCorners.alert(this.errmsg("zero-width box with no accountable parent", "warning"));
367        return;
368      }
369      if (curvyBrowser.get_style(boxDisp, 'display') === 'none') break;
370    }
371    // here, we've found the box whose display is set to 'none'.
372    var boxDispSave = boxDisp.style.display;
373    boxDisp.style.display = 'block'; // display in order to get browser to calculate clientWidth
374    boxWidth = this.box.clientWidth;
375  }
376
377  // all attempts have failed
378
379  if (!boxWidth) {
380    curvyCorners.alert(this.errmsg("zero-width box, cannot display", "error"));
381    this.applyCorners = function() {} // make the error harmless
382    return;
383  }
384  if (arguments[0] instanceof curvyCnrSpec)
385    this.spec = arguments[0].cloneOn(this.box); // convert non-pixel units
386  else {
387    this.spec = new curvyCnrSpec('');
388    this.spec.setfrom(this.settings); // no need for unit conversion, use settings param. directly
389  }
390
391  // Get box formatting details
392  var borderWidth     = curvyBrowser.get_style(this.box, "borderTopWidth");
393  var borderWidthB    = curvyBrowser.get_style(this.box, "borderBottomWidth");
394  var borderWidthL    = curvyBrowser.get_style(this.box, "borderLeftWidth");
395  var borderWidthR    = curvyBrowser.get_style(this.box, "borderRightWidth");
396  var borderColour    = curvyBrowser.get_style(this.box, "borderTopColor");
397  var borderColourB   = curvyBrowser.get_style(this.box, "borderBottomColor");
398  var borderColourL   = curvyBrowser.get_style(this.box, "borderLeftColor");
399  var borderColourR   = curvyBrowser.get_style(this.box, "borderRightColor");
400  var borderStyle     = curvyBrowser.get_style(this.box, "borderTopStyle");
401  var borderStyleB    = curvyBrowser.get_style(this.box, "borderBottomStyle");
402  var borderStyleL    = curvyBrowser.get_style(this.box, "borderLeftStyle");
403  var borderStyleR    = curvyBrowser.get_style(this.box, "borderRightStyle");
404
405  var boxColour       = curvyBrowser.get_style(this.box, "backgroundColor");
406  var backgroundImage = curvyBrowser.get_style(this.box, "backgroundImage");
407  var backgroundRepeat= curvyBrowser.get_style(this.box, "backgroundRepeat");
408  if (this.box.currentStyle && this.box.currentStyle.backgroundPositionX) {
409  var backgroundPosX  = curvyBrowser.get_style(this.box, "backgroundPositionX");
410  var backgroundPosY  = curvyBrowser.get_style(this.box, "backgroundPositionY");
411  }
412  else {
413    var backgroundPosX = curvyBrowser.get_style(this.box, 'backgroundPosition');
414    backgroundPosX = backgroundPosX.split(' ');
415    var backgroundPosY = backgroundPosX[1];
416    backgroundPosX = backgroundPosX[0];
417  }
418  var boxPosition     = curvyBrowser.get_style(this.box, "position");
419  var topPadding      = curvyBrowser.get_style(this.box, "paddingTop");
420  var bottomPadding   = curvyBrowser.get_style(this.box, "paddingBottom");
421  var leftPadding     = curvyBrowser.get_style(this.box, "paddingLeft");
422  var rightPadding    = curvyBrowser.get_style(this.box, "paddingRight");
423  var border          = curvyBrowser.get_style(this.box, "border");
424  var filter = curvyBrowser.ieVer > 7 ? curvyBrowser.get_style(this.box, 'filter') : null; // IE8 bug fix
425
426  var topMaxRadius    = this.spec.get('tR');
427  var botMaxRadius    = this.spec.get('bR');
428  var styleToNPx = function(val) {
429    if (typeof val === 'number') return val;
430    if (typeof val !== 'string') throw new Error('unexpected styleToNPx type ' + typeof val);
431    var matches = /^[-\d.]([a-z]+)$/.exec(val);
432    if (matches && matches[1] != 'px') throw new Error('Unexpected unit ' + matches[1]);
433    if (isNaN(val = parseInt(val))) val = 0;
434    return val;
435  }
436  var min0Px = function(val) {
437    return val <= 0 ? "0" : val + "px";
438  }
439
440  // Set formatting properties
441  try {
442    this.borderWidth     = styleToNPx(borderWidth);
443    this.borderWidthB    = styleToNPx(borderWidthB);
444    this.borderWidthL    = styleToNPx(borderWidthL);
445    this.borderWidthR    = styleToNPx(borderWidthR);
446    this.boxColour       = curvyObject.format_colour(boxColour);
447    this.topPadding      = styleToNPx(topPadding);
448    this.bottomPadding   = styleToNPx(bottomPadding);
449    this.leftPadding     = styleToNPx(leftPadding);
450    this.rightPadding    = styleToNPx(rightPadding);
451    this.boxWidth        = boxWidth;
452    this.boxHeight       = this.box.clientHeight;
453    this.borderColour    = curvyObject.format_colour(borderColour);
454    this.borderColourB   = curvyObject.format_colour(borderColourB);
455    this.borderColourL   = curvyObject.format_colour(borderColourL);
456    this.borderColourR   = curvyObject.format_colour(borderColourR);
457    this.borderString    = this.borderWidth + "px" + " " + borderStyle + " " + this.borderColour;
458    this.borderStringB   = this.borderWidthB + "px" + " " + borderStyleB + " " + this.borderColourB;
459    this.borderStringL   = this.borderWidthL + "px" + " " + borderStyleL + " " + this.borderColourL;
460    this.borderStringR   = this.borderWidthR + "px" + " " + borderStyleR + " " + this.borderColourR;
461    this.backgroundImage = ((backgroundImage != "none")? backgroundImage : "");
462    this.backgroundRepeat= backgroundRepeat;
463  }
464  catch(e) {
465    throw this.newError(e.message);
466  }
467  var clientHeight = this.boxHeight;
468  var clientWidth = boxWidth; // save it as it gets trampled on later
469  if (curvyBrowser.isOp) {
470    backgroundPosX = styleToNPx(backgroundPosX);
471    backgroundPosY = styleToNPx(backgroundPosY);
472    if (backgroundPosX) {
473      var t = clientWidth + this.borderWidthL + this.borderWidthR;
474      if (backgroundPosX > t) backgroundPosX = t;
475      backgroundPosX = (t / backgroundPosX * 100) + '%'; // convert to percentage
476    }
477    if (backgroundPosY) {
478      var t = clientHeight + this.borderWidth + this.borderWidthB;
479      if (backgroundPosY > t) backgroundPosY = t;
480      backgroundPosY = (t / backgroundPosY * 100) + '%'; // convert to percentage
481    }
482  }
483  if (curvyBrowser.quirksMode) {
484  }
485  else {
486    this.boxWidth -= this.leftPadding + this.rightPadding;
487    this.boxHeight -= this.topPadding + this.bottomPadding;
488  }
489
490  // Create content container
491  this.contentContainer = document.createElement("div");
492  if (filter) this.contentContainer.style.filter = filter; // IE8 bug fix
493  while (this.box.firstChild) this.contentContainer.appendChild(this.box.removeChild(this.box.firstChild));
494
495  if (boxPosition != "absolute") this.box.style.position = "relative";
496  this.box.style.padding = '0';
497  this.box.style.border = this.box.style.backgroundImage = 'none';
498  this.box.style.backgroundColor = 'transparent';
499
500  this.box.style.width   = (clientWidth + this.borderWidthL + this.borderWidthR) + 'px';
501  this.box.style.height  = (clientHeight + this.borderWidth + this.borderWidthB) + 'px';
502
503  // Ok we add an inner div to actually put things into this will allow us to keep the height
504
505  var newMainContainer = document.createElement("div");
506  newMainContainer.style.position = "absolute";
507  if (filter) newMainContainer.style.filter = filter; // IE8 bug fix
508  if (curvyBrowser.quirksMode) {
509    newMainContainer.style.width  = (clientWidth + this.borderWidthL + this.borderWidthR) + 'px';
510  } else {
511    newMainContainer.style.width  = clientWidth + 'px';
512  }
513  newMainContainer.style.height = min0Px(clientHeight + this.borderWidth + this.borderWidthB - topMaxRadius - botMaxRadius);
514  newMainContainer.style.padding  = "0";
515  newMainContainer.style.top    = topMaxRadius + "px";
516  newMainContainer.style.left   = "0";
517  if (this.borderWidthL)
518    newMainContainer.style.borderLeft = this.borderStringL;
519  if (this.borderWidth && !topMaxRadius)
520    newMainContainer.style.borderTop = this.borderString;
521  if (this.borderWidthR)
522    newMainContainer.style.borderRight = this.borderStringR;
523  if (this.borderWidthB && !botMaxRadius)
524    newMainContainer.style.borderBottom = this.borderStringB;
525  newMainContainer.style.backgroundColor    = boxColour;
526  newMainContainer.style.backgroundImage    = this.backgroundImage;
527  newMainContainer.style.backgroundRepeat   = this.backgroundRepeat;
528  newMainContainer.style.direction = 'ltr';
529  this.shell = this.box.appendChild(newMainContainer);
530
531  boxWidth = curvyBrowser.get_style(this.shell, "width");
532  if (boxWidth === "" || boxWidth === "auto" || boxWidth.indexOf("%") !== -1) throw this.newError('Shell width is ' + boxWidth);
533  this.boxWidth = (boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1) ? parseInt(boxWidth) : this.shell.clientWidth;
534
535  /*
536    This method creates the corners and
537    applies them to the div element.
538  */
539  this.applyCorners = function() {
540    /*
541      Set up background offsets. This may need to be delayed until
542      the background image is loaded.
543    */
544    this.backgroundPosX = this.backgroundPosY = 0;
545    if (this.backgroundObject) {
546      var bgOffset = function(style, imglen, boxlen) {
547        if (style === 0) return 0;
548        var retval;
549        if (style === 'right' || style === 'bottom') return boxlen - imglen;
550        if (style === 'center') return (boxlen - imglen) / 2;
551        if (style.indexOf('%') > 0) return (boxlen - imglen) * 100 / parseInt(style);
552        return styleToNPx(style);
553      }
554      this.backgroundPosX  = bgOffset(backgroundPosX, this.backgroundObject.width, clientWidth);
555      this.backgroundPosY  = bgOffset(backgroundPosY, this.backgroundObject.height, clientHeight);
556    }
557    else if (this.backgroundImage) {
558      this.backgroundPosX = styleToNPx(backgroundPosX);
559      this.backgroundPosY = styleToNPx(backgroundPosY);
560    }
561    /*
562      Create top and bottom containers.
563      These will be used as a parent for the corners and bars.
564    */
565    // Build top bar only if a top corner is to be drawn
566    if (topMaxRadius) {
567      newMainContainer = document.createElement("div");
568      newMainContainer.style.width = this.boxWidth + "px";
569      newMainContainer.style.fontSize = "1px";
570      newMainContainer.style.overflow = "hidden";
571      newMainContainer.style.position = "absolute";
572      newMainContainer.style.paddingLeft  = this.borderWidth + "px";
573      newMainContainer.style.paddingRight = this.borderWidth + "px";
574      newMainContainer.style.height = topMaxRadius + "px";
575      newMainContainer.style.top    = -topMaxRadius + "px";
576      newMainContainer.style.left   = -this.borderWidthL + "px";
577      this.topContainer = this.shell.appendChild(newMainContainer);
578    }
579    // Build bottom bar only if a bottom corner is to be drawn
580    if (botMaxRadius) {
581      var newMainContainer = document.createElement("div");
582      newMainContainer.style.width = this.boxWidth + "px";
583      newMainContainer.style.fontSize = "1px";
584      newMainContainer.style.overflow = "hidden";
585      newMainContainer.style.position = "absolute";
586      newMainContainer.style.paddingLeft  = this.borderWidthB + "px";
587      newMainContainer.style.paddingRight = this.borderWidthB + "px";
588      newMainContainer.style.height   =  botMaxRadius + "px";
589      newMainContainer.style.bottom   = -botMaxRadius + "px";
590      newMainContainer.style.left     = -this.borderWidthL + "px";
591      this.bottomContainer = this.shell.appendChild(newMainContainer);
592    }
593
594
595    var corners = this.spec.cornerNames();  // array of available corners
596
597    /*
598    Loop for each corner
599    */
600    for (var i in corners) if (!isNaN(i)) {
601      // Get current corner type from array
602      var cc = corners[i];
603      var specRadius = this.spec[cc + 'R'];
604      // Has the user requested the currentCorner be round?
605      // Code to apply correct color to top or bottom
606      var bwidth, bcolor, borderRadius, borderWidthTB;
607      if (cc == "tr" || cc == "tl") {
608        bwidth = this.borderWidth;
609        bcolor = this.borderColour;
610        borderWidthTB = this.borderWidth;
611      } else {
612        bwidth = this.borderWidthB;
613        bcolor = this.borderColourB;
614        borderWidthTB = this.borderWidthB;
615      }
616      borderRadius = specRadius - borderWidthTB;
617      var newCorner = document.createElement("div");
618      newCorner.style.height = this.spec.get(cc + 'Ru');
619      newCorner.style.width  = this.spec.get(cc + 'Ru');
620      newCorner.style.position = "absolute";
621      newCorner.style.fontSize = "1px";
622      newCorner.style.overflow = "hidden";
623      // THE FOLLOWING BLOCK OF CODE CREATES A ROUNDED CORNER
624      // ---------------------------------------------------- TOP
625      var intx, inty, outsideColour;
626      var trans = filter ? parseInt(/alpha\(opacity.(\d+)\)/.exec(filter)[1]) : 100; // IE8 bug fix
627      // Cycle the x-axis
628      for (intx = 0; intx < specRadius; ++intx) {
629        // Calculate the value of y1 which identifies the pixels inside the border
630        var y1 = (intx + 1 >= borderRadius) ? -1 : Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow(intx + 1, 2))) - 1;
631        // Calculate y2 and y3 only if there is a border defined
632        if (borderRadius != specRadius) {
633          var y2 = (intx >= borderRadius) ? -1 : Math.ceil(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow(intx, 2)));
634          var y3 = (intx + 1 >= specRadius) ? -1 : Math.floor(Math.sqrt(Math.pow(specRadius, 2) - Math.pow((intx+1), 2))) - 1;
635        }
636        // Calculate y4
637        var y4 = (intx >= specRadius) ? -1 : Math.ceil(Math.sqrt(Math.pow(specRadius, 2) - Math.pow(intx, 2)));
638        // Draw bar on inside of the border with foreground colour
639        if (y1 > -1) this.drawPixel(intx, 0, this.boxColour, trans, (y1 + 1), newCorner, true, specRadius);
640        // Draw border/foreground antialiased pixels and border only if there is a border defined
641        if (borderRadius != specRadius) {
642          // Cycle the y-axis
643          if (this.spec.antiAlias) {
644            for (inty = y1 + 1; inty < y2; ++inty) {
645              // For each of the pixels that need anti aliasing between the foreground and border colour draw single pixel divs
646              if (this.backgroundImage != "") {
647                var borderFract = curvyObject.pixelFraction(intx, inty, borderRadius) * 100;
648                this.drawPixel(intx, inty, bcolor, trans, 1, newCorner, borderFract >= 30, specRadius);
649              }
650              else if (this.boxColour !== 'transparent') {
651                var pixelcolour = curvyObject.BlendColour(this.boxColour, bcolor, curvyObject.pixelFraction(intx, inty, borderRadius));
652                this.drawPixel(intx, inty, pixelcolour, trans, 1, newCorner, false, specRadius);
653              }
654              else this.drawPixel(intx, inty, bcolor, trans >> 1, 1, newCorner, false, specRadius);
655            }
656            // Draw bar for the border
657            if (y3 >= y2) {
658              if (y2 == -1) y2 = 0;
659              this.drawPixel(intx, y2, bcolor, trans, (y3 - y2 + 1), newCorner, false, 0);
660            }
661            outsideColour = bcolor;  // Set the colour for the outside AA curve
662            inty = y3;               // start_pos - 1 for y-axis AA pixels
663          }
664          else { // no antiAlias
665            if (y3 > y1) { // NB condition was >=, changed to avoid zero-height divs
666              this.drawPixel(intx, (y1 + 1), bcolor, trans, (y3 - y1), newCorner, false, 0);
667            }
668          }
669        }
670        else {
671          outsideColour = this.boxColour;  // Set the colour for the outside curve
672          inty = y1;               // start_pos - 1 for y-axis AA pixels
673        }
674        // Draw aa pixels?
675        if (this.spec.antiAlias) {
676          // Cycle the y-axis and draw the anti aliased pixels on the outside of the curve
677          while (++inty < y4) {
678            // For each of the pixels that need anti aliasing between the foreground
678/border colour & background draw single pixel divs
679            this.drawPixel(intx, inty, outsideColour, (curvyObject.pixelFraction(intx, inty , specRadius) * trans), 1, newCorner, borderWidthTB <= 0, specRadius);
680          }
681        }
682      }
683      // END OF CORNER CREATION
684      // ---------------------------------------------------- END
685
686      /*
687      Now we have a new corner we need to reposition all the pixels unless
688      the current corner is the bottom right.
689      */
690      // Loop through all children (pixel bars)
691      for (var t = 0, k = newCorner.childNodes.length; t < k; ++t) {
692        // Get current pixel bar
693        var pixelBar = newCorner.childNodes[t];
694        // Get current top and left properties
695        var pixelBarTop    = parseInt(pixelBar.style.top);
696        var pixelBarLeft   = parseInt(pixelBar.style.left);
697        var pixelBarHeight = parseInt(pixelBar.style.height);
698        // Reposition pixels
699        if (cc == "tl" || cc == "bl") {
700          pixelBar.style.left = (specRadius - pixelBarLeft - 1) + "px"; // Left
701        }
702        if (cc == "tr" || cc == "tl"){
703          pixelBar.style.top =  (specRadius - pixelBarHeight - pixelBarTop) + "px"; // Top
704        }
705        pixelBar.style.backgroundRepeat = this.backgroundRepeat;
706
707        if (this.backgroundImage) switch(cc) {
708          case "tr":
709            pixelBar.style.backgroundPosition = (this.backgroundPosX - this.borderWidthL + specRadius - clientWidth - pixelBarLeft) + "px " + (this.backgroundPosY + pixelBarHeight + pixelBarTop + this.borderWidth - specRadius) + "px";
710          break;
711          case "tl":
712            pixelBar.style.backgroundPosition = (this.backgroundPosX - specRadius + pixelBarLeft + 1 + this.borderWidthL) + "px " + (this.backgroundPosY - specRadius + pixelBarHeight + pixelBarTop + this.borderWidth) + "px";
713          break;
714          case "bl":
715            pixelBar.style.backgroundPosition = (this.backgroundPosX - specRadius + pixelBarLeft + 1 + this.borderWidthL) + "px " + (this.backgroundPosY - clientHeight - this.borderWidth + (curvyBrowser.quirksMode ? pixelBarTop : -pixelBarTop) + specRadius) + "px";
716          break;
717          case "br":
718            if (curvyBrowser.quirksMode) {
719              pixelBar.style.backgroundPosition = (this.backgroundPosX - this.borderWidthL - clientWidth + specRadius - pixelBarLeft) + "px " + (this.backgroundPosY - clientHeight - this.borderWidth + pixelBarTop + specRadius) + "px";
720            } else {
721              pixelBar.style.backgroundPosition = (this.backgroundPosX - this.borderWidthL - clientWidth + specRadius - pixelBarLeft) + "px " + (this.backgroundPosY - clientHeight - this.borderWidth + specRadius - pixelBarTop) + "px";
722            }
723          //break;
724        }
725      }
726
727      // Position the container
728      switch (cc) {
729        case "tl":
730          newCorner.style.top = newCorner.style.left = "0";
731          this.topContainer.appendChild(newCorner);
732        break;
733        case "tr":
734          newCorner.style.top = newCorner.style.right = "0";
735          this.topContainer.appendChild(newCorner);
736        break;
737        case "bl":
738          newCorner.style.bottom = newCorner.style.left = "0";
739          this.bottomContainer.appendChild(newCorner);
740        break;
741        case "br":
742          newCorner.style.bottom = newCorner.style.right = "0";
743          this.bottomContainer.appendChild(newCorner);
744        //break;
745      }
746    }
747
748    /*
749      The last thing to do is draw the rest of the filler DIVs.
750    */
751
752    // Find out which corner has the bigger radius and get the difference amount
753    var radiusDiff = {
754      t : this.spec.radiusdiff('t'),
755      b : this.spec.radiusdiff('b')
756    };
757
758    for (z in radiusDiff) {
759      if (typeof z === 'function') continue; // for prototype, mootools frameworks
760      if (!this.spec.get(z + 'R')) continue; // no need if no corners
761      if (radiusDiff[z]) {
762        // Get the type of corner that is the smaller one
763        var smallerCornerType = (this.spec[z + "lR"] < this.spec[z + "rR"]) ? z + "l" : z + "r";
764
765        // First we need to create a DIV for the space under the smaller corner
766        var newFiller = document.createElement("div");
767        newFiller.style.height = radiusDiff[z] + "px";
768        newFiller.style.width  =  this.spec.get(smallerCornerType + 'Ru');
769        newFiller.style.position = "absolute";
770        newFiller.style.fontSize = "1px";
771        newFiller.style.overflow = "hidden";
772        newFiller.style.backgroundColor = this.boxColour;
773        if (filter) newFiller.style.filter = filter; // IE8 bug fix
774        // Set background image with original features
775        newFiller.style.backgroundImage = this.backgroundImage;
776        newFiller.style.backgroundRepeat = this.backgroundRepeat;
777
778        // Position filler
779        switch (smallerCornerType) {
780          case "tl":
781            newFiller.style.bottom =
782            newFiller.style.left   = "0";
783            newFiller.style.borderLeft = this.borderStringL;
784            // Set background image in original position
785            newFiller.style.backgroundPosition = this.backgroundPosX + "px " + (this.borderWidth + this.backgroundPosY - this.spec.tlR) + "px";
786            this.topContainer.appendChild(newFiller);
787          break;
788          case "tr":
789            newFiller.style.bottom =
790            newFiller.style.right  = "0";
791            newFiller.style.borderRight = this.borderStringR;
792            // Set background image in original position
793            newFiller.style.backgroundPosition = (this.backgroundPosX - this.boxWidth + this.spec.trR) + "px " + (this.borderWidth + this.backgroundPosY - this.spec.trR) + "px";
794            this.topContainer.appendChild(newFiller);
795          break;
796          case "bl":
797            newFiller.style.top    =
798            newFiller.style.left   = "0";
799            newFiller.style.borderLeft = this.borderStringL;
800            // Set background image in original position
801            newFiller.style.backgroundPosition = this.backgroundPosX + "px " + (this.backgroundPosY - this.borderWidth - this.boxHeight + radiusDiff[z] + this.spec.blR) + "px";
802            this.bottomContainer.appendChild(newFiller);
803          break;
804          case "br":
805            newFiller.style.top    =
806            newFiller.style.right  = "0";
807            newFiller.style.borderRight = this.borderStringR;
808            // Set background image in original position.
809            newFiller.style.backgroundPosition = (this.borderWidthL + this.backgroundPosX - this.boxWidth + this.spec.brR) + "px " + (this.backgroundPosY - this.borderWidth - this.boxHeight + radiusDiff[z] + this.spec.brR) + "px";
810            this.bottomContainer.appendChild(newFiller);
811          //break;
812        }
813      }
814
815
816      // Create the bar to fill the gap between each corner horizontally
817      var newFillerBar = document.createElement("div");
818      if (filter) newFillerBar.style.filter = filter; // IE8 bug fix
819      newFillerBar.style.position = "relative";
820      newFillerBar.style.fontSize = "1px";
821      newFillerBar.style.overflow = "hidden";
822      newFillerBar.style.width = this.fillerWidth(z);
823      newFillerBar.style.backgroundColor = this.boxColour;
824      newFillerBar.style.backgroundImage = this.backgroundImage;
825      newFillerBar.style.backgroundRepeat= this.backgroundRepeat;
826
827      switch (z) {
828        case "t":
829          // Top Bar
830          if (this.topContainer) {
831            if (curvyBrowser.quirksMode) {
832              newFillerBar.style.height = 100 + topMaxRadius + "px";
833            } else {
834              newFillerBar.style.height = 100 + topMaxRadius - this.borderWidth + "px";
835            }
836            newFillerBar.style.marginLeft  = this.spec.tlR ? (this.spec.tlR - this.borderWidthL) + "px" : "0";
837            newFillerBar.style.borderTop   = this.borderString;
838            if (this.backgroundImage) {
839              var x_offset = this.spec.tlR ?
840                (this.borderWidthL + this.backgroundPosX - this.spec.tlR) + "px " : this.backgroundPosX + "px ";
841              newFillerBar.style.backgroundPosition  = x_offset + this.backgroundPosY + "px";
842              // Reposition the box's background image
843              this.shell.style.backgroundPosition = this.backgroundPosX + "px " + (this.backgroundPosY - topMaxRadius + this.borderWidthL) + "px";
844            }
845            this.topContainer.appendChild(newFillerBar);
846          }
847        break;
848        case "b":
849          if (this.bottomContainer) {
850            // Bottom Bar
851            if (curvyBrowser.quirksMode) {
852              newFillerBar.style.height     = botMaxRadius + "px";
853            } else {
854              newFillerBar.style.height     = botMaxRadius - this.borderWidthB + "px";
855            }
856            newFillerBar.style.marginLeft   = this.spec.blR ? (this.spec.blR - this.borderWidthL) + "px" : "0";
857            newFillerBar.style.borderBottom = this.borderStringB;
858            if (this.backgroundImage) {
859              var x_offset = this.spec.blR ?
860                (this.backgroundPosX + this.borderWidthL - this.spec.blR) + "px " : this.backgroundPosX + "px ";
861              newFillerBar.style.backgroundPosition = x_offset + (this.backgroundPosY - clientHeight - this.borderWidth + botMaxRadius) + "px";
862            }
863            this.bottomContainer.appendChild(newFillerBar);
864          }
865        //break;
866      }
867    }
868
869    // style content container
870    this.contentContainer.style.position = "absolute";
871    // contentContainer.style.border = "1px dotted #000"; // DEBUG, comment for production
872    this.contentContainer.className    = "autoPadDiv";
873    this.contentContainer.style.left   = this.borderWidthL + "px";
874    // Get padding amounts
875    // Apply top padding
876    this.contentContainer.style.paddingTop = this.topPadding + "px";
877    this.contentContainer.style.top = this.borderWidth + "px";
878    // skip bottom padding - it doesn't show!
879    // Apply left and right padding
880    this.contentContainer.style.paddingLeft = this.leftPadding + "px";
881    this.contentContainer.style.paddingRight = this.rightPadding + "px";
882    z = clientWidth;
883    if (!curvyBrowser.quirksMode) z -= this.leftPadding + this.rightPadding;
884    this.contentContainer.style.width = z + "px";
885    this.contentContainer.style.textAlign = curvyBrowser.get_style(this.box, 'textAlign');
886    this.box.style.textAlign = 'left'; // important otherwise layout goes wild
887
888    this.box.appendChild(this.contentContainer);
889    if (boxDisp) boxDisp.style.display = boxDispSave;
890  }
891  if (this.backgroundImage) {
892    backgroundPosX = this.backgroundCheck(backgroundPosX);
893    backgroundPosY = this.backgroundCheck(backgroundPosY);
894    if (this.backgroundObject) {
895      this.backgroundObject.holdingElement = this;
896      this.dispatch = this.applyCorners;
897      this.applyCorners = function() {
898        if (this.backgroundObject.complete)
899          this.dispatch();
900        else this.backgroundObject.onload = new Function('curvyObject.dispatch(this.holdingElement);');
901      }
902    }
903  }
904}
905
906curvyObject.prototype.backgroundCheck = function(style) {
907  if (style === 'top' || style === 'left' || parseInt(style) === 0) return 0;
908  if (!(/^[-\d.]+px$/.test(style))  && !this.backgroundObject) {
909    this.backgroundObject = new Image;
910    var imgName = function(str) {
911      var matches = /url\("?([^'"]+)"?\)/.exec(str);
912      return (matches ? matches[1] : str);
913    }
914    this.backgroundObject.src = imgName(this.backgroundImage);
915  }
916  return style;
917}
918
919curvyObject.dispatch = function(obj) {
920  if ('dispatch' in obj)
921    obj.dispatch();
922  else throw obj.newError('No dispatch function');
923}
924
925// append a pixel DIV to newCorner
926
927curvyObject.prototype.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius) {
928  var pixel = document.createElement("div");
929  pixel.style.height   = height + "px";
930  pixel.style.width    = "1px";
931  pixel.style.position = "absolute";
932  pixel.style.fontSize = "1px";
933  pixel.style.overflow = "hidden";
934  var topMaxRadius = this.spec.get('tR');
935  pixel.style.backgroundColor = colour;
936  // Don't apply background image to border pixels
937  if (image && this.backgroundImage != "") {
938    pixel.style.backgroundImage = this.backgroundImage;
939    pixel.style.backgroundPosition  = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + topMaxRadius + inty) - this.borderWidth) + "px";
940  }
941  // Set opacity if the transparency is anything other than 100
942  if (transAmount != 100) curvyObject.setOpacity(pixel, transAmount);
943  // Set position
944  pixel.style.top = inty + "px";
945  pixel.style.left = intx + "px";
946  //pixel.nodeValue = ' ';
947  newCorner.appendChild(pixel);
948}
949
950curvyObject.prototype.fillerWidth = function(tb) {
951  var b_width, f_width;
952  b_width = curvyBrowser.quirksMode ? 0 : this.spec.radiusCount(tb) * this.borderWidthL;
953  if ((f_width = this.boxWidth - this.spec.radiusSum(tb) + b_width) < 0)
954    throw this.newError("Radius exceeds box width");
955  return f_width + 'px';
956}
957
958curvyObject.prototype.errmsg = function(msg, gravity) {
959  var extradata = "\ntag: " + this.box.tagName;
960  if (this.box.id) extradata += "\nid: " + this.box.id;
961  if (this.box.className) extradata += "\nclass: " + this.box.className;
962  var parent;
963  if ((parent = this.box.parentNode) === null)
964    extradata += "\n(box has no parent)";
965  else {
966    extradata += "\nParent tag: " + parent.tagName;
967    if (parent.id) extradata += "\nParent ID: " + parent.id;
968    if (parent.className) extradata += "\nParent class: " + parent.className;
969  }
970  if (gravity === undefined) gravity = 'warning';
971  return 'curvyObject ' + gravity + ":\n" + msg + extradata;
972}
973
974curvyObject.prototype.newError = function(msg) {
975  return new Error(this.errmsg(msg, 'exception'));
976}
977
978// ------------- UTILITY FUNCTIONS
979
980//  Convert a number 0..255 to hex
981
982
983curvyObject.IntToHex = function(strNum) {
984  var hexdig = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' ];
985
986  return hexdig[strNum >>> 4] + '' + hexdig[strNum & 15];
987}
988
989/*
990  Blends the two colours by the fraction
991  returns the resulting colour as a string in the format "#FFFFFF"
992*/
993
994curvyObject.BlendColour = function(Col1, Col2, Col1Fraction) {
995  if (Col1 === 'transparent' || Col2 === 'transparent') throw this.newError('Cannot blend with transparent');
996  if (Col1.charAt(0) !== '#') {
997    //curvyCorners.alert('Found colour1 ' + Col1 + ': please let us know you saw this report.');
998    Col1 = curvyObject.format_colour(Col1);
999  }
1000  if (Col2.charAt(0) !== '#') {
1001    //curvyCorners.alert('Found colour2 ' + Col2 + ': please let us know you saw this report.');
1002    Col2 = curvyObject.format_colour(Col2);
1003  }
1004  var red1 = parseInt(Col1.substr(1, 2), 16);
1005  var green1 = parseInt(Col1.substr(3, 2), 16);
1006  var blue1 = parseInt(Col1.substr(5, 2), 16);
1007  var red2 = parseInt(Col2.substr(1, 2), 16);
1008  var green2 = parseInt(Col2.substr(3, 2), 16);
1009  var blue2 = parseInt(Col2.substr(5, 2), 16);
1010
1011  if (Col1Fraction > 1 || Col1Fraction < 0) Col1Fraction = 1;
1012
1013  var endRed = Math.round((red1 * Col1Fraction) + (red2 * (1 - Col1Fraction)));
1014  if (endRed > 255) endRed = 255;
1015  if (endRed < 0) endRed = 0;
1016
1017
1018  var endGreen = Math.round((green1 * Col1Fraction) + (green2 * (1 - Col1Fraction)));
1019  if (endGreen > 255) endGreen = 255;
1020  if (endGreen < 0) endGreen = 0;
1021
1022  var endBlue = Math.round((blue1 * Col1Fraction) + (blue2 * (1 - Col1Fraction)));
1023  if (endBlue > 255) endBlue = 255;
1024  if (endBlue < 0) endBlue = 0;
1025
1026  return "#" + curvyObject.IntToHex(endRed) + curvyObject.IntToHex(endGreen)+ curvyObject.IntToHex(endBlue);
1027}
1028
1029/*
1030  For a pixel cut by the line determines the fraction of the pixel on the 'inside' of the
1031  line.  Returns a number between 0 and 1
1032*/
1033
1034curvyObject.pixelFraction = function(x, y, r) {
1035  var fraction;
1036  var rsquared = r * r;
1037
1038  /*
1039    determine the co-ordinates of the two points on the perimeter of the pixel that the
1040    circle crosses
1041  */
1042  var xvalues = new Array(2);
1043  var yvalues = new Array(2);
1044  var point = 0;
1045  var whatsides = "";
1046
1047  // x + 0 = Left
1048  var intersect = Math.sqrt(rsquared - Math.pow(x, 2));
1049
1050  if (intersect >= y && intersect < (y + 1)) {
1051    whatsides = "Left";
1052    xvalues[point] = 0;
1053    yvalues[point] = intersect - y;
1054    ++point;
1055  }
1056  // y + 1 = Top
1057  intersect = Math.sqrt(rsquared - Math.pow(y + 1, 2));
1058
1059  if (intersect >= x && intersect < (x + 1)) {
1060    whatsides += "Top";
1061    xvalues[point] = intersect - x;
1062    yvalues[point] = 1;
1063    ++point;
1064  }
1065  // x + 1 = Right
1066  intersect = Math.sqrt(rsquared - Math.pow(x + 1, 2));
1067
1068  if (intersect >= y && intersect < (y + 1)) {
1069    whatsides += "Right";
1070    xvalues[point] = 1;
1071    yvalues[point] = intersect - y;
1072    ++point;
1073  }
1074  // y + 0 = Bottom
1075  intersect = Math.sqrt(rsquared - Math.pow(y, 2));
1076
1077  if (intersect >= x && intersect < (x + 1)) {
1078    whatsides += "Bottom";
1079    xvalues[point] = intersect - x;
1080    yvalues[point] = 0;
1081  }
1082
1083  /*
1084    depending on which sides of the perimeter of the pixel the circle crosses calculate the
1085    fraction of the pixel inside the circle
1086  */
1087  switch (whatsides) {
1088    case "LeftRight":
1089      fraction = Math.min(yvalues[0], yvalues[1]) + ((Math.max(yvalues[0], yvalues[1]) - Math.min(yvalues[0], yvalues[1])) / 2);
1090    break;
1091
1092    case "TopRight":
1093      fraction = 1 - (((1 - xvalues[0]) * (1 - yvalues[1])) / 2);
1094    break;
1095
1096    case "TopBottom":
1097      fraction = Math.min(xvalues[0], xvalues[1]) + ((Math.max(xvalues[0], xvalues[1]) - Math.min(xvalues[0], xvalues[1])) / 2);
1098    break;
1099
1100    case "LeftBottom":
1101      fraction = yvalues[0] * xvalues[1] / 2;
1102    break;
1103
1104    default:
1105      fraction = 1;
1106  }
1107
1108  return fraction;
1109}
1110
1111// Returns an array of rgb values
1112
1113curvyObject.rgb2Array = function(rgbColour) {
1114  // Remove rgb()
1115  var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")"));
1116
1117  // Split RGB into array
1118  return rgbValues.split(", ");
1119}
1120
1121// This function converts CSS rgb(x, x, x) to hexadecimal
1122
1123curvyObject.rgb2Hex = function(rgbColour) {
1124  try {
1125    // Get array of RGB values
1126    var rgbArray = curvyObject.rgb2Array(rgbColour);
1127
1128    // Get RGB values
1129    var red   = parseInt(rgbArray[0]);
1130    var green = parseInt(rgbArray[1]);
1131    var blue  = parseInt(rgbArray[2]);
1132
1133    // Build hex colour code
1134    var hexColour = "#" + curvyObject.IntToHex(red) + curvyObject.IntToHex(green) + curvyObject.IntToHex(blue);
1135  }
1136  catch (e) {
1137    var msg = 'getMessage' in e ? e.getMessage() : e.message;
1138    throw new Error("Error (" + msg + ") converting RGB value to Hex in rgb2Hex");
1139  }
1140
1141  return hexColour;
1142}
1143
1144/*
1145  Function by Simon Willison from sitepoint.com
1146  Modified by Cameron Cooke adding Safari's rgba support
1147*/
1148
1149curvyObject.setOpacity = function(obj, opacity) {
1150  opacity = (opacity == 100) ? 99.999 : opacity;
1151
1152  if (curvyBrowser.isSafari && obj.tagName != "IFRAME") {
1153    // Get array of RGB values
1154    var rgbArray = curvyObject.rgb2Array(obj.style.backgroundColor);
1155
1156    // Get RGB values
1157    var red   = parseInt(rgbArray[0]);
1158    var green = parseInt(rgbArray[1]);
1159    var blue  = parseInt(rgbArray[2]);
1160
1161    // Safari using RGBA support
1162    obj.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity/100 + ")";
1163  }
1164  else if (typeof obj.style.opacity !== "undefined") { // W3C
1165    obj.style.opacity = opacity / 100;
1166  }
1167  else if (typeof obj.style.MozOpacity !== "undefined") { // Older Mozilla
1168    obj.style.MozOpacity = opacity / 100;
1169  }
1170  else if (typeof obj.style.filter !== "undefined") { // IE
1171    obj.style.filter = "alpha(opacity=" + opacity + ")";
1172  }
1173  else if (typeof obj.style.KHTMLOpacity !== "undefined") { // Older KHTML-based browsers
1174    obj.style.KHTMLOpacity = opacity / 100;
1175  }
1176}
1177
1178
1179// Cross browser add event wrapper
1180
1181curvyCorners.addEvent = function(elm, evType, fn, useCapture) {
1182  if (elm.addEventListener) {
1183    elm.addEventListener(evType, fn, useCapture);
1184    return true;
1185  }
1186  if (elm.attachEvent) return elm.attachEvent('on' + evType, fn);
1187  elm['on' + evType] = fn;
1188  return false;
1189}
1190if (typeof addEvent === 'undefined') addEvent = curvyCorners.addEvent; // only if necessary
1191
1192// Gets the computed colour.
1193curvyObject.getComputedColour = function(colour) {
1194  var d = document.createElement('DIV');
1195  d.style.backgroundColor = colour;
1196  document.body.appendChild(d);
1197
1198  if (window.getComputedStyle) { // Mozilla, Opera, Chrome, Safari
1199    var rtn = document.defaultView.getComputedStyle(d, null).getPropertyValue('background-color');
1200    d.parentNode.removeChild(d);
1201    if (rtn.substr(0, 3) === "rgb") rtn = curvyObject.rgb2Hex(rtn);
1202    return rtn;
1203  }
1204  else { // IE
1205    var rng = document.body.createTextRange();
1206    rng.moveToElementText(d);
1207    rng.execCommand('ForeColor', false, colour);
1208    var iClr = rng.queryCommandValue('ForeColor');
1209    var rgb = "rgb("+(iClr & 0xFF)+", "+((iClr & 0xFF00)>>8)+", "+((iClr & 0xFF0000)>>16)+")";
1210    d.parentNode.removeChild(d);
1211    rng = null;
1212    return curvyObject.rgb2Hex(rgb);
1213  }
1214}
1215
1216// convert colour name, rgb() and #RGB to #RRGGBB
1217curvyObject.format_colour = function(colour) {
1218  // Make sure colour is set and not transparent
1219  if (colour != "" && colour != "transparent") {
1220    // RGB Value?
1221    if (colour.substr(0, 3) === "rgb") {
1222      // Get HEX aquiv.
1223      colour = curvyObject.rgb2Hex(colour);
1224    }
1225    else if (colour.charAt(0) !== '#') {
1226      // Convert colour name to hex value
1227      colour = curvyObject.getComputedColour(colour);
1228    }
1229    else if (colour.length === 4) {
1230      // 3 chr colour code add remainder
1231      colour = "#" + colour.charAt(1) + colour.charAt(1) + colour.charAt(2) + colour.charAt(2) + colour.charAt(3) + colour.charAt(3);
1232    }
1233  }
1234  return colour;
1235}
1236
1237
1238// Get elements by class by Dustin Diaz / CPKS
1239// NB if searchClass is a class name, it MUST be preceded by '.'
1240
1241curvyCorners.getElementsByClass = function(searchClass, node) {
1242  var classElements = new Array;
1243  if (node === undefined) node = document;
1244  searchClass = searchClass.split('.'); // see if there's a tag in there
1245  var tag = '*'; // prepare for no tag
1246  if (searchClass.length === 1) {
1247    tag = searchClass[0];
1248    searchClass = false;
1249  }
1250  else {
1251    if (searchClass[0]) tag = searchClass[0];
1252    searchClass = searchClass[1];
1253  }
1254  var i, els, elsLen;
1255  if (tag.charAt(0) === '#') {
1256    els = document.getElementById(tag.substr(1));
1257    if (els) classElements.push(els);
1258  }
1259  else {
1260    els = node.getElementsByTagName(tag);
1261    elsLen = els.length;
1262    if (searchClass) {
1263      var pattern = new RegExp("(^|\\s)" + searchClass + "(\\s|$)");
1264      for (i = 0; i < elsLen; ++i) {
1265        if (pattern.test(els[i].className)) classElements.push(els[i]);
1266      }
1267    }
1268    else for (i = 0; i < elsLen; ++i) classElements.push(els[i]);
1269  }
1270  return classElements;
1271}
1272
1273if (curvyBrowser.isMoz || curvyBrowser.isWebKit) {
1274  var curvyCornersNoAutoScan = true; // it won't do anything anyway.
1275  curvyCorners.init = function() {}; // make it harmless
1276}
1276
1277else {
1278
1279  // autoscan code
1280
1281  curvyCorners.scanStyles = function() {
1282    function units(num) {
1283      if (!parseInt(num)) return 'px'; // '0' becomes '0px' for simplicity's sake
1284      var matches = /^[\d.]+(\w+)$/.exec(num);
1285      return matches[1];
1286    }
1287    var t, i, j;
1288
1289    if (curvyBrowser.isIE) {
1290      function procIEStyles(rule) {
1291        var style = rule.style;
1292
1293        if (curvyBrowser.ieVer > 6.0) {
1294          var allR = style['-webkit-border-radius'] || 0;
1295          var tR   = style['-webkit-border-top-right-radius'] || 0;
1296          var tL   = style['-webkit-border-top-left-radius'] || 0;
1297          var bR   = style['-webkit-border-bottom-right-radius'] || 0;
1298          var bL   = style['-webkit-border-bottom-left-radius'] || 0;
1299        }
1300        else {
1301          var allR = style['webkit-border-radius'] || 0;
1302          var tR   = style['webkit-border-top-right-radius'] || 0;
1303          var tL   = style['webkit-border-top-left-radius'] || 0;
1304          var bR   = style['webkit-border-bottom-right-radius'] || 0;
1305          var bL   = style['webkit-border-bottom-left-radius'] || 0;
1306        }
1307        if (allR || tL || tR || bR || bL) {
1308          var settings = new curvyCnrSpec(rule.selectorText);
1309          if (allR)
1310            settings.setcorner(null, null, parseInt(allR), units(allR));
1311          else {
1312            if (tR) settings.setcorner('t', 'r', parseInt(tR), units(tR));
1313            if (tL) settings.setcorner('t', 'l', parseInt(tL), units(tL));
1314            if (bL) settings.setcorner('b', 'l', parseInt(bL), units(bL));
1315            if (bR) settings.setcorner('b', 'r', parseInt(bR), units(bR));
1316          }
1317          curvyCorners(settings);
1318        }
1319      }
1320      for (t = 0; t < document.styleSheets.length; ++t) {
1321        try {
1322          if (document.styleSheets[t].imports) {
1323            for (i = 0; i < document.styleSheets[t].imports.length; ++i)
1324              for (j = 0; j < document.styleSheets[t].imports[i].rules.length; ++j)
1325                procIEStyles(document.styleSheets[t].imports[i].rules[j]);
1326          }
1327          for (i = 0; i < document.styleSheets[t].rules.length; ++i)
1328            procIEStyles(document.styleSheets[t].rules[i]);
1329        }
1330        catch (e) {
1331          if (typeof curvyCornersVerbose !== 'undefined' && curvyCornersVerbose)
1332            alert(e.message + " - ignored");
1333        } // catch but ignore any permission error
1334      }
1335    }
1336    else if (curvyBrowser.isOp) {
1337      for (t = 0; t < document.styleSheets.length; ++t) {
1338        if (operasheet.contains_border_radius(t)) {
1339          j = new operasheet(t);
1340          for (i in j.rules) if (!isNaN(i))
1341            curvyCorners(j.rules[i]);
1342        }
1343      }
1344    }
1345    else curvyCorners.alert('Scanstyles does nothing in Webkit/Firefox');
1346  };
1347
1348  // Dean Edwards/Matthias Miller/John Resig
1349
1350  curvyCorners.init = function() {
1351    // quit if this function has already been called
1352    if (arguments.callee.done) return;
1353
1354    // flag this function so we don't do the same thing twice
1355    arguments.callee.done = true;
1356
1357    // kill the timer
1358    if (curvyBrowser.isWebKit && curvyCorners.init.timer) {
1359      clearInterval(curvyCorners.init.timer);
1360      curvyCorners.init.timer = null;
1361    }
1362
1363    // do stuff
1364    curvyCorners.scanStyles();
1365  };
1366}
1367
1368if (typeof curvyCornersNoAutoScan === 'undefined' || curvyCornersNoAutoScan === false) {
1369  if (curvyBrowser.isOp)
1370    document.addEventListener("DOMContentLoaded", curvyCorners.init, false);
1371  else curvyCorners.addEvent(window, 'load', curvyCorners.init, false);
1372}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.