I am trying to create a pinterest like webpage using mansory.js and I am having trouble appending the unique description to each image. I know that the last line of my code is wrong but I have no idea how to fix it. I am basically adding all of the description tags into one span for each image.
I've tried looking at several other stackoverflow questions such as jQuery: Add element after another element and add image/s inside a div with jquery
but with no luck.
My entire pen is here http://codepen.io/OG/pen/VLEXgz
HTML
<body>
<h1>Camper Stories</h1>
<div id="content"></div>
</body>
CSS
h1{
text-align:center;
font-family: 'Lobster', cursive; font-size:80px;
color:purple;
}
#content {
width: auto;
margin: 0 auto;
}
.item {
display: inline-block;
float: left;
width: 300px;
height:300px;
margin: 2em;
position:relative;
}
.item img {
width: 300px;
height: auto;
}
JS
var url = 'http://www.freecodecamp.com/stories/hotStories';
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var myArr = JSON.parse(xmlhttp.responseText);
myFunction(myArr);
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send();
function myFunction(arr) {
var i;
var headlines = [];
//loop through json get need attributes
//for(i = 0; i < arr.length; i++){
for (i = 0; i < 5; i++) {
var headline = arr[i].headline;
headlines.push(headline);
var authorImg = arr[i].author.picture;
//console.log(img);
//error function
//if there is no thumbnail link the get author image
if (img === "") {
$('#content').append('<div class="item">' + '' + '<img id="myImg" src="' + authorImg + '" alt="' + headline + '" />' + '' + '</div>');
} else {
//if there is a thumbnail image then use that image
$('#content').append('<div class="item" id="hi">' + '' + '<img id="myImg" src="' + img + '" alt="' + headline + '" />' + '' + '</div>');
//if there is a 404 error with loading the thumbnail image then use author's image
$('img').one('error', function () {
this.src = '' + authorImg;
})
}
$(arr[i].headline).insertAfter("img");
}
}
See http://codepen.io/anon/pen/YXJvEK Is that what you mean? Append the headline after the corresponding image only?
$("<span>" + arr[i].headline+"</span>").insertAfter($("img").eq(i));
You should build your elements like this:
var wrapper = $("<div />");
var link = $("<href />");
var img = $("<img />");
...
Then add attributes and classes needed and append them to each other.
link.append(img);
wrapper.append(link);
...
In that way your code gets much more maintainable and you can append your span easily to your img (don't know exactly where you want the description).
Edit, since I've got my hands on a pc, here's the code you could use.
function myFunc (data) {
if(typeof data === "undefined") return; // output some error
for (var i = 0; i < data.length; i++) {
var item = data[i];
var upVote = item.rank;
var href = item.link;
var image = (item.image === "") ? item.author.picture : item.image;
var headline = item.headline;
// build elements
var wrapper = $("<div />");
var link = $("<a />");
var img = $("<img />");
var description = $("<span />");
// add attributes and classes
wrapper.addClass("item");
link.attr("href", link);
// you can also set multiple attributes at once
img.attr({"src": image, "alt": headline});
description.text(headline); // text(string) adds string to element
// append elements onto each other
link.append(img);
wrapper.append(link, description);
$("div.content").append(wrapper); // attach elements to DOM
}
}
Related
I need to wrap the < img > tag in < a > tag, for this it needes to get the address of the picture.
How to do this without using regexp?
And also i need to know width of the picture,
'onload' function breaks the event 'BeforeSetContent'
ed.on('BeforeSetContent', function (e) {
if (e.content.startsWith("<img")) {
var s = e.content.replace(/\<img src=\"(.+)\" alt.+\>/i,'$1');
console.log('SRC: '+s);
// var img = new Image();
// img.src = s;
// img.onload = function() {
// console.log('img-width: '+img.width);
// if (img.width > 450){
e.content = '<a class="ajax-modal modal_image hover_image" href="' + s + '">' + e.content + '</a>';
// }
// }
}
});
if you want open new window when clicking img, you can do this:
document.addEventListener('click', function(event) {
if (event.target.nodeName === 'IMG' && event.target.src && /^http/.test(event.target.src)) {
event.preventDefault()
window.open(event.target.src)
}
})
To answer the first question, if your image has an id then:
var imgsrc = document.getElementById("yourImageId").src;
If it does not have an id then use the parent e.g.:
var imgsrc = document.querySelectorAll('#imgParentDiv img')[0].src
i couldĀ get the address using jQuery
ed.on('BeforeSetContent', function (e) {
if (e.content.startsWith("<img ")) {
var objC = $(e.content).filter(':first');
var src = objC.attr('src');
e.content = '<a class="ajax-modal modal_image hover_image" href="' + src + '">' + e.content + '</a>';
}
});
how can i get the width of the picture using jQuery and my created object 'objC' ?
What i have:
JSON with id, name, position, department and address.
That same JSON have over 1000 random employees looped to a table.
Every person have a custom attribute (user_id) and same css class for hovering.
One hidden prepared and styled div for information when is hovered on one employee.
What i need:
I need when i hover on some employee to display all that employee information like name, position, department and address. Keep in mind that hover is working, but informations are still static. So basically, my logic is when custom attr user_id and JSON id match = fill the html.
How can i do that?
var xmlhttp = new XMLHttpRequest();
var url = "https://s3-eu-west-1.amazonaws.com/uploads-eu.hipchat.com/189576/1743369/lDhMee0RoA1IO5D/generated.json";
var employees;
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
employees = JSON.parse(this.responseText);
write(employees);
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
function write(arr) {
var i;
var out = '<table>';
for(i = 0; i < arr.length; i++) {
out += '<tr>';
out += '<td class="hoverKartX" user_id="' + arr[i].id + '">' + arr[i].name + '</td>';
out += '<td>' + arr[i].position + '</td>';
out += '</tr>';
}
out += '</table>';
document.getElementById('employees').innerHTML = out;
}
$(function() {
var moveLeft = 20;
var moveDown = 10;
$('.hoverKartX').hover(function(e) {
//$(this).parent().find(".hoverKart").show();
$(".hoverKart").show();
}, function() {
$('.hoverKart').hide();
});
$('.hoverKartX').mousemove(function(e) {
$(".hoverKart").css('top', e.pageY + moveDown).css('left', e.pageX + moveLeft);
// preventing 'falling' to the right on smaller screen
if ($(".hoverKart").position()['left'] + $('.hoverKart').width() > $(window).width()) {
$(".hoverKart").css("left", $(window).width() - $(".hoverKart").width());
};
// preventing 'falling from the bottom of the page'
if ((e.pageY + moveDown + $(".hoverKart").height()) > ($(window).scrollTop() + $(window).height())) {
$(".hoverKart").css("top", $(window).height() - $(".hoverKart").height() + $(window).scrollTop());
}
});
});
.hoverKart {
position: absolute;
width: 400px;
height: 220px;
border-radius: 25px;
border: 1px solid #999;
z-index: 1;
display: none;
background: #fff;
}
<!-- hidden div-->
<div class="hoverKart">
<div class="container">
<div class="cardTop"><p><!-- JSON DATA (ID) --></p></div>
<div class="imgHolder">
<img class="employee" src="img/img.jpg" alt="employee image">
<img class="eLogo" src="img/logo.jpg" alt="logo">
</div>
<div class="eInformation">
<p class="eName"><!-- JSON DATA (NAME) --></p>
<p class="ePos"><!-- JSON DATA (DEPARTMENT) --></p>
<div class="eDep">
<img src="img/icons-dep/5.png" alt="department logo">
</div>
<p class="eOp">Operations</p>
<p class="eOp2"><!-- JSON DATA (ADDRESS) --></p>
</div>
</div>
</div>
<div id="employees"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I have update your code and created a fiddle:
Check the working Fiddle.
$(function(){
var xmlhttp = new XMLHttpRequest();
var myGlobalJson;
var url = "https://s3-eu-west-1.amazonaws.com/uploads-eu.hipchat.com/189576/1743369/lDhMee0RoA1IO5D/generated.json";
var employees;
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
employees = JSON.parse(this.responseText);
myGlobalJson = employees;
write(employees);
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
function write(arr) {
var i;
var out = '<table>';
for(i = 0; i < arr.length; i++) {
out += '<tr>';
out += '<td class="hoverKartX" user_id="' + arr[i].id + '">' + arr[i].name + '</td>';
out += '<td>' + arr[i].position + '</td>';
out += '</tr>';
}
out += '</table>';
document.getElementById('employees').innerHTML = out;
bindMethods();
}
//$(function() {
function bindMethods(){
var moveLeft = 20;
var moveDown = 10;
$('.hoverKartX').hover(function(e) {
//$(this).parent().find(".hoverKart").show();
var currentUserId = parseInt(($(this).attr('user_id')));
//console.log(myGlobalJson);
//console.log(typeof parseInt($(this).attr('user_id')));
$.each(myGlobalJson, function(i, item) {
//console.log($(this).attr('user_id'));
if(item.id === currentUserId){
$(".hoverKart .cardTop").html(item.id);
$(".hoverKart .eName").html(item.name);
$(".hoverKart .ePos").html(item.position);
$(".hoverKart .eOp2").html(item.address);
return false;
}
});
$(".hoverKart").show();
}, function() {
$('.hoverKart').hide();
});
$('.hoverKartX').mousemove(function(e) {
$(".hoverKart").css('top', e.pageY + moveDown).css('left', e.pageX + moveLeft);
// preventing 'falling' to the right on smaller screen
if ($(".hoverKart").position()['left'] + $('.hoverKart').width() > $(window).width()) {
$(".hoverKart").css("left", $(window).width() - $(".hoverKart").width());
};
// preventing 'falling from the bottom of the page'
if ((e.pageY + moveDown + $(".hoverKart").height()) > ($(window).scrollTop() + $(window).height())) {
$(".hoverKart").css("top", $(window).height() - $(".hoverKart").height() + $(window).scrollTop());
}
});
}
//});
});
There were some issues in existing code:
You should bind hover method to field only when your write method execution is finished. Otherwise, it's working will be inconsistent, depending on how fast table is created.
I hope, It will solve your purpose.
Alright apology for different answer as it's whole different way to fix this issue like below,
As your main problem is your "hoverKartX" jquery events are not binded to any elements because your html elements are generated dynamically from xmlhttp, so first you need to make sure your events are binded to your html elements after generating it, probably you need to refactor your code and move your $('.hoverKartX').hover()... and $('.hoverKartX').mousemove()... in your function write(arr) as you had attached your mousehover and mousemove event's code in global context which will bind to no html element at the time of page load because you are generating these elements dynamically using xmlhttp,
then access your custom html attribute user_id by using jquery's attr like $(this).attr('user_id') in your mousehover or mousemove event and do whatever you want to do...
I don't understand why it is important to view or see when its just the logic I'm looking for.. However I just added the index.html file that can make things show... I hope it helps anyone !
what I'm trying to achieve is..
var small = document.getElementsByClassName("small");
var story = document.getElementsByClassName("story");
small.onclick = function() { story.style.display = "block"; }
I'm aware they should be done for loop and added as [i] in the end of both vars...
But how can i relate each small to story when they're both same id...
How can I tell
document.getElementsByClassName("small")[0];
to show
document.getElementsByClassName("story")[0];
when I have Multiple Class Values...
Thought about adding (this) in onclick() html tag but im not experienced enough....
Here's the Main Code:
var div = document.getElementById("content");
var ajax = new XMLHttpRequest();
ajax.open('GET', 'rss.json', true);
ajax.onreadystatechange = function()
{
if(ajax.readyState == 4 && ajax.status == 200)
{
var items = JSON.parse(ajax.responseText);
var output = '<ul class="main">';
for(var key in items)
{
output += '<li class="IDZ"><b><pre>' + items[key].IDZ + '</b></pre></li>';
output += '<li class="topic"><h1><u>' + items[key].topic + '</u></h1></li>';
output += '<li id="" class="small"><a href="#" >' + items[key].small + '</a></li><br>';
output += '<li class="story">' + items[key].story + '</li><br>';
output += '<li class="media"><img src='+items[key].media+'>' + '</li>';
output += '<hr>';
}
output += '</ul>';
div.innerHTML = output;
}
}
ajax.send(null);
rss.json file
{
"rss1":
{
"IDZ" : 1,
"topic" : "Topic One",
"small" : "A Brief Intro about this story.",
"story" : "Main Story starts when A B C were born to become all good and tidy for the little things that made IDZ : 1 A Story",
"media" : "images/IDZ1.jpg"
},
"rss2":
{
"IDZ" : 2,
"topic" : "Topic 2",
"small" : "A Brief Intro about another story.",
"story" : "Main Story starts when A B C were born to become all good and tidy for the little things that made IDZ : 2 A Story",
"media" : "images/IDZ2.jpg"
}
}
<!DOCTYPE html>
<html encoding="utf-8" >
<head>
<title>json parser</title>
<style>
/* { border: 0; margin:0; padding: 0;} */
body { position: relative; }
ul { }
li { list-style-type: none; font-size:1em;}
a { text-decoration: none; }
a:visited { color: #f22; }
.id { text-align: center; }
</style>
<script>
document.onreadystatechange = function()
{
if(document.readyState == "complete")
{
var loadscript = document.getElementById("content");
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "script.js";
loadscript.appendChild(script);
}
}
</script>
</head>
<body>
<div id="content">
</div>
</body>
</html>
You could use the "data" attribute to store the key and also include the key in the id as follows:
for(var key in items)
{
output += '<li id="" data-key="'+ key +'" class="small"><a href="#" >' + items[key].small + '</a></li><br>';
output += '<li class="story" id="story_key_'+ key +'">' + items[key].story + '</li><br>';
}
small.onclick = function(elem)
{
story.style.display = "block";
var storyKey = elem.dataset.key;
var storyItem = document.getElementById("story_key_" + storyKey);
}
(Note: this is only an idea, this code isn't working code)
In javascript only, no librairies, I am trying to create a carousel.
I have 2 items:
One div for the main image and the caption (the images and captions are loaded dynamically one by one after a setTimeOut)
Another one with a list of thumbnails. I'd like to upon clicking on a thumbnail display the right image and caption.
Here is the html:
<div class="slide">
<h2 id="description" class="title">La Slide #0</h2>
<img id="largeImg" class="car" src="images/0.jpg" width="658" height="267" alt="" />
</div>
<ul id="thumbs">
</ul>
and here are my functions:
// Function to display the images and the captions switching from one to the other
function slideshowAuto() {
document.querySelector('div.slide').id = 'slide-' + i;
var caption = document.getElementById("description");
caption.innerHTML = data.slides[i].slide_name;
var img= document.getElementById("largeImg");
img.src = data.slides[i].image_src;
if (i < totalSlides) {
i++;
} else {
i = 0;
}
setTimeout("slideshowAuto()",3000);
}
// Function to display the images and the captions swaping from one to the other
function swapSlide() {
document.querySelector('div.slide').id = 'slide-' + i; // add an id on the current slide
var caption = document.getElementById("description");
caption.innerHTML = data.slides[i].slide_name;
var img = document.getElementById("largeImg");
img.src = data.slides[i].image_src;
if (i < totalSlides) {
i++;
} else {
i = 0;
}
setTimeout("swapSlide()",50);
}
// Function to display all the thumbnails
function displayAllThumbs() {
thumbs = document.getElementById('thumbs');
html = '';
for( i=0 ; i < totalSlides; i++) {
html += '<li><a onclick="swapSlide(slide-' + i + ')"><img src="' + data.slides[i].thumbnail_src + '" alt="' + data.slides[i].slide_name + '" title="' + data.slides[i].slide_name + '" /></a></li>';
}
thumbs.innerHTML = html;
}
My troubles:
The slide content display the last variables instead of the first one.
The clic on the thumbnails don't swap the "slide" content.
Here is a link of where I'm at...
Anyone can help me with that?
First,you used the global i which is changed to 7 by function preload and rechanged by function displayAllThumbs,So you got trouble 1.
Scond,you click function is swapSlide(slide-' + i + '),the parameter is a variable that doesn't exsits,also your swapSlide doesn't accept parameter.
Change to this will solve your problem:
function preload(images) {
if (document.images) {
var imageArray = data.slides[i].image_src;
var imageObjs = [];
var imageObj = new Image();
for(var j=0; j <= totalSlides - 1;j ++) {
imageObj.src = imageArray[j];
imageObjs.push(imageObj);
}
}
}
// Function to display the images and the captions switching from one to the other
function slideshowAuto() {
setSlide(i);
if (i < totalSlides) {
i++;
} else {
i = 0;
}
//document.getElementById('slide').style.webkitTransition = 'opacity 1s';
setTimeout("slideshowAuto()",3000);
}
// Function to display the images and the captions swaping from one to the other
function swapSlide(index) {
i=index; //change the current i
setSlide(index);
}
// Function to display all the thumbnails
function displayAllThumbs() {
thumbs = document.getElementById('thumbs');
html = '';
for( var k=0 ; k < totalSlides; k++) {
html += '<li><a onclick="swapSlide(' + k + ')"><img src="' + data.slides[k].thumbnail_src + '" alt="' + data.slides[k].slide_name + '" title="' + data.slides[k].slide_name + '" /></a></li>';
}
thumbs.innerHTML = html;
}
function setSlide(index){
document.querySelector('div.slide').id = 'slide-' +index; // add an id on the current slide
var caption = document.getElementById("description");
caption.innerHTML = data.slides[index].slide_name;
var img = document.getElementById("largeImg");
img.src = data.slides[index].image_src;
}
And can i get accepted?
I add a new function to avoid the repeat.
function createList() {
var list = '';
var listID;
$.each(obj_JSON.colors, function(index, value) {
listID = "clr_" + index;
list = list + "<div id=" + listID + " alt='" + obj_JSON.colors[index].name + "'></div>"
clrList.html(list);
updateListColours(listID);
});
}
function updateListColours(x) {
$('#' + x).css({"background-color":"rgb(255, 0, 0)", "height":"25px", "width":"25px"});
}
When I watch it get created. The first div gets the style applied to it. Then the second gets created and the style is wiped from the first div and applied to the second and it goes on until the list is complete...
Why is this happening and how can I apply the style to each div? Expecting answer that shows i've done something really stupid as usual
Because this line clrList.html(list);, you are removing the previous element then add new created.
Instead, do it with:
$.each(obj_JSON.colors, function(index, value) {
listID = "clr_" + index;
list = "<div id=" + listID + " alt='" + obj_JSON.colors[index].name + "'></div>"
clrList.append(list);
updateListColours(listID);
});
There's a much easier solution:
function createList() {
$.each(obj_JSON.colors, function() {
var d = document.createElement('div');
d.setAttribute("alt",this.name);
d.className = "listcolour";
clrList.appendChild(d);
// ^ assumes `clrList` is a DOM node, not a jQuery object
});
}
And CSS:
.listcolour {
width: 25px;
height: 25px;
background-color: #f00;
}