This is the jQuery code that basically opens and closes a div:
jQuery('#filter_werk').find('.raven-sortable').addClass('opened');
var toggle = document.getElementById('deknop');
var slider = document.querySelector('.raven-sortable');
toggle.addEventListener('click', toggleSlider, false);
function toggleSlider(){
if (slider.classList.contains('opened')) {
slider.classList.remove('opened');
slider.classList.add('closed');
} else {
slider.classList.remove('closed');
slider.classList.add('opened');
}
}
</script>
What I'm trying to do is change the content of the following div from "FILTER +" to "FILTER -" and back again to "FILTER +" when its clicked again
<div id="deknop">FILTER +</div>
Could this be done without breaking the current jQuery code?
Thank you!
As I understood the function toggleSlider works fine so try:
function toggleSlider(){
if (slider.classList.contains('opened')) {
slider.classList.remove('opened');
slider.classList.add('closed');
toggle.innerHTML = "FILTER +";
} else {
slider.classList.remove('closed');
slider.classList.add('opened');
toggle.innerHTML = "FILTER -";
}
}
You can add some logic to your toggleSlider() function that will change your #deknop text based on what it currently is (either ‘FILTER +’ or ‘FILTER -‘ like this:
function toggleSlider(){
$('#deknop').html($('#deknop').text() == 'FILTER +' ? 'FILTER -' : 'FILTER +');
if (slider.classList.contains('opened')) {
slider.classList.remove('opened');
slider.classList.add('closed');
} else {
slider.classList.remove('closed');
slider.classList.add('opened');
}
}
Well,
if I had to do this jQuery-style, I would either way try to separate the data from the view. Something like:
(() => {
const state = {
sliderOpen: true,
};
const $slider = $('.raven-sortable');
const $toggle = $('#deknop');
const updateView = () => {
if (state.sliderOpen) {
$slider.addClass('opened').removeClass('closed');
} else {
$slider.addClass('closed').removeClass('opened');
}
$toggle.text(`FILTER ${state.sliderOpen ? '+' : '-'}`);
};
const onToggleClick = () => {
state.sliderOpen = !state.sliderOpen;
updateView();
};
$toggle.click(onToggleClick);
updateView();
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="raven-sortable">Raven sortable</button>
<button id="deknop"></button>
Related
Description & Goal
I have a list with items and clicking on an item shows a detail view, shows a close button and add the eventlistener for closing this item to the button.
By clicking on this button the detail view should be closed and the eventlistener should be removed.
I can't use an anonymous function because removing won't work with it (See here and here).
Problem
Removing doesn't work.
Code
export default class ToggleDetails {
constructor(jobAdId) {
this.jobAdId = jobAdId
this.opened = false
}
toggle() {
const jobAdContainer = document.getElementById(this.jobAdId)
// doing some other css manipulation for the detail view
this.handleCloseButton()
}
handleCloseButton() {
const closeButton = document.getElementById('uh-job-detail-close-button')
const $this = () => {
this.toggle()
}
if (this.opened === true) {
closeButton.classList.remove('uh-job-detail-close-button-show')
closeButton.removeEventListener('click', $this)
this.opened = false
} else {
closeButton.classList.add('uh-job-detail-close-button-show')
closeButton.addEventListener('click', $this)
this.opened = true
}
}
}
HTML structure
"Solution"/Workaround
I solved it, by cloning and replacing the button with itself. The clone doesn't have the eventlisteners (Thanks to this post)
handleCloseButton () {
const closeButton = document.getElementById(
'uh-job-detail-close-button')
closeButton.classList.toggle('uh-job-detail-close-button-show')
if (this.opened === true) {
const elClone = closeButton.cloneNode(true)
closeButton.parentNode.replaceChild(elClone, closeButton)
this.opened = !this.opened
} else {
closeButton.addEventListener('click',
() => { this.toggle() })
this.opened = !this.opened
}
}
Try using a named function and passing the value of this into toggle:
export default class ToggleDetails {
constructor(jobAdId) {
this.jobAdId = jobAdId
this.opened = false
}
toggle(t) {
// doing some other css manipulation for the detail view
t.handleCloseButton()
}
handleCloseButton() {
const closeButton = document.getElementById('uh-job-detail-close-button')
let listenerToggle = () => {
this.toggle(this);
};
if (this.opened === true) {
closeButton.classList.remove('uh-job-detail-close-button-show')
closeButton.removeEventListener('click', listenerToggle)
this.opened = false
} else {
closeButton.classList.add('uh-job-detail-close-button-show')
closeButton.addEventListener('click', listenerToggle)
this.opened = true
}
}
}
How to preserve the navigation bar (minimized position) when navigated to other module.
Collapsed Navigation Bar
sidebar-collapse will not preserve if navigated to other page.
Do you want your nav-bar to change from big to small when you move to a different place?
(sorry, I'm not allowed to comment yet).
Do you want your nav-bar to change from big to small when you move to a different place? It is always nice if you add some code :)
const menuToggle = document.querySelector('.menu-toggle');
const mainUl = document.querySelector(".main-ul");
const navBtn = document.querySelectorAll(".nav-a");
// Open and close meny on click
menuToggle.addEventListener("click", function () {
menuToggle.classList.toggle("open");
mainUl.classList.toggle("open");
});
// Close menu when clicked on an a-tag in the menu
navBtn.forEach((button) => {
button.addEventListener("click", function () {
navBtn.forEach((button) => button.classList.remove("active"));
this.classList.add("active");
mainUl.classList.toggle("open");
menuToggle.classList.toggle("open");
});
});
This is demo and source code I created
https://minhhungit.github.io/2020/10/16/011-keep-menu-toggle-state-after-page-reload/
namespace J {
export function storageSet(name, val) {
if (typeof (Storage) !== "undefined") {
localStorage.setItem(name, val);
} else {
//window.alert('Please use a modern browser to properly view this template!');
}
}
export function storageGet(name) {
if (typeof (Storage) !== "undefined") {
return localStorage.getItem(name);
} else {
return null;
}
}
}
In _Layout.cshtml put this code
<script type="text/javascript">
$().ready(function () {
new DailyTimelog.Common.SidebarSearch($('#SidebarSearch'), $('#SidebarMenu')).init();
// ...
// ...
$(window).bind("load resize layout", doLayout);
doLayout();
});
</script>
// Add these lines
<script type="text/javascript">
let sidebarToggleButton = $('.main-header .sidebar-toggle');
if (sidebarToggleButton) {
$(sidebarToggleButton).on('click', function (e) {
e.preventDefault();
let isSidebarCollapse = $('body').hasClass('sidebar-collapse');
J.storageSet('IS_SIDEBAR_COLLAPSE', !isSidebarCollapse);
});
}
</script>
And LeftNavigation.cshtml
<script type="text/javascript">
function openWindow(url, width, height) {
height = height || (screen.availHeight - 60);
// ...
// ...
}
// Add these lines
let isSidebarCollapseCache = J.storageGet('IS_SIDEBAR_COLLAPSE');
if (isSidebarCollapseCache == 'true') {
$('body').toggleClass('sidebar-collapse', true);
}
else {
$('body').toggleClass('sidebar-collapse', false);
}
</script>
``
#minhhungit Thank you for your demo.
I have used cookie implementation similar to ThemePreference.
Views/Shared/_Layout.cshtml
var theme = !themeCookie.IsEmptyOrNull() ? themeCookie : "blue";
// Add following lines
var sbNavCookie = Context.Request.Cookies["SBNavigationPreference"];
var sbNav = !sbNavCookie.IsEmptyOrNull() && sbNavCookie == "true" ? true : false;
in Body Tag,
<body ... class="...#(sbNav?" sidebar-collapse":"")">
In Script Tag,
<script type="text/javascript">
$().ready(function () {
// Add new lines
let sidebarToggleButton = $('.main-header .sidebar-toggle');
if (sidebarToggleButton) {
$(sidebarToggleButton).on('click', function (e) {
e.preventDefault();
let isSidebarCollapse = $('body').hasClass('sidebar-collapse');
$.cookie('SBNavigationPreference', !isSidebarCollapse, {
path: Q.Config.applicationPath,
expires: 365
});
});
}
I'm trying to change my text and image on click (mobile only) but it's not working. Only the image can be changed with the function I wrote. Could anyone help me with that, please?
Here is the live code: https://codepen.io/oleanderek/pen/OdNzME
document.querySelectorAll(".nav__label").forEach((el) => {
el.addEventListener('click', changeArrow);
el.addEventListener('click', changeText);
});
function changeArrow() {
var arrow = this.getElementsByClassName('arrow')[0];
if (arrow.classList.contains("down-arrow")) {
arrow.classList.remove("down-arrow");
arrow.classList.add("up-arrow");
} else if (arrow.classList.contains("up-arrow")) {
arrow.classList.remove("up-arrow");
arrow.classList.add("down-arrow");
}
}
function changeText() {
var changeText = this.getElementsByClassName('showText')[0];
if (changeText.classList.contains("showText")) {
arrow.classList.remove("showText");
arrow.classList.add("hideText");
} else if (changeText.classList.contains("hideText")) {
arrow.classList.remove("hideText");
arrow.classList.add("showText");
}
}
If you delete the class to change, the variable you define remains undefined. Therefore, you must define a class that you will not change. I added newClass This works fine.
HTML
<p class="newClass showText">.</p>
Javascript
document.querySelectorAll(".nav__label").forEach((el) => {
el.addEventListener('click', changeArrow);
el.addEventListener('click', changeText);
});
function changeArrow() {
var arrow = this.getElementsByClassName('arrow')[0];
if (arrow.classList.contains("down-arrow")) {
arrow.classList.remove("down-arrow");
arrow.classList.add("up-arrow");
} else if (arrow.classList.contains("up-arrow")) {
arrow.classList.remove("up-arrow");
arrow.classList.add("down-arrow");
}
}
function changeText() {
var changeText = document.querySelector(".newClass");
if (changeText.classList.contains("showText")) {
changeText.classList.remove("showText");
changeText.classList.add("hideText");
} else if (changeText.classList.contains("hideText")) {
changeText.classList.remove("hideText");
changeText.classList.add("showText");
}
}
I'm stumped with this one and would really appreciate someone's help.
I'm customizing highslide for integration with wordpress. Via the following code within the highslide.config.js file I'm adding a class name to certain elements and passing different attributes through an onClick call depending on certain conditions.
Everything works until I add the following code:
if(hsGroupByWpGallery){
slideshowGroup: this.parentNode.parentNode.parentNode.id
};
When the above code is present, not only does that one statement not execute, but the whole thing stops working. Even if the if statement is something like if(1=1){}; it still breaks.
If I have instead simply slideshowGroup: this.parentNode.parentNode.parentNode.id or nothing (the two options I'm looking for), both do what I would expect. I just need an if statement to switch between them.
Here's the relevant code:
jQuery(document).ready(function() {
var hsCustomGalleryGroupClass = 'fbbHighslide_GalleryGroup';
var hsCustomGalleryGroupChecker = 0;
var hsGroupByWpGallery = true;
jQuery('.' + hsCustomGalleryGroupClass).each(function(){
hsCustomGalleryGroupChecker++;
return false;
});
if (hsCustomGalleryGroupChecker > 0){
jQuery('.' + hsCustomGalleryGroupClass).each(function(i, $item) {
var grpID = $item.id;
jQuery('#' + grpID + ' .gallery-item a').addClass('highslide').each(function() {
this.onclick = function() {
return hs.expand(this, {
slideshowGroup: grpID
});
};
});
});
} else {
jQuery('.gallery-item a').addClass('highslide').each(function() {
this.onclick = function() {
return hs.expand(this, {
// This is the problem if statement
if(hsGroupByWpGallery){
slideshowGroup: this.parentNode.parentNode.parentNode.id
};
});
};
});
};
});
Thanks in advance.
The problem is you are trying to assign a conditional property.. you can't have a if condition inside a object definition like that
jQuery('.gallery-item a').addClass('highslide').each(function () {
this.onclick = function () {
var obj = {};
//assign the property only if the condition is tru
if (hsGroupByWpGallery) {
obj.slideshowGroup = this.parentNode.parentNode.parentNode.id;
}
return hs.expand(this, obj);
};
});
Another way to do the same is
jQuery('.gallery-item a').addClass('highslide').each(function () {
this.onclick = function () {
//if the flag is true sent an object with the property else an empty object
return hs.expand(this, hsGroupByWpGallery ? {
slideshowGroup: this.parentNode.parentNode.parentNode.id
} : {});
};
});
I think you might want this, based on the other code:
jQuery('.gallery-item a').addClass('highslide').each(function() {
this.onclick = function() {
if(hsGroupByWpGallery){
return hs.expand(this, {
slideshowGroup: this.parentNode.parentNode.parentNode.id
});
}
};
});
I added a custom 'quote' button.
ed.addButton('blockquote', {
title : 'blockquote',
cmd : 'mceblockquote',
image : url + '/img/blockquote.gif',
onclick : function() {
var blockquoteActive = tinyMCE.activeEditor.controlManager.get('blockquote').isActive();
if (blockquoteActive) {
//replace <blockquote> tags ?!
//set Button inactive
}
else {
ed.selection.setContent('<blockquote>' + ed.selection.getContent() + '</blockquote><br />');
}
}
});
ed.onNodeChange.add(function(ed, cm, n) {
cm.setActive('blockquote', n.nodeName == 'IMG');
})
When I click the button, everything works fine. The selection is quoted.
How do I replace the blockquote-tags when klicking the button again?
How do I set the button inactive?
Regards,
saromba
it worked thanks...
I've made some changes (maybe / probably improvements).
When nothing is selected, do nothing
When text is already quoted
When user marked the text with a double-click, the blockquote element will now be removed
onclick : function() {
var blockquoteActive = tinyMCE.activeEditor.controlManager.get('blockquote').isActive();
var selection = ed.selection.getContent();
if (blockquoteActive) {
if (selection) {
var parElem = ed.dom.getParent(ed.selection.getNode(), 'blockquote');
var inner = parElem.innerHTML;
ed.dom.remove(parElem);
ed.selection.setContent(inner);
}
else return
}
else {
if (selection) {
ed.selection.setContent('<blockquote>' + ed.selection.getContent() + '</blockquote><br />');
}
}
}
Try this. You may modify it a bit.
ed.addButton('blockquote', {
title : 'blockquote',
cmd : 'mceblockquote',
image : url + '/img/blockquote.gif',
onclick : function() {
var blockquoteActive = tinyMCE.activeEditor.controlManager.get('blockquote').isActive();
if (blockquoteActive) {
//replace <blockquote> tags ?!
content = ed.selection.getContent();
content.replace(/<\/?blockquote>/ig,'');
ed.selection.setContent(content);
//set Button inactive
// works only if blockquote is registered at the controlManager
ed.controlManager.setActive('blockquote', false);
}
else {
ed.selection.setContent('<blockquote>' + ed.selection.getContent() + '</blockquote><br />');
}
}
});