I am fairly new to JS, and have created a little piece of script and it does exactly what I want which is find some elements then adds elements with data populated from via ajax....
So I go from this...
<select><select/>
to this...
<select>
<option value="{ajax value data}"> {ajax text data} <option/>
...
<select/>
using this piece of script...
filteredSelectIds.forEach(function (item) {
let itemId = '#' + item;
let itemData = item.split('-')[0] + 's';
$.each(data[itemData], function (i, color) {
$(itemId).append($('<option/>', {
value: color.optionValue,
text : color.optionText
}));
});
});
Now, what I am trying to do is at the same time add a Font Awesome icon to each element so I need to end up with something like this,,,,
<select>
<option value="{ajax value data}"><i class="fa fa-icon"> {ajax text data} <i/><option/>
...
<select/>
How would I do that??
I'm also new at JS, try this.
element = '<i class="fa fa-icon"> {0} <i/>'.format("{ajax text data}")
$('<option/>').append( element );
So #brk gave me this solution which worked, and would work for putting an Element inside another
"Create the option tag & i tag & first append itag to option tag and then append option tag to item"
filteredSelectIds.forEach(function (item) {
let itemId = '#' + item;
let itemData = item.split('-')[0] + 's';
$.each(data[itemData], function (i, color) {
var selOption = $('<option value="' + color.optionValue + '"></option>');
selOption.append('<i class="fa fa-icon">'+color.optionText+'<i/>');
$(itemId).append(selOption); }); });
However, although this placed the element inside the element as I wanted, and this could principle could probably be used to place any element within another, Tibrogargan correctly pointed to a question that makes the point that elements cannot be place within elements (Not really the Point of my question, but helpful). My solution was simply using the unicode for the Font Awesome icon and escaping it with \u then used \xa0 for additional spaces as follows:-
filteredSelectIds.forEach(function (item) {
let itemId = '#' + item;
let itemData = item.split('-')[0] + 's';
$.each(data[itemData], function (i, color) {
$(itemId).append($('<option/>', {
value: color.optionValue,
text : '\ue905 \xa0\xa0\xa0' +color.optionText
}));
});
});
Thanks!
Related
EDIT: This is a more sound approach, since provided answer may have bugs when implementing a tags, or img tags.
================================================================
I am calling blog data from an API. (I've reformatted the data into an array by month).
So far, the blog titles print to the web page. I'd like a user to be able to click a title and have its description revealed.
Here is some of my code so far:
var blogPosts = $('#blog-posts');
$.each(byMonth, function(key, value) {
var outer = byMonth[key]
$.each(outer, function(k, v) {
var inner = outer[k]
var monthBlogPosts = $('<div class = "month"> </div>').appendTo(blogPosts);
$.each(inner, function(i, obj) {
title = inner[i].Title
description = inner[i].Description
date = inner[i].DatePublished
$('<div class = "title-list"><h3 class = "unique-title">' + title + '</h3></div>').appendTo(monthBlogPosts)
// if a title is clicked, show its Description
showDescription(description);
})
})
});
function showDescription(d){
$('.unique-title').on('click', function(){
$('<p>' + d + '</p>').appendTo('body')
console.log(d)
})
}
When I click a title, all descriptions print instead of the matching description. I understand this is because I called the function in a nested loop, but I've also had trouble calling the description variable outside of it.
I have also tried
showDescription(title, description)
//...
function showDescription(t, d){
$(title).on('click', function(){
$('<p>' + d + '</p>').appendTo('body')
console.log(d)
})
}
but then nothing is printed to the html page.
Essentially, I'd like to grab the title index, and print it's respective description when its clicked.
you should use event delegation to attach a click event to the document that will bubble up and trigger when .title-list is the event target.
$(document).on('click', '.title-list', function(event) {
showDescription(event.currentTarget) // pass the element being clicked (we will need it later)
})
you would also need to modify the way you get the description.
you could store you description in a data attribute of .title-list like so:
$('<div class = "title-list" data-description="'+ description +'"><h3 class = "unique-title">' + title + '</h3></div>').appendTo(monthBlogPosts)
so you can now modify showDescription() so it would get the data from the element we pass to the function
function showDescription(element){
var d = $(element).data('description')
$('<p>' + d + '</p>').appendTo('body')
console.log(d)
})
So ok. From whatever I could understand (by looking at your code). You cannot register an event with simple on for dynamically added element. You have to use on delegate.
Try this
1) remove the function call (inside a loop)
2) delete the entire function showDescription and add event as below:
$('#blog-posts').on('click', '.unique-title',function(){
alert('title clicked').
});
3) As to display the description I think the best way will be to add the description in a div and hide it. Display it later once the title is clicked.
(inside the loop)
$('<div class = "desc" style="display:none">' + description + '</div>').appendTo(monthBlogPosts);
then on #2 above. Replace with this.
$('#blog-posts').on('click', '.unique-title',function(){
$(this).next('.desc').show(); //I am assuming desc will be next to the clicked title here. You can modify it as needed.
});
Finally, this is just an overview of a code so might not work as expected but I am pretty sure this should give you an idea and get you started
I have a text input and on focusout, I have couple of select elements which I want to fill with the text field's value.
And I have bunch of select tags with 'NameSelect' class
$('.textField').focusout(function() {
var name = $(this).val();
var NameOption = $('<option>', { value: name, text: name, attrid: '1'});
var selects = $('#mainForm').find('.NameSelect');
$(selects).each(function(i, obj) {
console.log($(obj)); // it seems to get the right select
$(obj).append(NameOption);
})
}
However, when I do that, even though the selects get all the right elements and for loop for the right count, it only appends the option input to the latest object, not all of them.
What am I missing here?
The issue is because NameOption holds a reference to the option, hence if you append() it multiple times it will move between each parent element.
To fix this you can either clone() the element when you append it:
selects.append(NameOption.clone());
Or you could just provide append() with a string to create a new element each time it's called:
$('.textField').focusout(function() {
var name = $(this).val();
$('#mainForm').find('.NameSelect').append('<option value="' + name + '" attrid="1">' + name + '</option>');
})
});
Note that in both cases the each() is not required.
I am trying to show on mouse hover event data using jquery tool tip. have data like this way:
{"description":"marry christmas","date":"2016-12-25"}` that I got from server as JSON string. I am parsing that on my calendar like this way
holi is a variable name that holds above JSON string
this is my import
<link href = "https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css" rel = "stylesheet">
<script src = "https://code.jquery.com/jquery-1.10.2.js"></script>
<script src = "https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
$.each(JSON.parse(holi), function(i, item) {
var holidayDate=item.date+"";
var parts= holidayDate.split("-");
alert("parts:"+parts[2]);
document.getElementById(parts[2]+parts[1]).style.color="green";
var va= document.getElementById(parts[2]+parts[1]).innerHTML;
document.getElementById(parts[2]+parts[1]).innerHTML="<label id="+parts[2]+parts[1]+" title="+
item.description+">"+va+"</label>";
$("#"+parts[2]+parts[1]).tooltip();
});
}
Now when I hover on 25th December it is just showing me marry instead of "marry christamas" I tried this in chrome. please let me what's wrong in this??
You need to add quotes around the title attribute value. Try this:
document.getElementById(parts[2]+parts[1]).innerHTML
="<label id="+parts[2]+parts[1]+" title='"+item.description+"'>"+va+"</label>";
Notice the single quotes after the = and before the > around your item.description variable.
Also, as others have pointed out, avoid writing out the DOM from javascript. It is error prone and hard to maintain.
When constructing the title HTML, you need to take into account how the HTML will be parsed. If your title message has spaces, then the HTML attribute value has to be quoted.
You could clean up your code a lot by leveraging the jQuery APIs, since you're already using the library:
$.each(JSON.parse(holi), function(i, item) {
var holidayDate = item.date + "";
var parts = holidayDate.split("-");
var dayId = parts[2] + parts[1], day = $("#" + dayId);
day.css("color", "green")
.html($("<label/>", {
title: item.description,
html: day.html()
}))
.find("label").tooltip();
});
With jQuery, you can construct new HTML with less ugly quote-wrangling by using the form
$("<tagname/>" {
attribute: value,
attribute: value,
// ...
})
In this case, the code sets the "title" attribute and then the content; the "html" attribute works like the jQuery .html() method.
After that, it finds the just-added <label> element and invokes the .tooltip() method.
I am building html on the fly need to add data before I add it to DOM. Since I am looping thru' lot of information, I would like to add the relevant data info along with the dom I am building instead of adding the html and then looping thru again to add the data.
result.forEach(function(record) {
html += '<div id ="' record.ID + '">test content </div> ';
//add data to above
});
I can do another loop here after adding it to DOM
$(body).append(html);
testresult.forEach(function(record) {
$("#" +record.ID).data(record);
});
Instead of concatenating strings to piece together your HTML, you may way to try something like this:
result.forEach(function(record) {
$('.selector').append(function () {
var $div = $('<div></div>');
$div.attr('id', record.testID).text('some text');
return $div;
});
});
This creates a new div jquery object for each item in result. You can use the record object to add attributes, data, text, etc to you object. It will be added the DOM when the callback passed into .append returns your new jquery DOM object.
Start trying to use jQuery to create your html elements so you can take fully advantage of jQuery and its plugins.
Ex:
var div = $("<div></div>") // create the element
.text("test content") // change the inner text
.attr("id", record.testID); // set the element id
div.appendTo("body");
You can check out [http://www.w3schools.com/jquery/] as a great source for learning jQuery.
You have quotes problem in the following line :
html += '<div id =record.testID' + '>test content </div> ';
________^______________________^___^_____________________^
You should fix that using double quotes because as it's now the string will be considered as '<div id =record.testID'.
html += '<div id="'+record.testID+'">test content </div>';
Or you could use separated definition :
$.each(result, function(index,record) {
var div = $('<div>test content</div>');
div.attr('id', record.testID);
div.data('test', record.testDATA);
$('body').append(div);
})
Hope this helps.
var result = [{testID: 1,testDATA: 'data 1'},{testID: 2,testDATA: 'data 2'},{testID: 3,testDATA: 'data 3'}]
var html='';
$.each(result, function(index,record) {
var div = $('<div>test content</div>');
div.attr('id', record.testID);
div.data('test', record.testDATA);
console.log(div.data('test'));
$('body').append(div);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
How can I locate the tag which calls a JQuery script, when
the tag is dynamically loaded, so won't be the last
tag on the page?
I'm using the MagicSuggest autosuggest library. I want to give certain suggested items a different background color depending on their contents, which I'm currently doing by adding JQuery inside a tag, which I'm adding on to the String which is returned to be rendered inside the selection div. Then, to get the div the item is suggested in, I need to essentially get the parent() of the tag, and change it's css() properties. How can I get this current script tag however?
I'm currently assigned each new tag an id generated from incrementing a JS variable - which works, but isn't very 'nice'! Is there anyway I can directly target the tag with JQuery?
If it perhaps makes it clearer, here is my current selectionRenderer function.
selectionRenderer: function(a){
var toRet = a.english;
var blueBgScript = "<script id=ft" + freeTextFieldID + ">$('#ft" + freeTextFieldID + "').parent().css('background', 'blue');</script>"
if(a.id==a.english){
toRet += blueBgScript;
freeTextFieldID++;
}
return toRet;
},
Why don't you add some code at afterrender event instead? Add some tag to flag the options that need a different background, then detect the parents and add a class (or edit the bg property) or whatever you like:
var newMS = $('#idStr').magicSuggest({
data: 'states.php',
displayField: 'english',
valueField: 'id',
selectionRenderer: function(a){
var toRet = a.english;
if(a.id==a.english) toRet = "<span class='freetext'>" + toRet + "</span>";
return toRet;
},
});
$(newMS).on('selectionchange', function(event,combo,selection){
var selDivs = $(event.target._valueContainer[0].parentNode).children('div'); //Get all the divs in the selction
$.each(selDivs,function(index,value){ //For each selected item
var span = $(value).children('.freetext'); //It if contains a span of class freetext
if(span.length == 1) $(value).css('background','blue'); //Turn the background blue
});