Select multiple classes with attr. with jQuery - javascript

I have a function that I use for an interactive map, where I hover an element to show a specific region based on class that matches a country suffix. Im trying to figure out how to select multiple classes to show multiple regions.
Code:
var mapObj = jQuery('#vmap').data('mapObject');
jQuery('#countries').on('mouseover mouseout', 'a:first-child', function (event) {
// event.preventDefault();
var elem = event.target,
evtype = event.type;
if (evtype === 'mouseover') {
mapObj.select(jQuery(elem).attr('class'));
} else {
mapObj.deselect(jQuery(elem).attr('class'));
};
});
};
<ul id="countries">
<li><a class="SE" href="">Sweden</a></li>
<li><a class="DK" href="">Denmark</a></li>
</ul>
I might going this the wrong way, but I would like to target mutiple regions by using several classes:
<li><a class="SE DK" href="">Sweden and Denmark</a></li>
This of course doesn't work but illustrates what I want to do. whats the best approach here?
Example:
jQuery('#vmap').vectorMap({
map: 'world_en',
onLabelShow: function (event, label, code) {
if (code == 'se') {
var countryName = label[0].innerHTML;
var html = ['<span class="tooltip-up arrow-down-center">',
countryName,
': 50% of production',
'</span>'
].join("");
label[0].innerHTML = html;
}
},
backgroundColor: '#fff',
enableZoom: false,
color: '#ffffff',
hoverOpacity: 0.7,
selectedColor: '#666666',
showTooltip: true,
values: sample_data,
scaleColors: ['#C8EEFF', '#006491'],
normalizeFunction: 'polynomial',
pinMode: 'content',
regionsSelectableOne: false,
regionsSelectable: false,
series: {
regions: [{
scale: ['#C8EEFF', '#0071A4'],
normalizeFunction: 'polynomial'
}]
}
});
var mapObj = jQuery('#vmap').data('mapObject');
jQuery('#countries').on('mouseover mouseout', 'a:first-child', function (event) {
// event.preventDefault();
var elem = event.target,
evtype = event.type;
if (evtype === 'mouseover') {
mapObj.select(jQuery(elem).attr('class'));
} else {
mapObj.deselect(jQuery(elem).attr('class'));
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://www.10bestdesign.com/jqvmap/assets/jqvmaps/jqvmap.css" media="screen" rel="stylesheet" type="text/css">
<script src="https://www.10bestdesign.com/jqvmap/assets/jqvmaps/jquery.vmap.js"></script>
<script src="https://www.10bestdesign.com/jqvmap/assets/jqvmaps/maps/jquery.vmap.world.js"></script>
<script src="https://www.10bestdesign.com/jqvmap/assets/jqvmaps/jquery.vmap.sampledata.js"></script>
<div id="vmap" style="width: 800px; height: 400px;"></div>
<ul id="countries">
<li><a class="SE" href="">Sweden</a></li>
<li><a class="DK" href="">Denmark</a></li>
<li><a class="SE DK" href="">Sweden and Denmark</a></li>
</ul>

You can modify your select/deselect function to accept array of classes, or instead loop the classes and invoke select/deselect for each class name:
var mapObj = jQuery('#vmap').data('mapObject');
jQuery('#countries').on('mouseover mouseout', 'a:first-child', function (event) {
var elem = event.target;
var countryCodes = jQuery(elem).attr('class').split(/\s+/);
evtype = event.type;
if (evtype === 'mouseover') {
jQuery.each(countryCodes, function(index, code) {
mapObj.select(code);
});
} else {
jQuery.each(countryCodes, function(index, code) {
if (mapObj.isSelected(code)) {
mapObj.deselect(code);
} else {
mapObj.select(code);
mapObj.deselect(code);
}
});
};
});

you can split each class and put in foreach loop so all element will target where that class is exist
var mapObj = jQuery('#vmap').data('mapObject');
jQuery('#countries').on('mouseover mouseout', 'a:first-child', function (event) {
// event.preventDefault();
var elem = event.target,
evtype = event.type;
var attrClass = jQuery(elem).attr('class');
var claArr = attrClass.slit(" ");
jQuery(claArr).each(function(index,values){
if (evtype === 'mouseover') {
mapObj.select(values);
} else {
mapObj.deselect(values);
};
});
if (evtype === 'mouseover') {
mapObj.select(jQuery(elem).attr('class'));
} else {
mapObj.deselect(jQuery(elem).attr('class'));
};
});
};

Related

How to use leaflet-indoor plugin and draggable object in leaflet.1.0.3

When using leaflet v0.7.7 then leaflet-indoor works perfectly.
After updating to leaflet v1.0.3 markers become draggable, but now leaflet-indoor is not working.
Moreover, leaflet itself is throwing an error:
TypeError: Cannot read property 'call' of undefined
const MapController = function() {
// Containers
var $window = $(window),
mapEl = document.getElementById('map-base'),
mapFileName = window.mapFile,
resourceSidebar = document.getElementById('resourceSidebar'),
detailSidebar = document.getElementById('detailSidebar');
// Links
var addResource = document.querySelectorAll('[data-add-resource]');
setHeight();
// Create map perimeter
// console.log(window);
var view = window.mapDefaultView.split(',');
var map = new L.Map(mapEl, {
center: new L.LatLng(parseFloat(view[0]),parseFloat(view[1])),
zoom: parseFloat(window.mapDefaultZoom),
zoomControl: true
});
makePerimeter()
L.marker([parseFloat(view[0]),parseFloat(view[1])], {
draggable: true,
icon: L.divIcon({
iconSize: null,
html: "<div style='padding:1rem'>Hi</div>"
})
}).addTo(map);
// Not draggable
// Just here for visual reference
// when dragging marker
var circle = L.circle([parseFloat(view[0]),parseFloat(view[1])],100000).addTo(map);
L.control.mousePosition().addTo(map);
// Set heights on the main containers
function setHeight() {
var winHeight = $window.height()+'px';
mapEl.style.height = winHeight;
resourceSidebar.style.height = winHeight;
detailSidebar.style.height = winHeight;
}
// Open the detail sidebar
function toggleDetailSidebar() {
var el = detailSidebar;
if (el.classList.contains('active')) {
el.classList.remove('active');
} else {
el.classList.add('active');
}
}
// Create Perimeter, Guides, and Sections
function makePerimeter() {
$.get(window.mapDataFilePath, function(data) {
var baseLayer = new L.Indoor(data, {
getLevel: function(feature) {
if (feature.properties.relations.length === 0)
return null;
return feature.properties.relations[0].reltags.level;
},
onEachFeature: function(feature, layer) {
layer.bindPopup(JSON.stringify(feature.properties, null, 4));
},
style: function(feature) {
var fill = '#fafafa',
stroke = '#4d4d4d',
part = feature.properties.tags.buildingpart;
switch (part) {
case 'guide':
fill = '#eee';
stroke = '#eee';
break;
case 'section':
fill = 'transparent';
stroke = 'transparent';
break;
}
return {
fillColor: fill,
weight: 1,
color: stroke,
fillOpacity: 1
};
}
});
baseLayer.setLevel("0");
baseLayer.addTo(map);
var levelControl = new L.Control.Level({
level: "0",
levels: baseLayer.getLevels()
});
// Connect the level control to the indoor layer
levelControl.addEventListener("levelchange", baseLayer.setLevel, baseLayer);
levelControl.addTo(map);
perimeterWasMade()
});
}
function perimeterWasMade() {
// Save map view/zoom in hash, so it presists on refresh
var saveView = new L.Hash(map);
// Some other plugins I was messing around with
// Leave commented for now
//L.control.polylineMeasure({imperial: true}).addTo(map);
//L.control.mousePosition().addTo(map);
// 6' booth example
// This is the correct w/h of a 6'w booth that is 4'h
// except it is rotated incorrectly.
// It should be wider than it is tall.
var bounds = [
[ -0.0807 , 12.8787 ],
[ -0.0807 , 13.2845 ],
[ 0.5284 , 13.2845 ],
[ 0.5284 , 12.8787 ]
];
var booth = L.polygon(bounds, {color: 'red', weight: 1})
booth.addTo(map);
// Load booths
loadObjects()
}
function loadObjects() {
// load booths and prizes onto the map
loadJSON("booths.json", function(response) {
var actual_JSON = JSON.parse(response);
$.each(actual_JSON,function(i,val){
if (val.coordinate != undefined && val.size != null)
{
var size = val.size.split('x');
var marker = L.marker([val.coordinate.x,val.coordinate.y], {
id: val.id,
draggable: true,
icon: L.divIcon({
iconSize: null,
html: "<div style='height:"+size[0]+"; width="+size[1]+";'><div style=' padding:5px 10px;'>"+val.vendor.industry +" </div><span style='text-align:center;display:block;border-top:4px solid #888;'>"+val.vendor.name+"</span></div>"
})
}).addTo(map);
// label.dragging.enable();
marker.on('drag', function(event){
console.log("position");
});
//also display booths using leaflet.label
// var label = new L.Label();
// label.setContent("<div style='height:"+size[0]+"; width="+size[1]+";'><div style=' padding:5px 10px;'>"+val.vendor.industry +" </div><span style='text-align:center;display:block;border-top:4px solid #888;'>"+val.vendor.name+"</span></div>");
// label.setLatLng([val.coordinate.x,val.coordinate.y]);
// map.showLabel(label);
}
})
});
}
map.on('click', function(e) {
//alert(e.latlng);
});
// Catch click on resource in sidebar
if (addResource.length > 0) {
addResource.each(function() {
this.addEventListener('click', function(e) {
e.preventDefault();
mapEl.classList.add('adding-booth');
});
});
}
}

Google chart responsive

So i have this function to draw a graph, i already changed it a bit to try to make the chart responsive, but im not being able to do it...
here is the function:
$(document).ready(function(){
google.charts.load('current', {'packages': ['corechart']});
//alert('aa00'~
$('.error').hide();
$(".buttonSala").click(function() {
// validate and process form here
$('.error').hide();
var nome = $( "#nomeSala option:selected" ).val();
var objeto = $( "#sensorSala option:selected" ).val();
var canal = $( "#canalSala option:selected" ).val();
var datai = $("#datainisala").val();
var dataf = $("#datafimsala").val();
//alert(canal);
// Send the data using post
var posting = $.post( "getSala.php", { canal: canal, dataini: datai, datafim: dataf, objeto: objeto } );
// Put the results in a div
posting.done(
function drawChart1( data ) {
// Set a callback to run when the Google Visualization API is loaded.
$('.box-title').html(nome);
var response = JSON.parse(data);
var jsonData = response.channels[canal].values;
var desciption = response.channels[canal].info.chname;
google.charts.setOnLoadCallback(function() {
dataArray = [["ts", desciption ]];
for (var i = 0; i < jsonData.length; i++)
{
var tempArray = [jsonData[i].ts, parseFloat(jsonData[i].value.replace(",", "."))];
dataArray.push(tempArray);
}
// Create our data table out of JSON data loaded from server.
var data = google.visualization.arrayToDataTable(
dataArray
);
var options = {
curveType: 'function',
backgroundColor: '#fff',
colors: ['#5d4a50'],
vAxis: {
gridlines: {
color: 'transparent'
},
textStyle: {
color: '#666', fontSize: 16
}
},
legend: { position: 'bottom', textStyle: {
color: '#666', fontSize: 18
} }
};
// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
);
});
$(window).resize(function(){
drawChart1();
});
return false;
});
});
Then on my css i already added this:
.chart {
width: 100%;
min-height: 450px;
}
And my html is like this:
<div class="row">
<div class="col-md-12">
<div id="chart_div" class="chart"></div>
</div>
</div>
But the graph isn't responsive still... The div where the graph is being draw is responsive already, but when i resize the window, the graph inside just gets cut...
Any sugestions?
first, you can rely on the callback from google to know when the document is ready,
instead of --> $(document).ready(...
and the callback can be placed in the load statement,
no need to use setOnLoadCallback every time the chart needs to be drawn
recommend setup similar to the following snippet...
google.charts.load('current', {
callback: function () {
var googleChart = new google.visualization.AreaChart(document.getElementById('chart_div'));
var googleData = null;
$('.buttonSala').click(getData);
$(window).resize(drawChart);
function getData() {
$('.error').hide();
var nome = $( "#nomeSala option:selected" ).val();
$('.box-title').html(nome);
var objeto = $( "#sensorSala option:selected" ).val();
var canal = $( "#canalSala option:selected" ).val();
var datai = $("#datainisala").val();
var dataf = $("#datafimsala").val();
var posting = $.post( "getSala.php", { canal: canal, dataini: datai, datafim: dataf, objeto: objeto } );
posting.done(processData);
return false;
}
function processData(data) {
var response = JSON.parse(data);
var jsonData = response.channels[canal].values;
var desciption = response.channels[canal].info.chname;
dataArray = [["ts", desciption ]];
for (var i = 0; i < jsonData.length; i++) {
dataArray.push([
jsonData[i].ts,
parseFloat(jsonData[i].value.replace(",", "."))
]);
}
var googleData = google.visualization.arrayToDataTable(
dataArray
);
drawChart();
}
function drawChart() {
if (googleData === null) {
return;
}
googleChart.draw(googleData, {
curveType: 'function',
backgroundColor: '#fff',
colors: ['#5d4a50'],
vAxis: {
gridlines: {
color: 'transparent'
},
textStyle: {
color: '#666',
fontSize: 16
}
},
legend: {
position: 'bottom',
textStyle: {
color: '#666', fontSize: 18
}
}
});
}
},
packages: ['corechart']
});

Select box to appear inside jQuery Dialog on image click

I am trying to modify this example http://waynegm.github.io/imgNotes/examples/basic_interactive.html#
in order to get a select option to appear inside the dialog box when user clicks on the image. Currently the code places a marker on the area the user selects when in edit mode and opens a dialog box allowing them to enter text, with the options to save / cancel.
Inside the dialog box I want to change the textarea to a select list like:
<select>
<option value="head">Head</option>
<option value="leftarm">Left Arm</option>
<option value="rightarm">Right Arm</option>
<option value="leg">Leg</option>
</select>
It seems like it should be a simple change, I have made others samples where simple on image click makes the drop down appear. But this example has everything else I need like the options to delete and recording the co-ords of the place marker.
The current HTML:
<html>
<head>
<title>jQuery imgNotes - Interactive Base</title>
<style type="text/css" media="all">#import "css/marker.css";</style>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css" media="screen">
<script type="text/javascript" src="src/imgNotes.js"></script>
</head>
<body>
<div id="imgdiv" style="text-align: center">
<img id="image" src="image/personsit.jpg" style="border: 30px solid #ccc; padding:20px;" width=400/>
<br/>
<button id="toggleEdit">Edit</button> <button id="export">Export</button>
</div>
<div id=txt></div>
<script type="text/javascript">
;(function($) {
$(document).ready(function() {
var $img = $("#image").imgNotes();
//$img.imgNotes("import", [ {x: "0.5", y:"0.5", note:"AFL Grand Final Trophy"},
// {x: "0.4", y:"0.269", note: "Shoulder"},
// {x: "0.824", y: "0.593", note: "Fluffy microphone"}]);
var $toggle = $("#toggleEdit");
if ($img.imgNotes("option","canEdit")) {
$toggle.text("View");
} else {
$toggle.text("Edit");
}
$toggle.on("click", function() {
var $this = $(this);
if ($this.text()=="Edit") {
$this.text("View");
$img.imgNotes("option", "canEdit", true);
} else {
$this.text('Edit');
$img.imgNotes('option', 'canEdit', false);
}
});
var $export = $("#export");
$export.on("click", function() {
var $table = $("<table/>").addClass("gridtable");
var notes = $img.imgNotes('export');
$table.append("<th>X</th><th>Y</th><th>NOTE</th>");
$.each(notes, function(index, item) {
$table.append("<tr><td>" + item.x + "</td><td>" + item.y + "</td><td>" + item.note + "</td></tr>");
});
$('#txt').html($table);
});
});
})(jQuery);
</script>
</body>
</html>
imgNotes.js file
;(function($) {
$.widget("wgm.imgNotes", {
options: {
zoom: 1,
zoomStep: 0.1,
zoomable: true,
canEdit: false,
vAll: "middle",
hAll: "middle",
/*
* Default callback to create a marker indicating a note location
* See the examples for more elaborate alternatives.
*/
onAdd: function() {
this.options.vAll = "bottom";
this.options.hAll = "middle";
return $(document.createElement('span')).addClass("marker black").html(this.noteCount);
},
/*
* Default callback when the marker is clicked and the widget has canEdit = true
* Opens a dialog with a textarea to write a note.
* See the examples for a more elaborate alternative that includes a WYSIWYG editor
*/
onEdit: function(ev, elem) {
var $elem = $(elem);
$("#dialog-2").remove();
return $('<div id="dialog-2"></div>').dialog({
title: "Body Parts",
resizable: false,
modal: true,
height: "300",
width: "450",
position: { my: "left bottom", at: "right top", of: elem},
buttons: {
"Save": function() {
var txt = $('textarea', this).val();
// Put the editied note back into the data area of the element
// Very important that this step is included in custom callback implementations
$elem.data("note", txt);
$(this).dialog("close");
},
"Delete": function() {
$elem.trigger("remove");
$(this).dialog("close");
},
Cancel: function() {
$(this).dialog("close");
}
},
open: function() {
$(this).css("overflow", "hidden");
var textarea = $('<textarea id="txt" style="height:100%; width:100%;">');
$(this).html(textarea);
// Get the note text and put it into the textarea for editing
textarea.val($elem.data("note"));
}
})
},
/*
* Default callback when the marker is clicked and the widget has canEdit = false
* Opens a dialog displaying the contents of the marker's note
* See examples for alternatives such as using tooltips.
*/
onShow: function(ev, elem) {
var $elem = $(elem);
$('#NoteDialog').remove();
return $('<div id="NoteDialog"></div>').dialog({
modal: false,
resizable: false,
height: 300,
width: 250,
position: { my: "left bottom", at: "right top", of: elem},
buttons: {
"Close" : function() {
$(this).dialog("close");
}
},
open: function() {
// Get the note text and put it into the textarea for editing
$(this).html($elem.data("note"));
$(this).closest(".ui-dialog").find(".ui-dialog-titlebar:first").hide();
},
close: function() {
$(this).dialog("destroy");
}
});
},
/*
* Default callback when the markers are repainted
*/
onUpdateMarker: function(elem) {
var $elem = $(elem);
var $img = $(this.img);
var pos = $img.imgViewer("imgToView", $elem.data("relx"), $elem.data("rely"));
if (pos) {
$elem.css({
left: (pos.x - $elem.data("xOffset")),
top: (pos.y - $elem.data("yOffset")),
position: "absolute"
});
}
},
/*
* Default callback when the image view is repainted
*/
onUpdate: function() {
var self = this;
$.each(this.notes, function() {
self.options.onUpdateMarker.call(self, this);
});
}
},
_create: function() {
var self = this;
if (!this.element.is("img")) {
$.error('imgNotes plugin can only be applied to img elements');
}
// the note/marker elements
self.notes = [];
// the number of notes
self.noteCount = 0;
// the original img element
self.img = self.element[0];
var $img = $(self.img);
// attach the imgViewer plugin for zooming and panning with a custon click and update callbacks
$img.imgViewer({
onClick: function(ev, imgv) {
if (self.options.canEdit) {
ev.preventDefault();
var rpos = imgv.cursorToImg(ev.pageX, ev.pageY);
if (rpos) {
var elem = self.addNote(rpos.x, rpos.y);
self._trigger("onEdit", ev, elem);
}
}
},
onUpdate: function(ev, imgv) {
self.options.zoom = imgv.options.zoom;
self.options.onUpdate.call(self);
},
zoom: self.options.zoom,
zoomStep: self.options.zoomStep,
zoomable: self.options.zoomable
});
$img.imgViewer("update");
},
/*
* Remove the plugin
*/
destroy: function() {
this.clear();
$(this.img).imgViewer("destroy");
$.Widget.prototype.destroy.call(this);
},
_setOption: function(key, value) {
switch(key) {
case 'vAll':
switch(value) {
case 'top': break;
case 'bottom': break;
default: value = 'middle';
}
break;
case 'hAll':
switch(value) {
case 'left': break;
case 'right': break;
default: value = 'middle';
}
break;
}
var version = $.ui.version.split('.');
if (version[0] > 1 || version[1] > 8) {
this._super(key, value);
} else {
$.Widget.prototype._setOption.apply(this, arguments);
}
switch(key) {
case 'zoom':
$(this.img).imgViewer("option", "zoom", value);
break;
case 'zoomStep':
$(this.img).imgViewer("option", "zoomStep", value);
break;
case 'zoomable':
$(this.img).imgViewer("option", "zoomable", value);
break;
}
},
/*
* Pan the view to be centred at the given relative image location
*/
panTo: function(relx, rely) {
return $(this.img).imgViewer("panTo", relx, rely);
},
/*
* Add a note
*/
addNote: function(relx, rely, text) {
var self = this;
this.noteCount++;
var elem = this.options.onAdd.call(this);
var $elem = $(elem);
$(this.img).imgViewer("addElem",elem);
$elem.data("relx", relx).data("rely", rely).data("note", text);
switch (this.options.vAll) {
case "top": $elem.data("yOffset", 0); break;
case "bottom": $elem.data("yOffset", $elem.height()); break;
default: $elem.data("yOffset", Math.round($elem.height()/2));
}
switch (this.options.hAll) {
case "left": $elem.data("xOffset", 0); break;
case "right": $elem.data("xOffset", $elem.width()); break;
default: $elem.data("xOffset", Math.round($elem.width()/2));
}
$elem.click(function(ev) {
ev.preventDefault();
if (self.options.canEdit) {
self._trigger("onEdit", ev, elem);
} else {
self._trigger("onShow", ev, elem);
}
});
$elem.on("remove", function() {
self._delete(elem);
});
this.notes.push(elem);
$(this.img).imgViewer("update");
return elem;
},
/*
* Number of notes
*/
count: function() {
return this.noteCount;
},
/*
* Delete a note
*/
_delete: function(elem) {
this.notes = this.notes.filter(function(v) { return v!== elem; });
$(elem).off();
$(elem).remove();
$(this.img).imgViewer("update");
},
/*
* Clear all notes
*/
clear: function() {
var self = this;
var total = self.notes.length;
for ( var i = 0; i < total; i++ ){
var $this = self.notes[i];
$this.off();
$this.remove();
}
self.notes=[];
self.noteCount = 0;
},
/*
* Add notes from a javascript array
*/
import: function(notes) {
var self = this;
$.each(notes, function() {
self.addNote(this.x, this.y, this.note);
});
$(this.img).imgViewer("update");
},
/*
* Export notes to an array
*/
export: function() {
var notes = [];
$.each(this.notes, function() {
var $elem = $(this);
notes.push({
x: $elem.data("relx"),
y: $elem.data("rely"),
note: $elem.data("note")
});
});
return notes;
}
});
})(jQuery);
I would really appreciate if anyone could help me out.

JqvMap onRegionClick (bootstrap) PopOver fires only clicking twice

I am using JqvMap and I want to click on a region and this shall prompt a (bootstrap) popover with the name of the country as title, and the content should be some html links. This is my code:
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('#vmap').vectorMap({
map: 'world_en',
backgroundColor: '#333333',
color: '#ffffff',
hoverOpacity: 0.7,
selectedColor: '#666666',
enableZoom: true,
showTooltip: false,
values: sample_data,
scaleColors: ['#C8EEFF', '#006491'],
normalizeFunction: 'polynomial',
regionsSelectableOne: 'true',
onRegionClick: function(element, code, region) {
$(".popover-title").html(region);
jQuery('.jvectormap-region').popover({
placement: 'top',
container: '#vmap',
content: 'page 1</br>page 2</br>page 3</br>page 4</br>',
trigger: 'click',
html: 'true',
title: ' '
});
},
onRegionOver: function (event, code, region) {
document.body.style.cursor = "pointer";
},
onRegionOut: function (element, code, region) {
document.body.style.cursor = "default";
$('.jvectormap-region').popover('destroy');
// $('#vmap').vectorMap('deselect', code);
}
});
});
</script>
My problem at the moment is that I need to click twice on the map to make popover show up. I read it may be due to the fact that it is not initialized, but I can't seem to initialize it (where? how?)!
Can someone help me with these issues? I can't seem to figure out what the problem is..
So I kinda fixed it (probably in a nasty way but it does the trick).
Hope it will help someone else.
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('#vmap').vectorMap({
map: 'world_en',
backgroundColor: '#333333',
color: '#ffffff',
hoverOpacity: 0.7,
selectedColor: '#666666',
enableZoom: true,
showTooltip: false,
values: sample_data,
scaleColors: ['#C8EEFF', '#006491'],
normalizeFunction: 'polynomial',
regionsSelectableOne: true,
});
runPopOver();
});
</script>
<script type="text/javascript">
function runPopOver() {
var currentRegion;
jQuery('#vmap').bind('regionMouseOver.jqvmap',
function(event, code, region) {
document.body.style.cursor = "pointer";
currentRegion = region;
}
);
jQuery('#vmap').bind('regionMouseOut.jqvmap',
function(event, code, region) {
document.body.style.cursor = "default";
}
);
jQuery('#vmap').bind('regionClick.jqvmap',
function(event, code, region) {
if ($('#vmap [id^="popover"]').length > 1) {
$('#vmap [id^="popover"]').first().remove();
}
var snapshot_url = "http://www.business-anti-corruption.com/country-profiles/europe-central-asia/" + region + "/snapshot.aspx";
$(".popover-title").html(region);
$(".popover-content").html('Snapshot</br>page 2</br>page 3</br>page 4</br>');
}
);
jQuery('.jvectormap-region').popover({
placement: 'left',
container: '#vmap',
html: 'true',
title: ' '
});
}
</script>
So basically when I click on a region if there is more than 1 popover (even to be opened) I get a list of all the popover (2), take the first and remove it from the DOM (.first().remove()).
Here's a more permanent fix:
in the jquery.vmap.js find this bit of code:
jQuery(params.container).delegate(this.canvas.mode == 'svg' ? 'path' : 'shape', 'click', function (e) {
if (!params.multiSelectRegion) {
for (var key in mapData.pathes) {
map.countries[key].currentFillColor = map.countries[key].getOriginalFill();
map.countries[key].setFill(map.countries[key].getOriginalFill());
}
}
var path = e.target;
var code = e.target.id.split('_').pop();
jQuery(params.container).trigger('regionClick.jqvmap', [code, mapData.pathes[code].name]);
if (!regionClickEvent.isDefaultPrevented()) {
if (map.selectedRegions.indexOf(code) !== -1) {
map.deselect(code, path);
} else {
map.select(code, path);
}
}
//console.log(selectedRegions);
});
Replace it with this:
jQuery(params.container).delegate(this.canvas.mode == 'svg' ? 'path' : 'shape', 'mousedown mouseup', function (e) {
var PageCoords;
if (e.type == 'mousedown') {
pageCoords = event.pageX + "." + event.pageY;
}
if (e.type == 'mouseup') {
var pageCoords2 = event.pageX + "." + event.pageY;
if (pageCoords == pageCoords2) {
//we have a click. Do the ClickEvent
if (!params.multiSelectRegion) {
for (var key in mapData.pathes) {
map.countries[key].currentFillColor = map.countries[key].getOriginalFill();
map.countries[key].setFill(map.countries[key].getOriginalFill());
}
}
var path = e.target;
var code = e.target.id.split('_').pop();
regionClickEvent = $.Event('regionClick.jqvmap');
jQuery(params.container).trigger('regionClick.jqvmap', [code, mapData.pathes[code].name]);
if (!regionClickEvent.isDefaultPrevented()) {
if (map.selectedRegions.indexOf(code) !== -1) {
map.deselect(code, path);
} else {
map.select(code, path);
}
}
}
}
Instead of triggering a click immediately, the script now checks if it's a click or a drag. If it's a click, it fires the code you put in our onRegionClick.

Highlight text inside of a textarea

Is it possible to highlight text inside of a textarea using javascript? Either changing the background of just a portion of the text area or making a portion of the text selected?
Try this piece of code I wrote this morning, it will highlight a defined set of words:
<html>
<head>
<title></title>
<!-- Load jQuery -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<!-- The javascript xontaining the plugin and the code to init the plugin -->
<script type="text/javascript">
$(function() {
// let's init the plugin, that we called "highlight".
// We will highlight the words "hello" and "world",
// and set the input area to a widht and height of 500 and 250 respectively.
$("#container").highlight({
words: ["hello","world"],
width: 500,
height: 250
});
});
// the plugin that would do the trick
(function($){
$.fn.extend({
highlight: function() {
// the main class
var pluginClass = function() {};
// init the class
// Bootloader
pluginClass.prototype.__init = function (element) {
try {
this.element = element;
} catch (err) {
this.error(err);
}
};
// centralized error handler
pluginClass.prototype.error = function (e) {
// manage error and exceptions here
//console.info("error!",e);
};
// Centralized routing function
pluginClass.prototype.execute = function (fn, options) {
try {
options = $.extend({},options);
if (typeof(this[fn]) == "function") {
var output = this[fn].apply(this, [options]);
} else {
this.error("undefined_function");
}
} catch (err) {
this.error(err);
}
};
// **********************
// Plugin Class starts here
// **********************
// init the component
pluginClass.prototype.init = function (options) {
try {
// the element's reference ( $("#container") ) is stored into "this.element"
var scope = this;
this.options = options;
// just find the different elements we'll need
this.highlighterContainer = this.element.find('#highlighterContainer');
this.inputContainer = this.element.find('#inputContainer');
this.textarea = this.inputContainer.find('textarea');
this.highlighter = this.highlighterContainer.find('#highlighter');
// apply the css
this.element.css('position','relative');
// place both the highlight container and the textarea container
// on the same coordonate to superpose them.
this.highlighterContainer.css({
'position': 'absolute',
'left': '0',
'top': '0',
'border': '1px dashed #ff0000',
'width': this.options.width,
'height': this.options.height,
'cursor': 'text'
});
this.inputContainer.css({
'position': 'absolute',
'left': '0',
'top': '0',
'border': '1px solid #000000'
});
// now let's make sure the highlit div and the textarea will superpose,
// by applying the same font size and stuffs.
// the highlighter must have a white text so it will be invisible
this.highlighter.css({
'padding': '7px',
'color': '#eeeeee',
'background-color': '#ffffff',
'margin': '0px',
'font-size': '11px',
'font-family': '"lucida grande",tahoma,verdana,arial,sans-serif'
});
// the textarea must have a transparent background so we can see the highlight div behind it
this.textarea.css({
'background-color': 'transparent',
'padding': '5px',
'margin': '0px',
'font-size': '11px',
'width': this.options.width,
'height': this.options.height,
'font-family': '"lucida grande",tahoma,verdana,arial,sans-serif'
});
// apply the hooks
this.highlighterContainer.bind('click', function() {
scope.textarea.focus();
});
this.textarea.bind('keyup', function() {
// when we type in the textarea,
// we want the text to be processed and re-injected into the div behind it.
scope.applyText($(this).val());
});
} catch (err) {
this.error(err);
}
return true;
};
pluginClass.prototype.applyText = function (text) {
try {
var scope = this;
// parse the text:
// replace all the line braks by <br/>, and all the double spaces by the html version
text = this.replaceAll(text,'\n','<br/>');
text = this.replaceAll(text,' ',' ');
// replace the words by a highlighted version of the words
for (var i=0;i<this.options.words.length;i++) {
text = this.replaceAll(text,this.options.words[i],'<span style="background-color: #D8DFEA;">'+this.options.words[i]+'</span>');
}
// re-inject the processed text into the div
this.highlighter.html(text);
} catch (err) {
this.error(err);
}
return true;
};
// "replace all" function
pluginClass.prototype.replaceAll = function(txt, replace, with_this) {
return txt.replace(new RegExp(replace, 'g'),with_this);
}
// don't worry about this part, it's just the required code for the plugin to hadle the methods and stuffs. Not relevant here.
//**********************
// process
var fn;
var options;
if (arguments.length == 0) {
fn = "init";
options = {};
} else if (arguments.length == 1 && typeof(arguments[0]) == 'object') {
fn = "init";
options = $.extend({},arguments[0]);
} else {
fn = arguments[0];
options = $.extend({},arguments[1]);
}
$.each(this, function(idx, item) {
// if the component is not yet existing, create it.
if ($(item).data('highlightPlugin') == null) {
$(item).data('highlightPlugin', new pluginClass());
$(item).data('highlightPlugin').__init($(item));
}
$(item).data('highlightPlugin').execute(fn, options);
});
return this;
}
});
})(jQuery);
</script>
</head>
<body>
<div id="container">
<div id="highlighterContainer">
<div id="highlighter">
</div>
</div>
<div id="inputContainer">
<textarea cols="30" rows="10">
</textarea>
</div>
</div>
</body>
</html>
This was written for another post (http://facebook.stackoverflow.com/questions/7497824/how-to-highlight-friends-name-in-facebook-status-update-box-textarea/7597420#7597420), but it seems to be what you're searching for.
Easy script I wrote for this: Jsfiddle
OPTIONS:
Optional char counter.
Highlight several patterns with different colors.
Regex.
Collect matches to other containers.
Easy styling: fonts color and face, backgrounds, border radius and lineheight.
Ctrl+Shift for direction change.
//include function like in the fiddle!
//CREATE ELEMENT:
create_bind_textarea_highlight({
eleId:"wrap_all_highlighter",
width:400,
height:110,
padding:5,
background:'white',
backgroundControls:'#585858',
radius:5,
fontFamilly:'Arial',
fontSize:13,
lineHeight:18,
counterlettres:true,
counterFont:'red',
matchpatterns:[["(#[0-9A-Za-z]{0,})","$1"],["(#[0-9A-Za-z]{0,})","$1"]],
hightlightsColor:['#00d2ff','#FFBF00'],
objectsCopy:["copy_hashes","copy_at"]
//PRESS Ctrl + SHIFT for direction swip!
});
//HTML EXAMPLE:
<div id="wrap_all_highlighter" placer='1'></div>
<div id='copy_hashes'></div><!--Optional-->
<div id='copy_at'></div><!--Optional-->
Have Fun!
Improved version from above, also works with Regex and more TextArea fields:
<html>
<head>
<title></title>
<!-- Load jQuery -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<!-- The javascript xontaining the plugin and the code to init the plugin -->
<script type="text/javascript">
$(function() {
// let's init the plugin, that we called "highlight".
// We will highlight the words "hello" and "world",
// and set the input area to a widht and height of 500 and 250 respectively.
$("#container0").highlight({
words: [["hello","hello"],["world","world"],["(\\[b])(.+?)(\\[/b])","$1$2$3"]],
width: 500,
height: 125,
count:0
});
$("#container1").highlight({
words: [["hello","hello"],["world","world"],["(\\[b])(.+?)(\\[/b])","$1$2$3"]],
width: 500,
height: 125,
count: 1
});
});
// the plugin that would do the trick
(function($){
$.fn.extend({
highlight: function() {
// the main class
var pluginClass = function() {};
// init the class
// Bootloader
pluginClass.prototype.__init = function (element) {
try {
this.element = element;
} catch (err) {
this.error(err);
}
};
// centralized error handler
pluginClass.prototype.error = function (e) {
// manage error and exceptions here
//console.info("error!",e);
};
// Centralized routing function
pluginClass.prototype.execute = function (fn, options) {
try {
options = $.extend({},options);
if (typeof(this[fn]) == "function") {
var output = this[fn].apply(this, [options]);
} else {
this.error("undefined_function");
}
} catch (err) {
this.error(err);
}
};
// **********************
// Plugin Class starts here
// **********************
// init the component
pluginClass.prototype.init = function (options) {
try {
// the element's reference ( $("#container") ) is stored into "this.element"
var scope = this;
this.options = options;
// just find the different elements we'll need
this.highlighterContainer = this.element.find('#highlighterContainer'+this.options.count);
this.inputContainer = this.element.find('#inputContainer'+this.options.count);
this.textarea = this.inputContainer.find('textarea');
this.highlighter = this.highlighterContainer.find('#highlighter'+this.options.count);
// apply the css
this.element.css({'position':'relative',
'overflow':'auto',
'background':'none repeat scroll 0 0 #FFFFFF',
'height':this.options.height+2,
'width':this.options.width+19,
'border':'1px solid'
});
// place both the highlight container and the textarea container
// on the same coordonate to superpose them.
this.highlighterContainer.css({
'position': 'absolute',
'left': '0',
'top': '0',
'border': '1px dashed #ff0000',
'width': this.options.width,
'height': this.options.height,
'cursor': 'text',
'z-index': '1'
});
this.inputContainer.css({
'position': 'absolute',
'left': '0',
'top': '0',
'border': '0px solid #000000',
'z-index': '2',
'background': 'none repeat scroll 0 0 transparent'
});
// now let's make sure the highlit div and the textarea will superpose,
// by applying the same font size and stuffs.
// the highlighter must have a white text so it will be invisible
var isWebKit = navigator.userAgent.indexOf("WebKit") > -1,
isOpera = navigator.userAgent.indexOf("Opera") > -1,
isIE /*#cc_on = true #*/,
isIE6 = isIE && !window.XMLHttpRequest; // Despite the variable name, this means if IE lower than v7
if (isIE || isOpera){
var padding = '6px 5px';
}
else {
var padding = '5px 6px';
}
this.highlighter.css({
'padding': padding,
'color': '#eeeeee',
'background-color': '#ffffff',
'margin': '0px',
'font-size': '11px' ,
'line-height': '12px' ,
'font-family': '"lucida grande",tahoma,verdana,arial,sans-serif'
});
// the textarea must have a transparent background so we can see the highlight div behind it
this.textarea.css({
'background-color': 'transparent',
'padding': '5px',
'margin': '0px',
'width': this.options.width,
'height': this.options.height,
'font-size': '11px',
'line-height': '12px' ,
'font-family': '"lucida grande",tahoma,verdana,arial,sans-serif',
'overflow': 'hidden',
'border': '0px solid #000000'
});
// apply the hooks
this.highlighterContainer.bind('click', function() {
scope.textarea.focus();
});
this.textarea.bind('keyup', function() {
// when we type in the textarea,
// we want the text to be processed and re-injected into the div behind it.
scope.applyText($(this).val());
});
scope.applyText(this.textarea.val());
} catch (err) {
this.error(err)
}
return true;
};
pluginClass.prototype.applyText = function (text) {
try {
var scope = this;
// parse the text:
// replace all the line braks by <br/>, and all the double spaces by the html version
text = this.replaceAll(text,'\n','<br/>');
text = this.replaceAll(text,' ',' ');
text = this.replaceAll(text,' ',' ');
// replace the words by a highlighted version of the words
for (var i=0;i<this.options.words.length;i++) {
text = this.replaceAll(text,this.options.words[i][0],'<span style="background-color: #D8DFEA;">'+this.options.words[i][1]+'</span>');
//text = this.replaceAll(text,'(\\[b])(.+?)(\\[/b])','<span style="font-weight:bold;background-color: #D8DFEA;">$1$2$3</span>');
}
// re-inject the processed text into the div
this.highlighter.html(text);
if (this.highlighter[0].clientHeight > this.options.height) {
// document.getElementById("highlighter0")
this.textarea[0].style.height=this.highlighter[0].clientHeight +19+"px";
}
else {
this.textarea[0].style.height=this.options.height;
}
} catch (err) {
this.error(err);
}
return true;
};
// "replace all" function
pluginClass.prototype.replaceAll = function(txt, replace, with_this) {
return txt.replace(new RegExp(replace, 'g'),with_this);
}
// don't worry about this part, it's just the required code for the plugin to hadle the methods and stuffs. Not relevant here.
//**********************
// process
var fn;
var options;
if (arguments.length == 0) {
fn = "init";
options = {};
} else if (arguments.length == 1 && typeof(arguments[0]) == 'object') {
fn = "init";
options = $.extend({},arguments[0]);
} else {
fn = arguments[0];
options = $.extend({},arguments[1]);
}
$.each(this, function(idx, item) {
// if the component is not yet existing, create it.
if ($(item).data('highlightPlugin') == null) {
$(item).data('highlightPlugin', new pluginClass());
$(item).data('highlightPlugin').__init($(item));
}
$(item).data('highlightPlugin').execute(fn, options);
});
return this;
}
});
})(jQuery);
</script>
</head>
<body>
<div id="container0">
<div id="highlighterContainer0">
<div id="highlighter0"></div>
</div>
<div id="inputContainer0">
<textarea id="text1" cols="30" rows="15">hello world</textarea>
</div>
</div>
<h1> haus </h1>
<div id="container1">
<div id="highlighterContainer1">
<div id="highlighter1"></div>
</div>
<div id="inputContainer1">
<textarea cols="30" rows="15">hipp hipp
hurra,
[b]ich hab es jetzt![/b]</textarea>
</div>
</div>
</body>

Categories

Resources