Select2 not displayed when added dynamically for the first time - javascript

I am working with Jquery and I have a use case to add some elements dynamically on a button click.
While adding the 'select' dynamically, the select2 is not displayed when the add button is clicked for the first time, instead, a simple 'select' is displayed, and when we click on add button again, all the previous 'select' get formatted to select2.
I needed that when we click the add button, the first generated selects should also get the select2.
Following is the script:
var container = $(document.createElement('div')).css({
padding: '5px', margin: '20px', width: '400px', border: '1px solid',
borderTopColor: '#999', float: 'left', borderBottomColor: '#999',
borderLeftColor: '#999', borderRightColor: '#999'
});
var iCnt = 0;
function add()
{
if (iCnt <= 19) {
iCnt = iCnt + 1;
$(container).append($("<select class ='selinput' id=tb" + iCnt + " " + "value='Text Element " + iCnt + "' style='float : left; margin-right:70px;'>"));
//Add Property Selector
$(container).append(" ");
$(container).append($("<select class ='selinput2" + iCnt + "'' id=tb2" + iCnt + " " + "value='Text Element " + iCnt + " ' ><option value='equalto'>A</option><option value='notequalto'>B</option></select>"));
$(container).append(" ");
// ADD TEXTBOX.
$('select').select2({width : '20%'});
$(container).append('<input type=text class="input" id=tbtext' + iCnt + ' ' +
'placeholder="Value ' + iCnt + '" style="float : center;" /><br><br>');
// SHOW SUBMIT BUTTON IF ATLEAST "1" ELEMENT HAS BEEN CREATED.
if (iCnt == 1) {
var divSubmit = $(document.createElement('div'));
$(divSubmit).append('<input type=button class="bt"' +
'onclick="GetTextValue()"' +
'id=btSubmit value=Submit />');
}
// ADD BOTH THE DIV ELEMENTS TO THE "main" CONTAINER.
$('#main').after(container, divSubmit);
}
// AFTER REACHING THE SPECIFIED LIMIT, DISABLE THE "ADD" BUTTON.
// (20 IS THE LIMIT WE HAVE SET)
else {
$(container).append('<label>Reached the limit</label>');
$('#btAdd').attr('class', 'bt-disable');
$('#btAdd').attr('disabled', 'disabled');
}
}
Following is the link to js fiddle:
https://jsfiddle.net/hns0qk2b/43/
Please advise.

Your only problem is that you need your new elements added to the DOM before you can initialize select2. Add the elements to the DOM first, then your code will work.
// ADD BOTH THE DIV ELEMENTS TO THE "main" CONTAINER.
$('#main').after(container, divSubmit);
// Initialize select2
$('select').select2({width : '20%'});
See these changes applied to the fiddle:
https://jsfiddle.net/zjafvr3u/1/

Related

How to dynamically style data from a JSON input via div.innerHTML?

I'm currently using JS to fetch data from a JSON file and loop through it to display on the site, appending to a div in the html file i.e.
<div id = "groceries"></div>
JS code (skipping fetch code which works fine):
function appendData (data) {
const mainContainer = document.getElementById ('groceries');
for (let i = 0; i < data.length; i++) {
const div = document.createElement ('div');
div.innerHTML = '<b>' + data[i].item + '</b> x' + data[i].quantity + ' ' + data[i].calories + '<b> - ' + data[i].rating + '<br><br>';
mainContainer.appendChild (div);
}
}
The 'rating' data needs to be styled depending on what the rating is, i.e. green for 'Low', amber for 'Medium', red for 'High'...based on what's in the JSON file.
I'm not sure how to do this with pure JS / html / css however? I've tried searching around but it's surprisingly difficult to find a suitable answer.
Add a class based on the rating value. Aka
function appendData(data) {
const mainContainer = document.getElementById ('groceries');
for (let i = 0; i < data.length; i++) {
const div = document.createElement ('div');
div.classList.add('rating', 'rating--' + (data.rating < 3 ? 'low' : data.rating > 6 ? 'high' : 'med'));
div.innerHTML = '<b>' + data[i].item + '</b> x' + data[i].quantity + ' ' + data[i].calories + '<b> - ' + data[i].rating + '<br><br>';
mainContainer.appendChild (div);
}
}
Then in CSS you can simply do
.rating {
// Generic styling
}
.rating.rating--low {
color: #FF0000;
// Unique Styles
}
.rating.rating--med {
color: #FFFF00;
// Unique Styles
}
.rating.rating--high {
color: #00FF00;
// Unique Styles
}
I don't know if I get it right, but you can use simple if statement with prebuilded HTML DOM style object.
if(data[i].quantity > average){
div.style.color = "red"
}else if(data[i].quantity < average){
div.style.color = "green"
}
Hope I have helped.
Inside for loop, make a condition check to add a preferred text color,
If (data[i].rating === "High")
{div.style.color = "red"}
// and so on other conditions checked.
If (???) {...}
This example will make all text in div to be red.
If only rating portion to be color, maybe create p and multiple span(s). Then style each of them as preferred. ie.
<p style?><span style?><span style?><span style?>

Add a Class to some items depending on inner html

I'm working on a leaflet js map atm.
There are some items that I want to apply a class to, depending on their inner text. Seems as though two circles at a certain size just overlap. Adding some CSS in that case so they're no longer overlapping.
//function searches for all <text> elements within svg tags for the queryText
// and then appends them with the appendText
function addClasserino() {
let elements = document.querySelectorAll('map-marker marker-bg-condition'); // get all circle elements as a NodeList
elements.forEach(el => { // go through each text element
if (el.innerText < 10) { // if the innerHTML matches the query HTML then
elements.addClass('updated'); // add the class
}
})
}
document.addEventListener("DOMContentLoaded", function(){
//pass in the search text and the appending text as arguments
addClasserino();
});
This is what I got so far. Doesn't seem to be working.
.map-marker.marker-bg-condition needs to be moved across a bit. Got the CSS here:
.map-marker.marker-bg-condition.updated{
margin-top: -19px;
margin-left: -19px;
}
With Leaflet JS, the zoom level changes and items are updated accordingly. This of my map showing all details at the world view, and then breaking down to state as you zoom in.
The unexpected behavior is that the css isn't applying and where bubbles are overlapping is because of this. This is the original code but I can't change it and get it to work even with an if statement.
getMarkerHtml: function(count, color) {
var size = this.getMarkerSize(count);
var hsize = (size / 2) - 6;
var font = count < 1000 ? Math.ceil(size / 3) : Math.ceil(size / 4);
if(count < 100) {
font = font + 3;
}
var cluster_classes = [
'map-marker',
'marker-bg-' + (Filters.colors.profile === color ? 'profile' : 'condition')
];
if(this.zoomLevel !== 'zip') {
size = size * 1.5;
if(petMapFilters.colors.profile !== color) {
hsize = size / 2;
}
}
if(this.zoomLevel === 'zip') {
var cluster_styles = [
'margin-left: -' + hsize + 80 + 'px;', NOTE: I tried this to offset on zip zoom bit it's not working END OF NOTE
'margin-top: -' + hsize + 80 +'px;',
'width: ' + size + 'px;',
'height: ' + size + 'px;',
'font-size: ' + font + 'px;'
];
} else {
var cluster_styles = [
'margin-left: -' + hsize + 'px;',
'margin-top: -' + hsize + 'px;',
'width: ' + size + 'px;',
'height: ' + size + 'px;',
'font-size: ' + font + 'px;'
];};
var div_style = [
'line-height: ' + (size - (size * 0.3)) + 'px;'
];
count = this.formatCount(count);
return '<div class="' + cluster_classes.join(' ') + '" tabindex="0" style="' + cluster_styles.join(' ') + '"><div style="' + div_style.join(' ') + '">' + count + '</div></div>';
},
Please let me know what I am doing wrong here as I am not able to identify this myself.
The issue at hand:
Thanks.

Change width/height depending on class with data-attribute

I have the following JS code that changes the width depending on value of the data-percentage HTML attribute:
var addRule = (function (sheet) {
if(!sheet) return;
return function (selector, styles) {
if (sheet.insertRule) return sheet.insertRule(selector + " {" + styles + "}", sheet.cssRules.length);
if (sheet.addRule) return sheet.addRule(selector, styles);
}
}(document.styleSheets[document.styleSheets.length - 1]));
var i = 101;
while (i--) {
addRule("[data-percentage='" + i + "%']", "width:" + i + "%");
}
See the demo: http://jsfiddle.net/YYF35/
Instead of width, for some elements I want to change their height.
How can I change the code so that depending on class of the div I change the height or width of element (depending on the data-percentage attribute number of course)?
I don’t want to create a different HTML attribute for it, like so:
while (i--) {
addRule("[data-percentage-width='" + i + "%']", "width:" + i + "%");
addRule("[data-percentage-height='" + i + "%']", "height:" + i + "%");
}
jQuery can be used as well. Any ideas?
Your code is adding rules. If you really want to be doing that, just add more rules:
var i = 101;
while (i--) {
addRule("[data-percentage='" + i + "%'].change-width", "width:" + i + "%");
addRule("[data-percentage='" + i + "%'].change-height", "height:" + i + "%");
}
Now, elements with the change-width class will have their width modified, and elements with the change-height class will have their height modified (and you can use both if you like).
Try this:
$("div[data-percentage]").each(function(){
$(this).css({
width: $(this).attr('data-percentage')
//height: $(this).attr('data-percentage')
});
});
http://jsfiddle.net/YYF35/1/

Using variable to add and remove a form input field with jQuery

I am trying to add a hidden input field to a form when a span with class="checkbox" is clicked, and remove that same field when span with checkmark is clicked.
I am able to add the input, but I cannot remove it.
My HTML:
<span title="Here's My Title" class="wishlistcheck checkbox">1</span>
<form id="wishlistform"></form>
My Javascript:
$(document).ready(function() {
var appNum = 0;
$("span.wishlistcheck").click(function() {
var el = $(this);
var appName = el.attr("title");
var isChecked = el.hasClass('checkmark');
if(!isChecked) {
el.removeClass('checkbox');
el.addClass('checkmark');
appNum++
$("#wishlistform").append("<input id=\"" + appName + "\" type=\"hidden\" name=\"product_" + appNum + "\" value=\"" + appName + "\">");
} else {
el.removeClass('checkmark');
el.addClass('checkbox');
appNum--
$("input#" + appName).remove();
}
});
});
I guess you have to put the appNum-- after the .remove() method calling. Try it:
$(document).ready(function() {
var appNum = 0;
$("span.wishlistcheck").click(function() {
var el = $(this);
var appName = el.attr("title");
var isChecked = el.hasClass('checkmark');
if(!isChecked) {
el.removeClass('checkbox');
el.addClass('checkmark');
appNum++
$("#wishlistform").append("<input class=\"" + appName + "\" type=\"hidden\" name=\"product_" + appNum + "\" value=\"" + appName + "\">");
} else {
el.removeClass('checkmark');
el.addClass('checkbox');
appNum--
$("input[class=" + appName + "]").remove();
}
});
});
You probably have multiple DOM elements by that id tag, and so it may be removing an element matching that id but not the right one.
Try giving it a class name instead and getting more specific in your jQuery parameters by adding parent elements, i.e.
$('#wishlistform input#' + appName).remove();

JQuery: get a child as you append it

I am appending p tags to a div as I process a json request and would liek to style it according to what is in the request.
$(document).ready(function() {
function populatePage() {
var numberOfEntries = 0;
var total = 0;
var retrieveVal = "http://www.reddit.com/" + $("#addressBox").val() + ".json";
$("#redditbox").children().remove();
$.getJSON(retrieveVal, function (json) {
$.each(json.data.children, function () {
title = this.data.title;
url = this.data.url;
ups = this.data.ups;
downs = this.data.downs;
total += (ups - downs);
numberOfEntries += 1;
$("#redditbox").append("<p>" + ups + ":" + downs + " " + title + "<p>");
$("#redditbox :last-child").css('font-size', ups%20); //This is the line in question
});
$("#titlebox h1").append(total/numberOfEntries);
});
}
populatePage()
$(".button").click(function() {
populatePage();
});
});
Unfortunately things are not quite working out as planned. The styling at the line in question is applying to every child of the div, not just the one that happens to be appended at the time, so they all end up the same size, not sized dependent on their numbers.
how can I apply a style to the p tags as they are appended ot the div?
Edit: Thanks Fortes and Veggerby both worked, but i went with Fortes in the end because I did.
You can use JQuery's appendTo instead of append. For your example:
$("<p>" + ups + ":" + downs + " " + title + "<p>")
.css('font-size', ups%20)
.appendTo('#redditbox');
Here are the docs for appendTo: http://docs.jquery.com/Manipulation/appendTo
Replace:
$("#redditbox").append("<p>" + ups + ":" + downs + " " + title + "<p>");
with
var p = $("<p>" + ups + ":" + downs + " " + title + "<p>");
$("p", p).css('font-size', ups%20)
$("#redditbox").append(p);
Can probably be condensed even further.
Edit:
Condensed like:
$("#redditbox").append(
$("<p></p>").css('font-size', ups%20).append(ups + ":" + downs + " " + title + "")
);
Certain browsers/versions do not support the :last-child CSS selector. In that case they often ignore it and return all elements matching the remainder of the selector. This is possibly what you are seeing.
As usual IE is one such browser.
veggerby's approach should help you get around the need to use :last-child.

Categories

Resources