Generating random data-attributes for tabbed content - javascript

I'm trying to create random numbers so that they can be assigned to each class instance.
The reason I'm doing this is because I have tabbed content and when I have two instances of the tabbed modules, it resets the data attributes. For example:
My page has content with three tabs. These tabs currently have the data-item attribute of 1,2 and 3.
I then add another tab module of three tabs. When I add this module to the page, the data-item resets to 1.
In short, two tabs exist on page which has the data-item attribute of 1, 2 and 3.
So when I click on one tab, the other tab (which has the duplicated data-item) changes too.
When a user clicks a tab, it displays an image assigned to that section (they're linked through data-item).
So I'm trying to generate unique data-items and assign them to both a .tab and an .image. This will pair them up.
However, with my current approach, it's assigning them to all of the tabs.
Current approach:
$(function() {
// generate random id for data item
var randomnNmber = Math.floor(1000 + Math.random() * 9000);
$('.imageWrapper .image').each(function () {
$(this).attr('data-item',randomnNmber);
});
$('.tabsWrapper .tab').each(function () {
$(this).attr('data-item',randomnNmber);
});
$(".tab").on("click", function(){
var tabID = $(this).attr("data-item");
event.stopPropagation();
$('.image').removeClass('active');
$('.image[data-item = '+tabID+']').addClass('active');
$(".tab").removeClass("active");
$(this).addClass("active");
});
});
<div class="tabbedContent">
<div class="imageWrapper">
<div class="image">
<!-- image -->
</div>
<div class="image">
<!-- image -->
</div>
</div>
<div class="tabsWrapper">
<div class="tab">
<!-- tab text here -->
</div>
<div class="tab">
<!-- tab text here -->
</div>
</div>
</div>

Note random numbers are not guaranteed to be unique.
It's very likely that you will get duplicate numbers using this method.
You could add an array to store "used" numbers and check that to reduce duplicates.
But to answer your question:
Your code generates a single random number at the top and then assigns that single number too all (in turn) (as you've found).
You need to regenerate the number each time, but to get them in pairs you need a single loop.
I've also converted to .data() rather than .attr("data-
Updated snippet:
$(function() {
var images = $('.imageWrapper .image');
var tabs = $('.tabsWrapper .tab');
if (images.length !== tabs.length)
alert("tabs and images don't match");
else {
for (var i = 0; i < images.length; ++i) {
// generate a different random id for each pair
var randomNumber = Math.floor(1000 + Math.random() * 9000);
images.eq(i).data("item", randomNumber);
tabs.eq(i).data("item", randomNumber);
}
}
$(".tab")
.css("cursor", "pointer")
.on("click", function() {
var tabID = $(this).data("item");
event.stopPropagation();
$('.image').removeClass('active');
$(".image").filter(function() {
return $(this).data('item') == tabID
}).addClass('active');
$(".tab").removeClass("active");
$(this).addClass("active");
});
});
.active { color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="tabbedContent">
<div class="imageWrapper">
<div class="image">
image 1
<!-- image -->
</div>
<div class="image">
image 2
<!-- image -->
</div>
</div>
<div class="tabsWrapper">
<div class="tab">
tab 1
<!-- tab text here -->
</div>
<div class="tab">
tab 2
<!-- tab text here -->
</div>
</div>
</div>

Related

Hide particular div if all elements have the same class

I have a bunch of same elements on the page. All those elements have this particular structure:
<div id="9p" class="col s12 m6 l2 cardmaion globalcardclass">
<div class="card 9p">
<div class="card-content ">
<div class="row card-row">
<!-- a bunch of divs -->
<!-- a line of a card -->
<a data-category="here" class="hidden">
<div style="border-top:2px dotted gray;font-size:18px;background:ivory;margin-top:1px;"
id="belanimation" class="card-line waves-effect waves-green">
Some random text goes here <span class="card-line-q"> x 1</span><span
class="modspan "></span></div>
</a>
<!-- a line of a card -->
<a data-category="here" class="hidden">
<div style="border-top:2px dotted gray;font-size:18px;background:ivory;margin-top:1px;"
id="belanimation" class="card-line waves-effect waves-green">
Some random text goes here <span class="card-line-q"> x 2</span><span
class="modspan "></span></div>
</a>
<!-- a line of a card -->
<a data-category="here" class="hidden">
<div style="border-top:2px dotted gray;font-size:18px;background:ivory;margin-top:1px;"
id="belanimation" class="card-line waves-effect waves-green">
Some random text goes here <span class="card-line-q"> x 2</span><span
class="modspan "></span></div>
</a>
</div>
</div>
</div>
</div>
All the cards (example above) have common class = globalcardclass (it's only way to track that 'card elements')
All lines in a card could be (or not!) contains class = hidden
So I want a script to hide the whole card if all <a> elements (lines) have the class = hidden
If one or two elements (lines) do not have class hidden -- the card is shown.
I need to add another hide class to a particular card if all its children elements have class hidden.
Here I try something but It doesn't work at all. The hard part is... when the card element gets elements (lines) with class hidden that card must show up again...
Please, help.
<script>
$(document).ready(function () {
function FilterHere() {
var emptyCounter = 0
jQuery(".globalcardclass a").each(function () {
if ($(this).is('.hidden')) {
emptyCounter++
}
emptyCounter--
});
if (emptyCounter === 0) {
$(".globalcardclass").hide();
}
}
setTimeout(FilterHere, 2000);
});
</script>
UPD!
Here is new way to solve my problem:
jsfiddle.net/q6cekb18
But it also doesn't work...
UPD 2 (!)
Finally! I've got some progress!
$(".globalcardclass").filter(function(){
return $(this).find(".smoothmaion:visible").length == 0;
}).hide();
That code is working... All the card are hiding... But...
A card (.globalcardclass) is not showing up if 'line' element (.smoothmaion) becomes visible again... How to make it some sort of a... toggle?
Yeah... I can:
<script>
function Filtering()
{
$(".globalcardclass").filter(function(){
return $(this).find(".smoothmaion:visible").length == 0;
}).toggleClass( "hide_hide" )
};
</script>
But... When I use another button to filter different type of elements... That 'toggle' thing brings back that hidden element 'cause it has not change so ... toggle..
What can I do?

Replace Content of a Div on single page site

So I've been building a site based off a template I found online, a would appreciate any help getting it to function how I want it to. Currently its set up with filters that allow you to sort through multiple thumbnails. However I want the links that currently act as "filters" to instead replace the div where all the thumbnails show up.
I've searched around here looking at jQuery, to replace div content, including replacing the contents of the div, and hiding divs and showing them on click. Nothing I seem to do works though.
Ideally, I'd wrap the current UL in a div named "designprojects" and then when I click a filter that div gets replaced with a new one that has project info in it.
Here is the current HTML and Javascript that the site uses to make the filters function:
filter = function() {
if ($('#projects').length > 0) {
var $container = $('#projects');
$container.imagesLoaded(function() {
$container.isotope({
// options
animationEngine: 'best-available',
itemSelector: '.item-thumbs',
layoutMode: 'fitRows'
});
});
// filter items when filter link is clicked
var $optionSets = $('#options .option-set'),
$optionLinks = $optionSets.find('a');
$optionLinks.click(function() {
var $this = $(this);
// don't proceed if already selected
if ($this.hasClass('selected')) {
return false;
}
var $optionSet = $this.parents('.option-set');
$optionSet.find('.selected').removeClass('selected');
$this.addClass('selected');
// make option object dynamically, i.e. { filter: '.my-filter-class' }
var options = {},
key = $optionSet.attr('data-option-key'),
value = $this.attr('data-option-value');
// parse 'false' as false boolean
value = value === 'false' ? false : value;
options[key] = value;
if (key === 'layoutMode' && typeof changeLayoutMode === 'function') {
// changes in layout modes need extra logic
changeLayoutMode($this, options)
} else {
// otherwise, apply new options
$container.isotope(options);
}
return false;
});
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Portfolio Projects -->
<div class="row">
<div class="span3">
<!-- Filter -->
<nav id="options" class="work-nav">
<ul id="filters" class="option-set" data-option-key="filter">
<li class="type-work">Projects</li>
<li>All Projects</li>
<li>Starbucks CSR Project</li>
</ul>
</nav>
<!-- End Filter -->
</div>
<div class="span9">
<div class="row">
<section id="projects">
<ul class="thumbs">
<!-- Item Project and Filter Name -->
<li class="item-thumbs span3 StarbucksCSR">
<!-- Fancybox - Gallery Enabled - Title - Full Image -->
<a class="hover-wrap fancybox" data-fancybox-group="gallery" title="Project Title" href="_include/img/work/full/url.jpg">
<span class="overlay-img"></span>
<span class="overlay-img-thumb font-icon-plus"></span>
</a>
<!-- Thumb Image and Description -->
<img src="_include/img/work/thumbs/url.jpg" alt="Project info">
</li>
<!-- End Item Project -->
</ul>
</section>
</div>
</div>
</div>
<!-- End Portfolio Projects -->
To recap, when I click "All Projects" I want to see thumbnails that I can click and make full screen (current function, also want this to be the default).
When I click a project name, I want the div that holds all the thumbnails to be replaced with a paragraph about the project, and additonal thumbnails that can be clicked to extend to full screen.
My current progress can be seen at www.codyshipman.com
Look in the jQuery's .html() function. If you want to replace content of a <div> element, pass the new content as parameter to the .html(newContentAsString) function, for that <div> element. Look at the documentation for more info.

Scope issue in Javascript when writing to an array

BACKGROUND
I have a list of buyerNames and want the admin user to be able toggle their names. So far so good. Visually it works as expected. Admin user clicks on name and it's toggled on (background around the name and the items changes shade). Admin user can click and unclick names to his heart's desire.
CODE BELOW: I'm showing large sections of my code in case I'm messing something up in
a place where I don't think there's a problem.
<div class="headerSecondaryBg"> <!-- THE BACKGROUND LAYER - POSITION AND COLOR -->
<div class="buyerItems"> <!-- NUMBER OF BUYER ITEMS -->
<div class="item i1">42</div>
<div class="item i2">31</div>
<div class="item i3">57</div>
<div class="item i4">49</div>
<div class="item i5">16</div>
<div class="item i6">38</div>
<div class="item i7">24</div>
</div>
<div class="buyerNames"> <!-- BUYER NAMES -->
<div class="buyer b1">BUYERNAME 1 </div>
<div class="buyer b2">BUYERNAME 2 </div>
<div class="buyer b3">BUYERNAME 3 </div>
<div class="buyer b4">BUYERNAME 4 </div>
<div class="buyer b5">BUYERNAME 5 </div>
<div class="buyer b6">BUYERNAME 6 </div>
<div class="buyer b7">BUYERNAME 7 </div>
</div>
<div class="selectBuyer"> <!-- CREATES THE VISIBLE ON / OFF FOR THE TOGGLE AS PER DESIGN SPEC -->
<div class="selectBuyerOff b-on1"></div>
<div class="selectBuyerOff b-on2"></div>
<div class="selectBuyerOff b-on3"></div>
<div class="selectBuyerOff b-on4"></div>
<div class="selectBuyerOff b-on5"></div>
<div class="selectBuyerOff b-on6"></div>
<div class="selectBuyerOff b-on7"></div>
</div>
</div><!-- // END headerSecondaryBg -->
BACKGROUND
After the admin user has selected his buyers he clicks "show items" to reveal a hidden div below.
PROBLEM: Putting the toggled names into an array.
STEP 1:
Get buyerName (b-on1, b-on2 ... in this test example) and place in array.
$(".selectBuyer div" ).click(function(){
$(this).toggleClass("selectBuyerOn"); // show user that items are on or off
var all=$(this).attr('class');
console.log(all);
console.log = selectBuyerOff b-on1 selectBuyerOn.
EXACTLY WHAT WAS EXPECTED (considering I clicked on buyer 1)
STEP 2:
OK. Let's just have b-on1 and get rid of the other classes.
$(".selectBuyer div" ).click(function(){
$(this).toggleClass("selectBuyerOn"); // show user that items are on or off
var all=$(this).attr('class');
bbb=$(this).attr('class').split(' ')[1];
console.log(all);
console.log(bbb);
I get what's expected:
console.log(all) = selectBuyerOff b-on1 selectBuyerOn
console.log(bbb) = b-on1
STEP 3:
NOW let's put it into an array. (This goes immediately after the above code)
testArr=[];
testArr.push(all);
testArr.push(bbb);
console.log(testArr);
console.log = ["selectBuyerOff b-on1 selectBuyerOn", "b-on1"]
Now here's the problem - the array resets itself after every click.
I want the array to have b-on1 and b-on2 if the user selected those and
b-on1 and b-on2 if the user selected b-on1, b-on2, b-on3 (and then untoggled b-on3)
and yet the array is reset after every click.
How do I get this to work?
I tried removing var so that the variable would be in the global scope. I must be missing something simple.
When testArr=[] is executed, the testArr variable is assigned to a brand new empty array.
It sounds like you need to initialize this array just the once outside of the click handler, and then simply push values into the existing array within the handler. For example:
var testArr = [];
$(".selectBuyer div" ).click(function(){
$(this).toggleClass("selectBuyerOn"); // show user that items are on or off
var all=$(this).attr('class');
bbb=$(this).attr('class').split(' ')[1];
testArr.push(all);
testArr.push(bbb);
console.log(testArr);
/* ... */
});

Hide and Show WinJS.UI.PivotItem

I need to hide a WinJS.UI.PivotItem for a Windows Phone 8.1 app and then show it again once certain criteria have been met.
I thought it would be as simple as using CSS to show and hide the WinJS.UI.PivotItem, but it hides the .win-pivot-item element but not the .win-pivot-header?
How can I programmatically show and hide a WinJS.UI.PivotItem in a WinJS.UI.Pivot control?
<div id="divContent" data-win-control="WinJS.UI.Pivot" data-win-options="{title: 'Details', selectedIndex: 0}">
<div id="divSelected" style="display: none;" data-win-control="WinJS.UI.PivotItem" data-win-options="{'header': 'Currently Selected'}">
<!-- Content - Hide this until we need it -->
</div>
<div id="divSelections" data-win-control="WinJS.UI.PivotItem" data-win-options="{'header': 'Selections'}">
<!-- Content -->
</div>
<div id="divInformation" data-win-control="WinJS.UI.PivotItem" data-win-options="{'header': 'Other Information'}">
<!-- Content -->
</div>
<div id="divHistory" data-win-control="WinJS.UI.PivotItem" data-win-options="{'header': 'History'}">
<!-- Content -->
</div>
<div id="divDetails" data-win-control="WinJS.UI.PivotItem" data-win-options="{'header': 'Details'}">
<!-- Content -->
</div>
</div>
There currently isn't a direct API to show/hide WinJS.UI.PivotItems on the WinJS.UI.Pivot control.
Depending on your desired UX and criteria for show/hiding, you can programmatically add/remove a PivotItem from the list of PivotItems returned by the Pivot.items property on the WinJS.UI.Pivotcontrol.
For example:
function createPivotElement() {
// Use document.createElement("div") to build up the DOM for the Pivot Item
// Or you could render a page using the WinJS.UI.Pages API
// Return a DOM element
return document.createElement('div');
}
// When criteria is met...
// Find the pivot in the DOM
var p = document.querySelector(".myPivot");
var pivot = p.winControl;
var element = createPivotElement();
var pivotItem = new WinJS.UI.PivotItem(element, { header: 'New PivotItem' });
// Add new PivotItem
// You could use other things like splice to add it to a specific index etc.
pivot.items.push(pivotItem);
You can also look at the Pivot Sample or on http://try.buildwinjs.com/#pivot for more usage examples

The slideshow and the zoom function is not working anymore of fetching content

I have an images slideshow which each images can bee zoomed in the slideshow. And all the codes I used was working fine before I added some change there.
Here is the working code:
<div id="leftBigWraper"><!-- Example -->
<div id="bigPicture">
<div class="easyzoom easyzoom--overlay">
<p></p>
<img src="colour/big/Evan-Picone-Turtleneck-Sweater-Dress__01688224_balired_1.jpg" alt="" width="100%"/></div>
<div class="easyzoom easyzoom--overlay">
<p></p>
<img src="colour/big/Evan-Picone-Turtleneck-Sweater-Dress__01688224_balired_2.jpg" alt="" width="100%"/></div>
</div>
<div id="smallPicture">
<img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_balired_1.jpg" width="100%">
<img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_balired_2.jpg" width="100%">
</div>
</div><!-- End of Example -->
<!--End of Wraper in the Left Side (Product Images)-->
In the working code, all the content in the #bigPicture div is set maually, and the slideshow is run by this script:
var $el = $('#leftBigWraper'),
// SETUP ////////
F = 600 , // Fade Time
P = 5000 , // Pause Time
C = 0 , // Counter / Start Slide# (0 based)
///////////////////
$sl = $('#bigPicture > div'),
$th = $('#smallPicture > img'),
N = $sl.length,
T = 10000;
$sl.hide().eq(C).show();
$th.eq(C).addClass('on');
// ANIMATION
function anim() {
$sl.eq(C%N).stop(1).fadeTo(F,1).siblings().fadeTo(F,0);
$th.removeClass('on').eq(C%N).addClass('on');
}
// AUTO ANIMATE
function autoAnim() {
T = setTimeout(function() {
C++;
anim(); // Animate
autoAnim(); // Prepare another iteration
}, P+F);
}
autoAnim(); // Start loop
// HOVER PAUSE
$el.hover(function(e) {
return e.type==='mouseenter'? clearTimeout( T ) : autoAnim();
});
// HOVER THUMBNAILS
$th.on('mouseenter', function() {
C = $th.index( this );
anim();
});
THE WORKING FIDDLE
However, when all the contents in the #bigPicture div are set by calling it from hidden div and with Jquery, the slideshow and the zooming function is not working anymore.
The Jquery that I used to fill the blank div from the hidden div is here:
$(document).ready(function(){
$('#bigPicture').html($('#pilihWarna li #bigHidden:first').html());
$('#smallPicture').html($('#pilihWarna li #smallHidden:first').html());
$('#pilihWarna li').click(function(event) {
$('#bigPicture').html($(this).find('#bigHidden').html());
$('#smallPicture').html($(this).find('#smallHidden').html());
});
});
As follows:
First, I left the div of #bigPicture to be blank or without any content in there.
<!--Wraper in the Left Side (Product Images)-->
<div id="leftBigWraper"><!-- Example -->
<div id="bigPicture"></div>
<div id="smallPicture"></div>
</div><!-- End of Example -->
<!--End of Wraper in the Left Side (Product Images)-->
Then, I create some hidden div that will transfer all the contents insede the div to the #bigPicture div.
<ul id="pilihWarna" style="">
<li><img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_balired_1_7.jpg" width="10%">
<div id="bigHidden">
<div class="easyzoom easyzoom--overlay">
<p></p>
<img src="colour/big/Evan-Picone-Turtleneck-Sweater-Dress__01688224_balired_1.jpg"></div>
<div class="easyzoom easyzoom--overlay">
<p></p>
<img src="colour/big/Evan-Picone-Turtleneck-Sweater-Dress__01688224_balired_2.jpg"></div>
</div>
<div id="smallHidden">
<img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_balired_1.jpg">
<img src="colour/thumnail/Evan-Picone-Turtleneck-Sweater-Dress__01688224_balired_2.jpg">
</div>
</li>
The ul which its id is #pilihanWarna has at least 5 li, which I used as clickable menus that I have been discussing here
That's when the slidshow and the zooming images functions are not working anymore.
You're using the same IDs multiple times, IDs should be unique. Given multiple elements with the same ID:
<div id="foo">One</div>
<div id="foo">Two</div>
<div id="foo">Three</div>
Searching the DOM for the elements will only ever return the first instance:
document.getElementById('foo'); // returns <div id="foo">One</div>
Start by removing the duplicated IDs and using a different selector (a class probably, but you could just use an element selector too) and then you might be getting somewhere.

Categories