/**
* @license
* Copyright (c) 2016, Immo Schulz-Gerlach, www.isg-software.de
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
( function($) {
/**
* SVG Content Plug-in for jquery-progresspiesvg:
* Add an image to a progress pie chart, by default in background, alternatively in foreground.
* The image has to be available as external file in a web compatible format such as SVG, JPEG or PNG.
* This plug-in needs at least one argument (option <code>href</code>) specifying the URL from which to load the image.
* It will insert an image element into the SVG containing this reference URL. When rendering the pie's SVG code,
* the browser will then resolve this URL and lazily load the actual image resource, just like browsers
* load image files specified by <code>img</code> tags with <code>href</code> attributes in HTML.
* <p>The images, at least background images, used should usually be square (i.e. width == height).
* Non-square images are shrunk to fully fit into the square target area, vertically resp. horizontally centered.</p>
* <p>The target area, in which the image is fitted, is by default a square.
* You may set the <code>clipCircle</code> option in order to clip this square to a circle (with the
* square's width as diameter). Non-circular images fitted into that square will then be circularly clipped.
* <p>When drawing a pie, the target square is the full area covered by the pie chart plus the padding around it
* (which defaults to 0 but may be specified via the <code>progressPie</code>'s <code>padding</code> option).</p>
* <p>When drawing a ring (i.e. <code>progressPie</code>'s <code>ringWidth</code> option is defined), then, by
* default, this target area is fitted into the ring such that its width (and height) is the width of the
* free space inside the ring minus twice the <code>margin</code> which may optionally be set in the
* <code>contentPluginOptions</code>, see below. Yet this square area will still overlap the ring (except
* if the <code>clipCircle</code> option is true, see above).</p>
* <p>In ring mode you may set the <code>fullSize</code> option to true. In this case the image's target area
* is equivalent to that in pie mode.</p>
* <p>Via the <code>inBackground</code> option you may specify whether the image is to be positioned on top of
* the chart or behind it.</p>
* <p>A background image may also be used to fill the pie chart (instead of the background behind it).
* To achieve this, the pie has to be drawn in MASK mode,
* and the image has to be drawn as its first background (i.e. option <code>inBackground</code> has to be true (default)
* and no other content plug-in also draw into the background must be inserted before the image). See examples.</p>
* <p>To use this content plug-in add the option <code>contentPlugin: "image"</code> (or <code>contentPlugin: $.fn.progressPie.contentPlugin.image</code>)
* to your call of the progresspie plug-in.
* <p>Furthermore, also add the option <code>contentPluginOptions</code> to the progressPie plugin options.
* This is to be an object which must hold at least an <code>href</code> option. The following options are supported:</p>
* <ul>
* <li><code>href</code>: string, mandatory, holding the URL from which to load the image file.</li>
* <li><code>clipCircle</code>: boolean, defaults to false. If true, the target area (square) is reduced to a circle.
* The image is clipped by this circle, i.e. all areas of the image outside the circle will be invisible.</li>
* <li><code>fullSize</code>: boolean, defaults to false. Only affects drawing on a ring chart (i.e. with option <code>ringWidth</code> set):
* In this case, the value true causes the image to cover the whole ring graph (plus optional padding)
* instead of just the free space inside the ring.</li>
* <li><code>inBackground</code>: boolean, defaults to true. If false, the content is drawn on top of the pie or ring chart, if true,
* the pie or ring chart is drawn on top of the image. This only makes a difference if both overlap or if the MASK mode
* is used.</li>
* <li><code>margin</code>: number, defaults to undefined: Defines the margin in pixels left free around
* the image inside its target area. For a progress <em>pie</em> or if the <code>fullSize</code> option is truthy,
* this value (if the property is not set) defaults to zero. For a progress <em>ring</em> without <code>fullSize</code> option,
* the default margin value (if the property is not set) is 1.</li>
* </ul>
* <p>Please note: This function is called <em>internally</em> by the progressPie jQuery plug-in! Don't call this function directly,
* but use it as desrcibed above!</p>
* @function image
* @param {object} args object holding several arguments provided by the progressPie plug-in, including any option you specified in
* the object <code>contentPluginOptions</code>.
* @memberof jQuery.fn.progressPie.contentPlugin
* @requires jquery-progresspiesvg-min.js
*/
$.fn.progressPie.contentPlugin.image = {
draw: function(args) {
if (typeof args.href !== "string") {
throw new Error("$.fn.progressPie.contentPlugin.image requires argument 'href' of type 'string'!");
}
var opts = $.extend({}, $.fn.progressPie.contentPlugin.imageDefaults, args);
var r = opts.getBackgroundRadius();
var x = -r;
var y = -r;
var w = 2 * r;
var h = w;
if (opts.isFullSize()) {
//in fullsize mode the image shall not only cover the pie chart, but the pie chart plus its padding (if > 0).
var paddingTop = opts.pieOpts.getPadding(0);
var paddingRight = opts.pieOpts.getPadding(1);
var paddingBottom = opts.pieOpts.getPadding(2);
var paddingLeft = opts.pieOpts.getPadding(3);
x -= paddingLeft;
y -= paddingTop;
w += paddingLeft + paddingRight;
h += paddingTop + paddingBottom;
}
var img = args.newSvgElement("image");
img.setAttribute("width", w);
img.setAttribute("height", h);
img.setAttribute("x", x);
img.setAttribute("y", y);
img.setAttributeNS("http://www.w3.org/1999/xlink", "href", args.href);
if (opts.clipCircle) {
var cp = args.newDefElement("clipPath");
var id = args.createId("clipcircle");
cp.setAttribute("id", id);
img.setAttribute("clip-path", "url(#" + id + ")");
var c = args.newSvgSubelement(cp, "circle");
c.setAttribute("cx", 0);
c.setAttribute("cy", 0);
c.setAttribute("r", r);
}
},
inBackground: function(args) {
var opts = $.extend({}, $.fn.progressPie.contentPlugin.imageDefaults, args);
return opts.inBackground;
}
};
/**
* SVG Content Plug-in for jquery-progresspiesvg:
* Adds a square as background to a progress pie. The square's area is the area of the actual
* chart plus its padding (padding defaults to zero but can be set in the progress pie's options).
* <p>Use this plug-in by adding the option <code>contentPlugin: "backgroundRect"</code> (or <code>contentPlugin: $.fn.progressPie.contentPlugin.backgroundRect</code>)
* to your call of the progressPie plug-in.
* <p>Furthermore, also add the option <code>contentPluginOptions</code> to the progressPie plugin options.
* The following options are supported:</p>
* <ul>
* <li><code>stroke</code>: string defining the stroke of the rectangle (a color code or 'none')</li>
* <li><code>fill</code>: string defining the filling of the rectangle (a color code or 'none')</li>
* <li><code>strokeWidth</code>: number, optional: Width of the stroke in pixels.</li>
* </ul>
* <p>At least on of the options <code>stroke</code> or <code>fill</code> has to be specified.
* If you only want a filled square without a differently colored outline, only set the <code>fill</code>
* option and leave the <code>stroke</code> option undefined (no need to set it to 'none').
* Or vice-versa: If you want to draw a non-filled square, just set <code>stroke</code> and optionally
* also <code>strokeWidth</code>.</p>
* <p>Please note: This function is called <em>internally</em> by the progressPie jQuery plug-in! Don't call this function directly,
* but use it as described above!</p>
* @function backgroundRect
* @param {object} args object holding several arguments provided by the progressPie plug-in, including any option you specified in
* the object <code>contentPluginOptions</code>.
* @memberof jQuery.fn.progressPie.contentPlugin
* @requires jquery-progresspiesvg-min.js
*/
$.fn.progressPie.contentPlugin.backgroundRect = {
draw: function(args) {
if (typeof args.stroke !== "string" && typeof args.fill !== "string") {
throw new Error("$.fn.progressPie.contentPlugin.backgroundRect requires at least one of the two arguments 'fill' and 'stroke'.");
}
var stroke = typeof args.stroke === "string" ? args.stroke : "none";
var fill = typeof args.fill === "string" ? args.fill : "none";
var strokeWidth = typeof args.strokeWidth === "number" && stroke !== "none" ? args.strokeWidth : undefined;
args.addBackgroundRect(stroke, fill, strokeWidth);
},
inBackground: function() {
return true;
}
};
/**
* Default Options for the content plug-in "image".
* This is a public (static) object in order to allow users to globally modify the defaults
* before using the <code>image</code> content plug-in.
* @member imageDefaults
* @memberof jQuery.fn.progressPie.contentPlugin
* @property {boolean} inBackground - If false, the image is drawn on top of the chart (into the foreground),
* if true, the error icon will be drawn as background behind the chart. Defaults to true.
* @property {boolean} fullSize - when combined with a ring chart (<code>ringWidth</code> option set), the value
* true causes the image to be drawn (just like with pie charts) in full size, i.e. covering the whole chart plus
* its padding (if greater than zero). Defaults to false.
* @property {boolean} clipCircle - If set to true, the image will be clipped to the area of the circle centered
* in its square area with diameter equal to the square's side lengths. If the chart's padding is zero and the
* image is drawn full sized, the image will thus cover exactly the circular chart. If drawn inside a ring with
* fullSize == true, the image will be clipped to the inner space in order not to overlap the ring. Defaults to false.
*/
$.fn.progressPie.contentPlugin.imageDefaults = {
inBackground: true,
clipCircle: false,
fullSize: false
};
} (jQuery));