Added feature #14546: Make sprite icons / PNGs work in Internet Explorer 6 through...
authorBenni Mack <benni.mack@typo3.org>
Fri, 11 Jun 2010 22:00:30 +0000 (22:00 +0000)
committerBenni Mack <benni.mack@typo3.org>
Fri, 11 Jun 2010 22:00:30 +0000 (22:00 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@7883 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
typo3/sysext/t3skin/ext_tables.php
typo3/sysext/t3skin/images/backgrounds/module-menu-right.gif [new file with mode: 0644]
typo3/sysext/t3skin/pngfix/class.tx_templatehook.php [new file with mode: 0644]
typo3/sysext/t3skin/pngfix/iepngfix.htc [new file with mode: 0644]
typo3/sysext/t3skin/pngfix/iepngfix.js [new file with mode: 0644]
typo3/sysext/t3skin/pngfix/iepngfix.php [new file with mode: 0644]
typo3/sysext/t3skin/stylesheets/visual/module_menu.css

index 544fdab..81883bd 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,6 @@
 2010-06-11  Benjamin Mack  <benni@typo3.org>
 
+       * Added feature #14546: Make sprite icons / PNGs work in Internet Explorer 6 through PNGfix that works with background images (Thanks to Steffen Ritter)
        * Added feature #14546: Hook in typo3/template.php to add additional header data (Thanks to Steffen Ritter)
        * Fixed bug #14598: Add unique column name in page module (Thanks to Steffen Gebert)
        * Followup to #485: Hookrequest for ~ TemplaVoila unlink doesn't work for Non-Admins - added an additional hook parameter (Thanks to Tolleiv Nietsch)
index 13df89f..7cc8240 100644 (file)
@@ -168,6 +168,7 @@ if (TYPO3_MODE == 'BE' || (TYPO3_MODE == 'FE' && isset($GLOBALS['BE_USER']) && $
 
        $GLOBALS['TYPO3_CONF_VARS']['typo3/backend.php']['additionalBackendItems'][] = t3lib_extMgm::extPath('t3skin').'registerIe6Stylesheet.php';
 
+       $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preHeaderRenderHook'][] = t3lib_extMgm::extPath('t3skin').'pngfix/class.tx_templatehook.php:tx_templatehook->registerPngFix';
 }
 
 ?>
\ No newline at end of file
diff --git a/typo3/sysext/t3skin/images/backgrounds/module-menu-right.gif b/typo3/sysext/t3skin/images/backgrounds/module-menu-right.gif
new file mode 100644 (file)
index 0000000..cba693d
Binary files /dev/null and b/typo3/sysext/t3skin/images/backgrounds/module-menu-right.gif differ
diff --git a/typo3/sysext/t3skin/pngfix/class.tx_templatehook.php b/typo3/sysext/t3skin/pngfix/class.tx_templatehook.php
new file mode 100644 (file)
index 0000000..938c852
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+
+class tx_templatehook {
+       function registerPngFix($params,$parent) {
+                       // handle stupid IE6
+               $userAgent = t3lib_div::getIndpEnv('HTTP_USER_AGENT');
+
+               if(!(strpos($userAgent, 'MSIE 6') === false)
+               && strpos($userAgent, 'Opera') === false
+               && strpos($userAgent, 'MSIE 7') === false) {
+                               //make sure we match IE6 but not Opera or IE7
+                               $parent->loadJavascriptLib('sysext/t3skin/pngfix/iepngfix.js');
+                               $params['pageRenderer']->addCssInlineBlock('iepngfix', ".t3-icon { behavior: url('" . $parent->backPath . 'sysext/t3skin/pngfix/iepngfix.php' . "\');");
+               }
+
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/t3skin/pngfix/iepngfix.htc b/typo3/sysext/t3skin/pngfix/iepngfix.htc
new file mode 100644 (file)
index 0000000..0427ee2
--- /dev/null
@@ -0,0 +1,198 @@
+<public:component>\r
+<script type="text/javascript">\r
+\r
+// IE5.5+ PNG Alpha Fix v2.0 Alpha\r
+// (c) 2004-2009 Angus Turnbull http://www.twinhelix.com\r
+\r
+// This is licensed under the GNU LGPL, version 2.1 or later.\r
+// For details, see: http://creativecommons.org/licenses/LGPL/2.1/\r
+\r
+var IEPNGFix = window.IEPNGFix || {};\r
+IEPNGFix.data = IEPNGFix.data || {};\r
+\r
+\r
+// CONFIG: blankImg is the path to blank.gif, *relative to the HTML document*.\r
+// Try either:\r
+// * An absolute path like:  '/images/blank.gif'\r
+// * A path relative to this HTC file like:  thisFolder + 'blank.gif'\r
+var thisFolder = document.URL.replace(/(\\|\/)[^\\\/]*$/, '/');\r
+IEPNGFix.blankImg = thisFolder + 'iepngfix.gif';\r
+\r
+\r
+IEPNGFix.fix = function(elm, src, t) {\r
+       // Applies an image 'src' to an element 'elm' using the DirectX filter.\r
+       // If 'src' is null, filter is disabled.\r
+       // Disables the 'hook' to prevent infinite recursion on setting BG/src.\r
+       // 't' = type, where background tile = 0, background = 1, IMG SRC = 2.\r
+\r
+       var h = this.hook.enabled;\r
+       this.hook.enabled = 0;\r
+\r
+       var f = 'DXImageTransform.Microsoft.AlphaImageLoader';\r
+               src = (src || '').replace(/\(/g, '%28').replace(/\)/g, '%29');\r
+\r
+       if (\r
+               src && !(/IMG|INPUT/.test(elm.nodeName) && (t != 2)) &&\r
+               elm.currentStyle.width == 'auto' && elm.currentStyle.height == 'auto'\r
+       ) {\r
+               if (elm.offsetWidth) {\r
+                       elm.style.width = elm.offsetWidth + 'px';\r
+               }\r
+               if (elm.clientHeight) {\r
+                       elm.style.height = elm.clientHeight + 'px';\r
+               }\r
+               if (elm.currentStyle.display == 'inline') {\r
+                       elm.style.display = 'inline-block';\r
+               }\r
+       }\r
+       \r
+       if (t == 1) {\r
+               elm.style.backgroundImage = 'url("' + this.blankImg + '")';\r
+       }\r
+       if (t == 2) {\r
+               elm.src = this.blankImg;\r
+       }\r
+\r
+       if (elm.filters[f]) {\r
+               elm.filters[f].enabled = src ? true : false;\r
+               if (src) {\r
+                       elm.filters[f].src = src;\r
+               }\r
+       } else if (src) {\r
+               elm.style.filter = 'progid:' + f + '(src="' + src +\r
+                       '",sizingMethod="' + (t == 2 ? 'scale' : 'crop') + '")';\r
+       }\r
+\r
+       this.hook.enabled = h;\r
+};\r
+\r
+\r
+IEPNGFix.process = function(elm, init) {\r
+       // Checks the onpropertychange event (on first 'init' run, a fake event)\r
+       // and calls the filter-applying-functions.\r
+\r
+       if (\r
+               !/MSIE (5\.5|6)/.test(navigator.userAgent) ||\r
+               typeof elm.filters == 'unknown'\r
+       ) {\r
+               return;\r
+       }\r
+       if (!this.data[elm.uniqueID]) {\r
+               this.data[elm.uniqueID] = {\r
+                       className: ''\r
+               };\r
+       }\r
+       var data = this.data[elm.uniqueID],\r
+               evt = init ? { propertyName: 'src,backgroundImage' } : event,\r
+               isSrc = /src/.test(evt.propertyName),\r
+               isBg = /backgroundImage/.test(evt.propertyName),\r
+               isPos = /width|height|background(Pos|Rep)/.test(evt.propertyName),\r
+               isClass = !init && ((elm.className != data.className) &&\r
+                       (elm.className || data.className));\r
+       if (!(isSrc || isBg || isPos || isClass)) {\r
+               return;\r
+       }\r
+       data.className = elm.className;\r
+       var blank = this.blankImg.match(/([^\/]+)$/)[1],\r
+               eS = elm.style,\r
+               eCS = elm.currentStyle;\r
+\r
+       // Required for Whatever:hover - erase set BG if className changes.\r
+       if (\r
+               isClass && (eS.backgroundImage.indexOf('url(') == -1 ||\r
+               eS.backgroundImage.indexOf(blank) > -1)\r
+       ) {\r
+               return setTimeout(function() {\r
+                       eS.backgroundImage = '';\r
+               }, 0);\r
+       }\r
+\r
+       // Foregrounds.\r
+       if (isSrc && elm.src && { IMG: 1, INPUT: 1 }[elm.nodeName]) {\r
+               if ((/\.png/i).test(elm.src)) {\r
+                       if (!elm.oSrc) {\r
+                               // MM rollover compat\r
+                               elm.oSrc = elm.src;\r
+                       }\r
+                       this.fix(elm, elm.src, 2);\r
+               } else if (elm.src.indexOf(blank) == -1) {\r
+                       this.fix(elm, '');\r
+               }\r
+       }\r
+\r
+       // Backgrounds.\r
+       var bgSrc = eCS.backgroundImage || eS.backgroundImage;\r
+       if ((bgSrc + elm.src).indexOf(blank) == -1) {\r
+               var bgPNG = bgSrc.match(/url[("']+(.*\.png[^\)"']*)[\)"']/i);\r
+               if (bgPNG) {\r
+                       if (this.tileBG && !{ IMG: 1, INPUT: 1 }[elm.nodeName]) {\r
+                               this.tileBG(elm, bgPNG[1]);\r
+                               this.fix(elm, '', 1);\r
+                       } else {\r
+                               if (data.tiles && data.tiles.src) {\r
+                                       this.tileBG(elm, '');\r
+                               }\r
+                               this.fix(elm, bgPNG[1], 1);\r
+                               this.childFix(elm);\r
+                       }\r
+               } else {\r
+                       if (data.tiles && data.tiles.src) {\r
+                               this.tileBG(elm, '');\r
+                       }\r
+                       this.fix(elm, '');\r
+               }\r
+       } else if ((isPos || isClass) && data.tiles && data.tiles.src) {\r
+               this.tileBG(elm, data.tiles.src);\r
+       }\r
+/*\r
+       if (init) {\r
+               this.hook.enabled = 1;\r
+               elm.attachEvent('onpropertychange', this.hook);\r
+       }*/\r
+};\r
+\r
+\r
+IEPNGFix.childFix = function(elm) {\r
+       // "hasLayout" fix for unclickable children inside PNG backgrounds.\r
+       var tags = [\r
+                       'a',\r
+                       'input',\r
+                       'select',\r
+                       'textarea',\r
+                       'button',\r
+                       'iframe',\r
+                       'object'\r
+               ],\r
+               t = tags.length,\r
+               tFix = [];\r
+       while (t--) {\r
+               var pFix = elm.all.tags(tags[t]),\r
+                       e = pFix.length;\r
+               while (e--) {\r
+                       tFix.push(pFix[e]);\r
+               }\r
+       }\r
+       t = tFix.length;\r
+       if (t && (/relative|absolute/i).test(elm.currentStyle.position)) {\r
+               alert('IEPNGFix: Unclickable children of element:' +\r
+                       '\n\n<' + elm.nodeName + (elm.id && ' id=' + elm.id) + '>');\r
+       }\r
+       while (t--) {\r
+               if (!(/relative|absolute/i).test(tFix[t].currentStyle.position)) {\r
+                       tFix[t].style.position = 'relative';\r
+               }\r
+       }\r
+};\r
+\r
+\r
+IEPNGFix.hook = function() {\r
+       if (IEPNGFix.hook.enabled) {\r
+               IEPNGFix.process(element, 0);\r
+       }\r
+};\r
+\r
+\r
+IEPNGFix.process(element, 1);\r
+\r
+</script>\r
+</public:component>\r
diff --git a/typo3/sysext/t3skin/pngfix/iepngfix.js b/typo3/sysext/t3skin/pngfix/iepngfix.js
new file mode 100644 (file)
index 0000000..bb233de
--- /dev/null
@@ -0,0 +1,164 @@
+// IE5.5+ PNG Alpha Fix v2.0 Alpha: Background Tiling Support\r
+// (c) 2008-2009 Angus Turnbull http://www.twinhelix.com\r
+\r
+// This is licensed under the GNU LGPL, version 2.1 or later.\r
+// For details, see: http://creativecommons.org/licenses/LGPL/2.1/\r
+\r
+var IEPNGFix = window.IEPNGFix || {};\r
+\r
+IEPNGFix.tileBG = function(elm, pngSrc, ready) {\r
+       // Params: A reference to a DOM element, the PNG src file pathname, and a\r
+       // hidden "ready-to-run" passed when called back after image preloading.\r
+\r
+       var data = this.data[elm.uniqueID],\r
+               elmW = Math.max(elm.clientWidth, elm.scrollWidth),\r
+               elmH = Math.max(elm.clientHeight, elm.scrollHeight),\r
+               bgX = elm.currentStyle.backgroundPositionX,\r
+               bgY = elm.currentStyle.backgroundPositionY,\r
+               bgR = elm.currentStyle.backgroundRepeat;\r
+\r
+       // Cache of DIVs created per element, and image preloader/data.\r
+       if (!data.tiles) {\r
+               data.tiles = {\r
+                       elm: elm,\r
+                       src: '',\r
+                       cache: [],\r
+                       img: new Image(),\r
+                       old: {}\r
+               };\r
+       }\r
+       var tiles = data.tiles,\r
+               pngW = tiles.img.width,\r
+               pngH = tiles.img.height;\r
+\r
+       if (pngSrc) {\r
+               if (!ready && pngSrc != tiles.src) {\r
+                       // New image? Preload it with a callback to detect dimensions.\r
+                       tiles.img.onload = function() {\r
+                               this.onload = null;\r
+                               IEPNGFix.tileBG(elm, pngSrc, 1);\r
+                       };\r
+                       return tiles.img.src = pngSrc;\r
+               }\r
+       } else {\r
+               // No image?\r
+               if (tiles.src) ready = 1;\r
+               pngW = pngH = 0;\r
+       }\r
+       tiles.src = pngSrc;\r
+\r
+       if (!ready && elmW == tiles.old.w && elmH == tiles.old.h &&\r
+               bgX == tiles.old.x && bgY == tiles.old.y && bgR == tiles.old.r) {\r
+               return;\r
+       }\r
+\r
+       // Convert English and percentage positions to pixels.\r
+       var pos = {\r
+                       top: '0%',\r
+                       left: '0%',\r
+                       center: '50%',\r
+                       bottom: '100%',\r
+                       right: '100%'\r
+               },\r
+               x,\r
+               y,\r
+               pc;\r
+       x = pos[bgX] || bgX;\r
+       y = pos[bgY] || bgY;\r
+       if (pc = x.match(/(\d+)%/)) {\r
+               x = Math.round((elmW - pngW) * (parseInt(pc[1]) / 100));\r
+       }\r
+       if (pc = y.match(/(\d+)%/)) {\r
+               y = Math.round((elmH - pngH) * (parseInt(pc[1]) / 100));\r
+       }\r
+       x = parseInt(x);\r
+       y = parseInt(y);\r
+\r
+       var repeatX = false;\r
+       var repeatY = false;\r
+       \r
+       // Go!\r
+       this.hook.enabled = 0;\r
+       if (!({ relative: 1, absolute: 1 }[elm.currentStyle.position])) {\r
+               elm.style.position = 'relative';\r
+       } \r
+       var count = 0,\r
+               xPos,\r
+               maxX = repeatX ? elmW : x + 0.1,\r
+               yPos,\r
+               maxY = repeatY ? elmH : y + 0.1,\r
+               d,\r
+               s,\r
+               isNew;\r
+       if (pngW && pngH) {\r
+               for (xPos = x; xPos < maxX; xPos += pngW) {\r
+                       for (yPos = y; yPos < maxY; yPos += pngH) {\r
+                               isNew = 0;\r
+                               if (!tiles.cache[count]) {\r
+                                       tiles.cache[count] = document.createElement('div');\r
+                                       isNew = 1;\r
+                               }\r
+                               var clipR = Math.max(0, xPos + pngW > elmW ? elmW - xPos : pngW),\r
+                                       clipB = Math.max(0, yPos + pngH > elmH ? elmH - yPos : pngH);\r
+                               d = tiles.cache[count];\r
+                               s = d.style;\r
+                               s.behavior = 'none';\r
+                               s.left = (xPos - parseInt(elm.currentStyle.paddingLeft)) + 'px';\r
+                               s.top = yPos + 'px';\r
+                               s.width = clipR + 'px';\r
+                               s.height = clipB + 'px';\r
+                               s.clip = 'rect(' +\r
+                                       (yPos < 0 ? 0 - yPos : 0) + 'px,' +\r
+                                       clipR + 'px,' +\r
+                                       clipB + 'px,' +\r
+                                       (xPos < 0 ? 0 - xPos : 0) + 'px)';\r
+                               s.display = 'block';\r
+                               if (isNew) {\r
+                                       s.position = 'absolute';\r
+                                       s.zIndex = -999;\r
+                                       if (elm.firstChild) {\r
+                                               elm.insertBefore(d, elm.firstChild);\r
+                                       } else {\r
+                                               elm.appendChild(d);\r
+                                       }\r
+                               }\r
+                               this.fix(d, pngSrc, 0);\r
+                               count++;\r
+                       }\r
+               }\r
+       }\r
+       while (count < tiles.cache.length) {\r
+               this.fix(tiles.cache[count], '', 0);\r
+               tiles.cache[count++].style.display = 'none';\r
+       }\r
+\r
+       this.hook.enabled = 1;\r
+\r
+       // Cache so updates are infrequent.\r
+       tiles.old = {\r
+               w: elmW,\r
+               h: elmH,\r
+               x: bgX,\r
+               y: bgY,\r
+               r: bgR\r
+       };\r
+};\r
+\r
+\r
+IEPNGFix.update = function() {\r
+       // Update all PNG backgrounds.\r
+       for (var i in IEPNGFix.data) {\r
+               var t = IEPNGFix.data[i].tiles;\r
+               if (t && t.elm && t.src) {\r
+                       IEPNGFix.tileBG(t.elm, t.src);\r
+               }\r
+       }\r
+};\r
+IEPNGFix.update.timer = 0;\r
+\r
+if (window.attachEvent && !window.opera) {\r
+       window.attachEvent('onresize', function() {\r
+               clearTimeout(IEPNGFix.update.timer);\r
+               IEPNGFix.update.timer = setTimeout(IEPNGFix.update, 100);\r
+       });\r
+}\r
diff --git a/typo3/sysext/t3skin/pngfix/iepngfix.php b/typo3/sysext/t3skin/pngfix/iepngfix.php
new file mode 100644 (file)
index 0000000..7fabd5e
--- /dev/null
@@ -0,0 +1,11 @@
+<?php\r
+\r
+// Use this file in your CSS in place of the .HTC file if it works offline but not online.\r
+// It will send the correct MIME type so that IE will execute the script correctly.\r
+\r
+header('Content-Type: text/x-component');\r
+header('Expires: '.gmdate('D, d M Y H:i:s', time()+60*60*24*365).' GMT');\r
+header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime('iepngfix.htc')).' GMT');\r
+include('iepngfix.htc');\r
+\r
+?>\r
index fe6b653..2b87e59 100644 (file)
@@ -6,7 +6,7 @@ $Id$
 
 #typo3-side-menu {
        background: #dddddd;
-       background-image: url('../../images/backgrounds/module-menu-right.png');
+       background-image: url('../../images/backgrounds/module-menu-right.gif');
        background-position: right top;
        background-repeat: repeat-y;
 }