first commit
This commit is contained in:
commit
4d332ef662
27586 changed files with 3281783 additions and 0 deletions
150
rus/admin/_V4/_lib/ImageMapster-master/src/areacorners.js
Normal file
150
rus/admin/_V4/_lib/ImageMapster-master/src/areacorners.js
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/* areacorners.js
|
||||
determine the best place to put a box of dimensions (width,height) given a circle, rect or poly
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var u=$.mapster.utils;
|
||||
|
||||
|
||||
/**
|
||||
* Compute positions that will place a target with dimensions [width,height] outside
|
||||
* but near the boundaries of the elements "elements". When an imagemap is passed, the
|
||||
*
|
||||
* @param {Element|Element[]} elements An element or an array of elements (such as a jQuery object)
|
||||
* @param {Element} image The image to which area elements are bound, if this is an image map.
|
||||
* @param {Element} container The contianer in which the target must be constrained (or document, if missing)
|
||||
* @param {int} width The width of the target object
|
||||
* @return {object} a structure with the x and y positions
|
||||
*/
|
||||
u.areaCorners = function (elements, image, container, width, height) {
|
||||
var pos,found, minX, minY, maxX, maxY, bestMinX, bestMaxX, bestMinY, bestMaxY, curX, curY, nest, j,
|
||||
offsetx=0,
|
||||
offsety=0,
|
||||
rootx,
|
||||
rooty,
|
||||
iCoords,radius,angle,el,
|
||||
coords=[];
|
||||
|
||||
// if a single element was passed, map it to an array
|
||||
|
||||
elements = elements.length ?
|
||||
elements:
|
||||
[elements];
|
||||
|
||||
container = container ?
|
||||
$(container):
|
||||
$(document.body);
|
||||
|
||||
// get the relative root of calculation
|
||||
|
||||
pos = container.offset();
|
||||
rootx = pos.left;
|
||||
rooty = pos.top;
|
||||
|
||||
// with areas, all we know about is relative to the top-left corner of the image. We need to add an offset compared to
|
||||
// the actual container. After this calculation, offsetx/offsety can be added to either the area coords, or the target's
|
||||
// absolute position to get the correct top/left boundaries of the container.
|
||||
|
||||
if (image) {
|
||||
pos = $(image).offset();
|
||||
offsetx = pos.left;
|
||||
offsety = pos.top;
|
||||
}
|
||||
|
||||
// map the coordinates of any type of shape to a poly and use the logic. simpler than using three different
|
||||
// calculation methods. Circles use a 20 degree increment for this estimation.
|
||||
|
||||
for (j=0;j<elements.length;j++)
|
||||
{
|
||||
el=elements[j];
|
||||
if (el.nodeName==='AREA') {
|
||||
iCoords = u.split(el.coords,parseInt);
|
||||
|
||||
switch(el.shape) {
|
||||
case 'circle':
|
||||
curX=iCoords[0];
|
||||
curY=iCoords[1];
|
||||
radius=iCoords[2];
|
||||
coords=[];
|
||||
for (j=0;j<360;j+=20) {
|
||||
angle=j*Math.PI/180;
|
||||
coords.push(curX+radius*Math.cos(angle),curY+radius*Math.sin(angle));
|
||||
}
|
||||
break;
|
||||
case 'rect':
|
||||
coords.push(iCoords[0],iCoords[1],iCoords[2],iCoords[1],iCoords[2],iCoords[3],iCoords[0],iCoords[3]);
|
||||
break;
|
||||
default:
|
||||
coords=coords.concat(iCoords);
|
||||
break;
|
||||
}
|
||||
|
||||
// map area positions to it's real position in the container
|
||||
|
||||
for (j=0;j<coords.length;j+=2)
|
||||
{
|
||||
coords[j]=parseInt(coords[j],10)+offsetx;
|
||||
coords[j+1]=parseInt(coords[j+1],10)+offsety;
|
||||
}
|
||||
} else {
|
||||
el=$(el);
|
||||
pos = el.position();
|
||||
coords.push(pos.left,pos.top,
|
||||
pos.left+el.width(),pos.top,
|
||||
pos.left+el.width(),pos.top+el.height(),
|
||||
pos.left,pos.top+el.height());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
minX = minY = bestMinX = bestMinY = 999999;
|
||||
maxX = maxY = bestMaxX = bestMaxY = -1;
|
||||
|
||||
for (j = coords.length - 2; j >= 0; j -= 2) {
|
||||
curX = coords[j];
|
||||
curY = coords[j + 1];
|
||||
|
||||
if (curX < minX) {
|
||||
minX = curX;
|
||||
bestMaxY = curY;
|
||||
}
|
||||
if (curX > maxX) {
|
||||
maxX = curX;
|
||||
bestMinY = curY;
|
||||
}
|
||||
if (curY < minY) {
|
||||
minY = curY;
|
||||
bestMaxX = curX;
|
||||
}
|
||||
if (curY > maxY) {
|
||||
maxY = curY;
|
||||
bestMinX = curX;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// try to figure out the best place for the tooltip
|
||||
|
||||
if (width && height) {
|
||||
found=false;
|
||||
$.each([[bestMaxX - width, minY - height], [bestMinX, minY - height],
|
||||
[minX - width, bestMaxY - height], [minX - width, bestMinY],
|
||||
[maxX,bestMaxY - height], [ maxX,bestMinY],
|
||||
[bestMaxX - width, maxY], [bestMinX, maxY]
|
||||
],function (i, e) {
|
||||
if (!found && (e[0] > rootx && e[1] > rooty)) {
|
||||
nest = e;
|
||||
found=true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// default to lower-right corner if nothing fit inside the boundaries of the image
|
||||
|
||||
if (!found) {
|
||||
nest=[maxX,maxY];
|
||||
}
|
||||
}
|
||||
return nest;
|
||||
};
|
||||
} (jQuery));
|
||||
298
rus/admin/_V4/_lib/ImageMapster-master/src/areadata.js
Normal file
298
rus/admin/_V4/_lib/ImageMapster-master/src/areadata.js
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
/* areadata.js
|
||||
AreaData and MapArea protoypes
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var m = $.mapster, u = m.utils;
|
||||
|
||||
/**
|
||||
* Select this area
|
||||
*
|
||||
* @param {AreaData} me AreaData context
|
||||
* @param {object} options Options for rendering the selection
|
||||
*/
|
||||
function select(options) {
|
||||
// need to add the new one first so that the double-opacity effect leaves the current one highlighted for singleSelect
|
||||
|
||||
var me=this, o = me.owner;
|
||||
if (o.options.singleSelect) {
|
||||
o.clearSelections();
|
||||
}
|
||||
|
||||
// because areas can overlap - we can't depend on the selection state to tell us anything about the inner areas.
|
||||
// don't check if it's already selected
|
||||
if (!me.isSelected()) {
|
||||
if (options) {
|
||||
|
||||
// cache the current options, and map the altImageId if an altimage
|
||||
// was passed
|
||||
|
||||
me.optsCache = $.extend(me.effectiveRenderOptions('select'),
|
||||
options,
|
||||
{
|
||||
altImageId: o.images.add(options.altImage)
|
||||
});
|
||||
}
|
||||
|
||||
me.drawSelection();
|
||||
|
||||
me.selected = true;
|
||||
me.changeState('select', true);
|
||||
}
|
||||
|
||||
if (o.options.singleSelect) {
|
||||
o.graphics.refreshSelections();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deselect this area, optionally deferring finalization so additional areas can be deselected
|
||||
* in a single operation
|
||||
*
|
||||
* @param {boolean} partial when true, the caller must invoke "finishRemoveSelection" to render
|
||||
*/
|
||||
|
||||
function deselect(partial) {
|
||||
var me=this;
|
||||
me.selected = false;
|
||||
me.changeState('select', false);
|
||||
|
||||
// release information about last area options when deselecting.
|
||||
|
||||
me.optsCache=null;
|
||||
me.owner.graphics.removeSelections(me.areaId);
|
||||
|
||||
// Complete selection removal process. This is separated because it's very inefficient to perform the whole
|
||||
// process for multiple removals, as the canvas must be totally redrawn at the end of the process.ar.remove
|
||||
|
||||
if (!partial) {
|
||||
me.owner.removeSelectionFinish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the selection state of this area
|
||||
* @param {object} options Rendering options, if toggling on
|
||||
* @return {bool} The new selection state
|
||||
*/
|
||||
function toggle(options) {
|
||||
var me=this;
|
||||
if (!me.isSelected()) {
|
||||
me.select(options);
|
||||
}
|
||||
else {
|
||||
me.deselect();
|
||||
}
|
||||
return me.isSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
* An AreaData object; represents a conceptual area that can be composed of
|
||||
* one or more MapArea objects
|
||||
*
|
||||
* @param {MapData} owner The MapData object to which this belongs
|
||||
* @param {string} key The key for this area
|
||||
* @param {string} value The mapValue string for this area
|
||||
*/
|
||||
|
||||
m.AreaData = function (owner, key, value) {
|
||||
$.extend(this,{
|
||||
owner: owner,
|
||||
key: key || '',
|
||||
// means this represents the first key in a list of keys (it's the area group that gets highlighted on mouseover)
|
||||
isPrimary: true,
|
||||
areaId: -1,
|
||||
href: '',
|
||||
value: value || '',
|
||||
options:{},
|
||||
// "null" means unchanged. Use "isSelected" method to just test true/false
|
||||
selected: null,
|
||||
// xref to MapArea objects
|
||||
areasXref: [],
|
||||
// (temporary storage) - the actual area moused over
|
||||
area: null,
|
||||
// the last options used to render this. Cache so when re-drawing after a remove, changes in options won't
|
||||
// break already selected things.
|
||||
optsCache: null
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* The public API for AreaData object
|
||||
*/
|
||||
|
||||
m.AreaData.prototype = {
|
||||
constuctor: m.AreaData,
|
||||
select: select,
|
||||
deselect: deselect,
|
||||
toggle: toggle,
|
||||
areas: function() {
|
||||
var i,result=[];
|
||||
for (i=0;i<this.areasXref.length;i++) {
|
||||
result.push(this.owner.mapAreas[this.areasXref[i]]);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
// return all coordinates for all areas
|
||||
coords: function(offset) {
|
||||
var coords = [];
|
||||
$.each(this.areas(), function (i, el) {
|
||||
coords = coords.concat(el.coords(offset));
|
||||
});
|
||||
return coords;
|
||||
},
|
||||
reset: function () {
|
||||
$.each(this.areas(), function (i, e) {
|
||||
e.reset();
|
||||
});
|
||||
this.areasXref = [];
|
||||
this.options = null;
|
||||
},
|
||||
// Return the effective selected state of an area, incorporating staticState
|
||||
isSelectedOrStatic: function () {
|
||||
|
||||
var o = this.effectiveOptions();
|
||||
return u.isBool(o.staticState) ? o.staticState :
|
||||
this.isSelected();
|
||||
},
|
||||
isSelected: function () {
|
||||
return u.isBool(this.selected) ? this.selected :
|
||||
u.isBool(this.owner.area_options.selected) ? this.owner.area_options.selected : false;
|
||||
},
|
||||
isSelectable: function () {
|
||||
return u.isBool(this.effectiveOptions().staticState) ? false :
|
||||
(u.isBool(this.owner.options.staticState) ? false : u.boolOrDefault(this.effectiveOptions().isSelectable,true));
|
||||
},
|
||||
isDeselectable: function () {
|
||||
return u.isBool(this.effectiveOptions().staticState) ? false :
|
||||
(u.isBool(this.owner.options.staticState) ? false : u.boolOrDefault(this.effectiveOptions().isDeselectable,true));
|
||||
},
|
||||
isNotRendered: function() {
|
||||
var area = $(this.area);
|
||||
return area.attr('nohref') ||
|
||||
!area.attr('href') ||
|
||||
this.effectiveOptions().isMask;
|
||||
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Return the overall options effective for this area.
|
||||
* This should get the default options, and merge in area-specific options, finally
|
||||
* overlaying options passed by parameter
|
||||
*
|
||||
* @param {[type]} options options which will supercede all other options for this area
|
||||
* @return {[type]} the combined options
|
||||
*/
|
||||
|
||||
effectiveOptions: function (options) {
|
||||
|
||||
var opts = u.updateProps({},
|
||||
this.owner.area_options,
|
||||
this.options,
|
||||
options || {},
|
||||
{
|
||||
id: this.areaId
|
||||
}
|
||||
);
|
||||
|
||||
opts.selected = this.isSelected();
|
||||
|
||||
return opts;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the options effective for this area for a "render" or "highlight" mode.
|
||||
* This should get the default options, merge in the areas-specific options,
|
||||
* and then the mode-specific options.
|
||||
* @param {string} mode 'render' or 'highlight'
|
||||
* @param {[type]} options options which will supercede all other options for this area
|
||||
* @return {[type]} the combined options
|
||||
*/
|
||||
|
||||
effectiveRenderOptions: function (mode, options) {
|
||||
var allOpts,opts=this.optsCache;
|
||||
|
||||
if (!opts || mode==='highlight') {
|
||||
allOpts = this.effectiveOptions(options);
|
||||
opts = u.updateProps({},
|
||||
allOpts,
|
||||
allOpts["render_" + mode]
|
||||
);
|
||||
|
||||
if (mode!=='highlight') {
|
||||
this.optsCache=opts;
|
||||
}
|
||||
}
|
||||
return $.extend({},opts);
|
||||
},
|
||||
|
||||
// Fire callback on area state change
|
||||
changeState: function (state_type, state) {
|
||||
if ($.isFunction(this.owner.options.onStateChange)) {
|
||||
this.owner.options.onStateChange.call(this.owner.image,
|
||||
{
|
||||
key: this.key,
|
||||
state: state_type,
|
||||
selected: state
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
// highlight this area
|
||||
|
||||
highlight: function (options) {
|
||||
var o = this.owner;
|
||||
if (this.effectiveOptions().highlight) {
|
||||
o.graphics.addShapeGroup(this, "highlight",options);
|
||||
}
|
||||
o.setHighlightId(this.areaId);
|
||||
this.changeState('highlight', true);
|
||||
},
|
||||
|
||||
// select this area. if "callEvent" is true then the state change event will be called. (This method can be used
|
||||
// during config operations, in which case no event is indicated)
|
||||
|
||||
drawSelection: function () {
|
||||
|
||||
|
||||
this.owner.graphics.addShapeGroup(this, "select");
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
// represents an HTML area
|
||||
m.MapArea = function (owner,areaEl,keys) {
|
||||
if (!owner) {
|
||||
return;
|
||||
}
|
||||
var me = this;
|
||||
me.owner = owner; // a MapData object
|
||||
me.area = areaEl;
|
||||
me.areaDataXref=[]; // a list of map_data.data[] id's for each areaData object containing this
|
||||
me.originalCoords = [];
|
||||
$.each(u.split(areaEl.coords), function (i, el) {
|
||||
me.originalCoords.push(parseFloat(el));
|
||||
});
|
||||
me.length = me.originalCoords.length;
|
||||
me.shape = areaEl.shape.toLowerCase();
|
||||
me.nohref = areaEl.nohref || !areaEl.href;
|
||||
me.configure(keys);
|
||||
};
|
||||
m.MapArea.prototype= {
|
||||
constructor: m.MapArea,
|
||||
configure: function(keys) {
|
||||
this.keys = u.split(keys);
|
||||
},
|
||||
reset: function() {
|
||||
this.area=null;
|
||||
},
|
||||
coords: function (offset) {
|
||||
return $.map(this.originalCoords,function(e) {
|
||||
return offset ? e : e+offset;
|
||||
});
|
||||
}
|
||||
};
|
||||
} (jQuery));
|
||||
1049
rus/admin/_V4/_lib/ImageMapster-master/src/core.js
Normal file
1049
rus/admin/_V4/_lib/ImageMapster-master/src/core.js
Normal file
File diff suppressed because it is too large
Load diff
444
rus/admin/_V4/_lib/ImageMapster-master/src/graphics.js
Normal file
444
rus/admin/_V4/_lib/ImageMapster-master/src/graphics.js
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
/* graphics.js
|
||||
Graphics object handles all rendering.
|
||||
*/
|
||||
(function ($) {
|
||||
var p, m=$.mapster,
|
||||
u=m.utils,
|
||||
canvasMethods,
|
||||
vmlMethods;
|
||||
|
||||
/**
|
||||
* Implemenation to add each area in an AreaData object to the canvas
|
||||
* @param {Graphics} graphics The target graphics object
|
||||
* @param {AreaData} areaData The AreaData object (a collection of area elements and metadata)
|
||||
* @param {object} options Rendering options to apply when rendering this group of areas
|
||||
*/
|
||||
function addShapeGroupImpl(graphics, areaData, options) {
|
||||
var me = graphics,
|
||||
md = me.map_data,
|
||||
isMask = options.isMask;
|
||||
|
||||
// first get area options. Then override fade for selecting, and finally merge in the
|
||||
// "select" effect options.
|
||||
|
||||
$.each(areaData.areas(), function (i,e) {
|
||||
options.isMask = isMask || (e.nohref && md.options.noHrefIsMask);
|
||||
me.addShape(e, options);
|
||||
});
|
||||
|
||||
// it's faster just to manipulate the passed options isMask property and restore it, than to
|
||||
// copy the object each time
|
||||
|
||||
options.isMask=isMask;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hex value to decimal
|
||||
* @param {string} hex A hexadecimal toString
|
||||
* @return {int} Integer represenation of the hex string
|
||||
*/
|
||||
|
||||
function hex_to_decimal(hex) {
|
||||
return Math.max(0, Math.min(parseInt(hex, 16), 255));
|
||||
}
|
||||
function css3color(color, opacity) {
|
||||
return 'rgba(' + hex_to_decimal(color.substr(0, 2)) + ','
|
||||
+ hex_to_decimal(color.substr(2, 2)) + ','
|
||||
+ hex_to_decimal(color.substr(4, 2)) + ',' + opacity + ')';
|
||||
}
|
||||
/**
|
||||
* An object associated with a particular map_data instance to manage renderin.
|
||||
* @param {MapData} map_data The MapData object bound to this instance
|
||||
*/
|
||||
|
||||
m.Graphics = function (map_data) {
|
||||
//$(window).unload($.mapster.unload);
|
||||
// create graphics functions for canvas and vml browsers. usage:
|
||||
// 1) init with map_data, 2) call begin with canvas to be used (these are separate b/c may not require canvas to be specified
|
||||
// 3) call add_shape_to for each shape or mask, 4) call render() to finish
|
||||
|
||||
var me = this;
|
||||
me.active = false;
|
||||
me.canvas = null;
|
||||
me.width = 0;
|
||||
me.height = 0;
|
||||
me.shapes = [];
|
||||
me.masks = [];
|
||||
me.map_data = map_data;
|
||||
};
|
||||
|
||||
p = m.Graphics.prototype= {
|
||||
constructor: m.Graphics,
|
||||
|
||||
/**
|
||||
* Initiate a graphics request for a canvas
|
||||
* @param {Element} canvas The canvas element that is the target of this operation
|
||||
* @param {string} [elementName] The name to assign to the element (VML only)
|
||||
*/
|
||||
|
||||
begin: function(canvas, elementName) {
|
||||
var c = $(canvas);
|
||||
|
||||
this.elementName = elementName;
|
||||
this.canvas = canvas;
|
||||
|
||||
this.width = c.width();
|
||||
this.height = c.height();
|
||||
this.shapes = [];
|
||||
this.masks = [];
|
||||
this.active = true;
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Add an area to be rendered to this canvas.
|
||||
* @param {MapArea} mapArea The MapArea object to render
|
||||
* @param {object} options An object containing any rendering options that should override the
|
||||
* defaults for the area
|
||||
*/
|
||||
|
||||
addShape: function(mapArea, options) {
|
||||
var addto = options.isMask ? this.masks : this.shapes;
|
||||
addto.push({ mapArea: mapArea, options: options });
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a canvas that is sized and styled for the MapData object
|
||||
* @param {MapData} mapData The MapData object that will receive this new canvas
|
||||
* @return {Element} A canvas element
|
||||
*/
|
||||
|
||||
createVisibleCanvas: function (mapData) {
|
||||
return $(this.createCanvasFor(mapData))
|
||||
.addClass('mapster_el')
|
||||
.css(m.canvas_style)[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a group of shapes from an AreaData object to the canvas
|
||||
*
|
||||
* @param {AreaData} areaData An AreaData object (a set of area elements)
|
||||
* @param {string} mode The rendering mode, "select" or "highlight". This determines the target
|
||||
* canvas and which default options to use.
|
||||
* @param {striong} options Rendering options
|
||||
*/
|
||||
|
||||
addShapeGroup: function (areaData, mode,options) {
|
||||
// render includeKeys first - because they could be masks
|
||||
var me = this,
|
||||
list, name, canvas,
|
||||
map_data = this.map_data,
|
||||
opts = areaData.effectiveRenderOptions(mode);
|
||||
|
||||
if (options) {
|
||||
$.extend(opts,options);
|
||||
}
|
||||
|
||||
if (mode === 'select') {
|
||||
name = "static_" + areaData.areaId.toString();
|
||||
canvas = map_data.base_canvas;
|
||||
} else {
|
||||
canvas = map_data.overlay_canvas;
|
||||
}
|
||||
|
||||
me.begin(canvas, name);
|
||||
|
||||
if (opts.includeKeys) {
|
||||
list = u.split(opts.includeKeys);
|
||||
$.each(list, function (i,e) {
|
||||
var areaData = map_data.getDataForKey(e.toString());
|
||||
addShapeGroupImpl(me,areaData, areaData.effectiveRenderOptions(mode));
|
||||
});
|
||||
}
|
||||
|
||||
addShapeGroupImpl(me,areaData, opts);
|
||||
me.render();
|
||||
if (opts.fade) {
|
||||
|
||||
// fading requires special handling for IE. We must access the fill elements directly. The fader also has to deal with
|
||||
// the "opacity" attribute (not css)
|
||||
|
||||
u.fader(m.hasCanvas() ?
|
||||
canvas :
|
||||
$(canvas).find('._fill').not('.mapster_mask'),
|
||||
0,
|
||||
m.hasCanvas() ?
|
||||
1 :
|
||||
opts.fillOpacity,
|
||||
opts.fadeDuration);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// These prototype methods are implementation dependent
|
||||
};
|
||||
|
||||
function noop() {}
|
||||
|
||||
|
||||
// configure remaining prototype methods for ie or canvas-supporting browser
|
||||
|
||||
canvasMethods = {
|
||||
renderShape: function (context, mapArea, offset) {
|
||||
var i,
|
||||
c = mapArea.coords(null,offset);
|
||||
|
||||
switch (mapArea.shape) {
|
||||
case 'rect':
|
||||
context.rect(c[0], c[1], c[2] - c[0], c[3] - c[1]);
|
||||
break;
|
||||
case 'poly':
|
||||
context.moveTo(c[0], c[1]);
|
||||
|
||||
for (i = 2; i < mapArea.length; i += 2) {
|
||||
context.lineTo(c[i], c[i + 1]);
|
||||
}
|
||||
context.lineTo(c[0], c[1]);
|
||||
break;
|
||||
case 'circ':
|
||||
case 'circle':
|
||||
context.arc(c[0], c[1], c[2], 0, Math.PI * 2, false);
|
||||
break;
|
||||
}
|
||||
},
|
||||
addAltImage: function (context, image, mapArea, options) {
|
||||
context.beginPath();
|
||||
|
||||
this.renderShape(context, mapArea);
|
||||
context.closePath();
|
||||
context.clip();
|
||||
|
||||
context.globalAlpha = options.altImageOpacity || options.fillOpacity;
|
||||
|
||||
context.drawImage(image, 0, 0, mapArea.owner.scaleInfo.width, mapArea.owner.scaleInfo.height);
|
||||
},
|
||||
render: function () {
|
||||
// firefox 6.0 context.save() seems to be broken. to work around, we have to draw the contents on one temp canvas,
|
||||
// the mask on another, and merge everything. ugh. fixed in 1.2.2. unfortunately this is a lot more code for masks,
|
||||
// but no other way around it that i can see.
|
||||
|
||||
var maskCanvas, maskContext,
|
||||
me = this,
|
||||
md = me.map_data,
|
||||
hasMasks = me.masks.length,
|
||||
shapeCanvas = me.createCanvasFor(md),
|
||||
shapeContext = shapeCanvas.getContext('2d'),
|
||||
context = me.canvas.getContext('2d');
|
||||
|
||||
if (hasMasks) {
|
||||
maskCanvas = me.createCanvasFor(md);
|
||||
maskContext = maskCanvas.getContext('2d');
|
||||
maskContext.clearRect(0, 0, maskCanvas.width, maskCanvas.height);
|
||||
|
||||
$.each(me.masks, function (i,e) {
|
||||
maskContext.save();
|
||||
maskContext.beginPath();
|
||||
me.renderShape(maskContext, e.mapArea);
|
||||
maskContext.closePath();
|
||||
maskContext.clip();
|
||||
maskContext.lineWidth = 0;
|
||||
maskContext.fillStyle = '#000';
|
||||
maskContext.fill();
|
||||
maskContext.restore();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
$.each(me.shapes, function (i,s) {
|
||||
shapeContext.save();
|
||||
if (s.options.fill) {
|
||||
if (s.options.altImageId) {
|
||||
me.addAltImage(shapeContext, md.images[s.options.altImageId], s.mapArea, s.options);
|
||||
} else {
|
||||
shapeContext.beginPath();
|
||||
me.renderShape(shapeContext, s.mapArea);
|
||||
shapeContext.closePath();
|
||||
//shapeContext.clip();
|
||||
shapeContext.fillStyle = css3color(s.options.fillColor, s.options.fillOpacity);
|
||||
shapeContext.fill();
|
||||
}
|
||||
}
|
||||
shapeContext.restore();
|
||||
});
|
||||
|
||||
|
||||
// render strokes at end since masks get stroked too
|
||||
|
||||
$.each(me.shapes.concat(me.masks), function (i,s) {
|
||||
var offset = s.options.strokeWidth === 1 ? 0.5 : 0;
|
||||
// offset applies only when stroke width is 1 and stroke would render between pixels.
|
||||
|
||||
if (s.options.stroke) {
|
||||
shapeContext.save();
|
||||
shapeContext.strokeStyle = css3color(s.options.strokeColor, s.options.strokeOpacity);
|
||||
shapeContext.lineWidth = s.options.strokeWidth;
|
||||
|
||||
shapeContext.beginPath();
|
||||
|
||||
me.renderShape(shapeContext, s.mapArea, offset);
|
||||
shapeContext.closePath();
|
||||
shapeContext.stroke();
|
||||
shapeContext.restore();
|
||||
}
|
||||
});
|
||||
|
||||
if (hasMasks) {
|
||||
// render the new shapes against the mask
|
||||
|
||||
maskContext.globalCompositeOperation = "source-out";
|
||||
maskContext.drawImage(shapeCanvas, 0, 0);
|
||||
|
||||
// flatten into the main canvas
|
||||
context.drawImage(maskCanvas, 0, 0);
|
||||
} else {
|
||||
context.drawImage(shapeCanvas, 0, 0);
|
||||
}
|
||||
|
||||
me.active = false;
|
||||
return me.canvas;
|
||||
},
|
||||
|
||||
// create a canvas mimicing dimensions of an existing element
|
||||
createCanvasFor: function (md) {
|
||||
return $('<canvas width="' + md.scaleInfo.width + '" height="' +md.scaleInfo.height + '"></canvas>')[0];
|
||||
},
|
||||
clearHighlight: function () {
|
||||
var c = this.map_data.overlay_canvas;
|
||||
c.getContext('2d').clearRect(0, 0, c.width, c.height);
|
||||
},
|
||||
// Draw all items from selected_list to a new canvas, then swap with the old one. This is used to delete items when using canvases.
|
||||
refreshSelections: function () {
|
||||
var canvas_temp, map_data = this.map_data;
|
||||
// draw new base canvas, then swap with the old one to avoid flickering
|
||||
canvas_temp = map_data.base_canvas;
|
||||
|
||||
map_data.base_canvas = this.createVisibleCanvas(map_data);
|
||||
$(map_data.base_canvas).hide();
|
||||
$(canvas_temp).before(map_data.base_canvas);
|
||||
|
||||
map_data.redrawSelections();
|
||||
|
||||
$(map_data.base_canvas).show();
|
||||
$(canvas_temp).remove();
|
||||
}
|
||||
};
|
||||
|
||||
vmlMethods = {
|
||||
|
||||
renderShape: function (mapArea, options, cssclass) {
|
||||
var me = this, fill,stroke, e, t_fill, el_name, el_class, template, c = mapArea.coords();
|
||||
el_name = me.elementName ? 'name="' + me.elementName + '" ' : '';
|
||||
el_class = cssclass ? 'class="' + cssclass + '" ' : '';
|
||||
|
||||
t_fill = '<v:fill color="#' + options.fillColor + '" class="_fill" opacity="' +
|
||||
(options.fill ?
|
||||
options.fillOpacity :
|
||||
0) +
|
||||
'" /><v:stroke class="_fill" opacity="' +
|
||||
options.strokeOpacity + '"/>';
|
||||
|
||||
|
||||
stroke = options.stroke ?
|
||||
' strokeweight=' + options.strokeWidth + ' stroked="t" strokecolor="#' +
|
||||
options.strokeColor + '"' :
|
||||
' stroked="f"';
|
||||
|
||||
fill = options.fill ?
|
||||
' filled="t"' :
|
||||
' filled="f"';
|
||||
|
||||
switch (mapArea.shape) {
|
||||
case 'rect':
|
||||
template = '<v:rect ' + el_class + el_name + fill + stroke +
|
||||
' style="zoom:1;margin:0;padding:0;display:block;position:absolute;left:' +
|
||||
c[0] + 'px;top:' + c[1] + 'px;width:' + (c[2] - c[0]) +
|
||||
'px;height:' + (c[3] - c[1]) + 'px;">' + t_fill + '</v:rect>';
|
||||
break;
|
||||
case 'poly':
|
||||
template = '<v:shape ' + el_class + el_name + fill + stroke + ' coordorigin="0,0" coordsize="' + me.width + ',' + me.height
|
||||
+ '" path="m ' + c[0] + ',' + c[1] + ' l ' + c.slice(2).join(',')
|
||||
+ ' x e" style="zoom:1;margin:0;padding:0;display:block;position:absolute;top:0px;left:0px;width:' + me.width + 'px;height:' + me.height + 'px;">' + t_fill + '</v:shape>';
|
||||
break;
|
||||
case 'circ':
|
||||
case 'circle':
|
||||
template = '<v:oval ' + el_class + el_name + fill + stroke
|
||||
+ ' style="zoom:1;margin:0;padding:0;display:block;position:absolute;left:' + (c[0] - c[2]) + 'px;top:' + (c[1] - c[2])
|
||||
+ 'px;width:' + (c[2] * 2) + 'px;height:' + (c[2] * 2) + 'px;">' + t_fill + '</v:oval>';
|
||||
break;
|
||||
}
|
||||
e = $(template);
|
||||
$(me.canvas).append(e);
|
||||
|
||||
return e;
|
||||
},
|
||||
render: function () {
|
||||
var opts, me = this;
|
||||
|
||||
$.each(this.shapes, function (i,e) {
|
||||
me.renderShape(e.mapArea, e.options);
|
||||
});
|
||||
|
||||
if (this.masks.length) {
|
||||
$.each(this.masks, function (i,e) {
|
||||
opts = u.updateProps({},
|
||||
e.options, {
|
||||
fillOpacity: 1,
|
||||
fillColor: e.options.fillColorMask
|
||||
});
|
||||
me.renderShape(e.mapArea, opts, 'mapster_mask');
|
||||
});
|
||||
}
|
||||
|
||||
this.active = false;
|
||||
return this.canvas;
|
||||
},
|
||||
|
||||
createCanvasFor: function (md) {
|
||||
var w = md.scaleInfo.width,
|
||||
h = md.scaleInfo.height;
|
||||
return $('<var width="' + w + '" height="' + h
|
||||
+ '" style="zoom:1;overflow:hidden;display:block;width:'
|
||||
+ w + 'px;height:' + h + 'px;"></var>')[0];
|
||||
},
|
||||
|
||||
clearHighlight: function () {
|
||||
$(this.map_data.overlay_canvas).children().remove();
|
||||
},
|
||||
// remove single or all selections
|
||||
removeSelections: function (area_id) {
|
||||
if (area_id >= 0) {
|
||||
$(this.map_data.base_canvas).find('[name="static_' + area_id.toString() + '"]').remove();
|
||||
}
|
||||
else {
|
||||
$(this.map_data.base_canvas).children().remove();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// for all methods with two implemenatations, add a function that will automatically replace itself with the correct
|
||||
// method on first invocation
|
||||
|
||||
$.each(['renderShape',
|
||||
'addAltImage',
|
||||
'render',
|
||||
'createCanvasFor',
|
||||
'clearHighlight',
|
||||
'removeSelections',
|
||||
'refreshSelections'],
|
||||
function(i,e) {
|
||||
p[e]=(function(method) {
|
||||
return function() {
|
||||
p[method] = (m.hasCanvas() ?
|
||||
canvasMethods[method] :
|
||||
vmlMethods[method]) || noop;
|
||||
|
||||
return p[method].apply(this,arguments);
|
||||
};
|
||||
}(e));
|
||||
});
|
||||
|
||||
|
||||
} (jQuery));
|
||||
37
rus/admin/_V4/_lib/ImageMapster-master/src/license.js
Normal file
37
rus/admin/_V4/_lib/ImageMapster-master/src/license.js
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* ImageMapster
|
||||
Version: 1.2.14-beta1 (6/18/2013)
|
||||
|
||||
Copyright 2011-2012 James Treworgy
|
||||
|
||||
http://www.outsharked.com/imagemapster
|
||||
https://github.com/jamietre/ImageMapster
|
||||
|
||||
A jQuery plugin to enhance image maps.
|
||||
|
||||
*/
|
||||
|
||||
;
|
||||
|
||||
/// LICENSE (MIT License)
|
||||
///
|
||||
/// Permission is hereby granted, free of charge, to any person obtaining
|
||||
/// a copy of this software and associated documentation files (the
|
||||
/// "Software"), to deal in the Software without restriction, including
|
||||
/// without limitation the rights to use, copy, modify, merge, publish,
|
||||
/// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
/// permit persons to whom the Software is furnished to do so, subject to
|
||||
/// the following conditions:
|
||||
///
|
||||
/// The above copyright notice and this permission notice shall be
|
||||
/// included in all copies or substantial portions of the Software.
|
||||
///
|
||||
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
/// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
/// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
/// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
/// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
/// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
/// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
///
|
||||
/// January 19, 2011
|
||||
|
||||
926
rus/admin/_V4/_lib/ImageMapster-master/src/mapdata.js
Normal file
926
rus/admin/_V4/_lib/ImageMapster-master/src/mapdata.js
Normal file
|
|
@ -0,0 +1,926 @@
|
|||
/* mapdata.js
|
||||
the MapData object, repesents an instance of a single bound imagemap
|
||||
*/
|
||||
|
||||
|
||||
(function ($) {
|
||||
|
||||
var m = $.mapster,
|
||||
u = m.utils;
|
||||
|
||||
/**
|
||||
* Set default values for MapData object properties
|
||||
* @param {MapData} me The MapData object
|
||||
*/
|
||||
|
||||
function initializeDefaults(me) {
|
||||
$.extend(me,{
|
||||
complete: false, // (bool) when configuration is complete
|
||||
map: null, // ($) the image map
|
||||
base_canvas: null, // (canvas|var) where selections are rendered
|
||||
overlay_canvas: null, // (canvas|var) where highlights are rendered
|
||||
commands: [], // {} commands that were run before configuration was completed (b/c images weren't loaded)
|
||||
data: [], // MapData[] area groups
|
||||
mapAreas: [], // MapArea[] list. AreaData entities contain refs to this array, so options are stored with each.
|
||||
_xref: {}, // (int) xref of mapKeys to data[]
|
||||
highlightId: -1, // (int) the currently highlighted element.
|
||||
currentAreaId: -1,
|
||||
_tooltip_events: [], // {} info on events we bound to a tooltip container, so we can properly unbind them
|
||||
scaleInfo: null, // {} info about the image size, scaling, defaults
|
||||
index: -1, // index of this in map_cache - so we have an ID to use for wraper div
|
||||
activeAreaEvent: null
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of all image-containing options from an options object;
|
||||
* that is, containers that may have an "altImage" property
|
||||
*
|
||||
* @param {object} obj An options object
|
||||
* @return {object[]} An array of objects
|
||||
*/
|
||||
function getOptionImages(obj) {
|
||||
return [obj, obj.render_highlight, obj.render_select];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse all the altImage references, adding them to the library so they can be preloaded
|
||||
* and aliased.
|
||||
*
|
||||
* @param {MapData} me The MapData object on which to operate
|
||||
*/
|
||||
function configureAltImages(me)
|
||||
{
|
||||
var opts = me.options,
|
||||
mi = me.images;
|
||||
|
||||
// add alt images
|
||||
|
||||
if (m.hasCanvas()) {
|
||||
// map altImage library first
|
||||
|
||||
$.each(opts.altImages || {}, function(i,e) {
|
||||
mi.add(e,i);
|
||||
});
|
||||
|
||||
// now find everything else
|
||||
|
||||
$.each([opts].concat(opts.areas),function(i,e) {
|
||||
$.each(getOptionImages(e),function(i2,e2) {
|
||||
if (e2 && e2.altImage) {
|
||||
e2.altImageId=mi.add(e2.altImage);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// set area_options
|
||||
me.area_options = u.updateProps({}, // default options for any MapArea
|
||||
m.area_defaults,
|
||||
opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue a mouse move action based on current delay settings
|
||||
* (helper for mouseover/mouseout handlers)
|
||||
*
|
||||
* @param {MapData} me The MapData context
|
||||
* @param {number} delay The number of milliseconds to delay the action
|
||||
* @param {AreaData} area AreaData affected
|
||||
* @param {Deferred} deferred A deferred object to return (instead of a new one)
|
||||
* @return {Promise} A promise that resolves when the action is completed
|
||||
*/
|
||||
function queueMouseEvent(me,delay,area, deferred) {
|
||||
|
||||
deferred = deferred || u.when.defer();
|
||||
|
||||
function cbFinal(areaId) {
|
||||
if (me.currentAreaId!==areaId && me.highlightId>=0) {
|
||||
deferred.resolve();
|
||||
}
|
||||
}
|
||||
if (me.activeAreaEvent) {
|
||||
window.clearTimeout(me.activeAreaEvent);
|
||||
me.activeAreaEvent=0;
|
||||
}
|
||||
if (delay<0) {
|
||||
deferred.reject();
|
||||
} else {
|
||||
if (area.owner.currentAction || delay) {
|
||||
me.activeAreaEvent = window.setTimeout((function() {
|
||||
return function() {
|
||||
queueMouseEvent(me,0,area,deferred);
|
||||
};
|
||||
}(area)),
|
||||
delay || 100);
|
||||
} else {
|
||||
cbFinal(area.areaId);
|
||||
}
|
||||
}
|
||||
return deferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mousedown event. This is captured only to prevent browser from drawing an outline around an
|
||||
* area when it's clicked.
|
||||
*
|
||||
* @param {EventData} e jQuery event data
|
||||
*/
|
||||
|
||||
function mousedown(e) {
|
||||
if (!m.hasCanvas()) {
|
||||
this.blur();
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mouseover event. Handle highlight rendering and client callback on mouseover
|
||||
*
|
||||
* @param {MapData} me The MapData context
|
||||
* @param {EventData} e jQuery event data
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
|
||||
function mouseover(me,e) {
|
||||
var arData = me.getAllDataForArea(this),
|
||||
ar=arData.length ? arData[0] : null;
|
||||
|
||||
// mouseover events are ignored entirely while resizing, though we do care about mouseout events
|
||||
// and must queue the action to keep things clean.
|
||||
|
||||
if (!ar || ar.isNotRendered() || ar.owner.currentAction) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (me.currentAreaId === ar.areaId) {
|
||||
return;
|
||||
}
|
||||
if (me.highlightId !== ar.areaId) {
|
||||
me.clearEffects();
|
||||
|
||||
ar.highlight();
|
||||
|
||||
if (me.options.showToolTip) {
|
||||
$.each(arData,function(i,e) {
|
||||
if (e.effectiveOptions().toolTip) {
|
||||
e.showToolTip();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
me.currentAreaId = ar.areaId;
|
||||
|
||||
if ($.isFunction(me.options.onMouseover)) {
|
||||
me.options.onMouseover.call(this,
|
||||
{
|
||||
e: e,
|
||||
options:ar.effectiveOptions(),
|
||||
key: ar.key,
|
||||
selected: ar.isSelected()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mouseout event.
|
||||
*
|
||||
* @param {MapData} me The MapData context
|
||||
* @param {EventData} e jQuery event data
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
|
||||
function mouseout(me,e) {
|
||||
var newArea,
|
||||
ar = me.getDataForArea(this),
|
||||
opts = me.options;
|
||||
|
||||
|
||||
if (me.currentAreaId<0 || !ar) {
|
||||
return;
|
||||
}
|
||||
|
||||
newArea=me.getDataForArea(e.relatedTarget);
|
||||
|
||||
if (newArea === ar) {
|
||||
return;
|
||||
}
|
||||
|
||||
me.currentAreaId = -1;
|
||||
ar.area=null;
|
||||
|
||||
queueMouseEvent(me,opts.mouseoutDelay,ar)
|
||||
.then(me.clearEffects);
|
||||
|
||||
if ($.isFunction(opts.onMouseout)) {
|
||||
opts.onMouseout.call(this,
|
||||
{
|
||||
e: e,
|
||||
options: opts,
|
||||
key: ar.key,
|
||||
selected: ar.isSelected()
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear any active tooltip or highlight
|
||||
*
|
||||
* @param {MapData} me The MapData context
|
||||
* @param {EventData} e jQuery event data
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
|
||||
function clearEffects(me) {
|
||||
var opts = me.options;
|
||||
|
||||
me.ensureNoHighlight();
|
||||
|
||||
if (opts.toolTipClose
|
||||
&& $.inArray('area-mouseout', opts.toolTipClose) >= 0
|
||||
&& me.activeToolTip)
|
||||
{
|
||||
me.clearToolTip();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mouse click event handler
|
||||
*
|
||||
* @param {MapData} me The MapData context
|
||||
* @param {EventData} e jQuery event data
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
|
||||
function click(me,e) {
|
||||
var selected, list, list_target, newSelectionState, canChangeState, cbResult,
|
||||
that = this,
|
||||
ar = me.getDataForArea(this),
|
||||
opts = me.options;
|
||||
|
||||
function clickArea(ar) {
|
||||
var areaOpts,target;
|
||||
canChangeState = (ar.isSelectable() &&
|
||||
(ar.isDeselectable() || !ar.isSelected()));
|
||||
|
||||
if (canChangeState) {
|
||||
newSelectionState = !ar.isSelected();
|
||||
} else {
|
||||
newSelectionState = ar.isSelected();
|
||||
}
|
||||
|
||||
list_target = m.getBoundList(opts, ar.key);
|
||||
|
||||
if ($.isFunction(opts.onClick))
|
||||
{
|
||||
cbResult= opts.onClick.call(that,
|
||||
{
|
||||
e: e,
|
||||
listTarget: list_target,
|
||||
key: ar.key,
|
||||
selected: newSelectionState
|
||||
});
|
||||
|
||||
if (u.isBool(cbResult)) {
|
||||
if (!cbResult) {
|
||||
return false;
|
||||
}
|
||||
target = $(ar.area).attr('href');
|
||||
if (target!=='#') {
|
||||
window.location.href=target;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (canChangeState) {
|
||||
selected = ar.toggle();
|
||||
}
|
||||
|
||||
if (opts.boundList && opts.boundList.length > 0) {
|
||||
m.setBoundListProperties(opts, list_target, ar.isSelected());
|
||||
}
|
||||
|
||||
areaOpts = ar.effectiveOptions();
|
||||
if (areaOpts.includeKeys) {
|
||||
list = u.split(areaOpts.includeKeys);
|
||||
$.each(list, function (i, e) {
|
||||
var ar = me.getDataForKey(e.toString());
|
||||
if (!ar.options.isMask) {
|
||||
clickArea(ar);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
mousedown.call(this,e);
|
||||
|
||||
if (opts.clickNavigate && ar.href) {
|
||||
window.location.href=ar.href;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ar && !ar.owner.currentAction) {
|
||||
opts = me.options;
|
||||
clickArea(ar);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prototype for a MapData object, representing an ImageMapster bound object
|
||||
* @param {Element} image an IMG element
|
||||
* @param {object} options ImageMapster binding options
|
||||
*/
|
||||
m.MapData = function (image, options)
|
||||
{
|
||||
var me = this;
|
||||
|
||||
// (Image) main map image
|
||||
|
||||
me.image = image;
|
||||
|
||||
me.images = new m.MapImages(me);
|
||||
me.graphics = new m.Graphics(me);
|
||||
|
||||
// save the initial style of the image for unbinding. This is problematic, chrome
|
||||
// duplicates styles when assigning, and cssText is apparently not universally supported.
|
||||
// Need to do something more robust to make unbinding work universally.
|
||||
|
||||
me.imgCssText = image.style.cssText || null;
|
||||
|
||||
initializeDefaults(me);
|
||||
|
||||
me.configureOptions(options);
|
||||
|
||||
// create context-bound event handlers from our private functions
|
||||
|
||||
me.mouseover = function(e) { mouseover.call(this,me,e); };
|
||||
me.mouseout = function(e) { mouseout.call(this,me,e); };
|
||||
me.click = function(e) { click.call(this,me,e); };
|
||||
me.clearEffects = function(e) { clearEffects.call(this,me,e); };
|
||||
};
|
||||
|
||||
m.MapData.prototype = {
|
||||
constructor: m.MapData,
|
||||
|
||||
/**
|
||||
* Set target.options from defaults + options
|
||||
* @param {[type]} target The target
|
||||
* @param {[type]} options The options to merge
|
||||
*/
|
||||
|
||||
configureOptions: function(options) {
|
||||
this.options= u.updateProps({}, m.defaults, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Ensure all images are loaded
|
||||
* @return {Promise} A promise that resolves when the images have finished loading (or fail)
|
||||
*/
|
||||
|
||||
bindImages: function() {
|
||||
var me=this,
|
||||
mi = me.images;
|
||||
|
||||
// reset the images if this is a rebind
|
||||
|
||||
if (mi.length>2) {
|
||||
mi.splice(2);
|
||||
} else if (mi.length===0) {
|
||||
|
||||
// add the actual main image
|
||||
mi.add(me.image);
|
||||
// will create a duplicate of the main image, we need this to get raw size info
|
||||
mi.add(me.image.src);
|
||||
}
|
||||
|
||||
configureAltImages(me);
|
||||
|
||||
return me.images.bind();
|
||||
},
|
||||
|
||||
/**
|
||||
* Test whether an async action is currently in progress
|
||||
* @return {Boolean} true or false indicating state
|
||||
*/
|
||||
|
||||
isActive: function() {
|
||||
return !this.complete || this.currentAction;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return an object indicating the various states. This isn't really used by
|
||||
* production code.
|
||||
*
|
||||
* @return {object} An object with properties for various states
|
||||
*/
|
||||
|
||||
state: function () {
|
||||
return {
|
||||
complete: this.complete,
|
||||
resizing: this.currentAction==='resizing',
|
||||
zoomed: this.zoomed,
|
||||
zoomedArea: this.zoomedArea,
|
||||
scaleInfo: this.scaleInfo
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a unique ID for the wrapper of this imagemapster
|
||||
* @return {string} A string that is unique to this image
|
||||
*/
|
||||
|
||||
wrapId: function () {
|
||||
return 'mapster_wrap_' + this.index;
|
||||
},
|
||||
_idFromKey: function (key) {
|
||||
return typeof key === "string" && this._xref.hasOwnProperty(key) ?
|
||||
this._xref[key] : -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a comma-separated string of all selected keys
|
||||
* @return {string} CSV of all keys that are currently selected
|
||||
*/
|
||||
|
||||
getSelected: function () {
|
||||
var result = '';
|
||||
$.each(this.data, function (i,e) {
|
||||
if (e.isSelected()) {
|
||||
result += (result ? ',' : '') + this.key;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get an array of MapAreas associated with a specific AREA based on the keys for that area
|
||||
* @param {Element} area An HTML AREA
|
||||
* @param {number} atMost A number limiting the number of areas to be returned (typically 1 or 0 for no limit)
|
||||
* @return {MapArea[]} Array of MapArea objects
|
||||
*/
|
||||
|
||||
getAllDataForArea:function (area,atMost) {
|
||||
var i,ar, result,
|
||||
me=this,
|
||||
key = $(area).filter('area').attr(me.options.mapKey);
|
||||
|
||||
if (key) {
|
||||
result=[];
|
||||
key = u.split(key);
|
||||
|
||||
for (i=0;i<(atMost || key.length);i++) {
|
||||
ar = me.data[me._idFromKey(key[i])];
|
||||
if (ar){
|
||||
ar.area=area.length ? area[0]:area;
|
||||
// set the actual area moused over/selected
|
||||
// TODO: this is a brittle model for capturing which specific area - if this method was not used,
|
||||
// ar.area could have old data. fix this.
|
||||
result.push(ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
getDataForArea: function(area) {
|
||||
var ar=this.getAllDataForArea(area,1);
|
||||
return ar ? ar[0] || null : null;
|
||||
},
|
||||
getDataForKey: function (key) {
|
||||
return this.data[this._idFromKey(key)];
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the primary keys associated with an area group.
|
||||
* If this is a primary key, it will be returned.
|
||||
*
|
||||
* @param {string key An area key
|
||||
* @return {string} A CSV of area keys
|
||||
*/
|
||||
|
||||
getKeysForGroup: function(key) {
|
||||
var ar=this.getDataForKey(key);
|
||||
|
||||
return !ar ? '':
|
||||
ar.isPrimary ?
|
||||
ar.key :
|
||||
this.getPrimaryKeysForMapAreas(ar.areas()).join(',');
|
||||
},
|
||||
|
||||
/**
|
||||
* given an array of MapArea object, return an array of its unique primary keys
|
||||
* @param {MapArea[]} areas The areas to analyze
|
||||
* @return {string[]} An array of unique primary keys
|
||||
*/
|
||||
|
||||
getPrimaryKeysForMapAreas: function(areas)
|
||||
{
|
||||
var keys=[];
|
||||
$.each(areas,function(i,e) {
|
||||
if ($.inArray(e.keys[0],keys)<0) {
|
||||
keys.push(e.keys[0]);
|
||||
}
|
||||
});
|
||||
return keys;
|
||||
},
|
||||
getData: function (obj) {
|
||||
if (typeof obj === 'string') {
|
||||
return this.getDataForKey(obj);
|
||||
} else if (obj && obj.mapster || u.isElement(obj)) {
|
||||
return this.getDataForArea(obj);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
// remove highlight if present, raise event
|
||||
ensureNoHighlight: function () {
|
||||
var ar;
|
||||
if (this.highlightId >= 0) {
|
||||
this.graphics.clearHighlight();
|
||||
ar = this.data[this.highlightId];
|
||||
ar.changeState('highlight', false);
|
||||
this.setHighlightId(-1);
|
||||
}
|
||||
},
|
||||
setHighlightId: function(id) {
|
||||
this.highlightId = id;
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear all active selections on this map
|
||||
*/
|
||||
|
||||
clearSelections: function () {
|
||||
$.each(this.data, function (i,e) {
|
||||
if (e.selected) {
|
||||
e.deselect(true);
|
||||
}
|
||||
});
|
||||
this.removeSelectionFinish();
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Set area options from an array of option data.
|
||||
*
|
||||
* @param {object[]} areas An array of objects containing area-specific options
|
||||
*/
|
||||
|
||||
setAreaOptions: function (areas) {
|
||||
var i, area_options, ar;
|
||||
areas = areas || [];
|
||||
|
||||
// refer by: map_data.options[map_data.data[x].area_option_id]
|
||||
|
||||
for (i = areas.length - 1; i >= 0; i--) {
|
||||
area_options = areas[i];
|
||||
if (area_options) {
|
||||
ar = this.getDataForKey(area_options.key);
|
||||
if (ar) {
|
||||
u.updateProps(ar.options, area_options);
|
||||
|
||||
// TODO: will not deselect areas that were previously selected, so this only works
|
||||
// for an initial bind.
|
||||
|
||||
if (u.isBool(area_options.selected)) {
|
||||
ar.selected = area_options.selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// keys: a comma-separated list
|
||||
drawSelections: function (keys) {
|
||||
var i, key_arr = u.asArray(keys);
|
||||
|
||||
for (i = key_arr.length - 1; i >= 0; i--) {
|
||||
this.data[key_arr[i]].drawSelection();
|
||||
}
|
||||
},
|
||||
redrawSelections: function () {
|
||||
$.each(this.data, function (i, e) {
|
||||
if (e.isSelectedOrStatic()) {
|
||||
e.drawSelection();
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
///called when images are done loading
|
||||
initialize: function () {
|
||||
var imgCopy, base_canvas, overlay_canvas, wrap, parentId, css, i,size,
|
||||
img,sort_func, sorted_list, scale,
|
||||
me = this,
|
||||
opts = me.options;
|
||||
|
||||
if (me.complete) {
|
||||
return;
|
||||
}
|
||||
|
||||
img = $(me.image);
|
||||
|
||||
parentId = img.parent().attr('id');
|
||||
|
||||
// create a div wrapper only if there's not already a wrapper, otherwise, own it
|
||||
|
||||
if (parentId && parentId.length >= 12 && parentId.substring(0, 12) === "mapster_wrap") {
|
||||
wrap = img.parent();
|
||||
wrap.attr('id', me.wrapId());
|
||||
} else {
|
||||
wrap = $('<div id="' + me.wrapId() + '"></div>');
|
||||
|
||||
if (opts.wrapClass) {
|
||||
if (opts.wrapClass === true) {
|
||||
wrap.addClass(img[0].className);
|
||||
}
|
||||
else {
|
||||
wrap.addClass(opts.wrapClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
me.wrapper = wrap;
|
||||
|
||||
// me.images[1] is the copy of the original image. It should be loaded & at its native size now so we can obtain the true
|
||||
// width & height. This is needed to scale the imagemap if not being shown at its native size. It is also needed purely
|
||||
// to finish binding in case the original image was not visible. It can be impossible in some browsers to obtain the
|
||||
// native size of a hidden image.
|
||||
|
||||
me.scaleInfo = scale = u.scaleMap(me.images[0],me.images[1], opts.scaleMap);
|
||||
|
||||
me.base_canvas = base_canvas = me.graphics.createVisibleCanvas(me);
|
||||
me.overlay_canvas = overlay_canvas = me.graphics.createVisibleCanvas(me);
|
||||
|
||||
// Now we got what we needed from the copy -clone from the original image again to make sure any other attributes are copied
|
||||
imgCopy = $(me.images[1])
|
||||
.addClass('mapster_el '+ me.images[0].className)
|
||||
.attr({id:null, usemap: null});
|
||||
|
||||
size=u.size(me.images[0]);
|
||||
|
||||
if (size.complete) {
|
||||
imgCopy.css({
|
||||
width: size.width,
|
||||
height: size.height
|
||||
});
|
||||
}
|
||||
|
||||
me.buildDataset();
|
||||
|
||||
// now that we have processed all the areas, set css for wrapper, scale map if needed
|
||||
|
||||
css = {
|
||||
display: 'block',
|
||||
position: 'relative',
|
||||
padding: 0,
|
||||
width: scale.width,
|
||||
height: scale.height
|
||||
};
|
||||
|
||||
if (opts.wrapCss) {
|
||||
$.extend(css, opts.wrapCss);
|
||||
}
|
||||
// if we were rebinding with an existing wrapper, the image will aready be in it
|
||||
if (img.parent()[0] !== me.wrapper[0]) {
|
||||
|
||||
img.before(me.wrapper);
|
||||
}
|
||||
|
||||
wrap.css(css);
|
||||
|
||||
// move all generated images into the wrapper for easy removal later
|
||||
|
||||
$(me.images.slice(2)).hide();
|
||||
for (i = 1; i < me.images.length; i++) {
|
||||
wrap.append(me.images[i]);
|
||||
}
|
||||
|
||||
//me.images[1].style.cssText = me.image.style.cssText;
|
||||
|
||||
wrap.append(base_canvas)
|
||||
.append(overlay_canvas)
|
||||
.append(img.css(m.canvas_style));
|
||||
|
||||
// images[0] is the original image with map, images[1] is the copy/background that is visible
|
||||
|
||||
u.setOpacity(me.images[0], 0);
|
||||
$(me.images[1]).show();
|
||||
|
||||
u.setOpacity(me.images[1],1);
|
||||
|
||||
if (opts.isSelectable && opts.onGetList) {
|
||||
sorted_list = me.data.slice(0);
|
||||
if (opts.sortList) {
|
||||
if (opts.sortList === "desc") {
|
||||
sort_func = function (a, b) {
|
||||
return a === b ? 0 : (a > b ? -1 : 1);
|
||||
};
|
||||
}
|
||||
else {
|
||||
sort_func = function (a, b) {
|
||||
return a === b ? 0 : (a < b ? -1 : 1);
|
||||
};
|
||||
}
|
||||
|
||||
sorted_list.sort(function (a, b) {
|
||||
a = a.value;
|
||||
b = b.value;
|
||||
return sort_func(a, b);
|
||||
});
|
||||
}
|
||||
|
||||
me.options.boundList = opts.onGetList.call(me.image, sorted_list);
|
||||
}
|
||||
|
||||
me.complete=true;
|
||||
me.processCommandQueue();
|
||||
|
||||
if (opts.onConfigured && typeof opts.onConfigured === 'function') {
|
||||
opts.onConfigured.call(img, true);
|
||||
}
|
||||
},
|
||||
|
||||
// when rebind is true, the MapArea data will not be rebuilt.
|
||||
buildDataset: function(rebind) {
|
||||
var sel,areas,j,area_id,$area,area,curKey,mapArea,key,keys,mapAreaId,group_value,dataItem,href,
|
||||
me=this,
|
||||
opts=me.options,
|
||||
default_group;
|
||||
|
||||
function addAreaData(key, value) {
|
||||
var dataItem = new m.AreaData(me, key, value);
|
||||
dataItem.areaId = me._xref[key] = me.data.push(dataItem) - 1;
|
||||
return dataItem.areaId;
|
||||
}
|
||||
|
||||
me._xref = {};
|
||||
me.data = [];
|
||||
if (!rebind) {
|
||||
me.mapAreas=[];
|
||||
}
|
||||
|
||||
default_group = !opts.mapKey;
|
||||
if (default_group) {
|
||||
opts.mapKey = 'data-mapster-key';
|
||||
}
|
||||
|
||||
// the [attribute] selector is broken on old IE with jQuery. hasVml() is a quick and dirty
|
||||
// way to test for that
|
||||
|
||||
sel = m.hasVml() ? 'area' :
|
||||
(default_group ?
|
||||
'area[coords]' :
|
||||
'area[' + opts.mapKey + ']');
|
||||
|
||||
areas = $(me.map).find(sel).unbind('.mapster');
|
||||
|
||||
for (mapAreaId = 0;mapAreaId<areas.length; mapAreaId++) {
|
||||
area_id = 0;
|
||||
area = areas[mapAreaId];
|
||||
$area = $(area);
|
||||
|
||||
// skip areas with no coords - selector broken for older ie
|
||||
if (!area.coords) {
|
||||
continue;
|
||||
}
|
||||
// Create a key if none was assigned by the user
|
||||
|
||||
if (default_group) {
|
||||
curKey=String(mapAreaId);
|
||||
$area.attr('data-mapster-key', curKey);
|
||||
|
||||
} else {
|
||||
curKey = area.getAttribute(opts.mapKey);
|
||||
}
|
||||
|
||||
// conditions for which the area will be bound to mouse events
|
||||
// only bind to areas that don't have nohref. ie 6&7 cannot detect the presence of nohref, so we have to also not bind if href is missing.
|
||||
|
||||
if (rebind) {
|
||||
mapArea = me.mapAreas[$area.data('mapster')-1];
|
||||
mapArea.configure(curKey);
|
||||
} else {
|
||||
mapArea = new m.MapArea(me, area,curKey);
|
||||
me.mapAreas.push(mapArea);
|
||||
}
|
||||
|
||||
keys = mapArea.keys; // converted to an array by mapArea
|
||||
|
||||
|
||||
// Iterate through each mapKey assigned to this area
|
||||
for (j = keys.length - 1; j >= 0; j--) {
|
||||
key = keys[j];
|
||||
|
||||
if (opts.mapValue) {
|
||||
group_value = $area.attr(opts.mapValue);
|
||||
}
|
||||
if (default_group) {
|
||||
// set an attribute so we can refer to the area by index from the DOM object if no key
|
||||
area_id = addAreaData(me.data.length, group_value);
|
||||
dataItem = me.data[area_id];
|
||||
dataItem.key = key = area_id.toString();
|
||||
}
|
||||
else {
|
||||
area_id = me._xref[key];
|
||||
if (area_id >= 0) {
|
||||
dataItem = me.data[area_id];
|
||||
if (group_value && !me.data[area_id].value) {
|
||||
dataItem.value = group_value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
area_id = addAreaData(key, group_value);
|
||||
dataItem = me.data[area_id];
|
||||
dataItem.isPrimary=j===0;
|
||||
}
|
||||
}
|
||||
mapArea.areaDataXref.push(area_id);
|
||||
dataItem.areasXref.push(mapAreaId);
|
||||
}
|
||||
|
||||
href=$area.attr('href');
|
||||
if (href && href!=='#' && !dataItem.href)
|
||||
{
|
||||
dataItem.href=href;
|
||||
}
|
||||
|
||||
if (!mapArea.nohref) {
|
||||
$area.bind('click.mapster', me.click)
|
||||
.bind('mouseover.mapster, touchstart.mapster', me.mouseover)
|
||||
.bind('mouseout.mapster, touchend.mapster', me.mouseout)
|
||||
.bind('mousedown.mapster', me.mousedown);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// store an ID with each area.
|
||||
$area.data("mapster", mapAreaId+1);
|
||||
}
|
||||
|
||||
// TODO listenToList
|
||||
// if (opts.listenToList && opts.nitG) {
|
||||
// opts.nitG.bind('click.mapster', event_hooks[map_data.hooks_index].listclick_hook);
|
||||
// }
|
||||
|
||||
// populate areas from config options
|
||||
me.setAreaOptions(opts.areas);
|
||||
me.redrawSelections();
|
||||
|
||||
},
|
||||
processCommandQueue: function() {
|
||||
|
||||
var cur,me=this;
|
||||
while (!me.currentAction && me.commands.length) {
|
||||
cur = me.commands[0];
|
||||
me.commands.splice(0,1);
|
||||
m.impl[cur.command].apply(cur.that, cur.args);
|
||||
}
|
||||
},
|
||||
clearEvents: function () {
|
||||
$(this.map).find('area')
|
||||
.unbind('.mapster');
|
||||
$(this.images)
|
||||
.unbind('.mapster');
|
||||
},
|
||||
_clearCanvases: function (preserveState) {
|
||||
// remove the canvas elements created
|
||||
if (!preserveState) {
|
||||
$(this.base_canvas).remove();
|
||||
}
|
||||
$(this.overlay_canvas).remove();
|
||||
},
|
||||
clearMapData: function (preserveState) {
|
||||
var me = this;
|
||||
this._clearCanvases(preserveState);
|
||||
|
||||
// release refs to DOM elements
|
||||
$.each(this.data, function (i, e) {
|
||||
e.reset();
|
||||
});
|
||||
this.data = null;
|
||||
if (!preserveState) {
|
||||
// get rid of everything except the original image
|
||||
this.image.style.cssText = this.imgCssText;
|
||||
$(this.wrapper).before(this.image).remove();
|
||||
}
|
||||
|
||||
me.images.clear();
|
||||
|
||||
this.image = null;
|
||||
u.ifFunction(this.clearTooltip, this);
|
||||
},
|
||||
|
||||
// Compelete cleanup process for deslecting items. Called after a batch operation, or by AreaData for single
|
||||
// operations not flagged as "partial"
|
||||
|
||||
removeSelectionFinish: function () {
|
||||
var g = this.graphics;
|
||||
|
||||
g.refreshSelections();
|
||||
// do not call ensure_no_highlight- we don't really want to unhilight it, just remove the effect
|
||||
g.clearHighlight();
|
||||
}
|
||||
};
|
||||
} (jQuery));
|
||||
277
rus/admin/_V4/_lib/ImageMapster-master/src/mapimage.js
Normal file
277
rus/admin/_V4/_lib/ImageMapster-master/src/mapimage.js
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
/* mapimage.js
|
||||
the MapImage object, repesents an instance of a single bound imagemap
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
|
||||
var m = $.mapster,
|
||||
u = m.utils,
|
||||
ap=[];
|
||||
/**
|
||||
* An object encapsulating all the images used by a MapData.
|
||||
*/
|
||||
|
||||
m.MapImages = function(owner) {
|
||||
this.owner = owner;
|
||||
this.clear();
|
||||
};
|
||||
|
||||
|
||||
m.MapImages.prototype = {
|
||||
constructor: m.MapImages,
|
||||
|
||||
/* interface to make this array-like */
|
||||
|
||||
slice: function() {
|
||||
return ap.slice.apply(this,arguments);
|
||||
},
|
||||
splice: function() {
|
||||
ap.slice.apply(this.status,arguments);
|
||||
var result= ap.slice.apply(this,arguments);
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* a boolean value indicates whether all images are done loading
|
||||
* @return {bool} true when all are done
|
||||
*/
|
||||
complete: function() {
|
||||
return $.inArray(false, this.status) < 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Save an image in the images array and return its index
|
||||
* @param {Image} image An Image object
|
||||
* @return {int} the index of the image
|
||||
*/
|
||||
|
||||
_add: function(image) {
|
||||
var index = ap.push.call(this,image)-1;
|
||||
this.status[index] = false;
|
||||
return index;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the index of an Image within the images array
|
||||
* @param {Image} img An Image
|
||||
* @return {int} the index within the array, or -1 if it was not found
|
||||
*/
|
||||
|
||||
indexOf: function(image) {
|
||||
return u.indexOf(this,image);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear this object and reset it to its initial state after binding.
|
||||
*/
|
||||
|
||||
clear: function() {
|
||||
var me=this;
|
||||
|
||||
if (me.ids && me.ids.length>0) {
|
||||
$.each(me.ids,function(i,e) {
|
||||
delete me[e];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of the cross-reference IDs bound to this object
|
||||
* @type {string[]}
|
||||
*/
|
||||
|
||||
me.ids=[];
|
||||
|
||||
/**
|
||||
* Length property for array-like behavior, set to zero when initializing. Array prototype
|
||||
* methods will update it after that.
|
||||
*
|
||||
* @type {int}
|
||||
*/
|
||||
|
||||
me.length=0;
|
||||
|
||||
/**
|
||||
* the loaded status of the corresponding image
|
||||
* @type {boolean[]}
|
||||
*/
|
||||
|
||||
me.status=[];
|
||||
|
||||
|
||||
// actually erase the images
|
||||
|
||||
me.splice(0);
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Bind an image to the map and add it to the queue to be loaded; return an ID that
|
||||
* can be used to reference the
|
||||
*
|
||||
* @param {Image|string} image An Image object or a URL to an image
|
||||
* @param {string} [id] An id to refer to this image
|
||||
* @returns {int} an ID referencing the index of the image object in
|
||||
* map_data.images
|
||||
*/
|
||||
|
||||
add: function(image,id) {
|
||||
var index,src,me = this;
|
||||
|
||||
if (!image) { return; }
|
||||
|
||||
if (typeof image === 'string') {
|
||||
src = image;
|
||||
image = me[src];
|
||||
if (typeof image==='object') {
|
||||
return me.indexOf(image);
|
||||
}
|
||||
|
||||
image = $('<img />')
|
||||
.addClass('mapster_el')
|
||||
.hide();
|
||||
|
||||
index=me._add(image[0]);
|
||||
|
||||
image
|
||||
.bind('load',function(e) {
|
||||
me.imageLoaded.call(me,e);
|
||||
})
|
||||
.bind('error',function(e) {
|
||||
me.imageLoadError.call(me,e);
|
||||
});
|
||||
|
||||
image.attr('src', src);
|
||||
} else {
|
||||
|
||||
// use attr because we want the actual source, not the resolved path the browser will return directly calling image.src
|
||||
|
||||
index=me._add($(image)[0]);
|
||||
}
|
||||
if (id) {
|
||||
if (this[id]) {
|
||||
throw(id+" is already used or is not available as an altImage alias.");
|
||||
}
|
||||
me.ids.push(id);
|
||||
me[id]=me[index];
|
||||
}
|
||||
return index;
|
||||
},
|
||||
|
||||
/**
|
||||
* Bind the images in this object,
|
||||
* @param {boolean} retry when true, indicates that the function is calling itself after failure
|
||||
* @return {Promise} a promise that resolves when the images have finished loading
|
||||
*/
|
||||
|
||||
bind: function(retry) {
|
||||
var me = this,
|
||||
promise,
|
||||
triesLeft = me.owner.options.configTimeout / 200,
|
||||
|
||||
/* A recursive function to continue checking that the images have been
|
||||
loaded until a timeout has elapsed */
|
||||
|
||||
check=function() {
|
||||
var i;
|
||||
|
||||
// refresh status of images
|
||||
|
||||
i=me.length;
|
||||
|
||||
while (i-->0) {
|
||||
if (!me.isLoaded(i)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check to see if every image has already been loaded
|
||||
|
||||
if (me.complete()) {
|
||||
me.resolve();
|
||||
} else {
|
||||
// to account for failure of onLoad to fire in rare situations
|
||||
if (triesLeft-- > 0) {
|
||||
me.imgTimeout=window.setTimeout(function() {
|
||||
check.call(me,true);
|
||||
}, 50);
|
||||
} else {
|
||||
me.imageLoadError.call(me);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
promise = me.deferred=u.defer();
|
||||
|
||||
check();
|
||||
return promise;
|
||||
},
|
||||
|
||||
resolve: function() {
|
||||
var me=this,
|
||||
resolver=me.deferred;
|
||||
|
||||
if (resolver) {
|
||||
// Make a copy of the resolver before calling & removing it to ensure
|
||||
// it is not called twice
|
||||
me.deferred=null;
|
||||
resolver.resolve();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for image onload
|
||||
* @param {object} e jQuery event data
|
||||
*/
|
||||
|
||||
imageLoaded: function(e) {
|
||||
var me=this,
|
||||
index = me.indexOf(e.target);
|
||||
|
||||
if (index>=0) {
|
||||
|
||||
me.status[index] = true;
|
||||
if ($.inArray(false, me.status) < 0) {
|
||||
me.resolve();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Event handler for onload error
|
||||
* @param {object} e jQuery event data
|
||||
*/
|
||||
|
||||
imageLoadError: function(e) {
|
||||
clearTimeout(this.imgTimeout);
|
||||
this.triesLeft=0;
|
||||
var err = e ? 'The image ' + e.target.src + ' failed to load.' :
|
||||
'The images never seemed to finish loading. You may just need to increase the configTimeout if images could take a long time to load.';
|
||||
throw err;
|
||||
},
|
||||
/**
|
||||
* Test if the image at specificed index has finished loading
|
||||
* @param {int} index The image index
|
||||
* @return {boolean} true if loaded, false if not
|
||||
*/
|
||||
|
||||
isLoaded: function(index) {
|
||||
var img,
|
||||
me=this,
|
||||
status=me.status;
|
||||
|
||||
if (status[index]) { return true; }
|
||||
img = me[index];
|
||||
|
||||
if (typeof img.complete !== 'undefined') {
|
||||
status[index]=img.complete;
|
||||
} else {
|
||||
status[index]=!!u.imgWidth(img);
|
||||
}
|
||||
// if complete passes, the image is loaded, but may STILL not be available because of stuff like adblock.
|
||||
// make sure it is.
|
||||
|
||||
return status[index];
|
||||
}
|
||||
};
|
||||
} (jQuery));
|
||||
784
rus/admin/_V4/_lib/ImageMapster-master/src/redist/when.js
Normal file
784
rus/admin/_V4/_lib/ImageMapster-master/src/redist/when.js
Normal file
|
|
@ -0,0 +1,784 @@
|
|||
/** @license MIT License (c) copyright B Cavalier & J Hann */
|
||||
|
||||
/**
|
||||
* when
|
||||
* A lightweight CommonJS Promises/A and when() implementation
|
||||
*
|
||||
* when is part of the cujo.js family of libraries (http://cujojs.com/)
|
||||
*
|
||||
* Licensed under the MIT License at:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @version 1.2.0
|
||||
*/
|
||||
|
||||
/*lint-ignore-start*/
|
||||
|
||||
(function (define) {
|
||||
define(function () {
|
||||
var freeze, reduceArray, slice, undef;
|
||||
|
||||
//
|
||||
// Public API
|
||||
//
|
||||
|
||||
when.defer = defer;
|
||||
when.reject = reject;
|
||||
when.isPromise = isPromise;
|
||||
|
||||
when.all = all;
|
||||
when.some = some;
|
||||
when.any = any;
|
||||
|
||||
when.map = map;
|
||||
when.reduce = reduce;
|
||||
|
||||
when.chain = chain;
|
||||
|
||||
/** Object.freeze */
|
||||
freeze = Object.freeze || function (o) { return o; };
|
||||
|
||||
/**
|
||||
* Trusted Promise constructor. A Promise created from this constructor is
|
||||
* a trusted when.js promise. Any other duck-typed promise is considered
|
||||
* untrusted.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function Promise() { }
|
||||
|
||||
Promise.prototype = freeze({
|
||||
always: function (alwaysback, progback) {
|
||||
return this.then(alwaysback, alwaysback, progback);
|
||||
},
|
||||
|
||||
otherwise: function (errback) {
|
||||
return this.then(undef, errback);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Create an already-resolved promise for the supplied value
|
||||
* @private
|
||||
*
|
||||
* @param value anything
|
||||
* @return {Promise}
|
||||
*/
|
||||
function resolved(value) {
|
||||
|
||||
var p = new Promise();
|
||||
|
||||
p.then = function (callback) {
|
||||
var nextValue;
|
||||
try {
|
||||
if (callback) nextValue = callback(value);
|
||||
return promise(nextValue === undef ? value : nextValue);
|
||||
} catch (e) {
|
||||
return rejected(e);
|
||||
}
|
||||
};
|
||||
|
||||
return freeze(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an already-rejected {@link Promise} with the supplied
|
||||
* rejection reason.
|
||||
* @private
|
||||
*
|
||||
* @param reason rejection reason
|
||||
* @return {Promise}
|
||||
*/
|
||||
function rejected(reason) {
|
||||
|
||||
var p = new Promise();
|
||||
|
||||
p.then = function (callback, errback) {
|
||||
var nextValue;
|
||||
try {
|
||||
if (errback) {
|
||||
nextValue = errback(reason);
|
||||
return promise(nextValue === undef ? reason : nextValue)
|
||||
}
|
||||
|
||||
return rejected(reason);
|
||||
|
||||
} catch (e) {
|
||||
return rejected(e);
|
||||
}
|
||||
};
|
||||
|
||||
return freeze(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a rejected promise for the supplied promiseOrValue. If
|
||||
* promiseOrValue is a value, it will be the rejection value of the
|
||||
* returned promise. If promiseOrValue is a promise, its
|
||||
* completion value will be the rejected value of the returned promise
|
||||
*
|
||||
* @param promiseOrValue {*} the rejected value of the returned {@link Promise}
|
||||
*
|
||||
* @return {Promise} rejected {@link Promise}
|
||||
*/
|
||||
function reject(promiseOrValue) {
|
||||
return when(promiseOrValue, function (value) {
|
||||
return rejected(value);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new, CommonJS compliant, Deferred with fully isolated
|
||||
* resolver and promise parts, either or both of which may be given out
|
||||
* safely to consumers.
|
||||
* The Deferred itself has the full API: resolve, reject, progress, and
|
||||
* then. The resolver has resolve, reject, and progress. The promise
|
||||
* only has then.
|
||||
*
|
||||
* @memberOf when
|
||||
* @function
|
||||
*
|
||||
* @returns {Deferred}
|
||||
*/
|
||||
function defer() {
|
||||
var deferred, promise, listeners, progressHandlers, _then, _progress, complete;
|
||||
|
||||
listeners = [];
|
||||
progressHandlers = [];
|
||||
|
||||
/**
|
||||
* Pre-resolution then() that adds the supplied callback, errback, and progback
|
||||
* functions to the registered listeners
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param [callback] {Function} resolution handler
|
||||
* @param [errback] {Function} rejection handler
|
||||
* @param [progback] {Function} progress handler
|
||||
*
|
||||
* @throws {Error} if any argument is not null, undefined, or a Function
|
||||
*/
|
||||
_then = function unresolvedThen(callback, errback, progback) {
|
||||
var deferred = defer();
|
||||
|
||||
listeners.push(function (promise) {
|
||||
promise.then(callback, errback)
|
||||
.then(deferred.resolve, deferred.reject, deferred.progress);
|
||||
});
|
||||
|
||||
progback && progressHandlers.push(progback);
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers a handler for this {@link Deferred}'s {@link Promise}. Even though all arguments
|
||||
* are optional, each argument that *is* supplied must be null, undefined, or a Function.
|
||||
* Any other value will cause an Error to be thrown.
|
||||
*
|
||||
* @memberOf Promise
|
||||
*
|
||||
* @param [callback] {Function} resolution handler
|
||||
* @param [errback] {Function} rejection handler
|
||||
* @param [progback] {Function} progress handler
|
||||
*
|
||||
* @throws {Error} if any argument is not null, undefined, or a Function
|
||||
*/
|
||||
function then(callback, errback, progback) {
|
||||
return _then(callback, errback, progback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves this {@link Deferred}'s {@link Promise} with val as the
|
||||
* resolution value.
|
||||
*
|
||||
* @memberOf Resolver
|
||||
*
|
||||
* @param val anything
|
||||
*/
|
||||
function resolve(val) {
|
||||
complete(resolved(val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rejects this {@link Deferred}'s {@link Promise} with err as the
|
||||
* reason.
|
||||
*
|
||||
* @memberOf Resolver
|
||||
*
|
||||
* @param err anything
|
||||
*/
|
||||
function reject(err) {
|
||||
complete(rejected(err));
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param update
|
||||
*/
|
||||
_progress = function (update) {
|
||||
var progress, i = 0;
|
||||
while (progress = progressHandlers[i++]) progress(update);
|
||||
};
|
||||
|
||||
/**
|
||||
* Emits a progress update to all progress observers registered with
|
||||
* this {@link Deferred}'s {@link Promise}
|
||||
*
|
||||
* @memberOf Resolver
|
||||
*
|
||||
* @param update anything
|
||||
*/
|
||||
function progress(update) {
|
||||
_progress(update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transition from pre-resolution state to post-resolution state, notifying
|
||||
* all listeners of the resolution or rejection
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param completed {Promise} the completed value of this deferred
|
||||
*/
|
||||
complete = function (completed) {
|
||||
var listener, i = 0;
|
||||
|
||||
// Replace _then with one that directly notifies with the result.
|
||||
_then = completed.then;
|
||||
|
||||
// Replace complete so that this Deferred can only be completed
|
||||
// once. Also Replace _progress, so that subsequent attempts to issue
|
||||
// progress throw.
|
||||
complete = _progress = function alreadyCompleted() {
|
||||
// TODO: Consider silently returning here so that parties who
|
||||
// have a reference to the resolver cannot tell that the promise
|
||||
// has been resolved using try/catch
|
||||
throw new Error("already completed");
|
||||
};
|
||||
|
||||
// Free progressHandlers array since we'll never issue progress events
|
||||
// for this promise again now that it's completed
|
||||
progressHandlers = undef;
|
||||
|
||||
// Notify listeners
|
||||
// Traverse all listeners registered directly with this Deferred
|
||||
|
||||
while (listener = listeners[i++]) {
|
||||
listener(completed);
|
||||
}
|
||||
|
||||
listeners = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* The full Deferred object, with both {@link Promise} and {@link Resolver}
|
||||
* parts
|
||||
* @class Deferred
|
||||
* @name Deferred
|
||||
*/
|
||||
deferred = {};
|
||||
|
||||
// Promise and Resolver parts
|
||||
// Freeze Promise and Resolver APIs
|
||||
|
||||
promise = new Promise();
|
||||
promise.then = deferred.then = then;
|
||||
|
||||
/**
|
||||
* The {@link Promise} for this {@link Deferred}
|
||||
* @memberOf Deferred
|
||||
* @name promise
|
||||
* @type {Promise}
|
||||
*/
|
||||
deferred.promise = freeze(promise);
|
||||
|
||||
/**
|
||||
* The {@link Resolver} for this {@link Deferred}
|
||||
* @memberOf Deferred
|
||||
* @name resolver
|
||||
* @class Resolver
|
||||
*/
|
||||
deferred.resolver = freeze({
|
||||
resolve: (deferred.resolve = resolve),
|
||||
reject: (deferred.reject = reject),
|
||||
progress: (deferred.progress = progress)
|
||||
});
|
||||
|
||||
return deferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if promiseOrValue is a promise or not. Uses the feature
|
||||
* test from http://wiki.commonjs.org/wiki/Promises/A to determine if
|
||||
* promiseOrValue is a promise.
|
||||
*
|
||||
* @param promiseOrValue anything
|
||||
*
|
||||
* @returns {Boolean} true if promiseOrValue is a {@link Promise}
|
||||
*/
|
||||
function isPromise(promiseOrValue) {
|
||||
return promiseOrValue && typeof promiseOrValue.then === 'function';
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an observer for a promise or immediate value.
|
||||
*
|
||||
* @function
|
||||
* @name when
|
||||
* @namespace
|
||||
*
|
||||
* @param promiseOrValue anything
|
||||
* @param {Function} [callback] callback to be called when promiseOrValue is
|
||||
* successfully resolved. If promiseOrValue is an immediate value, callback
|
||||
* will be invoked immediately.
|
||||
* @param {Function} [errback] callback to be called when promiseOrValue is
|
||||
* rejected.
|
||||
* @param {Function} [progressHandler] callback to be called when progress updates
|
||||
* are issued for promiseOrValue.
|
||||
*
|
||||
* @returns {Promise} a new {@link Promise} that will complete with the return
|
||||
* value of callback or errback or the completion value of promiseOrValue if
|
||||
* callback and/or errback is not supplied.
|
||||
*/
|
||||
function when(promiseOrValue, callback, errback, progressHandler) {
|
||||
// Get a promise for the input promiseOrValue
|
||||
// See promise()
|
||||
var trustedPromise = promise(promiseOrValue);
|
||||
|
||||
// Register promise handlers
|
||||
return trustedPromise.then(callback, errback, progressHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns promiseOrValue if promiseOrValue is a {@link Promise}, a new Promise if
|
||||
* promiseOrValue is a foreign promise, or a new, already-resolved {@link Promise}
|
||||
* whose resolution value is promiseOrValue if promiseOrValue is an immediate value.
|
||||
*
|
||||
* Note that this function is not safe to export since it will return its
|
||||
* input when promiseOrValue is a {@link Promise}
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param promiseOrValue anything
|
||||
*
|
||||
* @returns Guaranteed to return a trusted Promise. If promiseOrValue is a when.js {@link Promise}
|
||||
* returns promiseOrValue, otherwise, returns a new, already-resolved, when.js {@link Promise}
|
||||
* whose resolution value is:
|
||||
* * the resolution value of promiseOrValue if it's a foreign promise, or
|
||||
* * promiseOrValue if it's a value
|
||||
*/
|
||||
function promise(promiseOrValue) {
|
||||
var promise, deferred;
|
||||
|
||||
if (promiseOrValue instanceof Promise) {
|
||||
// It's a when.js promise, so we trust it
|
||||
promise = promiseOrValue;
|
||||
|
||||
} else {
|
||||
// It's not a when.js promise. Check to see if it's a foreign promise
|
||||
// or a value.
|
||||
|
||||
deferred = defer();
|
||||
if (isPromise(promiseOrValue)) {
|
||||
// It's a compliant promise, but we don't know where it came from,
|
||||
// so we don't trust its implementation entirely. Introduce a trusted
|
||||
// middleman when.js promise
|
||||
|
||||
// IMPORTANT: This is the only place when.js should ever call .then() on
|
||||
// an untrusted promise.
|
||||
promiseOrValue.then(deferred.resolve, deferred.reject, deferred.progress);
|
||||
promise = deferred.promise;
|
||||
|
||||
} else {
|
||||
// It's a value, not a promise. Create an already-resolved promise
|
||||
// for it.
|
||||
deferred.resolve(promiseOrValue);
|
||||
promise = deferred.promise;
|
||||
}
|
||||
}
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a promise that will resolve when howMany of the supplied promisesOrValues
|
||||
* have resolved. The resolution value of the returned promise will be an array of
|
||||
* length howMany containing the resolutions values of the triggering promisesOrValues.
|
||||
*
|
||||
* @memberOf when
|
||||
*
|
||||
* @param promisesOrValues {Array} array of anything, may contain a mix
|
||||
* of {@link Promise}s and values
|
||||
* @param howMany
|
||||
* @param [callback]
|
||||
* @param [errback]
|
||||
* @param [progressHandler]
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function some(promisesOrValues, howMany, callback, errback, progressHandler) {
|
||||
|
||||
checkCallbacks(2, arguments);
|
||||
|
||||
return when(promisesOrValues, function (promisesOrValues) {
|
||||
|
||||
var toResolve, results, ret, deferred, resolver, rejecter, handleProgress, len, i;
|
||||
|
||||
len = promisesOrValues.length >>> 0;
|
||||
|
||||
toResolve = Math.max(0, Math.min(howMany, len));
|
||||
results = [];
|
||||
deferred = defer();
|
||||
ret = when(deferred, callback, errback, progressHandler);
|
||||
|
||||
// Wrapper so that resolver can be replaced
|
||||
function resolve(val) {
|
||||
resolver(val);
|
||||
}
|
||||
|
||||
// Wrapper so that rejecter can be replaced
|
||||
function reject(err) {
|
||||
rejecter(err);
|
||||
}
|
||||
|
||||
// Wrapper so that progress can be replaced
|
||||
function progress(update) {
|
||||
handleProgress(update);
|
||||
}
|
||||
|
||||
function complete() {
|
||||
resolver = rejecter = handleProgress = noop;
|
||||
}
|
||||
|
||||
// No items in the input, resolve immediately
|
||||
if (!toResolve) {
|
||||
deferred.resolve(results);
|
||||
|
||||
} else {
|
||||
// Resolver for promises. Captures the value and resolves
|
||||
// the returned promise when toResolve reaches zero.
|
||||
// Overwrites resolver var with a noop once promise has
|
||||
// be resolved to cover case where n < promises.length
|
||||
resolver = function (val) {
|
||||
// This orders the values based on promise resolution order
|
||||
// Another strategy would be to use the original position of
|
||||
// the corresponding promise.
|
||||
results.push(val);
|
||||
|
||||
if (! --toResolve) {
|
||||
complete();
|
||||
deferred.resolve(results);
|
||||
}
|
||||
};
|
||||
|
||||
// Rejecter for promises. Rejects returned promise
|
||||
// immediately, and overwrites rejecter var with a noop
|
||||
// once promise to cover case where n < promises.length.
|
||||
// TODO: Consider rejecting only when N (or promises.length - N?)
|
||||
// promises have been rejected instead of only one?
|
||||
rejecter = function (err) {
|
||||
complete();
|
||||
deferred.reject(err);
|
||||
};
|
||||
|
||||
handleProgress = deferred.progress;
|
||||
|
||||
// TODO: Replace while with forEach
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (i in promisesOrValues) {
|
||||
when(promisesOrValues[i], resolve, reject, progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a promise that will resolve only once all the supplied promisesOrValues
|
||||
* have resolved. The resolution value of the returned promise will be an array
|
||||
* containing the resolution values of each of the promisesOrValues.
|
||||
*
|
||||
* @memberOf when
|
||||
*
|
||||
* @param promisesOrValues {Array|Promise} array of anything, may contain a mix
|
||||
* of {@link Promise}s and values
|
||||
* @param [callback] {Function}
|
||||
* @param [errback] {Function}
|
||||
* @param [progressHandler] {Function}
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function all(promisesOrValues, callback, errback, progressHandler) {
|
||||
|
||||
checkCallbacks(1, arguments);
|
||||
|
||||
return when(promisesOrValues, function (promisesOrValues) {
|
||||
return _reduce(promisesOrValues, reduceIntoArray, []);
|
||||
}).then(callback, errback, progressHandler);
|
||||
}
|
||||
|
||||
function reduceIntoArray(current, val, i) {
|
||||
current[i] = val;
|
||||
return current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a promise that will resolve when any one of the supplied promisesOrValues
|
||||
* has resolved. The resolution value of the returned promise will be the resolution
|
||||
* value of the triggering promiseOrValue.
|
||||
*
|
||||
* @memberOf when
|
||||
*
|
||||
* @param promisesOrValues {Array|Promise} array of anything, may contain a mix
|
||||
* of {@link Promise}s and values
|
||||
* @param [callback] {Function}
|
||||
* @param [errback] {Function}
|
||||
* @param [progressHandler] {Function}
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function any(promisesOrValues, callback, errback, progressHandler) {
|
||||
|
||||
function unwrapSingleResult(val) {
|
||||
return callback ? callback(val[0]) : val[0];
|
||||
}
|
||||
|
||||
return some(promisesOrValues, 1, unwrapSingleResult, errback, progressHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Traditional map function, similar to `Array.prototype.map()`, but allows
|
||||
* input to contain {@link Promise}s and/or values, and mapFunc may return
|
||||
* either a value or a {@link Promise}
|
||||
*
|
||||
* @memberOf when
|
||||
*
|
||||
* @param promise {Array|Promise} array of anything, may contain a mix
|
||||
* of {@link Promise}s and values
|
||||
* @param mapFunc {Function} mapping function mapFunc(value) which may return
|
||||
* either a {@link Promise} or value
|
||||
*
|
||||
* @returns {Promise} a {@link Promise} that will resolve to an array containing
|
||||
* the mapped output values.
|
||||
*/
|
||||
function map(promise, mapFunc) {
|
||||
return when(promise, function (array) {
|
||||
return _map(array, mapFunc);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Private map helper to map an array of promises
|
||||
* @private
|
||||
*
|
||||
* @param promisesOrValues {Array}
|
||||
* @param mapFunc {Function}
|
||||
* @return {Promise}
|
||||
*/
|
||||
function _map(promisesOrValues, mapFunc) {
|
||||
|
||||
var results, len, i;
|
||||
|
||||
// Since we know the resulting length, we can preallocate the results
|
||||
// array to avoid array expansions.
|
||||
len = promisesOrValues.length >>> 0;
|
||||
results = new Array(len);
|
||||
|
||||
// Since mapFunc may be async, get all invocations of it into flight
|
||||
// asap, and then use reduce() to collect all the results
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i in promisesOrValues)
|
||||
results[i] = when(promisesOrValues[i], mapFunc);
|
||||
}
|
||||
|
||||
// Could use all() here, but that would result in another array
|
||||
// being allocated, i.e. map() would end up allocating 2 arrays
|
||||
// of size len instead of just 1. Since all() uses reduce()
|
||||
// anyway, avoid the additional allocation by calling reduce
|
||||
// directly.
|
||||
return _reduce(results, reduceIntoArray, results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Traditional reduce function, similar to `Array.prototype.reduce()`, but
|
||||
* input may contain {@link Promise}s and/or values, and reduceFunc
|
||||
* may return either a value or a {@link Promise}, *and* initialValue may
|
||||
* be a {@link Promise} for the starting value.
|
||||
*
|
||||
* @memberOf when
|
||||
*
|
||||
* @param promise {Array|Promise} array of anything, may contain a mix
|
||||
* of {@link Promise}s and values. May also be a {@link Promise} for
|
||||
* an array.
|
||||
* @param reduceFunc {Function} reduce function reduce(currentValue, nextValue, index, total),
|
||||
* where total is the total number of items being reduced, and will be the same
|
||||
* in each call to reduceFunc.
|
||||
* @param initialValue starting value, or a {@link Promise} for the starting value
|
||||
*
|
||||
* @returns {Promise} that will resolve to the final reduced value
|
||||
*/
|
||||
function reduce(promise, reduceFunc, initialValue) {
|
||||
var args = slice.call(arguments, 1);
|
||||
return when(promise, function (array) {
|
||||
return _reduce.apply(undef, [array].concat(args));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Private reduce to reduce an array of promises
|
||||
* @private
|
||||
*
|
||||
* @param promisesOrValues {Array}
|
||||
* @param reduceFunc {Function}
|
||||
* @param initialValue {*}
|
||||
* @return {Promise}
|
||||
*/
|
||||
function _reduce(promisesOrValues, reduceFunc, initialValue) {
|
||||
|
||||
var total, args;
|
||||
|
||||
total = promisesOrValues.length;
|
||||
|
||||
// Skip promisesOrValues, since it will be used as 'this' in the call
|
||||
// to the actual reduce engine below.
|
||||
|
||||
// Wrap the supplied reduceFunc with one that handles promises and then
|
||||
// delegates to the supplied.
|
||||
|
||||
args = [
|
||||
function (current, val, i) {
|
||||
return when(current, function (c) {
|
||||
return when(val, function (value) {
|
||||
return reduceFunc(c, value, i, total);
|
||||
});
|
||||
});
|
||||
}
|
||||
];
|
||||
|
||||
if (arguments.length > 2) args.push(initialValue);
|
||||
|
||||
return reduceArray.apply(promisesOrValues, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that resolution of promiseOrValue will complete resolver with the completion
|
||||
* value of promiseOrValue, or instead with resolveValue if it is provided.
|
||||
*
|
||||
* @memberOf when
|
||||
*
|
||||
* @param promiseOrValue
|
||||
* @param resolver {Resolver}
|
||||
* @param [resolveValue] anything
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function chain(promiseOrValue, resolver, resolveValue) {
|
||||
var useResolveValue = arguments.length > 2;
|
||||
|
||||
return when(promiseOrValue,
|
||||
function (val) {
|
||||
if (useResolveValue) val = resolveValue;
|
||||
resolver.resolve(val);
|
||||
return val;
|
||||
},
|
||||
function (e) {
|
||||
resolver.reject(e);
|
||||
return rejected(e);
|
||||
},
|
||||
resolver.progress
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Utility functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Helper that checks arrayOfCallbacks to ensure that each element is either
|
||||
* a function, or null or undefined.
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param arrayOfCallbacks {Array} array to check
|
||||
* @throws {Error} if any element of arrayOfCallbacks is something other than
|
||||
* a Functions, null, or undefined.
|
||||
*/
|
||||
function checkCallbacks(start, arrayOfCallbacks) {
|
||||
var arg, i = arrayOfCallbacks.length;
|
||||
while (i > start) {
|
||||
arg = arrayOfCallbacks[--i];
|
||||
if (arg != null && typeof arg != 'function') throw new Error('callback is not a function');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* No-Op function used in method replacement
|
||||
* @private
|
||||
*/
|
||||
function noop() { }
|
||||
|
||||
slice = [].slice;
|
||||
|
||||
// ES5 reduce implementation if native not available
|
||||
// See: http://es5.github.com/#x15.4.4.21 as there are many
|
||||
// specifics and edge cases.
|
||||
reduceArray = [].reduce ||
|
||||
function (reduceFunc /*, initialValue */) {
|
||||
// ES5 dictates that reduce.length === 1
|
||||
|
||||
// This implementation deviates from ES5 spec in the following ways:
|
||||
// 1. It does not check if reduceFunc is a Callable
|
||||
|
||||
var arr, args, reduced, len, i;
|
||||
|
||||
i = 0;
|
||||
arr = Object(this);
|
||||
len = arr.length >>> 0;
|
||||
args = arguments;
|
||||
|
||||
// If no initialValue, use first item of array (we know length !== 0 here)
|
||||
// and adjust i to start at second item
|
||||
if (args.length <= 1) {
|
||||
// Skip to the first real element in the array
|
||||
for (; ; ) {
|
||||
if (i in arr) {
|
||||
reduced = arr[i++];
|
||||
break;
|
||||
}
|
||||
|
||||
// If we reached the end of the array without finding any real
|
||||
// elements, it's a TypeError
|
||||
if (++i >= len) {
|
||||
throw new TypeError();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If initialValue provided, use it
|
||||
reduced = args[1];
|
||||
}
|
||||
|
||||
// Do the actual reduce
|
||||
for (; i < len; ++i) {
|
||||
// Skip holes
|
||||
if (i in arr)
|
||||
reduced = reduceFunc(reduced, arr[i], i, arr);
|
||||
}
|
||||
|
||||
return reduced;
|
||||
};
|
||||
|
||||
return when;
|
||||
});
|
||||
})(typeof define == 'function'
|
||||
? define
|
||||
: function (factory) {
|
||||
typeof module != 'undefined'
|
||||
? (module.exports = factory())
|
||||
: (jQuery.mapster_when = factory());
|
||||
}
|
||||
// Boilerplate for AMD, Node, and browser global
|
||||
);
|
||||
/*lint-ignore-end*/
|
||||
326
rus/admin/_V4/_lib/ImageMapster-master/src/scale.js
Normal file
326
rus/admin/_V4/_lib/ImageMapster-master/src/scale.js
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
/* scale.js: resize and zoom functionality
|
||||
requires areacorners.js, when.js
|
||||
*/
|
||||
|
||||
|
||||
(function ($) {
|
||||
var m = $.mapster, u = m.utils, p = m.MapArea.prototype;
|
||||
|
||||
m.utils.getScaleInfo = function (eff, actual) {
|
||||
var pct;
|
||||
if (!actual) {
|
||||
pct = 1;
|
||||
actual=eff;
|
||||
} else {
|
||||
pct = eff.width / actual.width || eff.height / actual.height;
|
||||
// make sure a float error doesn't muck us up
|
||||
if (pct > 0.98 && pct < 1.02) { pct = 1; }
|
||||
}
|
||||
return {
|
||||
scale: (pct !== 1),
|
||||
scalePct: pct,
|
||||
realWidth: actual.width,
|
||||
realHeight: actual.height,
|
||||
width: eff.width,
|
||||
height: eff.height,
|
||||
ratio: eff.width / eff.height
|
||||
};
|
||||
};
|
||||
// Scale a set of AREAs, return old data as an array of objects
|
||||
m.utils.scaleMap = function (image, imageRaw, scale) {
|
||||
|
||||
// stunningly, jQuery width can return zero even as width does not, seems to happen only
|
||||
// with adBlock or maybe other plugins. These must interfere with onload events somehow.
|
||||
|
||||
|
||||
var vis=u.size(image),
|
||||
raw=u.size(imageRaw,true);
|
||||
|
||||
if (!raw.complete()) {
|
||||
throw("Another script, such as an extension, appears to be interfering with image loading. Please let us know about this.");
|
||||
}
|
||||
if (!vis.complete()) {
|
||||
vis=raw;
|
||||
}
|
||||
return this.getScaleInfo(vis, scale ? raw : null);
|
||||
};
|
||||
|
||||
/**
|
||||
* Resize the image map. Only one of newWidth and newHeight should be passed to preserve scale
|
||||
*
|
||||
* @param {int} width The new width OR an object containing named parameters matching this function sig
|
||||
* @param {int} height The new height
|
||||
* @param {int} effectDuration Time in ms for the resize animation, or zero for no animation
|
||||
* @param {function} callback A function to invoke when the operation finishes
|
||||
* @return {promise} NOT YET IMPLEMENTED
|
||||
*/
|
||||
|
||||
m.MapData.prototype.resize = function (width, height, duration, callback) {
|
||||
var p,promises,newsize,els, highlightId, ratio,
|
||||
me = this;
|
||||
|
||||
// allow omitting duration
|
||||
callback = callback || duration;
|
||||
|
||||
function sizeCanvas(canvas, w, h) {
|
||||
if (m.hasCanvas()) {
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
} else {
|
||||
$(canvas).width(w);
|
||||
$(canvas).height(h);
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize resize action, do callback, pass control to command queue
|
||||
|
||||
function cleanupAndNotify() {
|
||||
|
||||
me.currentAction = '';
|
||||
|
||||
if ($.isFunction(callback)) {
|
||||
callback();
|
||||
}
|
||||
|
||||
me.processCommandQueue();
|
||||
}
|
||||
|
||||
// handle cleanup after the inner elements are resized
|
||||
|
||||
function finishResize() {
|
||||
sizeCanvas(me.overlay_canvas, width, height);
|
||||
|
||||
// restore highlight state if it was highlighted before
|
||||
if (highlightId >= 0) {
|
||||
var areaData = me.data[highlightId];
|
||||
areaData.tempOptions = { fade: false };
|
||||
me.getDataForKey(areaData.key).highlight();
|
||||
areaData.tempOptions = null;
|
||||
}
|
||||
sizeCanvas(me.base_canvas, width, height);
|
||||
me.redrawSelections();
|
||||
cleanupAndNotify();
|
||||
}
|
||||
|
||||
function resizeMapData() {
|
||||
$(me.image).css(newsize);
|
||||
// start calculation at the same time as effect
|
||||
me.scaleInfo = u.getScaleInfo({
|
||||
width: width,
|
||||
height: height
|
||||
},
|
||||
{
|
||||
width: me.scaleInfo.realWidth,
|
||||
height: me.scaleInfo.realHeight
|
||||
});
|
||||
$.each(me.data, function (i, e) {
|
||||
$.each(e.areas(), function (i, e) {
|
||||
e.resize();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (me.scaleInfo.width === width && me.scaleInfo.height === height) {
|
||||
return;
|
||||
}
|
||||
|
||||
highlightId = me.highlightId;
|
||||
|
||||
|
||||
if (!width) {
|
||||
ratio = height / me.scaleInfo.realHeight;
|
||||
width = Math.round(me.scaleInfo.realWidth * ratio);
|
||||
}
|
||||
if (!height) {
|
||||
ratio = width / me.scaleInfo.realWidth;
|
||||
height = Math.round(me.scaleInfo.realHeight * ratio);
|
||||
}
|
||||
|
||||
newsize = { 'width': String(width) + 'px', 'height': String(height) + 'px' };
|
||||
if (!m.hasCanvas()) {
|
||||
$(me.base_canvas).children().remove();
|
||||
}
|
||||
|
||||
// resize all the elements that are part of the map except the image itself (which is not visible)
|
||||
// but including the div wrapper
|
||||
els = $(me.wrapper).find('.mapster_el').add(me.wrapper);
|
||||
|
||||
if (duration) {
|
||||
promises = [];
|
||||
me.currentAction = 'resizing';
|
||||
els.each(function (i, e) {
|
||||
p = u.defer();
|
||||
promises.push(p);
|
||||
|
||||
$(e).animate(newsize, {
|
||||
duration: duration,
|
||||
complete: p.resolve,
|
||||
easing: "linear"
|
||||
});
|
||||
});
|
||||
|
||||
p = u.defer();
|
||||
promises.push(p);
|
||||
|
||||
// though resizeMapData is not async, it needs to be finished just the same as the animations,
|
||||
// so add it to the "to do" list.
|
||||
|
||||
u.when.all(promises).then(finishResize);
|
||||
resizeMapData();
|
||||
p.resolve();
|
||||
} else {
|
||||
els.css(newsize);
|
||||
resizeMapData();
|
||||
finishResize();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
m.MapArea = u.subclass(m.MapArea, function () {
|
||||
//change the area tag data if needed
|
||||
this.base.init();
|
||||
if (this.owner.scaleInfo.scale) {
|
||||
this.resize();
|
||||
}
|
||||
});
|
||||
|
||||
p.coords = function (percent, coordOffset) {
|
||||
var j, newCoords = [],
|
||||
pct = percent || this.owner.scaleInfo.scalePct,
|
||||
offset = coordOffset || 0;
|
||||
|
||||
if (pct === 1 && coordOffset === 0) {
|
||||
return this.originalCoords;
|
||||
}
|
||||
|
||||
for (j = 0; j < this.length; j++) {
|
||||
//amount = j % 2 === 0 ? xPct : yPct;
|
||||
newCoords.push(Math.round(this.originalCoords[j] * pct) + offset);
|
||||
}
|
||||
return newCoords;
|
||||
};
|
||||
p.resize = function () {
|
||||
this.area.coords = this.coords().join(',');
|
||||
};
|
||||
|
||||
p.reset = function () {
|
||||
this.area.coords = this.coords(1).join(',');
|
||||
};
|
||||
|
||||
m.impl.resize = function (width, height, duration, callback) {
|
||||
if (!width && !height) {
|
||||
return false;
|
||||
}
|
||||
var x= (new m.Method(this,
|
||||
function () {
|
||||
this.resize(width, height, duration, callback);
|
||||
},
|
||||
null,
|
||||
{
|
||||
name: 'resize',
|
||||
args: arguments
|
||||
}
|
||||
)).go();
|
||||
return x;
|
||||
};
|
||||
|
||||
/*
|
||||
m.impl.zoom = function (key, opts) {
|
||||
var options = opts || {};
|
||||
|
||||
function zoom(areaData) {
|
||||
// this will be MapData object returned by Method
|
||||
|
||||
var scroll, corners, height, width, ratio,
|
||||
diffX, diffY, ratioX, ratioY, offsetX, offsetY, newWidth, newHeight, scrollLeft, scrollTop,
|
||||
padding = options.padding || 0,
|
||||
scrollBarSize = areaData ? 20 : 0,
|
||||
me = this,
|
||||
zoomOut = false;
|
||||
|
||||
if (areaData) {
|
||||
// save original state on first zoom operation
|
||||
if (!me.zoomed) {
|
||||
me.zoomed = true;
|
||||
me.preZoomWidth = me.scaleInfo.width;
|
||||
me.preZoomHeight = me.scaleInfo.height;
|
||||
me.zoomedArea = areaData;
|
||||
if (options.scroll) {
|
||||
me.wrapper.css({ overflow: 'auto' });
|
||||
}
|
||||
}
|
||||
corners = $.mapster.utils.areaCorners(areaData.coords(1, 0));
|
||||
width = me.wrapper.innerWidth() - scrollBarSize - padding * 2;
|
||||
height = me.wrapper.innerHeight() - scrollBarSize - padding * 2;
|
||||
diffX = corners.maxX - corners.minX;
|
||||
diffY = corners.maxY - corners.minY;
|
||||
ratioX = width / diffX;
|
||||
ratioY = height / diffY;
|
||||
ratio = Math.min(ratioX, ratioY);
|
||||
offsetX = (width - diffX * ratio) / 2;
|
||||
offsetY = (height - diffY * ratio) / 2;
|
||||
|
||||
newWidth = me.scaleInfo.realWidth * ratio;
|
||||
newHeight = me.scaleInfo.realHeight * ratio;
|
||||
scrollLeft = (corners.minX) * ratio - padding - offsetX;
|
||||
scrollTop = (corners.minY) * ratio - padding - offsetY;
|
||||
} else {
|
||||
if (!me.zoomed) {
|
||||
return;
|
||||
}
|
||||
zoomOut = true;
|
||||
newWidth = me.preZoomWidth;
|
||||
newHeight = me.preZoomHeight;
|
||||
scrollLeft = null;
|
||||
scrollTop = null;
|
||||
}
|
||||
|
||||
this.resize({
|
||||
width: newWidth,
|
||||
height: newHeight,
|
||||
duration: options.duration,
|
||||
scroll: scroll,
|
||||
scrollLeft: scrollLeft,
|
||||
scrollTop: scrollTop,
|
||||
// closure so we can be sure values are correct
|
||||
callback: (function () {
|
||||
var isZoomOut = zoomOut,
|
||||
scroll = options.scroll,
|
||||
areaD = areaData;
|
||||
return function () {
|
||||
if (isZoomOut) {
|
||||
me.preZoomWidth = null;
|
||||
me.preZoomHeight = null;
|
||||
me.zoomed = false;
|
||||
me.zoomedArea = false;
|
||||
if (scroll) {
|
||||
me.wrapper.css({ overflow: 'inherit' });
|
||||
}
|
||||
} else {
|
||||
// just to be sure it wasn't canceled & restarted
|
||||
me.zoomedArea = areaD;
|
||||
}
|
||||
};
|
||||
} ())
|
||||
});
|
||||
}
|
||||
return (new m.Method(this,
|
||||
function (opts) {
|
||||
zoom.call(this);
|
||||
},
|
||||
function () {
|
||||
zoom.call(this.owner, this);
|
||||
},
|
||||
{
|
||||
name: 'zoom',
|
||||
args: arguments,
|
||||
first: true,
|
||||
key: key
|
||||
}
|
||||
)).go();
|
||||
|
||||
|
||||
};
|
||||
*/
|
||||
} (jQuery));
|
||||
402
rus/admin/_V4/_lib/ImageMapster-master/src/tooltip.js
Normal file
402
rus/admin/_V4/_lib/ImageMapster-master/src/tooltip.js
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
/* tooltip.js - tooltip functionality
|
||||
requires areacorners.js
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
|
||||
var m = $.mapster, u = m.utils;
|
||||
|
||||
$.extend(m.defaults, {
|
||||
toolTipContainer: '<div style="border: 2px solid black; background: #EEEEEE; width:160px; padding:4px; margin: 4px; -moz-box-shadow: 3px 3px 5px #535353; ' +
|
||||
'-webkit-box-shadow: 3px 3px 5px #535353; box-shadow: 3px 3px 5px #535353; -moz-border-radius: 6px 6px 6px 6px; -webkit-border-radius: 6px; ' +
|
||||
'border-radius: 6px 6px 6px 6px; opacity: 0.9;"></div>',
|
||||
showToolTip: false,
|
||||
toolTipFade: true,
|
||||
toolTipClose: ['area-mouseout','image-mouseout'],
|
||||
onShowToolTip: null,
|
||||
onHideToolTip: null
|
||||
});
|
||||
|
||||
$.extend(m.area_defaults, {
|
||||
toolTip: null,
|
||||
toolTipClose: null
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Show a tooltip positioned near this area.
|
||||
*
|
||||
* @param {string|jquery} html A string of html or a jQuery object containing the tooltip content.
|
||||
* @param {string|jquery} [template] The html template in which to wrap the content
|
||||
* @param {string|object} [css] CSS to apply to the outermost element of the tooltip
|
||||
* @return {jquery} The tooltip that was created
|
||||
*/
|
||||
|
||||
function createToolTip(html, template, css) {
|
||||
var tooltip;
|
||||
|
||||
// wrap the template in a jQuery object, or clone the template if it's already one.
|
||||
// This assumes that anything other than a string is a jQuery object; if it's not jQuery will
|
||||
// probably throw an error.
|
||||
|
||||
if (template) {
|
||||
tooltip = typeof template === 'string' ?
|
||||
$(template) :
|
||||
$(template).clone();
|
||||
|
||||
tooltip.append(html);
|
||||
} else {
|
||||
tooltip=$(html);
|
||||
}
|
||||
|
||||
// always set display to block, or the positioning css won't work if the end user happened to
|
||||
// use a non-block type element.
|
||||
|
||||
tooltip.css($.extend((css || {}),{
|
||||
display:"block",
|
||||
position:"absolute"
|
||||
})).hide();
|
||||
|
||||
$('body').append(tooltip);
|
||||
|
||||
// we must actually add the tooltip to the DOM and "show" it in order to figure out how much space it
|
||||
// consumes, and then reposition it with that knowledge.
|
||||
// We also cache the actual opacity setting to restore finally.
|
||||
|
||||
tooltip.attr("data-opacity",tooltip.css("opacity"))
|
||||
.css("opacity",0);
|
||||
|
||||
// doesn't really show it because opacity=0
|
||||
|
||||
return tooltip.show();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show a tooltip positioned near this area.
|
||||
*
|
||||
* @param {jquery} tooltip The tooltip
|
||||
* @param {object} [options] options for displaying the tooltip.
|
||||
* @config {int} [left] The 0-based absolute x position for the tooltip
|
||||
* @config {int} [top] The 0-based absolute y position for the tooltip
|
||||
* @config {string|object} [css] CSS to apply to the outermost element of the tooltip
|
||||
* @config {bool} [fadeDuration] When non-zero, the duration in milliseconds of a fade-in effect for the tooltip.
|
||||
*/
|
||||
|
||||
function showToolTipImpl(tooltip,options)
|
||||
{
|
||||
var tooltipCss = {
|
||||
"left": options.left + "px",
|
||||
"top": options.top + "px"
|
||||
},
|
||||
actalOpacity=tooltip.attr("data-opacity") || 0,
|
||||
zindex = tooltip.css("z-index");
|
||||
|
||||
if (parseInt(zindex,10)===0
|
||||
|| zindex === "auto") {
|
||||
tooltipCss["z-index"] = 9999;
|
||||
}
|
||||
|
||||
tooltip.css(tooltipCss)
|
||||
.addClass('mapster_tooltip');
|
||||
|
||||
|
||||
if (options.fadeDuration && options.fadeDuration>0) {
|
||||
u.fader(tooltip[0], 0, actalOpacity, options.fadeDuration);
|
||||
} else {
|
||||
u.setOpacity(tooltip[0], actalOpacity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide and remove active tooltips
|
||||
*
|
||||
* @param {MapData} this The mapdata object to which the tooltips belong
|
||||
*/
|
||||
|
||||
m.MapData.prototype.clearToolTip = function() {
|
||||
if (this.activeToolTip) {
|
||||
this.activeToolTip.stop().remove();
|
||||
this.activeToolTip = null;
|
||||
this.activeToolTipID = null;
|
||||
u.ifFunction(this.options.onHideToolTip, this);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Configure the binding between a named tooltip closing option, and a mouse event.
|
||||
*
|
||||
* If a callback is passed, it will be called when the activating event occurs, and the tooltip will
|
||||
* only closed if it returns true.
|
||||
*
|
||||
* @param {MapData} [this] The MapData object to which this tooltip belongs.
|
||||
* @param {String} option The name of the tooltip closing option
|
||||
* @param {String} event UI event to bind to this option
|
||||
* @param {Element} target The DOM element that is the target of the event
|
||||
* @param {Function} [beforeClose] Callback when the tooltip is closed
|
||||
* @param {Function} [onClose] Callback when the tooltip is closed
|
||||
*/
|
||||
function bindToolTipClose(options, bindOption, event, target, beforeClose, onClose) {
|
||||
var event_name = event + '.mapster-tooltip';
|
||||
|
||||
if ($.inArray(bindOption, options) >= 0) {
|
||||
target.unbind(event_name)
|
||||
.bind(event_name, function (e) {
|
||||
if (!beforeClose || beforeClose.call(this,e)) {
|
||||
target.unbind('.mapster-tooltip');
|
||||
if (onClose) {
|
||||
onClose.call(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
object: target,
|
||||
event: event_name
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a tooltip.
|
||||
*
|
||||
* @param {string|jquery} [tooltip] A string of html or a jQuery object containing the tooltip content.
|
||||
*
|
||||
* @param {string|jquery} [target] The target of the tooltip, to be used to determine positioning. If null,
|
||||
* absolute position values must be passed with left and top.
|
||||
*
|
||||
* @param {string|jquery} [image] If target is an [area] the image that owns it
|
||||
*
|
||||
* @param {string|jquery} [container] An element within which the tooltip must be bounded
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param {object|string|jQuery} [options] options to apply when creating this tooltip - OR -
|
||||
* The markup, or a jquery object, containing the data for the tooltip
|
||||
*
|
||||
* @config {string} [closeEvents] A string with one or more comma-separated values that determine when the tooltip
|
||||
* closes: 'area-click','tooltip-click','image-mouseout' are valid values
|
||||
* then no template will be used.
|
||||
* @config {int} [offsetx] the horizontal amount to offset the tooltip
|
||||
* @config {int} [offsety] the vertical amount to offset the tooltip
|
||||
* @config {string|object} [css] CSS to apply to the outermost element of the tooltip
|
||||
*/
|
||||
|
||||
function showToolTip(tooltip,target,image,container,options) {
|
||||
var corners,
|
||||
ttopts = {};
|
||||
|
||||
options = options || {};
|
||||
|
||||
|
||||
if (target) {
|
||||
|
||||
corners = u.areaCorners(target,image,container,
|
||||
tooltip.outerWidth(true),
|
||||
tooltip.outerHeight(true));
|
||||
|
||||
// Try to upper-left align it first, if that doesn't work, change the parameters
|
||||
|
||||
ttopts.left = corners[0];
|
||||
ttopts.top = corners[1];
|
||||
|
||||
} else {
|
||||
|
||||
ttopts.left = options.left;
|
||||
ttopts.top = options.top;
|
||||
}
|
||||
|
||||
ttopts.left += (options.offsetx || 0);
|
||||
ttopts.top +=(options.offsety || 0);
|
||||
|
||||
ttopts.css= options.css;
|
||||
ttopts.fadeDuration = options.fadeDuration;
|
||||
|
||||
showToolTipImpl(tooltip,ttopts);
|
||||
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a tooltip positioned near this area.
|
||||
*
|
||||
* @param {string|jquery} [content] A string of html or a jQuery object containing the tooltip content.
|
||||
|
||||
* @param {object|string|jQuery} [options] options to apply when creating this tooltip - OR -
|
||||
* The markup, or a jquery object, containing the data for the tooltip
|
||||
* @config {string|jquery} [container] An element within which the tooltip must be bounded
|
||||
* @config {bool} [template] a template to use instead of the default. If this property exists and is null,
|
||||
* then no template will be used.
|
||||
* @config {string} [closeEvents] A string with one or more comma-separated values that determine when the tooltip
|
||||
* closes: 'area-click','tooltip-click','image-mouseout' are valid values
|
||||
* then no template will be used.
|
||||
* @config {int} [offsetx] the horizontal amount to offset the tooltip
|
||||
* @config {int} [offsety] the vertical amount to offset the tooltip
|
||||
* @config {string|object} [css] CSS to apply to the outermost element of the tooltip
|
||||
*/
|
||||
m.AreaData.prototype.showToolTip= function(content,options) {
|
||||
var tooltip, closeOpts, target, tipClosed, template,
|
||||
ttopts = {},
|
||||
ad=this,
|
||||
md=ad.owner,
|
||||
areaOpts = ad.effectiveOptions();
|
||||
|
||||
// copy the options object so we can update it
|
||||
options = options ? $.extend({},options) : {};
|
||||
|
||||
content = content || areaOpts.toolTip;
|
||||
closeOpts = options.closeEvents || areaOpts.toolTipClose || md.options.toolTipClose || 'tooltip-click';
|
||||
|
||||
template = typeof options.template !== 'undefined' ?
|
||||
options.template :
|
||||
md.options.toolTipContainer;
|
||||
|
||||
options.closeEvents = typeof closeOpts === 'string' ?
|
||||
closeOpts = u.split(closeOpts) :
|
||||
closeOpts;
|
||||
|
||||
options.fadeDuration = options.fadeDuration ||
|
||||
(md.options.toolTipFade ?
|
||||
(md.options.fadeDuration || areaOpts.fadeDuration) : 0);
|
||||
|
||||
target = ad.area ?
|
||||
ad.area :
|
||||
$.map(ad.areas(),
|
||||
function(e) {
|
||||
return e.area;
|
||||
});
|
||||
|
||||
if (md.activeToolTipID===ad.areaId) {
|
||||
return;
|
||||
}
|
||||
|
||||
md.clearToolTip();
|
||||
|
||||
md.activeToolTip = tooltip = createToolTip(content,
|
||||
template,
|
||||
options.css);
|
||||
|
||||
md.activeToolTipID = ad.areaId;
|
||||
|
||||
tipClosed = function() {
|
||||
md.clearToolTip();
|
||||
};
|
||||
|
||||
bindToolTipClose(closeOpts,'area-click', 'click', $(md.map), null, tipClosed);
|
||||
bindToolTipClose(closeOpts,'tooltip-click', 'click', tooltip,null, tipClosed);
|
||||
bindToolTipClose(closeOpts,'image-mouseout', 'mouseout', $(md.image), function(e) {
|
||||
return (e.relatedTarget && e.relatedTarget.nodeName!=='AREA' && e.relatedTarget!==ad.area);
|
||||
}, tipClosed);
|
||||
|
||||
|
||||
showToolTip(tooltip,
|
||||
target,
|
||||
md.image,
|
||||
options.container,
|
||||
template,
|
||||
options);
|
||||
|
||||
u.ifFunction(md.options.onShowToolTip, ad.area,
|
||||
{
|
||||
toolTip: tooltip,
|
||||
options: ttopts,
|
||||
areaOptions: areaOpts,
|
||||
key: ad.key,
|
||||
selected: ad.isSelected()
|
||||
});
|
||||
|
||||
return tooltip;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parse an object that could be a string, a jquery object, or an object with a "contents" property
|
||||
* containing html or a jQuery object.
|
||||
*
|
||||
* @param {object|string|jQuery} options The parameter to parse
|
||||
* @return {string|jquery} A string or jquery object
|
||||
*/
|
||||
function getHtmlFromOptions(options) {
|
||||
|
||||
// see if any html was passed as either the options object itself, or the content property
|
||||
|
||||
return (options ?
|
||||
((typeof options === 'string' || options.jquery) ?
|
||||
options :
|
||||
options.content) :
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate or remove a tooltip for an area. When this method is called on an area, the
|
||||
* key parameter doesn't apply and "options" is the first parameter.
|
||||
*
|
||||
* When called with no parameters, or "key" is a falsy value, any active tooltip is cleared.
|
||||
*
|
||||
* When only a key is provided, the default tooltip for the area is used.
|
||||
*
|
||||
* When html is provided, this is used instead of the default tooltip.
|
||||
*
|
||||
* When "noTemplate" is true, the default tooltip template will not be used either, meaning only
|
||||
* the actual html passed will be used.
|
||||
*
|
||||
* @param {string|AreaElement} key The area for which to activate a tooltip, or a DOM element.
|
||||
*
|
||||
* @param {object|string|jquery} [options] options to apply when creating this tooltip - OR -
|
||||
* The markup, or a jquery object, containing the data for the tooltip
|
||||
* @config {string|jQuery} [content] the inner content of the tooltip; the tooltip text or HTML
|
||||
* @config {Element|jQuery} [container] the inner content of the tooltip; the tooltip text or HTML
|
||||
* @config {bool} [template] a template to use instead of the default. If this property exists and is null,
|
||||
* then no template will be used.
|
||||
* @config {int} [offsetx] the horizontal amount to offset the tooltip.
|
||||
* @config {int} [offsety] the vertical amount to offset the tooltip.
|
||||
* @config {string|object} [css] CSS to apply to the outermost element of the tooltip
|
||||
* @config {string|object} [css] CSS to apply to the outermost element of the tooltip
|
||||
* @config {bool} [fadeDuration] When non-zero, the duration in milliseconds of a fade-in effect for the tooltip.
|
||||
* @return {jQuery} The jQuery object
|
||||
*/
|
||||
|
||||
m.impl.tooltip = function (key,options) {
|
||||
return (new m.Method(this,
|
||||
function mapData() {
|
||||
var tooltip, target, md=this;
|
||||
if (!key) {
|
||||
md.clearToolTip();
|
||||
} else {
|
||||
target=$(key);
|
||||
if (md.activeToolTipID ===target[0]) {
|
||||
return;
|
||||
}
|
||||
md.clearToolTip();
|
||||
|
||||
md.activeToolTip = tooltip = createToolTip(getHtmlFromOptions(options),
|
||||
options.template || md.options.toolTipContainer,
|
||||
options.css);
|
||||
md.activeToolTipID = target[0];
|
||||
|
||||
bindToolTipClose(['tooltip-click'],'tooltip-click', 'click', tooltip, null, function() {
|
||||
md.clearToolTip();
|
||||
});
|
||||
|
||||
md.activeToolTip = tooltip = showToolTip(tooltip,
|
||||
target,
|
||||
md.image,
|
||||
options.container,
|
||||
options);
|
||||
}
|
||||
},
|
||||
function areaData() {
|
||||
if ($.isPlainObject(key) && !options) {
|
||||
options = key;
|
||||
}
|
||||
|
||||
this.showToolTip(getHtmlFromOptions(options),options);
|
||||
},
|
||||
{
|
||||
name: 'tooltip',
|
||||
args: arguments,
|
||||
key: key
|
||||
}
|
||||
)).go();
|
||||
};
|
||||
} (jQuery));
|
||||
103
rus/admin/_V4/_lib/ImageMapster-master/src/zepto.js
Normal file
103
rus/admin/_V4/_lib/ImageMapster-master/src/zepto.js
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/* zepto.js
|
||||
Monkey patch for Zepto to add some methods ImageMapster needs
|
||||
*/
|
||||
|
||||
/*global Zepto: true, jQuery: true */
|
||||
|
||||
if (window.Zepto) {
|
||||
jQuery = Zepto;
|
||||
|
||||
(function ($) {
|
||||
var hasOwn = Object.prototype.hasOwnProperty;
|
||||
|
||||
$.css=function( elem, name ) {
|
||||
|
||||
return getComputedStyle(elem,name);
|
||||
};
|
||||
|
||||
$.trim = function (str) {
|
||||
return str.replace(/^\s+/, '').replace(/\s+$/, '');
|
||||
};
|
||||
$.inArray = function (target, arr) {
|
||||
return arr.indexOf(target);
|
||||
};
|
||||
/*lint-ignore-start*/
|
||||
$.isEmptyObject=function(obj) {
|
||||
for ( var name in obj ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
$.isWindow = function(obj) {
|
||||
return obj && typeof obj === "object" && "setInterval" in obj;
|
||||
};
|
||||
|
||||
$.isPlainObject= function( obj ) {
|
||||
// Must be an Object.
|
||||
// Because of IE, we also have to check the presence of the constructor property.
|
||||
// Make sure that DOM nodes and window objects don't pass through, as well
|
||||
if ( !obj || typeof obj !== "object" || obj.nodeType || $.isWindow( obj ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// Not own constructor property must be Object
|
||||
if ( obj.constructor &&
|
||||
!hasOwn.call(obj, "constructor") &&
|
||||
!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
|
||||
return false;
|
||||
}
|
||||
} catch ( e ) {
|
||||
// IE8,9 Will throw exceptions on certain host objects #9897
|
||||
return false;
|
||||
}
|
||||
|
||||
// Own properties are enumerated firstly, so to speed up,
|
||||
// if last one is own, then all properties are own.
|
||||
|
||||
var key;
|
||||
for ( key in obj ) {}
|
||||
|
||||
return typeof key === 'undefined' || hasOwn.call( obj, key );
|
||||
}
|
||||
/*lint-ignore-end*/
|
||||
$.fn.clone = function () {
|
||||
var ret = $();
|
||||
this.each(function () {
|
||||
ret = ret.add(this.cloneNode(true));
|
||||
});
|
||||
return ret;
|
||||
};
|
||||
$.fn.stop=function() {
|
||||
return this;
|
||||
};
|
||||
$.fn.elOrEmpty = function () {
|
||||
return this.length ? this[0] : {};
|
||||
};
|
||||
$.each(["Height", "Width"], function( i, name ) {
|
||||
//var type = name.toLowerCase();
|
||||
// outerHeight and outerWidth
|
||||
//$.fn[ "outer" + name ] = function( margin ) {
|
||||
// var elem = this[0],
|
||||
// cl=margin?"margin":"border";
|
||||
// return elem ?
|
||||
// elem.style ?
|
||||
// (parseFloat( $.css( elem, cl+'-top-'+type)+ ) :
|
||||
// this[ type ]() :
|
||||
// null;
|
||||
// };
|
||||
$.fn["outer"+name]=function() {
|
||||
return this[name.toLowerCase()]();
|
||||
};
|
||||
});
|
||||
$.fn.position = $.fn.position || function () {
|
||||
var el = this.elOrEmpty();
|
||||
return {
|
||||
left: this.left,
|
||||
top: this.top
|
||||
};
|
||||
};
|
||||
$.browser = {};
|
||||
$.browser.msie = false;
|
||||
} (jQuery));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue