Accordion AJAX JSON content - javascript

I have the following html structure
<div class="accordion-container">
<ul class="accordion">
<li class="accordion-header">
<a class="is-active link">Accordion header<i class="accordion-header-icon"></i></a>
<div class="accordion-content js-accordion-content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eum, quos!</p>
</div>
</li>
<li class="accordion-header">
<a class="link">Accordion header<i class="accordion-header-icon"></i></a>
<div class="accordion-content js-accordion-content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nulla sed ducimus iusto, atque veniam, laborum ratione quibusdam sapiente. Sint.</p>
</div>
</li>
<li class="accordion-header">
<a class="link">Accordion header<i class="accordion-header-icon"></i></a>
<div class="accordion-content js-accordion-content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nulla sed ducimus iusto, atque veniam, laborum ratione quibusdam sapiente. Sint.</p>
</div>
</li>
<li class="accordion-header">
<a class="link">Accordion header<i class="accordion-header-icon"></i></a>
<div class="accordion-content js-accordion-content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nulla sed ducimus iusto, atque veniam, laborum ratione quibusdam sapiente. Sint.</p>
</div>
</li>
</ul>
</div>
and this css
.accordion-content {
display: none; }
I'm trying to populate the accordion-content with content from a json file only when click on each accordion header (.link)
I've tried this but it doesn't work as intended. When I click on a header it populates all the other accordion-content.
$(document).ready(function () {
$('.accordion').each(function (index) {
$(this).children('li').first().children('a').addClass('is-active').next().addClass('is-open').show();
});
$('.accordion').on('click', 'li > a', function (event) {
if (!$(this).hasClass('is-active')) {
event.preventDefault();
var accordionTabs = $(this).closest('.accordion');
accordionTabs.find('.is-open').removeClass('is-open').slideUp('fast');
$(this).next().toggleClass('is-open').slideToggle('fast');
accordionTabs.find('.is-active').removeClass('is-active');
$(this).addClass('is-active').closest('.accordion-content', function () {
$.getJSON('public/js/result.json', function (jd) {
$('.js-accordion-content').html('<p>Name: ' + jd.name + '</p>');
$('.js-accordion-content').append('<p>Age : ' + jd.age+ '</p>');
$('.js-accordion-content').append('<p>Sex: ' + jd.sex+ '</p>');
});
});
} else {
event.preventDefault();
}
});
});
The json looks like this:
{
"name": "Zara Ali",
"age" : "67",
"sex": "female"
}

jQuery's closest method does not accept an anonymous function as the 2nd argument, and therefore this never fires in your code.
$(this).addClass('is-active').closest('.accordion-content', function () {
I don't see you doing anything with the .accordion-content selector anyway, so just omit it.
$(this).addClass('is-active');
$.getJSON(....
You will also need to cache a reference to your element that fired the click event in order to reference in within the result of your ajax callback:
var self = $(this);
We need to natively wrap it as a jQuery object because the 2nd argument we pass in as context needs to apply .parent() in order to actually get the .js-accordion-content element.
$('.js-accordion-content', self.parent()).html('<p>Name: ' + jd.name + '</p>');
$('.js-accordion-content', self.parent()).append('<p>Age : ' + jd.age + '</p>');
$('.js-accordion-content', self.parent()).append('<p>Sex: ' + jd.sex + '</p>');
jsFiddle

The query ".js-accordion-content" is ambiguous to all similar elements with the same class name. Isolate it to the current "accordion"
replace:
$(this).addClass('is-active').closest('.accordion-content', function () {
$.getJSON('public/js/result.json', function (jd) {
$('.js-accordion-content').html('<p>Name: ' + jd.name + '</p>');
$('.js-accordion-content').append('<p>Age : ' + jd.age+ '</p>');
$('.js-accordion-content').append('<p>Sex: ' + jd.sex+ '</p>');
});
with
var self = this;
$(this).addClass('is-active').closest('.accordion-content', function () {
$.getJSON('public/js/result.json', function (jd) {
$('.js-accordion-content', self).html('<p>Name: ' + jd.name + '</p>');
$('.js-accordion-content', self).append('<p>Age : ' + jd.age+ '</p>');
$('.js-accordion-content', self).append('<p>Sex: ' + jd.sex+ '</p>');
});
Notice the use of self referencing the accordion.

Related

changing background images in JavaScript not working

i want in seconds the background image in landing page changes automatically
but it dosn't change and i don't know why and i wrote correctly the code
and here is my path images
img/img1.jpg,
img/img2.jpg,
and so on
<div class="landing-page">
<div class="overlay"></div>
<div class="header-area">
<div class="logo">
special design
</div>
<ul class="links">
<li>About </li>
<li>Service </li>
<li>Products </li>
<li>contact </li>
</ul>
</div>
<div class="introduction-text">
<h1>We Are <span class="main-color">Creative Agency</span></h1>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Atque et quidem nostrum tempore ab delectus totam in ducimus! Quae amet corrupti magni et. Adipisci officia at ipsum iste accusantium ullam!</p>
</div>
</div>
my javascript code page
var myBackground = document.getElementsByClassName('landing-page');
var myImages =[
'img1.jpg',
'img2.jpg',
'img3.jpg',
'img4.jpg',
];
myRandomNumber = Math.floor(Math.random() * myImages.length);
console.log(myRandomNumber);
setInterval(() => {
var randomNumber = myRandomNumber;
myBackground.style.backgroundImage = 'url("img/' + myImages[myRandomNumber] + '")';
}, 1000);
changeImage(myBackground,myImages);
"use strict";
window.addEventListener('load', onLoaded, false);
var myImages = ['img1.jpg', 'img2.jpg', 'img3.jpg', 'img4.jpg'];
function onLoaded(event) {
setInterval(
() => {
let tgtElem = document.querySelector('.loading-page');
let randIndex = Math.floor(Math.random() * myImages.length);
tgtElem.textContent = `img/${myImages[randIndex]}`;
tgtElem.style.backgroundImage = `url("img/${myImages[randIndex]}")`;
}, 1000
);
}
header {
background-color: #888;
color: #ddd;
}
<header>
<h1>title</h1>
</header>
<div class='loading-page'>
</div>

Get data of p element of div element jquery

I want to know how can i get data of p element which is a children of div element. remember there are many div elements with same classes. it would be better to use events. As i am beginner I am unable to do it.
jQuery(document).ready(function($) {
$(".wp-block-wish-block-01-wish-block-01-editable").find('.social-link').on('click', function(event) {
var elementText = $(event.target).text();
console.log(elementText);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wp-block-wish-block-01-wish-block-01-editable share-block-content">
<p class="ab-testimonial-title">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Atque porro incidunt error nostrum, labore saepe pariatur similique officia voluptatem! Repellendus iure commodi aliquid nemo nisi rerum quasi sunt, ducimus libero!. </p>
<div class="block-share-links">
<strong>Share:</strong>
<div class="share-links">
<a class="social-link" href="#"><img src="http://localhost/cs/wp-content/plugins/wish-block/assets/021-facebook.png"></a>
<img src="http://localhost/cs/wp-content/plugins/wish-block/assets/043-twitter.png">
<img src="http://localhost/cs/wp-content/plugins/wish-block/assets/049-stumbleupon.png">
</div>
</div>
</div>
There are many blocks like this. What i want to do is that when user clicks the .social-link the text of first element p should be logged in console using jQuery or JavaScript.
This should solve your problem. It searches for the closest parent of the clicked element which has the specified class. Then it looks for the first child element (because of the >) with the specified class and extracts its text.
$('.social-link').click(function() {
var value = $(this).closest('.share-block-content').find('> .ab-testimonial-title').text();
console.log(value);
});
I suppose all of these blocks share the class share-block-content. Then it would be possible to get the text of the <p> element like this:
$(".social-link").on("click", function() {
let text = $(this).closest(".share-block-content").find("p").text();
console.log(text);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wp-block-wish-block-01-wish-block-01-editable share-block-content">
<p class="ab-testimonial-title">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Atque porro incidunt error nostrum, labore saepe pariatur similique officia voluptatem! Repellendus iure commodi aliquid nemo nisi rerum quasi sunt, ducimus libero!. </p>
<div class="block-share-links">
<strong>Share:</strong>
<div class="share-links">
<a class="social-link" href="#"><img src="http://localhost/cs/wp-content/plugins/wish-block/assets/021-facebook.png"></a>
<img src="http://localhost/cs/wp-content/plugins/wish-block/assets/043-twitter.png">
<img src="http://localhost/cs/wp-content/plugins/wish-block/assets/049-stumbleupon.png">
</div>
</div>
</div>
What i want to do is that when user clicks the .social-link the text of first element p should be logged in console
You can do this easily by using the .closest() method to find the closest parent element with class as share-block-content and then find the first p inside that div like:
jQuery(document).ready(function($) {
$(".wp-block-wish-block-01-wish-block-01-editable").find('.social-link').on('click', function(event) {
var elementText = $(this).closest('.share-block-content').find('p:first').text();
console.log(elementText);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wp-block-wish-block-01-wish-block-01-editable share-block-content">
<p class="ab-testimonial-title">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Atque porro incidunt error nostrum, labore saepe pariatur similique officia voluptatem! Repellendus iure commodi aliquid nemo nisi rerum quasi sunt, ducimus libero!. </p>
<div class="block-share-links">
<strong>Share:</strong>
<div class="share-links">
<a class="social-link" href="#"><img src="http://localhost/cs/wp-content/plugins/wish-block/assets/021-facebook.png"></a>
<img src="http://localhost/cs/wp-content/plugins/wish-block/assets/043-twitter.png">
<img src="http://localhost/cs/wp-content/plugins/wish-block/assets/049-stumbleupon.png">
</div>
</div>
</div>

Javascript hiding objects in loop

Please help me. I want to hide ext by clicking on link, but something is wrong
But I could write only this, and don't undertand why it's not working! Maybe there is another way to do it? It's every time fills the same function. to li1 li2func, therefore thereis li1
Link to jsfiddler
html:`
<div>
<div class="left">
<ul>
<li><a id="11" href="#">one</a></li>
<li><a id="12" href="#">two</a></li>
<li><a id="13" href="#">three</a></li>
</ul>
</div>
<div class="right">
<p id="1">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque, qui.
</p>
<p id="2">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellendus reiciendis veritatis voluptatibus optio explicabo? Dignissimos ex amet mollitia doloribus a.
</p>
<p id="3">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Impedit porro quisquam harum nemo, vitae itaque.</p>
</div>
</div>`
JS code:
var el = document.getElementsByTagName("p");
var cs = document.getElementsByTagName("a");
if(el) {
for (i = 0; i < el.length; i++) {
td = cs[i];
(function (_td) {
td.addEventListener('click', function(){
console.log(_td);
console.log(i);
document.getElementsByTagName("div")[i].className += document.getElementsByTagName("div")[i].className ? ' invis' : 'invis';
});
})(td);
You have a few problems with your javascript. You should have noticed this error in your javascript console: "Uncaught TypeError: Cannot read property 'className' of undefined", which might have led you to discover that document.getElementsByTagName("div") is not the selector you should be using. You did the work to produce an array of p tags (inexplicably named el), but then didn't make any reference to that within the closure you built.
Here's one way to fix that problem: give your closure a second argument, and pass the p tag of the corresponding number (i) to the a tag to which you're binding the click handler. Then modify the className string of that element.
var el = document.getElementsByTagName("p");
var cs = document.getElementsByTagName("a");
if(el) {
for (i = 0; i < el.length; i++) {
td = cs[i];
ptag = el[i];
(function (_td,_el) {
td.addEventListener('click', function(){
console.log(_td);
console.log(i);
_el.className += _el.className ? ' invis' : 'invis';
});
})(td,ptag);
}
}
One other thing: you'll notice that console.log(i) always produces 3 because that i is not bound to the scope of the click handler, but rather the outer scope of the for loop, so when the user clicks on one of the a tags, the loop has already completed and i will always equal 3.
While you tagged jquery this is how can you do with jquery by using the index() of href's closest li
$('ul > li > a').on('click' , function(){
var ThisId = $(this).closest('li').index();
$('div.right > p:eq('+ThisId+')').slideToggle(100);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div class="left">
<ul>
<li><a id="11" href="#">one</a></li>
<li><a id="12" href="#">two</a></li>
<li><a id="13" href="#">three</a></li>
</ul>
</div>
<div class="right">
<p id="1">
1 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque, qui.
</p>
<p id="2">
2 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repellendus reiciendis veritatis voluptatibus optio explicabo? Dignissimos ex amet mollitia doloribus a.
</p>
<p id="3">3 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Impedit porro quisquam harum nemo, vitae itaque.</p>
</div>
</div>
document.getElementsByTagName will never return null, so if(el) in your code is unnecessary. An empty array will always evaluate to true. If you want i to not equal 3, then you have to add it to the closure at the moment it is 0, 1, and 2. I called it _index here:
var paragraphs = document.getElementsByTagName("p");
var links = document.getElementsByTagName("a");
for (i = 0; i < paragraphs.length; i++) {
link = links[i];
paragraph = paragraphs[i];
(function (_link,_paragraph, _index) {
_link.addEventListener('click', function(){
console.log(_link);
console.log(_index);
_paragraph.classList.toggle('invis');
});
})(link,paragraph, i);
}
Here is a cleaner version
function init(link, paragraph, index) {
link.addEventListener('click', function(){
paragraph.classList.toggle('invis');
});
}
var paragraphs = document.getElementsByTagName("p");
var links = document.getElementsByTagName("a");
for (i = 0; i < paragraphs.length; i++) {
init(links[i], paragraphs[i], i);
}

Accessing component controller from transcluded HTML

Plunker, because the snippet editor isn't liking me today.
Quick Info
I'm working on using .component() in place of .directive() when using Angular 1.6 to get myself more into the type of design pattern used by Angular 2. The issue is that I cannot use any references to either $tabs or $tab (the controllers for those respective components). Nothing is output by using either {{$tab.tabsCtrl.nothing}} or {{$tabs.nothing}}.
Please Note:this is not my actual scenario, but it does share a common problem with what I am actually doing.
I've searched around and I get a lot of results for the Angular 2 components, but if I am being honest reading through it is basically Greek.
Code Reference(not working in snippet editor, only for reference)
// Code goes here
angular.module('main.app', [])
.component('tabs', {
controller: function($http) {
this.tabs = [];
this.nothing = 'nada';
this.addTab = function(tab) {
this.tabs.push(tab);
}; //end addTab
this.selectTab = function(tab) {
this.tabs.map(function(item) {
item.selected = false;
});
var selected = this.tabs.filter(function(item) {
return item === tab;
});
if (selected.length) selected[0].selected = true;
}; //End selectTab
},
template: '<ul class="nav nav-tabs nav-justify justify-content-center"><li class="nav-item" ng-repeat="tab in $tabs.tabs" >{{tab.tabTitle}}</li></ul><div class="tabs-content" ng-transclude></div>',
transclude: true,
controllerAs: '$tabs'
})
.component('tab', {
require: {
'tabsCtrl': '^tabs'
},
bindings: {
'tabTitle': '#',
'selected': '<'
},
controller: function() {
this.$onInit = function() {
this.selected = this.selected || false;
this.tabsCtrl.addTab(this);
}; //end $onInit
},
transclude: true,
controllerAs: '$tab',
template: '<div class="tab" ng-show="$tab.selected"><div ng-transclude></div></div>'
})
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>
<tabs>
<tab tab-title="First Tab" selected="true">
<div class="jumbotron">
<h3>Lorem ipsum.</h3>
<p class="lead">Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto, in!</p>
</div>
some other text
</tab>
<tab tab-title="Second Tab">
<strong>With a header!</strong>
<div class="row">
<div class="col-6 bg-primary">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi, quam, quod, optio qui cum rerum vel eos rem aspernatur quia maxime incidunt numquam ipsum eum neque dicta distinctio. Minus, itaque.</div>
<div class="col-6 bg-danger">Reprehenderit, numquam, rerum, reiciendis neque adipisci provident ea quo illo praesentium inventore fuga quisquam ducimus? Ipsum, autem, illo ullam corporis incidunt ad labore accusantium tempora officia quas quia eaque facere.</div>
</div>
</tab>
<tab tab-title="Potato Tab">
<h3>Big books {{$tabs.nothing||'nah'}}</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste quos assumenda vero fugiat officia pariatur consequatur deserunt quisquam veniam nemo?</p>
<p>Fugiat, error, impedit, accusantium consequuntur beatae facere esse voluptatum enim animi porro commodi modi cupiditate aliquam iure ipsa. A, officiis!</p>
<p>Architecto velit quod explicabo laborum reprehenderit culpa tempora facilis minima eum. Natus aliquid eaque laboriosam accusamus dolor hic similique ad.</p>
</tab>
</tabs>
Thanks, just in case I forget to say it in the future!
The transcluded scope will be a child scope of the directive's isolate scope.
Since components use isolate scopes, you can't make use of prototypal inheritance by just doing {{$tabs.nothing}}. It would work if $tabs was exposed via $rootScope however, or any other non-isolate scope above tabs in the hierarchy (only ng-app in your example, so only $rootScope).
You can walk the scope chain manually.
Based on your example:
The current scope would be the transcluded child scope of the tab directive
The first $parent would be the isolate tab scope
The second $parent would be the transcluded child scope of the tabs directive
The third $parent would be the isolate tab scope
This gives:
{{$parent.$parent.$parent.$tabs.nothing}}
Demo: http://plnkr.co/edit/jpTGVKWKEQlmGYpaeqtZ?p=preview
In most cases this isn't really a feasible solution. Probably better to expose the functionality that the transcluded content needs via a service.
Hard to give a better solution without knowing the real use case.

Delete an element from the code using jquery

I'm trying Jquery and now I have a problem.
I want to remove an element from my webpage. So, when I press the delete button - the big element must disappear. Using the JQ I have written something like this
$(document).ready(function(){
$(".delete").click(function(){
$(this).parents(".block").animate({ opacity: 'hide' }, "slow");
})
});
It have worked fine until I didn't add subdiv, or answer. And how the application must works now? I press the delete button and it must remove current block.
<div class = "block">
<div class = "postbuttons">
<img src = "img/delete-icon.png" class = "delete"></a>
<img src = "img/edit-icon.png" class = "edit"></a>
</div>
<div class = "postinfo">
<span class = "author">Da Monkey wrote:</span> <span class = "date">on <span>13.13.13</span></span>
</div>
<div class = "post">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, voluptate, unde, impedit iste sint assumenda consequatur ipsum nesciunt</p>
<a class = "answerlink" href = "#">Answer</a>
</div>
<div class = "answer">
<div class = "postbuttons">
<img src = "img/delete-icon.png" class = "delete"></a>
<img src = "img/edit-icon.png" class = "edit"></a>
</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fuga, numquam, culpa, omnis explicabo ut asperiores ipsam porro alias quisquam nisi iste non a maiores! Nulla odio unde dolorum officia vero. </p>
<div class = "answerinfo">
- Macaque on <span>13.13.13</span>
</div>
</div>
If you didn't understand me here the result
Respect to the funcionality:
$(document).ready(function(){
$(".delete").click(function(){
$(this).closest(".block").animate({ opacity: 'hide' }, "slow");
});
});
you should use closest instead of parents because it stop once it has found the first math and parents travels to the root of the dom. Also if you dont need the block anymore you can remove it with the jquery method remove(), after tue animation ended with a callback function.
Also you are missing some semicolons, and tags
$(document).ready(function(){
$(".delete").click(function(){
$(this).parents(".block").animate({ opacity: 'hide' }, "slow");
}) // here needs a semicolon
});
Missing tags
<div class = "block">
<div class = "postbuttons">
<img src = "img/delete-icon.png" class = "delete"></a> <--! missing <a> -->
<img src = "img/edit-icon.png" class = "edit"></a> <--! missing <a> -->
</div>
<div class = "postinfo">
<span class = "author">Da Monkey wrote:</span> <span class = "date">on <span>13.13.13</span></span>
</div>
<div class = "post">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, voluptate, unde, impedit iste sint assumenda consequatur ipsum nesciunt</p>
<a class = "answerlink" href = "#">Answer</a>
</div>
<div class = "answer">
<div class = "postbuttons">
<img src = "img/delete-icon.png" class = "delete"></a> <--! missing <a> -->
<img src = "img/edit-icon.png" class = "edit"></a> <--! missing <a> -->
</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fuga, numquam, culpa, omnis explicabo ut asperiores ipsam porro alias quisquam nisi iste non a maiores! Nulla odio unde dolorum officia vero. </p>
<div class = "answerinfo">
- Macaque on <span>13.13.13</span>
</div>
</div>
I hope I was Useful.
Try hiding the container of the container of the delete button, which will work regardless of its class:
$(document).ready(function(){
$(".delete").click(function(){
$(this).parents(".postbuttons").parent().animate({ opacity: 'hide' }, "slow");
})
});

Categories

Resources