/**
 * DD_roundies, this adds rounded-corner CSS in standard browsers and VML sublayers in IE that accomplish a similar appearance when comparing said browsers.
 * Author: Drew Diller
 * Email: drew.diller@gmail.com
 * URL: http://www.dillerdesign.com/experiment/DD_roundies/
 * Version: 0.0.2a
 * Licensed under the MIT License: http://dillerdesign.com/experiment/DD_roundies/#license
 *
 * Usage:
 * DD_roundies.addRule('#doc .container', '10px 5px'); // selector and multiple radii
 * DD_roundies.addRule('.box', 5, true); // selector, radius, and optional addition of border-radius code for standard browsers.
 *
 * Just want the PNG fixing effect for IE6, and don't want to also use the DD_belatedPNG library?  Don't give any additional arguments after the CSS selector.
 * DD_roundies.addRule('.your .example img');
 **/
var DD_roundies = {

   ns: 'DD_roundies',
   
   IE6: false,
   IE7: false,
   IE8: false,
   IEversion: function(){
      if (document.documentMode != 8 && document.namespaces && !document.namespaces[this.ns]) {
         this.IE6 = true;
         this.IE7 = true;
      } else if (document.documentMode == 8) {
         this.IE8 = true;
      }
   },
   querySelector: document.querySelectorAll,
   selectorsToProcess: [],
   imgSize: {},
   
   createVmlNameSpace: function(){ /* enable VML */
      if (this.IE6 || this.IE7) {
         document.namespaces.add(this.ns, 'urn:schemas-microsoft-com:vml');
      }
      if (this.IE8) {
         document.writeln('<?import namespace="' + this.ns + '" implementation="#default#VML" ?>');
      }
   },
   
   createVmlStyleSheet: function(){ /* style VML, enable behaviors */
      /*
       Just in case lots of other developers have added
       lots of other stylesheets using document.createStyleSheet
       and hit the 31-limit mark, let's not use that method!
       further reading: http://msdn.microsoft.com/en-us/library/ms531194(VS.85).aspx
       
       @Note Dale Larsen -- Here is a fix where I put the style element already on edit.jsp. This fixes render duplication
       */
      var style = document.getElementById('roundiesStyleBlock');
      if (!style) {
         style = document.createElement('style');
         //style.setAttribute('id', 'roundiesStyleBlock');
         document.documentElement.firstChild.insertBefore(style, document.documentElement.firstChild.firstChild);
      }
      if (style.styleSheet) { /* IE */
         try {
            var styleSheet = style.styleSheet;
            styleSheet.addRule(this.ns + '\\:*', '{behavior:url(#default#VML)}');
            this.styleSheet = styleSheet;
         } catch (err) {
         }
      } else {
         this.styleSheet = style;
      }
   },
   
   /**
    * Method to use from afar - refer to it whenever.
    * Example for IE only: DD_roundies.addRule('div.boxy_box', '10px 5px');
    * Example for IE, Firefox, and WebKit: DD_roundies.addRule('div.boxy_box', '10px 5px', true);
    * @param {String} selector - REQUIRED - a CSS selector, such as '#doc .container'
    * @param {Integer} radius - REQUIRED - the desired radius for the box corners
    * @param {Boolean} standards - OPTIONAL - true if you also wish to output -moz-border-radius/-webkit-border-radius/border-radius declarations
    * @param {Boolean} callback - OPTIONAL - set a function if you want to call this after a set has loaded to get a callback
    **/
   addRule: function(selector, rad, standards, callback, notInline){
      if ($.browser.msie || notInline) {
         //log('selector: ' + selector + '. rad: ' + rad + '. standards: ' + standards + '. callback: ' + callback + '. notInline: ' + notInline + '.');
         if (typeof rad == 'undefined' || rad === null) {
            rad = 0;
         }
         if (rad.constructor.toString().search('Array') == -1) {
            rad = rad.toString().replace(/[^0-9 ]/g, '').split(' ');
         }
         for (var i = 0; i < 4; i++) {
            rad[i] = (!rad[i] && rad[i] !== 0) ? rad[Math.max((i - 2), 0)] : rad[i];
         }
         if (this.styleSheet) {
            if (this.styleSheet.addRule) {
               /** remove old roundies before applying new ones, using jquery **/
               DD_roundies.createVmlNameSpace();
               var selectors = selector.split(','); /* multiple selectors supported, no need for multiple calls to this anymore */
               for (var i = 0; i < selectors.length; i++) {
                  if (selectors[i] && selectors != 'false' && selectors != ' false' && selectors != 'false ') {
                     var passObj = $(selectors[i]).get(0);
                     //DD_roundies.rerender(passObj);//not sure if this is needed
                     modSS.removeCssRule(selectors[i], this.styleSheet);//remove any previous rules of the same selector
                     //log(selectors[i] + ' : ' + passObj.id);
                     this.styleSheet.addRule(selectors[i], 'behavior:expression(DD_roundies.roundify.call(this, [' + rad.join(',') + '], ' + callback + '))'); /* seems to execute the function without adding it to the stylesheet - interesting... */
                  }
               }
            } else if (standards) {
               //log(selector + ' {border-radius:' + moz_implementation + '; -moz-border-radius:' + moz_implementation + ';}');
               var moz_implementation = rad.join('px ') + 'px';
               this.styleSheet.appendChild(document.createTextNode(selector + ' {border-radius:' + moz_implementation + '; -moz-border-radius:' + moz_implementation + ';}'));
               this.styleSheet.appendChild(document.createTextNode(selector + ' {-webkit-border-top-left-radius:' + rad[0] + 'px ' + rad[0] + 'px; -webkit-border-top-right-radius:' + rad[1] + 'px ' + rad[1] + 'px; -webkit-border-bottom-right-radius:' + rad[2] + 'px ' + rad[2] + 'px; -webkit-border-bottom-left-radius:' + rad[3] + 'px ' + rad[3] + 'px;}'));
            }
         } else if (this.IE8) {
            this.selectorsToProcess.push({
               'selector': selector,
               'radii': rad
            });
         }
      } else if (!$.browser.msie && standards && !notInline) {
         //log(selector + ' : ' + rad);
         doRoundCorners(selector, rad);
      }
   },
   
   readPropertyChanges: function(el){
      try {
         switch (event.propertyName) {
         
            case 'style.border':
            case 'style.borderStyle':
            case 'style.borderWidth':
            case 'style.padding':
            case 'style.backgroundColor':
            case 'style.backgroundImage':
            case 'style.backgroundPosition':
            case 'style.backgroundRepeat':
               this.applyVML(el);
               break;
            case 'style.borderColor':
               this.vmlStrokeColor(el);
               break;
            case 'style.display':
               el.vmlBox.style.display = (el.style.display == 'none') ? 'none' : 'block';
               break;
            case 'style.filter':
               this.vmlOpacity(el);
               break;
            case 'style.zIndex':
               el.vmlBox.style.zIndex = el.style.zIndex;
               this.applyVML(el);
               break;
            case 'innerHTML':
               this.rerender(el);
         }
      } catch (err) {
         //alert('error in dd_roundies: '+ err.description);
      }
   },
   
   applyVML: function(el, callback){
      el.runtimeStyle.cssText = '';
      this.vmlFill(el);
      this.vmlStrokeColor(el);
      this.vmlStrokeWeight(el);
      this.vmlStrokeStyle(el);
      this.vmlOffsets(el);
      this.vmlPath(el);
      this.nixBorder(el);
      this.vmlOpacity(el);
      if (callback) {
         callback.call(this);
      }
   },
   
   removeVML: function(el){
      //log('sanitize');
      if (el.runtimeStyle.cssText) el.runtimeStyle.cssText = '';//this is here for element that may have been removed and reinsterted into the DOM and therefore have no element
      if (el.firstChild && (el.firstChild.nodeName == 'ignore' || el.firstChild.nodeName == 'shape')) {
         //log('in: ' + el.id);
         el.removeChild(el.firstChild);
         el.runtimeStyle.cssText = '';
         DD_roundies.removeVML(el);
      }
   },
   
   rerender: function(el){
      DD_roundies.sanitize(el);
      //log(el.id);
      el.style.behavior = ''; /* Magic! As soon as behavior style is removed, document stylesheet somewhere will probably match it and execute the roundify function in the scope of this element again, effectively starting over from scratch. */
   },
   
   getNextValidSibling: function(el){ /* apparently, el.nextSibling wasn't enough, as a DD_roundy element appears to unwrap itself into 5 elements once in the DOM (???) */
      do {
         el = el.nextSibling;
      }
      while (el && (el.nodeName == 'ignore' || el.nodeName == 'shape'))
      return el;
   },
   
   sanitize: function(el){
      var collection = new Array();
      collection.push(el);
      var others = el.getElementsByTagName('ignore');
      var len = others.length;
      for (var i = 0; i < len; i++) {
         collection.push(DD_roundies.getNextValidSibling(others[i]));
      }
      len = collection.length;
      for (var i = 0; i < len; i++) {
         DD_roundies.removeVML(collection[i]);
      }
   },
   
   vmlOpacity: function(el){
      if (el.currentStyle.filter.search('lpha') != -1) {
         var trans = el.currentStyle.filter;
         trans = parseInt(trans.substring(trans.lastIndexOf('=') + 1, trans.lastIndexOf(')')), 10) / 100;
         for (var v in el.vml) {
            if (trans >= 0 && trans <= 1) {
               el.vml[v].filler.opacity = trans;
            }
         }
      }
   },
   
   vmlFill: function(el){
      if (!el.currentStyle) {
         return;
      } else {
         var elStyle = el.currentStyle;
      }
      el.runtimeStyle.backgroundColor = '';
      el.runtimeStyle.backgroundImage = '';
      var noColor = (elStyle.backgroundColor == 'transparent');
      var noImg = true;
      if (elStyle.backgroundImage != 'none' || el.isImg) {
         if (!el.isImg) {
            el.vmlBg = elStyle.backgroundImage;
            el.vmlBg = el.vmlBg.substr(5, el.vmlBg.lastIndexOf('")') - 5);
         } else {
            el.vmlBg = el.src;
         }
         var lib = this;
         if (!lib.imgSize[el.vmlBg]) { /* determine size of loaded image */
            var img = document.createElement('img');
            img.attachEvent('onload', function(){
               this.width = this.offsetWidth; /* weird cache-busting requirement! */
               this.height = this.offsetHeight;
               lib.vmlOffsets(el);
            });
            img.className = lib.ns + '_sizeFinder';
            img.runtimeStyle.cssText = 'behavior:none; position:absolute; top:-10000px; left:-10000px; border:none;'; /* make sure to set behavior to none to prevent accidental matching of the helper elements! */
            img.src = el.vmlBg;
            img.removeAttribute('width');
            img.removeAttribute('height');
            document.body.insertBefore(img, document.body.firstChild);
            lib.imgSize[el.vmlBg] = img;
         }
         el.vml.image.filler.src = el.vmlBg;
         noImg = false;
      }
      el.vml.image.filled = !noImg;
      el.vml.image.fillcolor = 'none';
      el.vml.color.filled = !noColor;
      el.vml.color.fillcolor = elStyle.backgroundColor;
      el.runtimeStyle.backgroundImage = 'none';
      el.runtimeStyle.backgroundColor = 'transparent';
   },
   
   vmlStrokeColor: function(el){
      el.vml.stroke.fillcolor = el.currentStyle.borderColor;
   },
   
   vmlStrokeWeight: function(el){
      var borders = ['Top', 'Right', 'Bottom', 'Left'];
      el.bW = {};
      for (var b = 0; b < 4; b++) {
         el.bW[borders[b]] = parseInt(el.currentStyle['border' + borders[b] + 'Width'], 10) || 0;
      }
   },
   
   vmlStrokeStyle: function(el){
      //add stroke style functionality here... someday
   },
   
   vmlOffsets: function(el){
      var dims = ['Left', 'Top', 'Width', 'Height'];
      for (var d = 0; d < 4; d++) {
         el.dim[dims[d]] = el['offset' + dims[d]];
      }
      var assign = function(obj, topLeft){
         obj.style.left = (topLeft ? 0 : el.dim.Left) + 'px';
         obj.style.top = (topLeft ? 0 : el.dim.Top) + 'px';
         obj.style.width = el.dim.Width + 'px';
         obj.style.height = el.dim.Height + 'px';
      };
      for (var v in el.vml) {
         var mult = (v == 'image') ? 1 : 2;
         el.vml[v].coordsize = (el.dim.Width * mult) + ', ' + (el.dim.Height * mult);
         assign(el.vml[v], true);
      }
      assign(el.vmlBox, false);
      el.vmlBox.style.zIndex = el.style.zIndex;//trying to get the zIndex to not be lost for the vmlBox, everytime I apply it, it changes
      if (DD_roundies.IE8) {
         el.vml.stroke.style.margin = '-1px';
         if (typeof el.bW == 'undefined') {
            this.vmlStrokeWeight(el);
         }
         el.vml.color.style.margin = (el.bW.Top - 1) + 'px ' + (el.bW.Left - 1) + 'px';
      }
   },
   
   vmlPath: function(el){
      var coords = function(direction, w, h, r, aL, aT, mult){
         var cmd = direction ? ['m', 'qy', 'l', 'qx', 'l', 'qy', 'l', 'qx', 'l'] : ['qx', 'l', 'qy', 'l', 'qx', 'l', 'qy', 'l', 'm']; /* whoa */
         aL *= mult;
         aT *= mult;
         w *= mult;
         h *= mult;
         var R = r.slice(); /* do not affect original array */
         for (var i = 0; i < 4; i++) {
            R[i] *= mult;
            R[i] = Math.min(w / 2, h / 2, R[i]); /* make sure you do not get funky shapes - pick the smallest: half of the width, half of the height, or current value */
         }
         var coords = [cmd[0] + Math.floor(0 + aL) + ',' + Math.floor(R[0] + aT), cmd[1] + Math.floor(R[0] + aL) + ',' + Math.floor(0 + aT), cmd[2] + Math.ceil(w - R[1] + aL) + ',' + Math.floor(0 + aT), cmd[3] + Math.ceil(w + aL) + ',' + Math.floor(R[1] + aT), cmd[4] + Math.ceil(w + aL) + ',' + Math.ceil(h - R[2] + aT), cmd[5] + Math.ceil(w - R[2] + aL) + ',' + Math.ceil(h + aT), cmd[6] + Math.floor(R[3] + aL) + ',' + Math.ceil(h + aT), cmd[7] + Math.floor(0 + aL) + ',' + Math.ceil(h - R[3] + aT), cmd[8] + Math.floor(0 + aL) + ',' + Math.floor(R[0] + aT)];
         if (!direction) {
            coords.reverse();
         }
         var path = coords.join('');
         return path;
      };
      
      if (typeof el.bW == 'undefined') {
         this.vmlStrokeWeight(el);
      }
      var bW = el.bW;
      var rad = el.DD_radii.slice();
      
      /* determine outer curves */
      var outer = coords(true, el.dim.Width, el.dim.Height, rad, 0, 0, 2);
      
      /* determine inner curves */
      rad[0] -= Math.max(bW.Left, bW.Top);
      rad[1] -= Math.max(bW.Top, bW.Right);
      rad[2] -= Math.max(bW.Right, bW.Bottom);
      rad[3] -= Math.max(bW.Bottom, bW.Left);
      for (var i = 0; i < 4; i++) {
         rad[i] = Math.max(rad[i], 0);
      }
      var inner = coords(false, el.dim.Width - bW.Left - bW.Right, el.dim.Height - bW.Top - bW.Bottom, rad, bW.Left, bW.Top, 2);
      var image = coords(true, el.dim.Width - bW.Left - bW.Right + 1, el.dim.Height - bW.Top - bW.Bottom + 1, rad, bW.Left, bW.Top, 1);
      
      /* apply huge path string */
      el.vml.color.path = inner;
      el.vml.image.path = image;
      el.vml.stroke.path = outer + inner;
      
      this.clipImage(el);
   },
   
   nixBorder: function(el){
      var s = el.currentStyle;
      var sides = ['Top', 'Left', 'Right', 'Bottom'];
      for (var i = 0; i < 4; i++) {
         el.runtimeStyle['padding' + sides[i]] = (parseInt(s['padding' + sides[i]], 10) || 0) + (parseInt(s['border' + sides[i] + 'Width'], 10) || 0) + 'px';
      }
      el.runtimeStyle.border = 'none';
   },
   
   clipImage: function(el){
      var lib = DD_roundies;
      if (!el.vmlBg || !lib.imgSize[el.vmlBg]) {
         return;
      }
      var thisStyle = el.currentStyle;
      var bg = {
         'X': 0,
         'Y': 0
      };
      var figurePercentage = function(axis, position){
         var fraction = true;
         switch (position) {
            case 'left':
            case 'top':
               bg[axis] = 0;
               break;
            case 'center':
               bg[axis] = 0.5;
               break;
            case 'right':
            case 'bottom':
               bg[axis] = 1;
               break;
            default:
               if (position.search('%') != -1) {
                  bg[axis] = parseInt(position, 10) * 0.01;
               } else {
                  fraction = false;
               }
         }
         var horz = (axis == 'X');
         bg[axis] = Math.ceil(fraction ? ((el.dim[horz ? 'Width' : 'Height'] - (el.bW[horz ? 'Left' : 'Top'] + el.bW[horz ? 'Right' : 'Bottom'])) * bg[axis]) - (lib.imgSize[el.vmlBg][horz ? 'width' : 'height'] * bg[axis]) : parseInt(position, 10));
         bg[axis] += 1;
      };
      for (var b in bg) {
         figurePercentage(b, thisStyle['backgroundPosition' + b]);
      }
      el.vml.image.filler.position = (bg.X / (el.dim.Width - el.bW.Left - el.bW.Right + 1)) + ',' + (bg.Y / (el.dim.Height - el.bW.Top - el.bW.Bottom + 1));
      var bgR = thisStyle.backgroundRepeat;
      var c = {
         'T': 1,
         'R': el.dim.Width + 1,
         'B': el.dim.Height + 1,
         'L': 1
      }; /* these are defaults for repeat of any kind */
      var altC = {
         'X': {
            'b1': 'L',
            'b2': 'R',
            'd': 'Width'
         },
         'Y': {
            'b1': 'T',
            'b2': 'B',
            'd': 'Height'
         }
      };
      if (bgR != 'repeat') {
         c = {
            'T': (bg.Y),
            'R': (bg.X + lib.imgSize[el.vmlBg].width),
            'B': (bg.Y + lib.imgSize[el.vmlBg].height),
            'L': (bg.X)
         }; /* these are defaults for no-repeat - clips down to the image location */
         if (bgR.search('repeat-') != -1) { /* now let's revert to dC for repeat-x or repeat-y */
            var v = bgR.split('repeat-')[1].toUpperCase();
            c[altC[v].b1] = 1;
            c[altC[v].b2] = el.dim[altC[v].d] + 1;
         }
         if (c.B > el.dim.Height) {
            c.B = el.dim.Height + 1;
         }
      }
      el.vml.image.style.clip = 'rect(' + c.T + 'px ' + c.R + 'px ' + c.B + 'px ' + c.L + 'px)';
   },
   
   pseudoClass: function(el){
      var self = this;
      setTimeout(function(){ /* would not work as intended without setTimeout */
         self.applyVML(el);
      }, 1);
   },
   
   reposition: function(el){
      this.vmlOffsets(el);
      this.vmlPath(el);
   },
   allAlreadyProcessed: [],//having bug that at times roundify is executed multiple times for one element, which results in a white layer covering everything
   roundify: function(rad, callback){
      var thisAlreadyProcessed = false;
      if (DD_roundies.allAlreadyProcessed) {
         for (var i = 0; i < DD_roundies.allAlreadyProcessed.length; i++) {
            if (DD_roundies.allAlreadyProcessed[i] == this.id) {
               thisAlreadyProcessed = true;
            }
         }
      }
      if (!thisAlreadyProcessed) {
         DD_roundies.allAlreadyProcessed.push(this.id);
         this.style.behavior = 'none';
         if (!this.currentStyle) {
            return;
         } else {
            var thisStyle = this.currentStyle;
         }
         var allowed = {
            BODY: false,
            TABLE: false,
            TR: false,
            TD: false,
            SELECT: false,
            OPTION: false,
            TEXTAREA: false
         };
         if (allowed[this.nodeName] === false) { /* elements not supported yet */
            return;
         }
         var self = this; /* who knows when you might need a setTimeout */
         var lib = DD_roundies;
         this.DD_radii = rad;
         this.dim = {};
         
         /* attach handlers */
         var handlers = {
            resize: 'reposition',
            move: 'reposition'
         };
         if (this.nodeName == 'A') {
            var moreForAs = {
               mouseleave: 'pseudoClass',
               mouseenter: 'pseudoClass',
               focus: 'pseudoClass',
               blur: 'pseudoClass'
            };
            for (var a in moreForAs) {
               handlers[a] = moreForAs[a];
            }
         }
         for (var h in handlers) {
            this.attachEvent('on' + h, function(){
               lib[handlers[h]](self);
            });
         }
         this.attachEvent('onpropertychange', function(){
            lib.readPropertyChanges(self);
         });
         
         /* ensure that this element and its parent is given hasLayout (needed for accurate positioning) */
         var giveLayout = function(el){
            el.style.zoom = 1;
            if (el.currentStyle.position == 'static') {
               el.style.position = 'relative';
            }
         };
         giveLayout(this.offsetParent);
         giveLayout(this);
         
         /* create vml elements */
         this.vmlBox = document.createElement('ignore'); /* IE8 really wants to be encased in a wrapper element for the VML to work, and I don't want to disturb getElementsByTagName('div') - open to suggestion on how to do this differently */
         this.vmlBox.runtimeStyle.cssText = 'behavior:none; position:absolute; margin:0; padding:0; border:0; background:none;'; /* super important - if something accidentally matches this (you yourseld did this once, Drew), you'll get infinitely-created elements and a frozen browser! */
         this.vmlBox.style.zIndex = thisStyle.zIndex;
         this.vml = {
            'color': true,
            'image': true,
            'stroke': true
         };
         for (var v in this.vml) {
            this.vml[v] = document.createElement(lib.ns + ':shape');
            this.vml[v].setAttribute('class', 'ddroundiesElm');
            this.vml[v].filler = document.createElement(lib.ns + ':fill');
            this.vml[v].filler.setAttribute('class', 'ddroundiesElm');
            this.vml[v].appendChild(this.vml[v].filler);
            this.vml[v].stroked = false;
            this.vml[v].style.position = 'absolute';
            this.vml[v].style.zIndex = thisStyle.zIndex;
            this.vml[v].coordorigin = '1,1';
            this.vmlBox.appendChild(this.vml[v]);
         }
         this.vml.image.fillcolor = 'none';
         this.vml.image.filler.type = 'tile';
         this.parentNode.insertBefore(this.vmlBox, this);
         
         this.isImg = false;
         if (this.nodeName == 'IMG') {
            this.isImg = true;
            this.style.visibility = 'hidden';
         }
         
         setTimeout(function(){
            lib.applyVML(self, callback);
         }, 1);
         //thisStyle.zIndex = thisStyle.zIndex;
      }
   }
   
};

try {
   document.execCommand("BackgroundImageCache", false, true);
} catch (err) {
}
DD_roundies.IEversion();
DD_roundies.createVmlNameSpace();
DD_roundies.createVmlStyleSheet();

if (DD_roundies.IE8 && document.attachEvent && DD_roundies.querySelector) {
   document.attachEvent('onreadystatechange', function(){
      if (document.readyState == 'complete') {
         var selectors = DD_roundies.selectorsToProcess;
         var length = selectors.length;
         var delayedCall = function(node, radii, index){
            setTimeout(function(){
               DD_roundies.roundify.call(node, radii);
            }, index * 100);
         };
         for (var i = 0; i < length; i++) {
            var results = document.querySelectorAll(selectors[i].selector);
            var rLength = results.length;
            for (var r = 0; r < rLength; r++) {
               if (results[r].nodeName != 'INPUT') { /* IE8 doesn't like to do this to inputs yet */
                  delayedCall(results[r], selectors[i].radii, r);
               }
            }
         }
      }
   });
}

