I have a webpage with images.
A user can click on images to show() or hyde() these images.
Sometimes, the user opens a popup to watch a video.
Then the code hide() all elements previously opened.
When the user closes the video, i need to know which elements was previously opened in order to show only them.
What is the best way to do that ?
What i've done :
I've created an array and i push images names into it.
var arr_popup_open = [];
Then, this function is called when user open a popup and hide all elements :
function toggleAllPopup() {
if( $('#popup_micro_1').is(":visible"))
{
$('#popup_micro_1').hide();
arr_popup_open.push('#popup_micro_1');
}
if( $('#popup_micro_2').is(":visible"))
{
$('#popup_micro_2').hide();
arr_popup_open.push('#popup_micro_2');
}
if( $('#popup_micro_3').is(":visible"))
{
$('#popup_micro_3').hide();
arr_popup_open.push('#popup_micro_3');
}
}
// and so on ... I have 7 images so it seems it's not very well optimized
When i need to show only images previously opened, i execute this code, a loop to show() elements in array.
$('#close_pop_up').click(function() {
for(var i= 0; i < arr_popup_open.length; i++)
{
$(arr_popup_open[i]).show();
}
});
What do you think about that ? Is there a better way to to do it ?
There are a few ways you could go about this with jQuery. Your way should work, but if you want to reduce the amount of code you could do something like:
var visibleDivs = $('div:visible', '#ContainerDiv');
Alternatively you could add a specific class to all visible elements when you show them and use:
var visibleDivs = $('.someClassName');
When hiding them due to your popup, you can store the list in the data of any element. In this case, putting it on #close_pop_up might make sense:
visibleDivs.hide();
$('#close_pop_up').data('myDivs', visibleDivs);
When you want to show them again in your click function:
$('#close_pop_up').click(function() {
$(this).data('myDivs').show();
});
Looks fine to me. Just remember to clear arr_popup_open in the start of the toggleopen function.
The alternative you could do if you really wanted is to keep the information of what is open or closed in Javascript variables that get updated when you open and close things. This way you don't need to depend on complex things such as is(:visible)
Related
Background information
I am trying to make a functional chrome-extension popup-window that enables the user to add links (based on the open tab's URL) when he desires it, and deletes one link or delete all of the links in just one click. Down below are all of my files! I must say in advance that I am not very good (and not experienced) with using jQuery's library but if that's the only solution that I have, than I will use it in my code.
The problem
The buttons to delete all the links and the button to add one link does work perfectly without bugs. However, the button to which one link should be deleted doesn't work, I tried various ways including splicing. I am trying to remove the link from the DOM and from the chrome.storage.local, both actions do not work. In the following code you can see all of the files I have thus far. The code of when the 'X' button is pressed doesn't get executed (see these pictures): https://i.stack.imgur.com/gg1Dy.png and https://i.stack.imgur.com/4oGdI.png
The code
manifest.json:
gist.github.com/kobrajunior/78acda830c2d1c384333542422f1494d
popup.js:
functions to look at: addToDom and removeMe and the very first event listener when the DOM is fully loaded
gist.github.com/kobrajunior/4852f85ae18cfb9edbe542a820b8c107
For extra information (if needed), the popup.html:
gist.github.com/kobrajunior/1c26691734c19391c62dc336ed2e1791
Thank you in advance.
For the following lines in popup.js, you want to restore (show all the items/buttons) and bind listeners, however don't forget addToDom is called inside the callback of chrome.storage.local.get, that means by the time you assign value to allButtons, they're not added to DOM, that causes allButtons.length === 0 and you didn't bind anything in fact.
Try to move the binding logic inside the callback of restore (You may encounter other issues however that's not covered in this quesions).
document.addEventListener('DOMContentLoaded', function () {
restore();
var allButtons = document.getElementsByClassName('buttons');
function listenI(i) {
allButtons[i].addEventListener('click', () => removeMe(i));
}
for (var i = 0; i < allButtons.length; i++) {
listenI(i);
}
});
function restore() {
// get the tab link and title
chrome.storage.local.get({ urlList: [], titleList: [] }, function (data) {
urlList = data.urlList;
titleList = data.titleList;
// add the titles and url's to the DOM
for (var i = 0, n = urlList.length; i < n; i++) {
addToDom(urlList[i], titleList[i]);
}
});
}
While I've done some Javascript coding, I consider myself a more novice, Frankenstein-type coder, basically cutting and pasting with trial and error to see if I can get something to work...just a heads up on my honest assessment of my experience level.
I've got a unique thing I'm developing for, and hoping to get some help with Javascript. Here's what I'm trying / need to do: for a webpage based kiosk presentation, I'm using one HTML webpage, but with multiple sections whose visibility toggles on/off based on a Javascript I currently have that works fine. (I don't want to / can't use regular HTML pages with links because of how it ends up running).
The only problem with the above issue is that there's no easy way to create a 'back' or 'previous page' link for an end page that may have multiple ways to get to it. It won't 'know' where the user came from.
So here's what I'd like to do: pass 2 variables through my OnClick javascript function, the DIV name that needs to toggle on/off ... AND a 2nd variable of the current visible DIV name so that the next DIV that toggles on can 'remember' what the previous (and now invisible) DIV was so that there can be an accurate 'back' button.
Here's some sample code:
Each DIV section that turns on an off is setup like this:
<div id="sectionName" class="content">
</div>
These DIVs have buttons/links that are setup like this:
These run a Javacript:
function toggleVisibility(selectedTab) {
var content = document.getElementsByClassName('content');
for(var i=0; i<content.length; i++) {
if(content[i].id == selectedTab) {
content[i].style.display = 'block';
} else {
content[i].style.display = 'none';
}
}
}
So what I'm hoping is that there is a way to do something like this:
So that when that is clicked, the next DIV that turns on could also include a Javascript generated link based on that passed variable, something like:
Previous<br>Menu
I'm aware that Javascript toggling of DIVs on and off may not allow the generation of a dynamic Javascript link like the one I'm describing above, so I'm throwing this out there for some help from other, far more experienced programmers. Ideally, I'd like to try and fit everything into what I've created so far, so I don't have to start over from scratch. Any ideas?
Please reference this sample page:
www.gs3creative.com/test/
You could use location hashes (mypage.html#mydivid) and then use history.back() to handle 'back' navigation.
To stitch up the div's showing on the correct hash value....
var oldHash = '';
// fires when the hash changes
function hash_changed() {
var hash = location.hash.replace('#', ''); // get the div ID
var div = document.getElementById(hash); // find the content div on the page
var allDivs = document.getElementByClassName('content'); // get all of the content divs
// hide all the content divs
for (var i = 0; i < allDivs.length; i++) {
var thisDiv = allDivs[i];
thisDiv.style.display = 'none';
}
// only show the right one
div.style.display = 'block';
}
// this triggers the event
setInterval(function() {
// if the hash has changed, fire the function
if (oldHash != location.hash) {
oldHash = location.hash;
hash_changed();
}
}, 100); // call every 100 ms so that there is no lag
So if you set the navigation to 'mypage.html#sectionName' it would hide all other div's of the class 'content' and then only show the div with the ID of 'sectionName'.
An easy solution for me would be to render two content pages on a HTML page and show and hide content when needed from a onlick handler via javascript in your CSS add a class:
function showDiv() {
document.getElementById("theObject").className = "visible";
}
CSS:
// Switch between the content adding the classes and removing the old class
.visible{
display:none;
}
.show{
display:block;
}
Another solution using sessions "php" via javascript to hold the variables with in statements.
<?php if (session_status() == PHP_SESSION_NONE) {
session_start();
$_SESSION['user_is where_variable'] = "im on page div 1";
}
This could also be done through js anyways.
javascript have a conditional statement using your $_SESSION vars;
if (variable == "im on page div 1" ){
// your functions
}else if ( variable == "im on page div 1"){
// another function
}
Create your click handler to update the variables in the session.
I have a button on a banner at the top of my page that launches several yui2 overlays on to the screen. Each overlay has a close button on it (which just changes the visibility to hidden so it can be reused). After the overlays are launched, there is also a button on the banner that appears will close all overlays if clicked.
This gives the use the option to close all or close each one individually. This is what i am stuck on:
If the user closes an individual overlay, after I close the overlay, I want to check if any other overlay is still open. If they happen to have closed all of them individually, then I need to revert the banner at the top and remove the "close all button".
I can search for all overlays by doing a:
var elements = YAHOO.util.Dom.getElementsByClassName('test');
I cant think of the logic I would need to do to go through that array each time they close an overlay to see all of them are set to visibility if hidden. If so, then execute a function. If there is still any overlays visible on the page, then do nothing.
This is the answer I came up with. Just not sure if it is correct.
var elements = document.getElementsByClassName('test');
var visiblecounter = 0;
for (var i = 0; i < elements.length; i++) {
if(elements[i].style.visibility!='hidden'){
alert("not hidden");
visiblecounter ++;
}
}
if(visiblecounter > 0){
alert("all overlays are closed individually. you can remove close all button");
}
You mention you are reusing those overlays so since you are pooling the overlays for reuse, I assume you have them in an array or something like that. Instead of checking the DOM (which is always expensive) to see if they are visible or not, loop through the array of overlays checking the visible attribute, like:
var anyVisible = false;
for (i = 0; i < myOverlays.length; i+=1) {
anyVisible |= myOverlays[i].cfg.getProperty("visible");
}
If any of them are visible, disable the button.
I am not sure I get the question, but I will try my best to help. Here are some things I would do. I also define an active class, so my HTML elements would be written as this:
<div class="john active"></div>
and in my css I would write.
.john {display: none};
.active {display: block};
So by default the object is hidden! But when you append the "active" class to it, it appears on the screen. So now we can do the following wizardry.
$(".hideButton").click(function() {
$(this).removeClass("active");
});
If I want to hide all the other objects, assuming that they have the same parent in the DOM
$(".hideOthersButton").click(function() {
$(this).siblings().removeClass("active");
});
if I want to hide all objects that share the same parent.
$(".hideEverything").click(function() {
$(".parent").children().removeClass("active");
});
I hope this helps! let me know if you need more help. The solution uses Jquery but you can repurpose the logic for anything else.
Simply put I'm trying to sync two slideshows created using widgetkit lib in a joomla website, eg. when user clicks next slide on one, the other one also runs nextSlide() function in the slideshow.js. Same for previous. The problems I'm having is widgetkit uses anonymous functions for creating those slideshows and I dont have global references to them after they are created. With my limited programming knowledge I cant seem to trigger the nextSlide function for other slideshows once inside click handler.
If anyone can take a look it would be most welcome.
EDIT:
Of course I forgot to link the example webpage
http://www.yootheme.com/widgetkit/examples/slideshow
Mine is similar with only 2 slideshows, but is still only on local server.
Taking a brief look at widgetkit here is one possible solution. Using jquery you can search for any objects that have a class of slides with a child of next and click all others. The code provided below isn't tested but should point you in the right direction. As long as you don't call stop propagation or prevent default then the original click handlers should still fire.
var slideshow_count = $('.slides .next').length;
var cascade_countdown = 0;
$('.slides .next').each(function() {
$(this).click(function() {
// stop an infinite loop if we're already cascading till we've done it for all the elements.
if(cascade_countdown != 0) {
cascade_countdown--;
return true;
}
// we don't include the slideshow we're clicking in this count
cascade_countdown = slideshow_count - 1;
var clicked_el = this;
$('.slides .next').each(function() {
// only click elements that aren't the initiator
if(this !== clicked_el) {
$(this).click();
}
});
});
});
Ran into problem with creating custom select dropdown plugin in jQuery. I'm at the one-at-the-time-open feature. Meaning, that when you open a dropdown, then other(s) will close.
My first idea was to create some global array with all dropdowns in it as objects. Then in the "opening"-function, I would add the first line to first check that none of the dropdowns are open (if open, then close them.)
I created a very scaled version of my script: http://jsfiddle.net/ngGGy/1/
Idea would be to have only one dropdown open at the time. Meaning, that when you open one, other(s) must be closed, if not they will automatically close when a new one is opened.
Your dropdown set seems to behave like an accordion.
This is easier to accomplish if you wrap each dropdown in a div with a class, then use that to target all the dropdown uls you have.
I forked your jsfiddle with a working example.
(EDIT updated fiddle link)
You can keep track of the DropDownSelectized lists like this: http://jsfiddle.net/pimvdb/ngGGy/3/.
(function($){
var lists = $(); // cache of lists
$.fn.DropDownSelect = function (settings) {
jQuery.globalEval("var zindex = 100");
var thiselement = $(this);
var thislist = thiselement.next('ul');
lists = lists.add(thislist); // add current one to cache
thiselement.click(function () {
lists.slideUp(); // hide all lists initially
if (thislist.is(':visible')) {
thislist.slideUp();
} else {
thislist.css('z-index', ++zindex).slideDown();
}
});
};
})(jQuery);
You're definitely on the right track, but if you're only going to have one dropdown list open at a time then you want them to be related somehow. Fortunately your markup is already there, so all we should have to do is modify the JS. I've updated your jsFiddle project here: http://jsfiddle.net/ninjascript/ngGGy/4/
First the selector. jQuery will let you select attributes that are similar by using ^= like this:
$('div[id^=button]').DropDownSelect();
Now we just have to update your plugin a bit. Notice that what used to be 'thislist' is now called 'everylist'. Now we can enforce that every list closes on click before opening the list associated with the button that was clicked.
(function($){
$.fn.DropDownSelect = function (settings) {
jQuery.globalEval("var zindex = 100");
var thiselement = $(this);
var everylist = thiselement.next('ul');
thiselement.click(function () {
var thislist = $(this).next('ul');
if (everylist.is(':visible')) {
everylist.slideUp();
}
thislist.css('z-index', ++zindex).slideDown();
});
};
})(jQuery);
Good luck!
Why not raise an event that all drop-downs subscribe to. pass in the id (or instance) of the one currently being opened. In the handler check whether the handling instance is the one being opened. If not, close it.