Template:INSA-Lyon/roundies
From 2010.igem.org
(New page: /** * http://www.dillerdesign.com/experiment/DD_roundies/DD_roundies_0.0.2a.js * DD_roundies, this adds rounded-corner CSS in standard browsers and VML sublayers in IE that accomplish a si...)
Newer edit →
Revision as of 07:24, 31 August 2010
/**
- http://www.dillerdesign.com/experiment/DD_roundies/DD_roundies_0.0.2a.js
- 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 */ var style = document.createElement('style'); 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 **/ addRule: function(selector, rad, standards) { 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) { /* IE */ var selectors = selector.split(','); /* multiple selectors supported, no need for multiple calls to this anymore */ for (var i=0; i<selectors.length; i++) { this.styleSheet.addRule(selectors[i], 'behavior:expression(DD_roundies.roundify.call(this, [' + rad.join(',') + ']))'); /* seems to execute the function without adding it to the stylesheet - interesting... */ } } else if (standards) { 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}); } },
readPropertyChanges: function(el) { switch (event.propertyName) { case 'style.border': case 'style.borderWidth': case 'style.padding': this.applyVML(el); break; case 'style.borderColor': this.vmlStrokeColor(el); break; case 'style.backgroundColor': case 'style.backgroundPosition': case 'style.backgroundRepeat': this.applyVML(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; break; } },
applyVML: function(el) { el.runtimeStyle.cssText = ; this.vmlFill(el); this.vmlStrokeColor(el); this.vmlStrokeWeight(el); this.vmlOffsets(el); this.vmlPath(el); this.nixBorder(el); this.vmlOpacity(el); },
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) { 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; } },
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);
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); },
roundify: function(rad) { 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 elent 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].filler = document.createElement(lib.ns + ':fill'); 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); }, 1); }
};
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); } } } } }); }
DD_roundies.addRule('#search-controls', '6px'); DD_roundies.addRule('#bodyContent', '0 0 20px 20px'); DD_roundies.addRule('.firstHeading', '20px 20px 0 0'); DD_roundies.addRule('#p-logo', '6px'); DD_roundies.addRule('div.colonnegauche', '10px'); DD_roundies.addRule('div.colonnedroite', '10px'); DD_roundies.addRule('div.titredroite', '10px'); DD_roundies.addRule('div.sponsors', '10px'); DD_roundies.addRule('div#corps', '10px'); DD_roundies.addRule('div#corps2', '10px'); DD_roundies.addRule('div#corps3', '10px'); DD_roundies.addRule('div#corps4', '10px'); DD_roundies.addRule('a', '8px');
DD_roundies.addRule('ul#topnav li span', '6px'); DD_roundies.addRule('div#menug li a ', '5px'); DD_roundies.addRule('div#ssmenug li a ', '5px');