jQuery dynamically add content to div - javascript

What I'm trying to do is add for each items in a xml file their content to a html page. I'm trying to make it so that every item content is inside an <article> tag. However, It's my first time using jQuery and my end result is not what I want.
let $items = $(xmlContent).find("item");
$items.each(function() {
let title = $(this).find('title').text();
let date = $(this).find('pubDate').text();
let link = $(this).find('link').text();
let guid = $(this).find('guid').text();
let photo = $(this).find('media').html();
$("#world").append("<article></article>", [$("<a>", {
href: link
}) + ("<h3>" + title + "</h3>")]);
This is what the end result currently is:
<article></article>
[object Object]
<h3>Students Fainting From Hunger in Venezuela’s Failing School System</h3>
And what I want it to become:
<article> <a href= myLink <h3>Students Fainting From Hunger in Venezuela’s Failing School System</h3> </a> </article>
I want to apply my link so that everywhere the user click on the content it goes to the link. Hopefully you can guide me. Thanks!

You can build your article element step by step.
Create 'article' as an element, then create your 'a' element. Append the 'h3' element to the 'a' element before appending 'a' to 'article', and then 'article' to '#world'.
let article = $("<article></article>")
let a = $("<a></a>", {href: link})
a.append("<h3>" + title + "</h3>")
article.append(a)
$("#world").append(article)

You're not using append as described in the documentation -- see the type of arguments you can pass.
Maybe you intended this:
$("#world").append(
$("<article>").append(
$("<a>", { href: link }),
$("<h3>").text(title)
)
);

Related

How can I add the same XML tags multiple times, with different content?

I have some problems with my code. I want to create an XML Document with JQuery / JavaScript. I am now at the point, where I want to create a few Tags and populate them each with the same tags but different content inside the tags.
Here is the code for better understand
function setItems(xmlDoc, channelTag){
const itemList = [];
const itemTitle = xmlDoc.createElement("title");
const itemLink = xmlDoc.createElement("link");
const itemGuid = xmlDoc.createElement("guid");
const itemMediaContent = xmlDoc.createElement("media:content");
const itemMediaDescription = xmlDoc.createElement("media:description");
itemList.push(itemTitle, itemLink, itemGuid, itemMediaContent, itemMediaDescription);
for (var i = 0; i < jsonObj.length; i++){
var item = xmlDoc.createElement("item");
channelTag.appendChild(item);
//Populate the <item> with the tags from "itemList" and content from "jsonObj"
$.each(itemList, function(index) {
$(channelTag).children('item')[i].appendChild(itemList[index]).textContent = jsonObj[0].title;
})
}
}
The Output of the code looks like this:
<item></item>
<item></item>
<item>
<title>Something</title>
<guid>Something</guid>
<link>Something</link>
<media:content>Something</media:description>
<media:description>Something</media:description>
</item>
It always populates the last item-Tag but not the ones above. What I want is that every item-Tag has the same child-Tags (e.g. title, link, guid and so on). Is there something i am missing some unique tags or something like that?
Edited:
Here is some minimal HTML and XML. The values for the function "xmlDoc" and "channelTag" just contains some Document Elements, where my items should be appended, like so:
<rss>
<channel>
<title>SomeTitle</title>
<atom:link href="Link" rel="self" type="application/rss+xml"/>
<link>SomeLink</link>
<description>SomeDesc</description>
<item></item>
<item></item>
<item></item>
</channel>
</rss>
<div class="col-5 col-sm-5 col-lg-3 order-2 count">
<a class="guid1"><img class="card-img image1"></a>
</div>
<div class="col-7 col-sm-7 col-lg-5 order-2">
<div class="card-body">
<a class="guid1">
<h5 class="card-title title1 overflow-title"></h5>
</a>
<p class="card-text body1 text-body overflow-body"></p>
<div class="card-body subtitle">
</div>
</div>
</div>
There are several issues with your code but the area we mostly want to focus on is this:
for (var i = 0; i < jsonObj.length; i++){
var item = xmlDoc.createElement("item");
channelTag.appendChild(item); // you're adding a node here
$.each(itemList, function(index) {
$(channelTag).children('item')[i].appendChild(... // and here
})
}
Instead of appending nodes multiple times per iteration, you should create and populate your node before add it it to channelTag.
Here's a way your could do it:
// use a "$" sign as a variable name prefix, so you know it's a Document Element and not a regular javascript variable
var $item = xmlDoc.createElement("item");
// you don't need jQuery for this iteration
itemList.forEach(function (item, index) {
$item.appendChild(itemList[index]).textContent = jsonObj[0].title;
});
// if "channelTag" is a Document Element, rename it "$channelTag"
$channelTag.appendChild(item);
Couple things about the code above:
you don't need jQuery, use forEach instead
there is no way telling what type is channelTag. If it is a selector (of type string), use $(selector), but you are using the appendChild() method before, suggesting it's actually a Document Element. In that case you don't need to wrap it with $()
I don't have the context needed to test this code, so no guarantee it'll work out of the box. But try and re-read your code and go through it top-to-bottom. For each variable, describe its type and value. I found that to be helpful when I'm lost in code.

Getting and setting attributes with Kendo sortable on change event

Would just like to get and set different attributes when a list item is moved to the other list on my mvc page... I can't access anything so far. The problem is in the javascript, it hits the onchange event fine. I didnt post the "available list" in the cshtml for brevity. this is what the console.log as the bottom reads:
SpecialNeedInActiveList change: Meds per tube newIndex: -1 oldIndex: 5 action: remove
SpecialNeedActiveList change: Meds per tube newIndex: 3 oldIndex: -1 action: receive
Any help would be appreciated, this has taken way too long for me.
HTML:
<div class="col-md-6" id="SpecialNeedContainerLL">
<ul id="SpecialNeedActiveList" class="col-md-6">
#if (Model.SelectedSpecialNeeds.Any())
{
foreach (var y in Model.SelectedSpecialNeeds)
{
<li class="list-item" selected-personspecialneed="#y.PersonSpecialNeedId" selected-need-type="#y.SpecialNeedTypeId"> #y.SpecialNeedDescription </li>
}
}
</ul>
</div>
#(Html.Kendo().Sortable()
.For("#SpecialNeedActiveList")
.ConnectWith("#SpecialNeedInActiveList")
.PlaceholderHandler("placeholder")
.Events(events => events.Change("onChange"))
)
Javascript:
function onChange(e) {
var id = e.sender.element.attr("id"),
text = e.item.text(),
newIndex = e.newIndex,
oldIndex = e.oldIndex;
if (id == 'SpecialNeedActiveList' && newIndex > -1) {
//add item to selected list
//remove item from availables list
/*NONE of the following works...*/
//var oldPersonSpecialNeedId = e.sender.element.getAttribute('available-personspecialneed');
//var oldSpecialNeedTypeId = e.sender.element.getAttribute('available-need-type');
//e.sender.element.removeAttribute('available-personspecialneed');
//e.sender.element.removeAttribute('available-need-type');
//e.sender.element.setAttribute('selected-personspecialneed', oldPersonSpecialNeedId);
//e.sender.element.setAttribute('selected-need-type', oldSpecialNeedTypeId);
}
console.log(id + " change: " + text + " newIndex: " + newIndex + " oldIndex: " + oldIndex + " action: " + e.action);
}
When you are in the change event handler(onChange()), e.sender.element is NOT the item that was dragged, it is the list that sent the change event, the <ul> element.
The item being drag/dropped is contained in the e.item field, which you should be able to manipulate as normal, for example using jQuery(but you may use whatever DOM manipulation technique you like):
var $item = $(e.item);
var oldPersonSpecialNeedId = $item.attr('selected-personspecialneed');
var oldSpecialNeedTypeId = $item.attr('selected-need-type');
$item.attr("selected-personspecialneed", "new" + oldPersonSpecialNeedId);
$item.attr("selected-need-type", "new" + oldSpecialNeedTypeId);
Here's a working example showing the attributes being changed:http://dojo.telerik.com/#Stephen/arUpO
It is based on single list from the code in your question rather than 2 lists but it simply demonstrates how to access the dragged element from the sortable change event, which is the core of your problem.
Having said that, I would probably investigate using a DataSource-bound list so that you can manipulate fields of a model instead of attributes of a DOM element. http://demos.telerik.com/aspnet-mvc/sortable/integration-listview is a good place to start.

Custom data attributes with multiple elements

I'm trying to make a custom data attributes on my website in lightbox. I just made it for one element in Javascript and it works fine but I want to make it works in multiple elements.
How it works now: I have "a" element with id="image-1" and I want to make that javascript will recognise id image-2,3,4... and show correct data from custom attributes. Note that I can't use onclick because it makes that lightbox stops work.
Here is HTML:
<div class="col-xs-12 col-sm-4 col-md-3 col-lg-3">
<div class="thumbnail grid-wrapper thumbnail-single">
<a id="image-1" href="img/photo2.jpeg" data-tags="<li>t31232est</li> <li>test</li>" data-fb="http://test1.pl" data-tt="http://test2.pl" data-gplus="http://te23432st3.pl" data-lightbox="roadtrip" data-title="This is a caption. This is a caption This is a caption This is a caption"><img src="img/photo2.jpeg" class="img-responsive" alt="..."></a>
</div>
</div>
<div class="col-xs-12 col-sm-4 col-md-3 col-lg-3">
<div class="thumbnail grid-wrapper thumbnail-single">
<a id="image-2" href="img/photo3.jpg" data-tags="<li>test</li> <li>test</li>" data-fb="http://test55.pl" data-tt="http://test253342.pl" data-gplus="http://tes32423t3.pl" data-lightbox="roadtrip" data-title="This is a caption. This is a caption This is a caption This is a caption"><img src="img/photo3.jpg" class="img-responsive" alt="..."></a>
</div>
</div>
Here is JS:
var global = document.getElementById('image-1');
var tagList = global.getAttribute('data-tags');
var facebook = global.getAttribute('data-fb');
var twitter = global.getAttribute('data-tt');
var gplus = global.getAttribute('data-gplus');
$('<div id="lightboxOverlay" class="lightboxOverlay"></div><div id="lightbox" class="lightbox"><div class="lb-outerContainer"><div class="lb-container"><img class="lb-image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" /><div class="lb-nav"><a class="lb-prev" href="" ></a><a class="lb-next" href="" ></a></div><div class="lb-loader"><a class="lb-cancel"></a></div></div></div><div class="lb-dataContainer"><div class="lb-data"><div class="lb-details"><ul class="tag-list">' + tagList +'</ul><br/><span class="lb-caption"></span><span class="lb-number"></span></div><div class="lb-closeContainer">' +
'<ul class="social-list"><li><img src="img/fb_circle_white.png" class="img-responsive"></li><li><img src="img/tt_circle_white.png" class="img-responsive"></li><li><img src="img/gplus_circle_white.png" class="img-responsive"></li></ul><a class="lb-close"></a></div></div></div></div>').appendTo($('body'));
I'm trying to make it works on Lightbox Plugin (http://lokeshdhakar.com/projects/lightbox2/)
UPDATE
I just used function in onclick and when I'm testing it, it shows correct IDs. But still can't put it into getElementByID as a string.
id="image-1" onclick="GetID(this.id)"
window.GetID = function(elem_id){
alert(elem_id);
}
var global = document.getElementById(GetID());
var tagList = global.getAttribute('data-tags');
var facebook = global.getAttribute('data-fb');
var twitter = global.getAttribute('data-tt');
var gplus = global.getAttribute('data-gplus');
UPDATE 2:
Almost done. I've made my variables global. Console log shows correct ID and other data attribs. Problem is when I'm trying to put result into html in javascript. Here is example.
<ul class="social-list"><li><img src="img/fb_circle_white.png" class="img-responsive"></li>
+ current JS:
id="image-1" onclick="window.GetID(this.id)"
var global;
var tagList;
var facebook;
var twitter;
var gplus;
window.GetID = function(elem_id){
console.log(elem_id);
global = document.getElementById(elem_id);
console.log(global);
tagList = global.getAttribute('data-tags');
console.log(tagList);
facebook = global.getAttribute('data-fb');
console.log(facebook);
twitter = global.getAttribute('data-tt');
console.log(twitter);
gplus = global.getAttribute('data-gplus');
console.log(gplus);
}
+ image of console response.
A good solution would be to get the id attribute of 'a' element when clicking it put it in a var and use it to get data attributes.
Assuming 'a' elements are inside a div '#container' here is my solution
$('#container a').click(function(){
var image_id = '#' + $(this).attr('id');
var tagList = $(image_id).data('tags');
var facebook = $(image_id).data('fb');
var twitter = $(image_id).data('tt');
var gplus = $(image_id).data('gplus');
});
not sure if I am understanding correctly. But if the id of the divs are consistent, meaning image-1, image-2, image-3,... and so on, you could use and expression selector and loop through the number of elements in that array to add/append your dynamic html inside those divs without using a click event to get the id. Ex -
var array_of_divs = $("div[id^=image-]") // this gives you an array of all the element having the id starting with 'image-'
further you can loop though the length of this array and add your dynamic html based on the id of the parent : ("image-"+counter_variable])
let me know if this helps.

How to get value of elements without using IDs in JavaScript

Lets say I had the following code:
<div class="post">
<h2 itemprop="name">
The Post Title
</h2>
<div class="details">
<span>
<em class="date">Jul 17, 2014 </em>
</span>
<span>
Category:
Staff Profile
</span>
</div>
How would I possibly get the values of "The Post Title" and "Staff Profile" using JavaScript without changing the HTML on the page at all? i.e. I couldn't use getElementbyID for example. I could use jQuery if I had to but would rather not if possible.
You can get these values using getElementsByTagName which returns an array
document.getElementsByTagName("a")[0].innerHTML // returns The Post Title
document.getElementsByTagName("a")[1].innerHTML // returns Staff Profile
If these links are the first ones you can use indexes 0 and 1, otherwise you should look for the right index
Update
Another way that may be simple is to select these links inside the div with the class post
var links = document.getElementsByClassName("post")[index].getElementsByTagName("a");
links[0].innerHTML; // returns The Post Title
links[1].innerHTML; // returns Staff Profile
This solution would be the best one if the index of the div with the class post doesn't change
For a jQuery based expression you can use this:
$('a').map(function() {
return [this.href, this.textContent];
}).get();
which should return:
[ [ 'http://www.example.com', 'The Post Title' ],
[ 'http://sitename/category/staff-profile/', 'Staff Profile' ] ]
Should you specifically want the original relative URLs instead of the normalised full URLs, use this.getAttribute(href) in place of this.href
For a pure (ES5) equivalent:
[].map.call(document.getElementsByTagName('a'), function (el) {
return [el.href, el.textContent];
});
Older browsers that don't support the W3C standard .textContent property may require the .innerText property instead, e.g.:
return [el.href, el.textContent || el.innerText];
You can do:
var posts = document.querySelector('.post');
for (var i = 0; i < posts.length; i++) {
var links = document.querySelectorAll('a');
var title = links[0].innerText || links[0].textContent;
var profile = links[1].innerText || links[1].textContent;
}
If you are using a more modern browser, you can use document.querySelectorAll() which takes in CSS style selector syntax.
var aList = document.querySelectorAll('.post a');
for (var i = 0; i < aList.length; ++i) {
alert(aList[i].innerHTML);
}
JSFiddle
I used '.post a' rather than just 'a' because I assume your page may have other 'a' tags in it that you don't necessarily want.

How do i get a value from Kendo UI template

I have this template:
var template = kendo.template("<div class='relatedItemRow'>"
+ "<span id='relatedItemName'>Related Item #: Number #</span>"
+ "<div class='relatedItemRowInfo'><span >#: Name #</span>"
+ "<a data-relatedItemID='#: Value #' class='removeRelatedItem'>"
+ "<img src= '#: Img #'/</a></div><br class='clear'/></div>");
var data = {
Name: "" + checkbox.getAttribute('flatName'),
Number: $('#relatedItemsList').children().length + 1,
Img: '/Content/images/x_remove.png',
Value: checkbox.value
};
var result = template(data);
$("#relatedItemsList").append(result);
I am able to access the data-relatedItemID by using:
$('#relatedItemsList').children().eq(i).children().last().attr('data-relatedItemID')
But how do I get to the Number field in data? I want to change that one dynamically.
I have tried:
$('#relatedItemsList').children().eq(i).children().attr('Number') == 5
but it does not work. Any idea how to do that?
I know that there is an answer for this question even accepted but I'd like to suggest a different approach that I think it is much simpler and more Kendo UI oriented and is using Kendo UI ObservableObject. This allows you to update an HTML that is bound to the ObservableObject without having to crawl the HTML.
This approach is as follow:
Wrap your data definition with a Kendo Observable Array initialization.
Redefine your template and start using using data-binding.
Append this new template to your HTML.
Bind data to the HTML.
Now you can get current value using data.get("Number") or set a new value using data.set("Number", 5) and the HTML get magically updated.
The code is:
Template definition
<script type="text/kendo-template" id="template">
<div class='relatedItemRow'>
<span id='relatedItemName'>Related Item <span data-bind="text : Number"></span></span>
<div class='relatedItemRowInfo'>
<span data-bind="html : Name"></span>
<a class='removeRelatedItem' data-bind="attr: { data-relatedItemID : Value }">
<img data-bind="attr : { src : Img }"/>
</a>
</div>
<br class='clear'/>
</div>
</script>
data definition as:
var data = new kendo.data.ObservableObject({
Name: "" + checkbox.getAttribute('flatName'),
Number: $('#relatedItemsList').children().length + 1,
Img: '/Content/images/x_remove.png',
Value: checkbox.value
});
and the initialization of the HTML is:
$("#relatedItemsList").append($("#template").html());
Getting current value of Number is:
var old = data.get("Number");
Setting is:
data.set("Number", 5);
Running example in JSFiddle here : http://jsfiddle.net/OnaBai/76GWW/
The variable "result" and thus the data you're trying to change aren't a Kendo templates, they're just html created by the template, and the number is just text in the html. To modify the number without rebuilding the whole string, you need to change the template so you can select the number by itself with jQuery by putting it in it's own element, and adding something to identify it.
var template = kendo.template("<div class='relatedItemRow'><span id='relatedItemName'>Related Item <span class='relatedNumberValue'>#: Number #</span></span><div class='relatedItemRowInfo'><span >#: Name #</span><a data-relatedItemID='#: Value #' class='removeRelatedItem'><img src= '#: Img #'/</a></div><br class='clear'/></div>");
//other code the same
And once you can select it, then you can change it like this.
$('#relatedItemsList').children().eq(i).find('.relatedNumberValue').text(5);
And retrieve it like this.
var foo = $('#relatedItemsList').children().eq(i).find('.relatedNumberValue').text();

Categories

Resources