Duplicate HTML in jQuery into a BootStrap Modal - javascript

The function below is called after an icon is clicked, which creates a modal. During the function, I traverse up the DOM, grab a HTML canvas and display it in the modal. The problem I am having is that it is removing the HTML I grab initially, I want it to be duplicated. Can anyone shed some light on this?
JS:
$('#chartModal').on('show.bs.modal', function (event) {
console.log('yeppp');
// Button that triggered the modal
const button = $(event.relatedTarget)
// Get corresponding chart's HTML
const chart = button.parent().next()[0]
var modal = $(this)
// Update modal's content with the corresponding chart
modal.find('.modal-body').html(chart)
})
Regards,
James.

Since you are using jQuery, you can use the .clone() method like so:
$('#chartModal').on('show.bs.modal', function (event) {
// Button that triggered the modal
var button = $(event.relatedTarget);
// Get corresponding chart's HTML
// "chart" is a plain node here
var chart = button.parent().next()[0];
var modal = $(this);
// Update modal's content with the corresponding chart
modal.find('.modal-body').html($(chart).clone());
})
// OR
$('#chartModal').on('show.bs.modal', function (event) {
// Button that triggered the modal
var button = $(event.relatedTarget);
// Get corresponding chart's HTML
// "chart" is now a jQuery object
var chart = button.parent().next();
var modal = $(this);
// Update modal's content with the corresponding chart
modal.find('.modal-body').html(chart.clone());
})

Your current code snippet seems overly complicated in my opinion.
Here's a different solution that might be easier to follow:
HTML:
...
<canvas class="one-of-my-charts"></canvas>
...
JS:
$('.one-of-my-charts').click(function(e) {
$('#the-chart-modal').html(e.target);
$('#the-chart-modal').modal('show');
});

Related

How to update data table on data change highcharts

I have a pie chart that I'm updating dynamically on button click using the code below.
On Button click
$("#myChart").highcharts().series[0].setData($.extend(true, [], data1))
I'm using keys to populate the data table.
keys: ['Count','Value'],
This works fine and updates the chart but I also have export data table enabled in export menu but that data table doesn't update. It remains the same on all successive button clicks.
How can I update the data table with button click to show data for new data.
here is a fiddle but it doesn't really use buttons but just to give you an idea of my chart : https://jsfiddle.net/mewohraz/1/
Update: The solution below works but I had to comment out this piece of code that I'm using to toggle the viewData table. It allows me to close the table if you click on viewData again. How do I get to work it with chart.viewData()?
Highcharts.Chart.prototype.viewData = function () {
if (!this.insertedTable) {
var div = document.createElement('div');
div.className = 'highcharts-data-table';
// Insert after the chart container
this.renderTo.parentNode.insertBefore(div, this.renderTo.nextSibling);
div.innerHTML = this.getTable();
this.insertedTable = true;
div.id = this.container.id + '-data-table';
}
else {
$('#' + this.container.id + '-data-table').toggle();
}
};
You need to call viewData internal method to refresh the data table:
$('#update').on('click', function() {
var data1 = [...];
chart.series[0].setData(data1);
chart.viewData();
});
Live demo: https://jsfiddle.net/BlackLabel/ahowu9tm/

How to return specific Geojson feature property using another property, e.g. return longitude property by name?

I'm trying to create an interface with Mapbox that zooms to the polygon the user clicks on using this function while also updating a dropdown menu value in an non-map div.
When the user clicks on a polygon/town in the map, it will zoom to that correct feature by using this map.on('click...) script.
map.on('click', 'Map Layer', function (e) {
townnames = e.features[0].properties.Object_Name;
townlat = e.features[0].properties.Object_latitude;
townlong = e.features[0].properties.Object_longitude;
map.setFilter('LayerFiltered', ['==', 'TOWN_NAME', Object_Name]);
map.setFilter('LayerClicked', ['!=', 'TOWN_NAME', Object_Name]);
map.setLayoutProperty('LayerFiltered', 'visibility', 'visible');
map.flyTo({
center: [
townlong, townlat],
zoom : 11.5
});
However I'm trying to trigger the same function using the dropdown menu.
I've figured out how to filter the layer using the inner HTML value from options in the dropdown menu, and setting them equal to the "Object_Name" in setFilter. But is there any way to return other properties from the geojson associated with a feature based on one of its properties like "TOWN_NAME"?
In other words can I use a variable from the dropdown menu so instead of returning e.features[0].properties.Object_longitude when a user clicks on a feature, when they click on its associated value in the dropdown menu it will return something to the effect of-"features.TOWN_NAME=DROPDOWN_VALUE_NAME".properties.Object_longitude"?
I apologize if this is unclear.
The dropdown does not fire the load event. You have to break the work above into general methods to be called by a handler for the map and for the dropdown.
Edit: The drop down is not being assigned the click event and would need to be given a listener to call a function that is also called by the map objects click listener.
demo
// Add an event listener for the links in the sidebar listing
listings.addEventListener('change', function () {
// Update the currentFeature to the store associated with the clicked link
var clickedListing = data.features[listings.selectedIndex];
// 1. Fly to the point associated with the clicked link
flyToStore(clickedListing);
// 2. Close all other popups and display popup for clicked store
createPopUp(clickedListing);
});
}
// Add an event listener for when a user clicks on the map
map.on('click', function (e) {
// Query all the rendered points in the view
var features = map.queryRenderedFeatures(e.point, { layers: ['locations'] });
if (features.length) {
var clickedPoint = features[0];
// 1. Fly to the point
flyToStore(clickedPoint);
// 2. Close all other popups and display popup for clicked store
createPopUp(clickedPoint);
// Find the index of the store.features that corresponds to the clickedPoint that fired the event listener
var selectedFeature = clickedPoint.properties.address;
for (var i = 0; i < stores.features.length; i++) {
if (stores.features[i].properties.address === selectedFeature) {
selectedFeatureIndex = i;
}
}
// Select the correct list item using the found index
var listings = document.getElementById('mySelect').selectedIndex = selectedFeatureIndex ;
}
});

Remove Button is deleting all img tags and not the selected one

This is my image uploader:
My Code for adding an image which works perfect:
jQuery(function($){
// Set all variables to be used in scope
var frame, selections, attachment,
metaBox = $('#gallery-meta-box.postbox'), // Your meta box id here
addImgLink = metaBox.find('.upload-custom-img'),
delImgLink = metaBox.find('.delete-custom-img'),
imgContainer = metaBox.find('.custom-img-container'),
imgIdInput = metaBox.find('.custom-img-id' );
// Add image from frame
addImgLink.on( 'click', function( event ){
event.preventDefault();
// If the media frame already exists, reopen it
if ( frame ) {
frame.open();
return;
}
// Create a new media frame
frame = wp.media({
title: 'Select Images',
button: {
text: 'Add Image'
},
multiple: true
});
// When an image is selected in the media frame
frame.on( 'select', function() {
// Get media attachments details from the frame state
selections = frame.state().get('selection');
selections.map(function(attachment){
attachment = attachment.toJSON();
// Send the attachment URL to our custom image input field
imgContainer.append(
'<li>'
+ '<img data-attachment-id="id-media-1993'+attachment.id+'" src="'+attachment.url+'" class="gallery-thumbnail" alt="'+attachment.title+'" style="max-width:150px; max-height:150px;"/>'
+ '<a class="delete-custom-img" href="#">Remove Image</a>'
+ '</li>');
// Send the attachment id to our hidden input
imgIdInput.val(attachment.id);
console.log(attachment);
});
});
// Finally, open the modal on click
frame.open();
});
// MY DELETE BUTTON :
imgContainer.on( 'click', delImgLink, function(event){
event.preventDefault();
var galleryThumbnail = $(this).find('img');
console.log(galleryThumbnail);
});
});
When you do watch the image uploader you can see the remove links. When I click on the remove and it doesn't matter which one of the remove button it's giving my the id's of both and same for the src.
see result:
When I click on the remove link, I want information about the current image, not all the images inside my div element.
Hopefully someone can explain it.
The issue is that, while you are using event delegation to handle dynamic elements, the delegation is pre-determined, so does not pick up the elements correctly
delImgLink = metaBox.find('.delete-custom-img'),
Change
imgContainer.on( 'click', delImgLink, ...
to
imgContainer.on('click', 'a.delete-custom-img',
then this will be the button and you can find the relevant image either with .closest().find() or .prevAll("img").first() (or other method):
imgContainer.on('click', 'a.delete-custom-img', function(event){
event.preventDefault();
var galleryThumbnail = $(this).closest("li").find('img');
console.log(galleryThumbnail);
});
In your original code, if this was the delete button then
$(this).find('img')
would not find anything as find find child items and there are no child items under your delete anchor, so this must be referring to something else, higher up.
You need jquery closet() to find nearest img and then delete it.
Or you can do it by
$(this).parent().find('img');
To achieve expected reult, use below option of adding event to imageContainer images and $(this) will provide the details of selected image
$(".imgContainer img").on( 'click', function(event){
event.preventDefault();
var galleryThumbnail = $(this);
console.log(galleryThumbnail[0].id);
});
https://codepen.io/nagasai/pen/VQJoZj

Link add-on SDK panel to toolbar button

The add-on SDK attaches panels to widgets as seen here. I would like to achieve the same effect using the add-on SDK with a toolbar button instead.
The toolbar button I'm using is of the type menu-button, which means that the left side is an icon and has an oncommand listener. The right side is a drop-down arrow which shows its contents on click. Here's the code to create such a button with the add-on SDK:
const doc = require('sdk/window/utils').getMostRecentBrowserWindow().document;
var navBar = doc.getElementById('nav-bar')
var btn = doc.createElement('toolbarbutton');
btn.setAttribute('id', 'hylytit');
btn.setAttribute('type', 'menu-button');
btn.setAttribute('class', 'toolbarbutton-1');
btn.setAttribute('image', data.url('resources/hylyt_off.png'));
btn.setAttribute('orient', 'horizontal');
btn.setAttribute('label', 'Hylyt.it');
btn.addEventListener('command', function(event) {
if (event.button===0) btnClick();
console.log(TAG+'button clicked');
}, false);
var panel = doc.createElement('panel');
panel.setAttribute('id', 'search-panel');
panel.addEventListener('command', function(event) {
console.log(TAG+'dropdown clicked');
}, false);
var label = doc.createElement('label');
label.setAttribute('control', 'name');
label.setAttribute('value', 'Article List');
var textbox = doc.createElement('textbox');
textbox.setAttribute('id', 'name');
panel.appendChild(label);
panel.appendChild(textbox);
btn.appendChild(panel);
navBar.appendChild(btn);
The panel above is not an add-on SDK panel, it's a XUL panel and is severely limited in that it can't be styled with CSS. On top of this, the panel's onCommand listener never fires despite the fact that the btn's onCommand fires as expected. The XUL panel shows itself when I click the dropdown button (as long as it has children), but because I can't access its click handler, I can't just create an add-on SDK panel on click.
So my question is this. Is there a way to access the toolbar button's menu portion's click handler or is there a way to append an add-on SDK panel as a child of a toolbar button?
Thanks for pointing me in the direction of arrow panels. Is there a way to place an HTML file in one rather than having to dynamically create XUL elements? The effect I'm trying to achieve is similar to the Pocket extension, which does one thing when the button part is clicked and another when the arrow is clicked. – willlma 7 hours ago
You have 900+ rep, you should know better. It is common knowledge to create another question topic rather then ask how to do something different in a comment especially after solution acceptance.
Nonetheless, this is what you do to accomplish the Pocket toolbarbutton effect. Based on code supplied by contributor above.
Ask another question and I'll move this there and you can accept my solution there.
var doc = document;
var navBar = doc.getElementById('nav-bar')
var btn = doc.createElement('toolbarbutton');
btn.setAttribute('id', 'hylytit');
btn.setAttribute('type', 'menu-button');
btn.setAttribute('class', 'toolbarbutton-1');
btn.setAttribute('image', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAYAAADtc08vAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDowMjgwMTE3NDA3MjA2ODExODcxRjlGMzUzNEZGQkNGQiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxRUM5MTQ0MkJFNkUxMUUxOUM3NzgwMzc3MDc2Rjk1MCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxRUM5MTQ0MUJFNkUxMUUxOUM3NzgwMzc3MDc2Rjk1MCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgTWFjaW50b3NoIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MDI4MDExNzQwNzIwNjgxMTg3MUZFQTk0QUU4RTMwMEYiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDI4MDExNzQwNzIwNjgxMTg3MUY5RjM1MzRGRkJDRkIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5kJv/fAAAByUlEQVR42qRTPWvCYBC+mKiolFYURVSwfoCLkw4iGDM5WoO460/o4tKuHToV+gd0t5Ku4mQWJ8Fd/NhEpy6K3+ldakKsi+ALb3hzd89zd8+9L6MoCtyyOPpkMpl3m81WM5lMV4GOxyOsVqu3Xq/3qhIEg8Ga1+sFs9l8FcFut4P5fP6Cxz8CAvt8PmBZ9iqCw+Ggn9WaKTOB9/s9FAoF4Hn+LIjOZCMfxVGrWrWcFkRiWiwWiMfjIv6GOI77kGUZ1us15PN5SKVSz2ifttvtL2yBPRNRI1gsFiCK4pMkSVUE/GBrn5vN5i4ajVYxpFEsFuuRSIR1u91wQcAwDOAkwOl0VjBjCIFit9sdoOshl8sNsLp6IBCoOBwOME5LJSABqU8i8Pv91Kcwm83kdDrNk9/lcslYTYLi7HY7aBidIJvNTjqdziNpQBmIBDVIoFDT05TuPR6PCqbs2+0WBEGYqJWfbmKx2WxKo9FIDSAbtgDL5VLNQqRWq1Vtky4R6gDlcpnE/mYMV7nearUqw+FQJzEuDRyLxaBUKjXQVDVWoJNgFZV+vw/j8VgXi4DhcBiSySRl18H6+P5tAbekXC7p5DuLZ259jb8CDAAxmdyX9iaHkQAAAABJRU5ErkJggg==');
btn.setAttribute('orient', 'horizontal');
btn.setAttribute('label', 'Hylyt.it');
////
var toolbarbuttonPanel = doc.createElement('panel');
toolbarbuttonPanel.setAttribute('id', 'toolbarbutton-panel');
toolbarbuttonPanel.setAttribute('type', 'arrow');
var toolbarbuttonLabel = doc.createElement('label');
toolbarbuttonLabel.setAttribute('value', 'toolbarbutton panel');
toolbarbuttonPanel.appendChild(toolbarbuttonLabel);
////
////
var dropmarkerPanel = doc.createElement('panel');
dropmarkerPanel.setAttribute('id', 'dropmarker-panel');
dropmarkerPanel.setAttribute('type', 'arrow');
var dropmarkerLabel = doc.createElement('label');
dropmarkerLabel.setAttribute('value', 'dropmarker panel');
dropmarkerPanel.appendChild(dropmarkerLabel);
////
navBar.appendChild(btn);
var mainPopupSet = document.querySelector('#mainPopupSet');
mainPopupSet.appendChild(dropmarkerPanel);
mainPopupSet.appendChild(toolbarbuttonPanel);
btn.addEventListener('click',function(event) {
console.log('event.originalTarget',event.originalTarget);
if (event.originalTarget.nodeName == 'toolbarbutton') {
dropmarkerPanel.openPopup(btn);
} else if (event.originalTarget.nodeName == 'xul:toolbarbutton') {
toolbarbuttonPanel.openPopup(btn);
}
}, false);
Panels don't have an onCommand method see MDN - Panels Article
You can make your panel stylized, give it type arrow like panel.setAttribute('type', 'arrow') and then to attach to your button. I didn't give it type arrow below.
Heres the working code. Copy paste to scratchpad and set Environment > Browser then run it.
var doc = document; //to put this back in sdk do const doc = require('sdk/window/utils').getMostRecentBrowserWindow().document;
var navBar = doc.getElementById('nav-bar')
var btn = doc.createElement('toolbarbutton');
btn.setAttribute('id', 'hylytit');
btn.setAttribute('type', 'menu-button');
btn.setAttribute('class', 'toolbarbutton-1');
btn.setAttribute('image', ''); //i made this image blank because i dont have the image and im running from scratchpad
btn.setAttribute('orient', 'horizontal');
btn.setAttribute('label', 'Hylyt.it');
var panel = doc.createElement('panel');
btn.addEventListener('command', function(event) { //moved this below var panel = doc.createElement because panel needs to be crated before we write this function
//if (event.button===0) btnClick();
//console.log(TAG+'button clicked'); //what is TAG? its undefeined for me
panel.openPopup(btn);
}, false);
panel.setAttribute('id', 'search-panel');
/*
panel.addEventListener('command', function(event) {
console.log(TAG+'dropdown clicked'); //what is TAG? its undefeined for me
}, false);
*/
var label = doc.createElement('label');
label.setAttribute('control', 'name');
label.setAttribute('value', 'Article List');
var textbox = doc.createElement('textbox');
textbox.setAttribute('id', 'name');
panel.appendChild(label);
panel.appendChild(textbox);
btn.appendChild(panel);
navBar.appendChild(btn);
You can create a Toolbarbutton and Panel using the Addon SDK and some Jetpack modules. Try toolbarwidget-jplib and browser-action-jplib by Rob--W.
You can easy add a button to the toolbar and style the panel whatever you want with css / html:
var badge = require('browserAction').BrowserAction({
default_icon: 'images/icon19.png', // optional
default_title: 'Badge title', // optional; shown in tooltip
default_popup: 'popup.html' // optional
});

Jquery - Initialize Select Box after first use

Page is loaded with a hidden select box in it.
I click on a button
I append elements to this select box, I move it and I make it visible
I apply plugin Chosen on it
This is done by this function
function moveHiddenSelect(idOffline, type, idMedia, mediaName){
var $selToReplace = $("#"+type+"_"+idOffline);
var $selOriginal = $("#originalSelect");
$selToReplace.replaceWith($selOriginal);
$.getScript('/lib/chosen/chosen.jquery.min.js', function(){
$selOriginal.chosen(); //load plugin script and apply it on the select box
});
$selOriginal.css("width", "220px");
$selOriginal.css("visibility", "visible");
}
No problem when I click the button one time, but when I click again on the button (step 2) nothing is happend..
The chosen() should be called once, just for creation.
After updating the values of each dropdown, you could use: $(DropdoenElement).trigger("liszt:updated");
function moveHiddenSelect(idOffline, type, idMedia, mediaName){
var $selToReplace = $("#"+type+"_"+idOffline);
var $selOriginal = $("#originalSelect");
$selToReplace.replaceWith($selOriginal);
selOriginal.chosen(); // Init the plugin
$.getScript('/lib/chosen/chosen.jquery.min.js', function(){
//load plugin script and apply it on the select box
selOriginal.trigger("liszt:updated")
});
$selOriginal.css("width", "220px");
$selOriginal.css("visibility", "visible");
}
Hope it helps!

Categories

Resources