/*
 * Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

<public:component lightWeight="true">
<public:attach event="onpropertychange" onevent="propertyChanged()" />
<public:attach event="onbeforeprint" onevent="beforePrint()" for="window"/>
<public:attach event="onafterprint" onevent="afterPrint()" for="window"/>
<script>

/*
 * PNG Behavior
 *
 * This script was created by Erik Arvidsson (http://webfx.eae.net/contact.html#erik)
 * for WebFX (http://webfx.eae.net)
 * Copyright 2002-2004
 *
 * For usage see license at http://webfx.eae.net/license.html
 *
 * Version: 1.02
 * Created: 2001-??-??    First working version
 * Updated: 2002-03-28    Fixed issue when starting with a non png image and
 *                      switching between non png images
 *          2003-01-06    Fixed RegExp to correctly work with IE 5.0x
 *          2004-05-09  When printing revert to original
 *
 */

var supported = /MSIE ((5\.5)|[6789])/.test(navigator.userAgent) &&
                navigator.platform == "Win32";

var realSrc;
var blankSrc = "/images/blank.gif";
var isPrinting = false;

if (supported) fixImage();

function propertyChanged() {
    if (!supported || isPrinting) return;

    var pName = event.propertyName;
    if (pName != "src") return;
    // if not set to blank
    if (!new RegExp(blankSrc).test(src))
        fixImage();
};

function fixImage() {
    // get src
    var src = element.src;

    // check for real change
    if (src == realSrc && /\.png$/i.test(src)) {
        element.src = blankSrc;
        return;
    }

    if ( ! new RegExp(blankSrc).test(src)) {
        // backup old src
        realSrc = src;
    }

    // test for png
    if (/\.png$/i.test(realSrc)) {
        // set blank image
        element.src = blankSrc;
        // set filter
        element.runtimeStyle.filter = "progid:DXImageTransform.Microsoft." +
                    "AlphaImageLoader(src='" + src + "',sizingMethod='scale')";
    }
    else {
        // remove filter
        element.runtimeStyle.filter = "";
    }
}

function beforePrint() {
    isPrinting = true;
    element.src = realSrc;
    element.runtimeStyle.filter = "";
    realSrc = null;
}

function afterPrint() {
    isPrinting = false;
    fixImage();
}

</script>
</public:component>
