1(function(root, factory) { 2 if (typeof define === 'function' && define.amd) { 3 define(['jquery'], factory); 4 } else { 5 factory(root.jQuery); 6 } 7})(this, function($) { 8 var has_VML, has_canvas, create_canvas_for, add_shape_to, clear_canvas, shape_from_area, 9 canvas_style, hex_to_decimal, css3color, is_image_loaded, options_from_area; 10 11 has_canvas = !!document.createElement('canvas').getContext; 12 13 // VML: more complex 14 has_VML = (function() { 15 var a = document.createElement('div'); 16 a.innerHTML = '<v:shape id="vml_flag1" adj="1" />'; 17 var b = a.firstChild; 18 b.style.behavior = "url(#default#VML)"; 19 return b ? typeof b.adj == "object": true; 20 })(); 21 22 if(!(has_canvas || has_VML)) { 23 $.fn.maphilight = function() { return this; }; 24 return; 25 } 26 27 if (has_canvas) { 28 29 hex_to_decimal = function(hex) { 30 return Math.max(0, Math.min(parseInt(hex, 16), 255)); 31 }; 32 css3color = function(color, opacity) { 33 //return 'rgba(' + hex_to_decimal(color.substr(0, 2)) + ',' + hex_to_decimal(color.substr(2, 2)) + ',' + hex_to_decimal(color.substr(4, 2)) + ',' + opacity + ')'; 34 return 'rgba(79,148,243,0.6)'; //for testing previous ios version in older ipad 35 }; 36 create_canvas_for = function(img) { 37 var c = $('<canvas style="width:' + $(img).width() + 'px;height:' + $(img).height() + 'px;" id="map_canvas"></canvas>').get(0); 38 c.getContext("2d").clearRect(0, 0, $(img).width(), $(img).height()); 39 return c; 40 }; 41 var draw_shape = function(context, shape, coords, x_shift, y_shift) { 42 x_shift = x_shift || 0; 43 y_shift = y_shift || 0; 44 45 context.beginPath(); 46 if(shape == 'rect') { 47 // x, y, width, height 48 context.rect(coords[0] + x_shift, coords[1] + y_shift, coords[2] - coords[0], coords[3] - coords[1]); 49 } else if(shape == 'poly') { 50 context.moveTo(coords[0] + x_shift, coords[1] + y_shift); 51 for(i=2; i < coords.length; i+=2) { 52 context.lineTo(coords[i] + x_shift, coords[i+1] + y_shift); 53 } 54 } else if(shape == 'circ') { 55 // x, y, radius, startAngle, endAngle, anticlockwise 56 context.arc(coords[0] + x_shift, coords[1] + y_shift, coords[2], 0, Math.PI * 2, false); 57 } 58 context.closePath(); 59 }; 60 add_shape_to = function(canvas, shape, coords, options, name) { 61 var i, context = canvas.getContext('2d'); 62 63 // Because I don't want to worry about setting things back to a base state 64 65 // Shadow has to happen first, since it's on the bottom, and it does some clip / 66 // fill operations which would interfere with what comes next. 67 if(options.shadow) { 68 context.save(); 69 if(options.shadowPosition == "inside") { 70 // Cause the following stroke to only apply to the inside of the path 71 draw_shape(context, shape, coords); 72 context.clip(); 73 } 74 75 // Redraw the shape shifted off the canvas massively so we can cast a shadow 76 // onto the canvas without having to worry about the stroke or fill (which 77 // cannot have 0 opacity or width, since they're what cast the shadow). 78 var x_shift = canvas.width * 100; 79 var y_shift = canvas.height * 100; 80 draw_shape(context, shape, coords, x_shift, y_shift); 81 82 context.shadowOffsetX = options.shadowX - x_shift; 83 context.shadowOffsetY = options.shadowY - y_shift; 84 context.shadowBlur = options.shadowRadius; 85 context.shadowColor = css3color(options.shadowColor, options.shadowOpacity); 86 87 // Now, work out where to cast the shadow from! It looks better if it's cast 88 // from a fill when it's an outside shadow or a stroke when it's an interior 89 // shadow. Allow the user to override this if they need to. 90 var shadowFrom = options.shadowFrom; 91 if (!shadowFrom) { 92 if (options.shadowPosition == 'outside') { 93 shadowFrom = 'fill'; 94 } else { 95 shadowFrom = 'stroke'; 96 } 97 } 98 if (shadowFrom == 'stroke') { 99 context.strokeStyle = "rgba(0,0,0,1)"; 100 context.stroke(); 101 } else if (shadowFrom == 'fill') { 102 context.fillStyle = "rgba(0,0,0,1)"; 103 context.fill(); 104 } 105 context.restore(); 106 107 // and now we clean up 108 if(options.shadowPosition == "outside") { 109 context.save(); 110 // Clear out the center 111 draw_shape(context, shape, coords); 112 context.globalCompositeOperation = "destination-out"; 113 context.fillStyle = "rgba(0,0,0,1);"; 114 context.fill();
115 context.restore(); 116 } 117 } 118 119 context.save(); 120 121 draw_shape(context, shape, coords); 122 123 // fill has to come after shadow, otherwise the shadow will be drawn over the fill, 124 // which mostly looks weird when the shadow has a high opacity 125 if(options.fill) { 126 context.fillStyle = css3color(options.fillColor, options.fillOpacity); 127 context.fill(); 128 } 129 // Likewise, stroke has to come at the very end, or it'll wind up under bits of the 130 // shadow or the shadow-background if it's present. 131 if(options.stroke) { 132 context.strokeStyle = css3color(options.strokeColor, options.strokeOpacity); 133 context.lineWidth = options.strokeWidth; 134 context.stroke(); 135 } 136 137 context.restore(); 138 139 if(options.fade) { 140 $(canvas).css('opacity', 0).animate({opacity: 1}, 100); 141 } 142 }; 143 clear_canvas = function(canvas) { 144 canvas.getContext('2d').clearRect(0, 0, canvas.width,canvas.height); 145 }; 146 } else { // ie executes this code 147 create_canvas_for = function(img) { 148 return $('<var style="zoom:1;overflow:hidden;display:block;width:'+img.width+'px;height:'+img.height+'px;"></var>').get(0); 149 }; 150 add_shape_to = function(canvas, shape, coords, options, name) { 151 var fill, stroke, opacity, e; 152 for (var i in coords) { coords[i] = parseInt(coords[i], 10); } 153 fill = '<v:fill color="#'+options.fillColor+'" opacity="'+(options.fill ? options.fillOpacity : 0)+'" />'; 154 stroke = (options.stroke ? 'strokeweight="'+options.strokeWidth+'" stroked="t" strokecolor="#'+options.strokeColor+'"' : 'stroked="f"'); 155 opacity = '<v:stroke opacity="'+options.strokeOpacity+'"/>'; 156 if(shape == 'rect') { 157 e = $('<v:rect name="'+name+'" filled="t" '+stroke+' style="zoom:1;margin:0;padding:0;display:block;position:absolute;left:'+coords[0]+'px;top:'+coords[1]+'px;width:'+(coords[2] - coords[0])+'px;height:'+(coords[3] - coords[1])+'px;"></v:rect>'); 158 } else if(shape == 'poly') { 159 e = $('<v:shape name="'+name+'" filled="t" '+stroke+' coordorigin="0,0" coordsize="'+canvas.width+','+canvas.height+'" path="m '+coords[0]+','+coords[1]+' l '+coords.join(',')+' x e" style="zoom:1;margin:0;padding:0;display:block;position:absolute;top:0px;left:0px;width:'+canvas.width+'px;height:'+canvas.height+'px;"></v:shape>'); 160 } else if(shape == 'circ') { 161 e = $('<v:oval name="'+name+'" filled="t" '+stroke+' style="zoom:1;margin:0;padding:0;display:block;position:absolute;left:'+(coords[0] - coords[2])+'px;top:'+(coords[1] - coords[2])+'px;width:'+(coords[2]*2)+'px;height:'+(coords[2]*2)+'px;"></v:oval>'); 162 } 163 e.get(0).innerHTML = fill+opacity; 164 $(canvas).append(e); 165 }; 166 clear_canvas = function(canvas) { 167 // jquery1.8 + ie7 168 var $html = $("<div>" + canvas.innerHTML + "</div>"); 169 $html.children('[name=highlighted]').remove(); 170 canvas.innerHTML = $html.html(); 171 }; 172 } 173 174 shape_from_area = function (area) { 175 /* var imgSize = $("#epaper_img").find('#epaper_pge_img')[0], 176 widthRatio = imgSize.width / imgSize.naturalWidth, 177 heightRatio = imgSize.height / imgSize.naturalHeight,*/ 178 var shape = area.getAttribute('shape').toLowerCase().substr(0, 4); 179 180 var i, coords = area.getAttribute('coords').split(','); 181 /*if (shape == 'circ') { 182 var x1 = parseInt(coords[0]), 183 x2 = x1 + parseInt(coords[2]), 184 newRad = Math.round(x2 * widthRatio - x1 * widthRatio); 185 coords[0] = Math.round(x1 * widthRatio); 186 coords[1] = Math.round(coords[1] * heightRatio); 187 coords[2] = newRad; 188 } else { 189 for (i = 0; i < coords.length; i++) { 190 coords[i] = i % 2 == 0 ? parseInt(coords[i] * widthRatio) : parseInt(coords[i] * heightRatio); 191 } 192 }*/ 193 for (i = 0; i < coords.length; i++) { 194 coords[i] = parseFloat(coords[i]); 195 } 196 return [shape, coords]; 197 }; 198 199 options_from_area = function(area, options) { 200 var $area = $(area); 201 var cusOptions = $area.data('maphilight'); 202 cusOptions.fillColor = '4f94f3'; 203 return $.extend({}, options, $.metadata ? $area.metadata() : false, cusOptions); 204 }; 205 206 is_image_loaded = function(img) { 207 if(!img.complete) { return false; } // IE
208 if(typeof img.naturalWidth != "undefined" && img.naturalWidth === 0) { return false; } // Others 209 return true; 210 }; 211 212 canvas_style = { 213 position: 'absolute', 214 left: 0, 215 top: 0, 216 padding: 0, 217 border: 0 218 }; 219 220 var ie_hax_done = false; 221 $.fn.maphilight = function(opts) { 222 opts = $.extend({}, $.fn.maphilight.defaults, opts); 223 224 if(!has_canvas && !ie_hax_done) { 225 $(window).ready(function() { 226 document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); 227 var style = document.createStyleSheet(); 228 var shapes = ['shape','rect', 'oval', 'circ', 'fill', 'stroke', 'imagedata', 'group','textbox']; 229 $.each(shapes, 230 function() { 231 style.addRule('v\\:' + this, "behavior: url(#default#VML); antialias:true"); 232 } 233 ); 234 }); 235 ie_hax_done = true; 236 } 237 238 return this.each(function () { 239 //this = $("#epaper_img").find('img')[0]; 240 var img, wrap, options, map, canvas, canvas_always, highlighted_shape, usemap; 241 img = $(this); 242 var imgSize = $("#epaper_img").find('img')[0]; 243 //imgSize.width = imgSize.width < 320 ? 320 : imgSize.width; 244 //imgSize.height = imgSize.height < 667 ? 667 : imgSize.height; 245 //this.width = this.width != imgSize.width ? imgSize.width : this.width; 246 //this.height = this.height != imgSize.height ? imgSize.height : this.height; 247 if(!is_image_loaded(this)) { 248 // If the image isn't fully loaded, this won't work right. Try again later. 249 return window.setTimeout(function() { 250 img.maphilight(opts); 251 }, 200); 252 } 253 254 options = $.extend({}, opts, $.metadata ? img.metadata() : false, img.data('maphilight')); 255 256 // jQuery bug with Opera, results in full-url#usemap being returned from jQuery's attr. 257 // So use raw getAttribute instead. 258 usemap = img.get(0).getAttribute('usemap'); 259 260 if (!usemap) { 261 return; 262 } 263 264 map = $('map[name="'+usemap.substr(1)+'"]'); 265 266 if(!(img.is('img,input[type="image"]') && usemap && map.length > 0)) { 267 return; 268 } 269 270 if(img.hasClass('maphilighted')) { 271 // We're redrawing an old map, probably to pick up changes to the options. 272 // Just clear out all the old stuff. 273 var wrapper = img.parent(); 274 img.insertBefore(wrapper); 275 wrapper.remove(); 276 $(map).unbind('.maphilight'); 277 } 278 var screenWidth = (window.innerWidth > 0) ? window.innerWidth : screen.width; 279 imgSize.width = screenWidth > 700 ? imgSize.width : $("#epaper_img").width(); 280 281 var thenum = parseInt(imgSize.width); 282 wrap = $('<div></div>').css({ 283 display:'block', 284 backgroundImage:'url("'+this.src+'")', 285 backgroundSize: 'contain', 286 backgroundRepeat: 'no-repeat', 287 position:'relative', 288 padding:0, 289 width: imgSize.width+"px",//this.width, 290 height:imgSize.height,//this.height 291 }); 292 if(options.wrapClass) { 293 if(options.wrapClass === true) { 294 wrap.addClass($(this).attr('class')); 295 } else { 296 wrap.addClass(options.wrapClass); 297 } 298 } 299 // Firefox has a bug that prevents tabbing into the image map if 300 // we set opacity of the image to 0, but very nearly 0 works! 301 img.before(wrap).css('opacity', 0.0000000001).css(canvas_style).remove(); 302 if(has_VML) { img.css('filter', 'Alpha(opacity=0)'); } 303 wrap.append(img); 304 305 canvas = create_canvas_for(this); 306 $(canvas).css(canvas_style); 307 canvas.height = imgSize.height;//this.height; 308 canvas.width = imgSize.width;//this.width; 309 310 img.before(canvas); // if we put this after, the mouseover events wouldn't fire. 311 img.addClass('maphilighted'); 312 313 314 315 //var c = document.getElementById("myCanvas"); 316 //var ctx = canvas.getContext("2d"); 317 318 // Red rectangle 319 //ctx.beginPath(); 320 //ctx.lineWidth = "6"; 321 //ctx.strokeStyle = "red"; 322 //ctx.rect(5, 5, 290, 140); 323 //ctx.stroke(); 324 325 326 $(map).bind('alwaysOn.maphilight', function() {
327 // Check for areas with alwaysOn set. These are added to a *second* canvas, 328 // which will get around flickering during fading. 329 if(canvas_always) { 330 clear_canvas(canvas_always); 331 } 332 if(!has_canvas) { 333 $(canvas).empty(); 334 } 335 $(map).find('area[coords]').each(function() { 336 var shape, area_options; 337 area_options = options_from_area(this, options); 338 var width = (window.innerWidth > 0) ? window.innerWidth : screen.width; 339 if (width < 970) { 340 $(this).click(function (e) { 341 shape = shape_from_area(this); 342 clear_canvas(canvas); 343 area_options.alwaysOn = true; 344 //area_options.fade = false; 345 add_shape_to(canvas, shape[0], shape[1], area_options, ""); 346 var isSelected = $(this).attr("selected"); 347 if(isSelected){ 348 //$(this).attr("selected", false); 349 //$(canvas).empty(); 350 clear_canvas(canvas); 351 } else { 352 $("area").attr("selected", false); 353 $(this).attr("selected", true); 354 e.stopPropagation(); 355 } 356 }); 357 } 358 359 if(area_options.alwaysOn) { 360 if(!canvas_always && has_canvas) { 361 canvas_always = create_canvas_for(img[0]); 362 $(canvas_always).css(canvas_style); 363 canvas_always.width = img[0].width; 364 canvas_always.height = img[0].height; 365 img.before(canvas_always); 366 } 367 area_options.fade = area_options.alwaysOnFade; // alwaysOn shouldn't fade in initially 368 shape = shape_from_area(this); 369 if (has_canvas) { 370 add_shape_to(canvas_always, shape[0], shape[1], area_options, ""); 371 } else { 372 add_shape_to(canvas, shape[0], shape[1], area_options, ""); 373 } 374 } 375 }); 376 }).trigger('alwaysOn.maphilight') 377 .bind('mouseover.maphilight, focusin.maphilight, click.maphilight', function (e) { 378 clear_canvas(canvas); 379 var shape, area_options, area = e.target; 380 area_options = options_from_area(area, options); 381 if(!area_options.neverOn && !area_options.alwaysOn) { 382 shape = shape_from_area(area); 383 add_shape_to(canvas, shape[0], shape[1], area_options, "highlighted"); 384 if(area_options.groupBy) { 385 var areas; 386 // two ways groupBy might work; attribute and selector 387 if(/^[a-zA-Z][\-a-zA-Z]+$/.test(area_options.groupBy)) { 388 areas = map.find('area['+area_options.groupBy+'="'+$(area).attr(area_options.groupBy)+'"]'); 389 } else { 390 areas = map.find(area_options.groupBy); 391 } 392 var first = area; 393 areas.each(function() { 394 if(this != first) { 395 var subarea_options = options_from_area(this, options); 396 if(!subarea_options.neverOn && !subarea_options.alwaysOn) { 397 var shape = shape_from_area(this); 398 add_shape_to(canvas, shape[0], shape[1], subarea_options, "highlighted"); 399 } 400 } 401 }); 402 } 403 // workaround for IE7, IE8 not rendering the final rectangle in a group 404 if(!has_canvas) { 405 $(canvas).append('<v:rect></v:rect>'); 406 } 407 } 408 }) 409 .bind('mouseout.maphilight, focusout.maphilight', function (e) { clear_canvas(canvas); }); 410 411 }); 412 $('body').find('.image-map').click(function () { 413 $(map).trigger('focusin.maphilight'); 414 }); 415 }; 416 $.fn.maphilight.defaults = { 417 fill: true, 418 fillColor: '4f94f3', 419 fillOpacity: 0.2, 420 stroke: true, 421 strokeColor: '4f94f3', 422 strokeOpacity: 1, 423 strokeWidth: 1, 424 fade: true, 425 alwaysOn: false, 426 neverOn: false, 427 groupBy: false, 428 wrapClass: true, 429 // plenty of shadow: 430 shadow: false, 431 shadowX: 0, 432 shadowY: 0, 433 shadowRadius: 6, 434 shadowColor: '000000', 435 shadowOpacity: 0.8, 436 shadowPosition: 'outside', 437 shadowFrom: false 438 }; 439});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.