How to add a class in jquery when different attribute value changes? - javascript

I am working on a html code as shown below. The screen-shot beneath the code belong to the class schedule-action-bar from the code below. (removed ct, at nt from the code at this moment in order to minimize my question)
<div class="schedule-wrapper" id="js-schedule-wrapper" data-timezone="nt"> <!-- It changes to pt, mt, and et -->
<div class="schedule-action-bar" onclick="timezoneCheck()">
<div class="schedule-timezone-filter">
Select your timezone:
<ul id="js-timezone-picker">
<li>
<button id="js-time-pt" class="" data-timezone="pt">PT</button>
</li>
<li>
<button id="js-time-mt" class="" data-timezone="mt">MT</button>
</li>
<li>
<button id="js-time-et" class="" data-timezone="et">ET</button>
</li>
</ul>
</div>
</div>
<!-- want to add this class -->
<!--
<div class="schedule-date-bar">
April 12
</div>
-->
<div class="schedule-show">
<div class="schedule-show-time">
<time datetime="21:00 11-04-2019" data-timezone="pt">21:00</time>
<time datetime="22:00 11-04-2019" data-timezone="mt">22:00</time>
<time datetime="00:00 12-04-2019" data-timezone="et">00:00</time>
</div>
</div>
<!-- .schedule-show -->
</div>
Screenshot:
Problem Statement:
When different timezone is selected from the UI (in the screenshot), the value
of data-timezone changes to pt, mt and et at Line#A. What I want to do now is to add a <div class="schedule-date-bar"> <!-- whatever date belong to the respective timezone --> </div> before the schedule-show class
<script>
function timezoneCheck() {
jQuery(function ($) {
$("#js-schedule-wrapper").click(function () {
if ($('#js-schedule-wrapper').attr('data-timezone') === 'et') {
} else if ($('#js-schedule-wrapper').attr('data-timezone') === 'pt') {
} else if ($('#js-schedule-wrapper').attr('data-timezone') === 'mt') {
}
})
})
}
</script>
This is what I have tried above but more need to be done.

Related

Bootstrap 4 change accordion behaviour

I'm using HTML templates, which are based on Bootstrap 4.3.1 to present my students with learning content. In the current templates, all accordion panels are closed on page load and each accordion panel can be opened regardless of how many others have also been opened.
A working example can be found on this CodePen: https://codepen.io/hagelslag1001/pen/MWGeZJr
The HTML code is as follows:
<h2>Accordion: Group of 2</h2>
<p class="small">Accordion: start copy</p>
<!-- Accordion headings should be changed to respect page hierarchy -->
<div class="accordion shadow mb-5">
<div class="card">
<div class="card-header">
<h2 class="card-title">
Accordion 1 of 2
</h2>
</div>
<div class="collapse">
<div class="card-body">
<p>Insert Accordion 1 of 2 content here.</p>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h2 class="card-title">
Accordion 2 of 2
</h2>
</div>
<div class="collapse">
<div class="card-body">
<p>Insert Accordion 2 of 2 content here.</p>
</div>
</div>
</div>
</div>
<p class="small">Accordion: end copy</p>
Is it possible to change this default behaviour so that only one panel can be opened at a time? (i.e. as soon as a new panel is opened, the previously opened panel will automatically close)
The Bootstrap examples use (data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne") to accomplish this for the accordions in these templates
I can't figure out how to accomplish this, since the HTML code for the accordions in these templates look different than the Bootstrap 4 examples, which use either an a or button tag to trigger the collapsible event.
Here is a simpler answer based on your CodePen: https://codepen.io/mrtcntn/pen/MWGeZdP
According the Bootstrap 4 docs, you need id="accordion" on the top level div and you don't need to give ids like id="accordion_1" and id="accordion_2".
Therefore I removed the first portion from the JS and added id="accordion" at line 18 in the HTML.
You can do this by letting javascript check for active classes and only allowing one at the time. Here's a simplified example.
// DOM here
let nav = document.querySelector(".nav");
// Handlers here
const clickHandler = function (e) {
if (e.target.classList.contains("nav__link")) {
const link = e.target;
const siblings = link.closest(".nav").querySelectorAll(".nav__link");
link.classList.toggle("active");
// removes all actives except for the clicked one
siblings.forEach((el) => {
if (el !== link) el.classList.remove("active");
});
}
};
// Listeners here
nav.addEventListener("click", clickHandler);
body {
font-family: sans-serif;
}
.nav__link {
display: block;
width: 100%;
}
.active {
background: #0f0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<div class="nav">
<ul class="nav__links">
<li class="nav__item">
<a class="nav__link" href="#accordeon--1">Accordeon 1</a>
</li>
<li class="nav__item">
<a class="nav__link" href="#accordeon--2">Accordeon 2</a>
</li>
<li class="nav__item">
<a class="nav__link" href="#accordeon--3">Accordeon 3</a>
</li>
<li class="nav__item">
<a class="nav__link" href="#accordeon--4"
>Accordeon 4</a
>
</li>
</ul>
</div>
</div>
<script src="src/index.js"></script>
</body>
</html>

Trying to pass variables to another function

Okay, I dont know why my codepen version and my real one act different, but they are. In my codepen both windows start off with all of them open. In my real version you only see 2 sets of 01-Postpone and 02-Approve, the way they should be. Here, in my code snippet, the first text box does not populate, but the values are logged in the console.
Okay, so now my problem. Clicking any 1 of these slides opens a box underneath it with 2 options. PROCEED and CANCEL. With my fun function, it gets the 3 variables perfectly when 1 of those options is clicked ( see them in my console).
When PROCEED is clicked, I need those 3 variables so that I can run an ajax post to an external file. How do I get the 3 fun variables into my proceed function? I thought with var, they would be global, but I have tried many possibilities without success to access them. I do not want to use cookies as I am sure this is possible without them.
I have another freaky issue, but that is for another day when I get this part to work. Any assistance would greatly be appreciated.
https://codepen.io/lepew/pen/agNBzo
// 00 - CANCEL
function cancel00() {
alert("Cancel");
}
// End CANCEL
// 02 - PROCEED
function proceed01() {
// Ajax will go here
alert("This works.");
}
// End of PROCEED
// 03 - Get the data-field variables
function fun(obj) {
var one = obj.dataset.self,
two = obj.dataset.record,
three = obj.dataset.selectedoption;
//
console.log(one, two, three);
//
}
//external file
$(document).ready(function() {
$(".dropdown-link").on("click", function() {
//
const tranSpeed = "slow";
//
//
// Get code variable and be able to access this value elsewhere.
var selectmycode = $(this).attr("data-selectedoption");
//
// Display the variable in CONSOLE.
console.log(selectmycode);
//
// Get clicked option.
var selOption = $(this).data("selectedoption");
//
// Out the value of selectedoption into text field thecode.
var thecoder = $(".thecode").attr("value", selOption);
//
//
//
// Get next "here".
var here = $(this).closest(".bind_Name").next(".here");
//
// Populate stuff.
$(here).find("legend").text(`Option ${selOption}`);
//
// TO DETECT IF DATA HAS CHANGED.
var dataChanged = $(here).data("seloption") !== selOption;
$(here).data("seloption", selOption);
console.log(dataChanged)
//
// Show the dropdown if data changed.
var target = $(here).find(".dropdown-container");
//
// This will close all other open options.
$(".dropdown-container").not(target).hide(tranSpeed);
//
if (dataChanged) {
$(target).show(tranSpeed);
} else {
// Or toggle it otherwise.
$(target).toggle(tranSpeed);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="bind_Area">
<div class="bind_Name">
<div class="dropdown">
<div class="dropdown-link" onclick="fun(this);" data-selectedoption="01" data-record="123456820" data-self="123456830">01-Postpone
</div>
<!-- end of #dropdown-link -->
</div>
<!-- end of #dropdown -->
<div class="dropdown">
<div class="dropdown-link" onclick="fun(this);" data-selectedoption="02" data-record="123456820" data-self="123456830">02-Approve
</div>
<!-- end of #dropdown-link -->
</div>
<!-- end of #dropdown -->
</div>
<!-- end of #bind_Name -->
<div class="here">
<div class="dropdown-container">
<fieldset>
<legend></legend>
<input type="text" class="thecode" data-code="">
<input type="text" class="peter" data-user="123456820" value="123456820">
<input type="text" id="mary" data-product="123456830" value="123456830">
<div>PROCEED</div>
<div>CANCEL</div>
</fieldset>
</div>
<!-- end of #dropdown-container -->
</div>
<!-- end of #here -->
<div class="bind_Note"></div>
</div>
<!-- end of #bind_Area -->
<br>
<br>
<br>
<div class="bind_Area">
<div class="bind_Name">
<div class="dropdown">
<div class="dropdown-link" onclick="fun(this);" data-selectedoption="01" data-record="123456820" data-self="123456831">01-Postpone
</div>
<!-- end of #dropdown-link -->
</div>
<!-- end of #dropdown -->
<div class="dropdown">
<div class="dropdown-link" onclick="fun(this);" data-selectedoption="02" data-record="123456820" data-self="123456831">02-Approve
</div>
<!-- end of #dropdown-link -->
</div>
<!-- end of #dropdown -->
</div>
<!-- end of #bind_Name -->
<div class="here">
<div class="dropdown-container">
<fieldset>
<legend>
<div class="fubar"></div>
</legend>
<div>
<input type="text" class="thecode" data-code="">
<input type="text" class="peter" data-user="123456820" value="123456820">
<input type="text" id="mary" data-product="123456831" value="123456831">
</div>
<!-- end of #blank div -->
<div>PROCEED</div>
<div>CANCEL</div>
</fieldset>
</div>
<!-- end of #dropdown-container -->
</div>
<!-- end of #here -->
<div class="bind_Note">
</div>
</div>
<!-- end of #bind_Area -->
<br>
<br>
<br>

call Load more function for active tab

I'm trying to develop a load more function for a specific tab pane, in this case, the active tab pane. I'm having issues with this jquery function because I'm calling the load more in the end of all tabs, and in my JS function I can't figure out how to load after the pane that is active, in which the button was clicked. This way I keep loading the questions in the last pane, but I couldnt print without var lastItem = $('div.question-col .question-summary:last');
$(document).ready(function () {
$(".load-more").on('click', function (e) {
var tab = $(this).data('tab');
var next_page = $(this).data('next-page');
console.log(next_page);
console.log(tab);
$.get($(this).data('url') + '?tab=' + tab + '&page=' + next_page, function (data) {
addNewQuestions($.parseJSON(data));
});
$(this).data('next-page', parseInt(next_page) + 1);
});
siteStats();
});
function addNewQuestions(objects) {
$.each(objects, function (i, object) {
console.log(object);
var lastItem = $('div.question-col .question-summary:last');
var newLine = lastItem.clone(true);
var newObject = newLine.find('.question-info');
updateTitleAndLink(newObject.find('.summary a'), object);
updateCreationDate(newObject.find('.question-updated-at'), object);
updateQuestionAnswers(newObject.find('.question-answers'), object);
updateAnswerCount(newObject.find('.answers-count'), object);
updateViewsCount(newObject.find('.views-count'), object);
updateVotesCount(newObject.find('.votes-count'), object);
updateSolvedStatus(newObject.find('.status'), object)
lastItem.after(newLine);
});
}
The update functions are not relevant to this case, I guess.
<div id="tabs" class="tab-content">
<ul>
<li>Recent Questions</li>
<li>Unanswered Questions</li>
<li>Top Scored Questions</li>
</ul>
{if empty($recent_questions)}
<div class = "col-sm-12" style = "text-align: center"><strong>No questions to load!</strong></div>
{/if}
{if !empty($recent_questions)}
<div id="recent_questions" class="question-col">
<!-- Questions come here -->
<div class = "load-more"
data-next-page = "1"
data-url = "{url('controller/api/questions/load_more_questions')}"
data-tab = "recent_questions">
<a id="loadMore">
Load More...
</a>
</div>
</div>
{/if}
<div id="unanswered_questions">
<!-- Questions come here -->
<div class = "load-more"
data-next-page = "1"
data-url = "{url('controller/api/questions/load_more_questions')}"
data-tab = "unanswered_questions">
<a id="loadMore">
Load More...
</a>
</div>
</div>
<div id="top">
<!-- Questions come here -->
<div class = "load-more"
data-next-page = "1"
data-url = "{url('controller/api/questions/load_more_questions')}"
data-tab = "top_scored_questions">
<a id="loadMore">
Load More...
</a>
</div>
</div>
//Questions come here - Question template
<div class="question-summary narrow">
<div class="question-info col-md-12">
<div class="votes">
<div class="votes-count">
<span title="{$question['votes_count']} votes">
{if $question['votes_count']}
{$question['votes_count']}
{else}
0
{/if}
</span>
</div>
<div>votes</div>
</div>
<div {if $question['solved_date']}
class="status answered-accepted"
{else}
class="status answer-selected"
{/if}
title="one of the answers was accepted as the correct answer">
<div class="answers-count">
<span title="{$question['answers_count']} answer">{$question['answers_count']}</span></div>
<div>answer</div>
</div>
<div class="views">
<div class="views-count">
<span title="{$question['views_counter']} views">{$question['views_counter']}</span></div>
<div>views</div>
</div>
<div class="summary question-title">
<h3>
<a href="{questionUrl($question['publicationid'])}"
data-base-question-url = "{questionUrl('')}"
style="font-size: 15px; line-height: 1.4; margin-bottom: .5em;">
{$question['title']}
</a>
</h3>
</div>
<div class = "statistics col-sm-12 text-right" style="padding-top: 8px">
<span>
<i class = "glyphicon glyphicon-time"></i>
<span class="question-updated-at">{$question['creation_date']}</span>
</span>
<span>
<i class = "glyphicon glyphicon-comment"></i>
<span class="question-answers">{$question['answers_count']}</span>
</span>
</div>
</div>
</div>
My question is: is there any way to put my loaded content after the last item of the active pane?
Kind regards

distinguishing html with css sectors

I would like to restyle the nav id="jive-breadcrumb" with CSS. I want to have a different style when div class="jive-alert-type jive-alert-announcement" is present and when div class="jive-alert-type jive-alert-announcement" is not present.
I've gotten this for with the css sectors:
section#j-main div#jive-body nav#jive-breadcrumb ul { }
My second css selector
section#j-main :not(???) div#jive-body nav#jive-breadcrumb ul { }
How do I write the selector to be different?
Here is the section of css with
<section>
<span>
<script>...</script>
</span>
<div id="jive-alert-container">
<!-- the presence or absence of this inner div is what makes
the two html fragments different -->
<div id="jive-alert-global" role="marquee" class="clearfix">
</div>
</div>
<div id="jive-body" class="clearfix" role="main">
<nav id="jive-breadcrumb" aria-label="Communities Breadcrumbs" role="navigation">
<ul><li>Support Communities</li><li>The Lounge</li>
<li>Full Host Bar</li>
</ul>
</nav>
</div>
</section>
Here is the case where div class="jive-alert-type jive-alert-announcement" is not present.
<section>
<span>
<script>...</script>
</span>
<!-- The following div doesn't have any tags in it. I need to detect this with a css selector to generate different css. -->
<div id="jive-alert-container">
</div>
<div id="jive-body" class="clearfix" role="main">
<nav id="jive-breadcrumb">
<ul><li>The Lounge</li>
<li>Full Host Bar</li>
</ul>
</nav>
...
</div>
...
</section>
css presently does not select parent element. You can use MutationObserver to perform a task when an element is appended to or removed from DOM, or a specific parent element within DOM.
var jive = document.getElementById("jive-alert-container");
var breadcrumb = document.getElementById("jive-breadcrumb");
breadcrumb.classList.toggle("present");
var config = {childList: true};
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation);
if (mutation.addedNodes.length
&& mutation.addedNodes[0].id === "jive-alert-global") {
breadcrumb.classList.toggle("present");
}
if (mutation.removedNodes.length
&& mutation.removedNodes[0].id === "jive-alert-global") {
breadcrumb.classList.toggle("present");
}
})
});
observer.observe(jive, config);
var clone = jive.querySelector("#jive-alert-global").cloneNode(true);
setTimeout(function() {
jive.querySelector("#jive-alert-global").remove();
setTimeout(function() {
jive.appendChild(clone);
}, 5000);
}, 5000)
#jive-breadcrumb.present {
color: green;
}
#jive-breadcrumb:not(.present) {
color: blue;
}
<section>
<span>
<script></script>
</span>
<div id="jive-alert-container">
<!-- the presence or absence of this inner div is what makes
the two html fragments different -->
<div id="jive-alert-global" role="marquee" class="clearfix">
jive alert global
</div>
</div>
<div id="jive-body" class="clearfix" role="main">
<nav id="jive-breadcrumb" aria-label="Communities Breadcrumbs" role="navigation">
<ul>
<li>Support Communities</li>
<li>The Lounge</li>
<li>Full Host Bar</li>
</ul>
</nav>
</div>
</section>
The css selector section#j-main implies that there is an html element with the given id: <section id="j-main">.
Replacing the section you want to modify with <section id="j-main"> should make that section respond to the css block you have defined above.
Also note that you can only have one unique id per element on the page, so the jive-body, and jive-breadcrumb ids should be changed to classes.
This should yield:
section#j-main div.jive-body nav.jive-breadcrumb ul { css customizations here }
...
<div class="jive-body" class="clearfix" role="main">
<nav class="jive-breadcrumb" aria-label="Communities Breadcrumbs" role="navigation">
<ul><li>Support Communities</li><li>The Lounge</li>
<li>Full Host Bar</li>
</ul>
</nav>
</div>
</section>
...
<div class="jive-alert-type jive-alert-announcement" is not present.
<!-- This section will not have the changes -->
<section>
<div class="jive-body" class="clearfix" role="main">
<nav class="jive-breadcrumb">
<ul><li>The Lounge</li>
<li>Full Host Bar</li>
</ul>
</nav>
...
</div>
...
</section>

Toggle only this item

i've a problem to toggle only (this) 1 'card'
$('a[rel="toggle_comments"]').click(function(){
var div = $('.comments');
$(div, this).slideToggle('slow');
});
<!-- This is a example code -->
<section>
<div class="mainclass">
[...]
<div class="select">
Test
</div>
</div>
<ul class="comments">
<!-- Content -->
</ul>
</section>
<section>
<div class="mainclass">
[...]
<div class="select">
Test
</div>
</div>
<ul class="comments">
<!-- Content -->
</ul>
</section>
[...]
When I clicked at 'toggle_comments', toggle all '.comments' classes, not only that, I have clicked. Anyone have any ideas?
Sorry for my bad english.
I hope you understand what I mean - Thanks :-)
If you want to toggle only the .comments under the <section> tag your link is in, do this:
$('a[rel="toggle_comments"]').click(function(){
// find the closest section tag (parent) and find all child `.comments`
var $comments = $(this).closest('section').find('.comments');
$comments.slideToggle('slow');
});
If you want to toggle all .comments:
$('a[rel="toggle_comments"]').click(function(){
$('.comments').slideToggle('slow');
});

Categories

Resources