Table of contents
Introduction
As you may know, i've been working on Vista sidebar's gadgets for a while now, and i had to deal with a lot of specifics problems. Indeed, gadget development is very similar to IE web browser programing, but Microsoft thought it was smart to add some specificities, just as if they had no way to modify the IE7 rendering engine nor the win32 API to fit the gadget needs.
Well, now it is the way it is, the only solution is to deal with the given platform.
If you ever tried to create a partially transparent background gadget, you may have experienced one of following problem:
- pink effect: the pink outline around images or text over transparent parts
- black background: a black background coming from nowhere
If you didn't, you're lucky, if you did and didn't find a workaround, i'll try to give a method in this article.
Single part background
To have a single part background, you'll need an empty gadget and a png image representing your gadget background. I assume you already have all this.
First to show your gadget background, you need to define an HTML element to receive the image. This element is a Microsoft specific tag called g:background. You can find the specifications and documentation in this page.
Be carefull, as we use the g:background tag, don't use a doctype and especialy no xhtml doctype !
So, now you page should look like this:
<html> <head> </head> <body style="width:150px;height:200px;" > <g:background id="background" align="center" style="z-index:999;position:absolute;top:0;left:0;width:150px;height:200px;" src="./path/to/your/background" /> <div id="content"> </div> </body> </html>
This should be enough to have it working.
You may have note that it I fixed the background and the body sizes, it is mandatory to avoid any unwanted effect I mentioned in the introduction. Please make sure that those sizes are the same as your background image.
If you added some content, you should have noticed that the result isn't the expected one. That's because we didn't position the content correctly. let's add some rules in the css stylesheet:
#content{ width:100%; height:100%; padding:0; margin:0; position:absolute; top:0; left:0; }
Well, it is now exactly as we expected, isn't it ?
NO ? Damn, why does the text over the transparent area has a pink border ?
Well, I don't know, and the only way I found to add some text on the transparent area is to use the g:background addTextObject method. Otherwise, just try not to write anything in the transparent area :).
Ok, we now have a fixed size and single part background, but what can I do if I want to resize my gadget ? should I embed a background image per size ? let's go further to play around a bit.
Multi part background
Html code
I assume that if you reached this paragraph you want extensible transparent background, so let's dive into the subject.
First of all, you'll need a blanc gadget with the same code as previous paragraph.
As the background image isn't the same anymore, let's replace the g:background source with a transparent image of 1px square. You may now have following index html file:
<html> <head> <script type="text/javascript">//<![CDATA[ /** * @description * gadget initialization function */ function init() { /* your initialization code */ } /** * @description * changes the background size and images * * @param {Number} height the new gadget height * @param {String} headerUrl the new gadget header image url * @param {String} midleSliceUrl the new gadget middle repeat slice 1px height * @param {String} footerUrl the new gadget footer image url */ function setBackground( height, headerUrl, midleSliceUrl, footerUrl ) { /* code given in the article will come here */ } //]]></script> </head> <body onload="init()"> <g:background id="background" align="center" style="z-index:999;position:absolute;top:0;left:0;width:150px;height:200px;" src="./path/to/transparent.png" /> <div id="content"> </div> </body> </html>
So, let's see how to fill in those functions.
Needed inputs
To achieve our goal, we'll separate the background into 3 parts, the top one, a repeating slice and the bottom. An improvement (for speed reason) could be to introduce a 4th image, that is a 10 or 20 pixel height image for the middle slice you will repeat, and for the last part use the 1px height slice. I'll let you do this improvement.
- An image for the header, i'll call it header.png
- A 1px height middle slice i'll call middleSlice.png. It will be repeated as many time as needed
- A footer image, i'll call it footer.png
implementation
So, everything is ready to code, let's go.
First of all we'll code the resizing part, as we've seen before the body and the background has to be the same size, and most important the same size as the images.
// resize part // parses the height as integer, just in case var _nHeight = parseInt(height, 10); var _body = document.body || document.documentElement; var _background = document.getElementById('background'); _body.style.height = _nHeight + 'px'; _background.style.height= _nHeight + 'px';
So, now we've got the gadget at the right size, next step is to add the images to fill the background:
// fill the background image //load the images to get the sizes var _headerHeight, _sliceHeight, _footerHeight, _headerImg = new Image(), _sliceImg = new Image(), _footerImg = new Image(); _headerImg.onerror=function(){System.Debug.outputString('header not loaded')}; _sliceImg.onerror=function(){System.Debug.outputString('slice not loaded')}; _footerImg.onerror=function(){System.Debug.outputString('footer not loaded')}; _headerImg.src= headerUrl; _sliceImg.src= midleSliceUrl; _footerImg.src= footerUrl; // set the sizes _headerHeight = _headerImg.height; _sliceHeight = _sliceImg.height; _footerHeight = _footerImg.height; var _top = 0; // add the header _background.addImageObject(headerUrl, 0, _top); _top+= _headerHeight; //calculate the middle part height var _middlepartHeight = _nHeight - _headerHeight - _footerHeight; // and append the slice as many time as needed for(var _i=0; _i<_middlepartHeight; _i+=_sliceHeight) { _background.addImageObject(headerUrl, 0, _top); _top+= _sliceHeight; } // now add the footer _background.addImageObject(footerUrl, 0, _top); // That's all folk !
Here we are, we've got our resize function ! let's do the call into the init function:
setBackground( 300, './path/to/header.png', './path/to/middleSlice.png', './path/to/footer.png')
Conclusion
As usual i'll give some documentation link for fast find:
And also an hint, add a bigger slice (for instance 30px) to avoid too much iteration, and use the 1px slice to fill the difference. have fun !