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.
Related
With the help of SO member the.marolie I learned how to implement a JS filter/selector [the 'demo JS filter']. I have this working perfectly on a test page: it shows/hides divs according to "data-types" assigned to them in the body html. However, the selection is made by sliding down a <select> dropdown list and letting go at the preferred option. That's not quite what I want.
I want to utilise my existing nav-bar dropdown ['my dropdown'] as the filter/selector. I especially want to retain the existing interactivity of my dropdown, whereby one click/tap reveals the whole of the dropdown content block, and one click outside the content block closes it.
I want the elements within my dropdown to represent various show/hide <div> 'options' for the html page, and enable the user to choose from these via an additional click/tap (essentially what the demo JS filter does, but at the instigation of a click/tap). Once revealed via a nav-bar click/tap, the whole dropdown content block has to stay on-screen -as it currently does- for this to be practically possible.
After making my dropdown identifiable via id="media-selector-demo" and name="filter" I was hoping that I could assign the demo JS filter's <option> elements to the <a> elements in it, and the whole thing would function like the <select> dropdown of the demo JS filter. I had a vague idea that using <a> elements might obviate the need for another onClick in the JS. I've tried various combinations of <a> and <option> elements, but nothing has worked yet.
Do I need another onClick to invoke the JS filter via my dropdown? or
Can I invoke the JS filter via 'active' <a> status?
I'm struggling by trial and error.
Here are what I think are the relevant sections of code pertaining to all discussed above:
My dropdown is based on the following code.
JS in the page head:
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myDropdownJS() {
document.getElementsByClassName("navbarDROPDOWN-JS")[0].classList.toggle("show");
}
// Close the dropdown if the user clicks outside of it
window.onclick = function(e) {
if (!e.target.matches('.dropbtn')) {
var myDropdown = document.getElementsByClassName("navbarDROPDOWN-JS")[0];
if (myDropdown.classList.contains('show')) {
myDropdown.classList.remove('show');
}
}
}
My dropdown html in nav bar (most of the css is just design styling):
<span class="dropdown" onclick="myFunction()">
<a class="dropbtn navbarDROP-ICON" style="opacity:0.5; padding-top:0px;">menu</a>
<a class="dropbtn navbarDROP-TXT" style="opacity:0.5">menu </a>
<a class="dropbtn navbarDROP-TXT">Career Works by Date </a>
<div class="dropdown-content navbarDROPDOWN-JS" >
<a class="tag-bgd-INSTLLN" href="#">Installations (all media)</a>
<a class="tag-bgd-MOVIMG" href="#">Works with moving image (inc. vid/film releases)</a>
<a class="tag-bgd-SNDMUS" href="#">...with sound and music (inc. sound/music releases)</a>
<a class="tag-bgd-PHOTO" href="#">...with photographs</a>
<a class="tag-bgd-DRAW" href="#">...with drawing (inc. 2D works)</a>
<a class="tag-bgd-TXT" href="#">...with text</a>
<a class="tag-bgd-PERF" href="#">...with performative action</a>
<a class="tag-bgd-COLPUB" href="#">Collaborative and public works</a>
<a class="tag-bgd-OBJDEV" href="#">>Objects, garments, devices</a>
<a class="tag-bgd-EDPUB" href="#">Editions, publications</a>
<a class="tag-bgd-CAREER" href="#">Career Works by Date</a>
</div>
Above: the <a href> elements were going to contain URLs for alternatively styled pages. There is no need for these if I can enable the user to selectively show/hide parts of just this one page, via this dropdown.
The demo JS filter is based on the following code (via SO user the.marolie).
JS at page end:
var select = document.getElementById('media-selector-demo');
var filter;
select.addEventListener("change", function() {
filter = select.value;
var elements = document.querySelectorAll('.wk-date_ITEM');
elements.forEach((el) => {
var type = el.dataset.type.split(', ');
if (type.includes(filter)) {
el.classList.remove('hide-by-media');
} else {
el.classList.add('hide-by-media');
}
})
});
Demo JS filter CSS:
.hide-by-media {
display: none;
}
Demo JS filter html in page body:
<select id="media-selector-demo" name="filter">
<option value="INSTLLN"> Installations (all media)</option>
<option value="MOVIMG"> Works with moving image (inc. vid/film releases)</option>
<option value="SNDMUS" >...with sound and music (inc. sound/music releases)</option>
</select>
Example div in page body (there are 80-100 of these):
<!-- ++++++++++ START FULL-WIDTH LIST ENTRY '2017 STATE OF DREAD' ++++++++++ -->
<div id="state-of-dread" class="w3-container wk-date_ITEM" data-type="INSTLLN, SNDMUS">
<div class="w3-container wk-date_TXT-IMG">
<div class="wk-date_GRID">
<div class= "h3 wk-date_DATE"> 2017 </div>
<div class="wk-date_TTL"><h1>State of Dread</h1></div>
<div class="h2 wk-date_KIND-1" >Installation</div>
<div class="p wk-date_KIND-2" ><span class="sound">Sound</span>, for x2 interconnected rooms.<br>AB, CD, EF, Solo exhibition (as trio), Ohrenhoch sound gallery, Berlin.</div>
<div class="wk-date_IMG">
<div class="w3-container w3-right wk-date_IMG-BOX-LSCP">
<img src="../../imgs/INSTALLATION-EVENT/2017_dread_thmb.jpg"
alt="'xx' by Andrew Stones, installation view, xx"></div>
</div>
</div>
</div>
</div>
<!-- ++++++++++ END FULL-WIDTH LIST ENTRY '2017 STATE OF DREAD' ++++++++++ -->
Demo JS filter: JS at end of page:
<script type="text/javascript">
var select = document.getElementById('media-selector-demo');
var filter;
select.addEventListener("change", function() {
filter = select.value;
var elements = document.querySelectorAll('.wk-date_ITEM');
elements.forEach((el) => {
var type = el.dataset.type.split(', ');
if (type.includes(filter)) {
el.classList.remove('hide-by-media');
} else {
el.classList.add('hide-by-media');
}
})
});
</script>
What you would need to do is change the event listener from select, change to drop down element, click. you would also need to add the values of the options from the select as data-value attributes on the drop down elements.
1 - add a data-value attribute to the elements to represent what to hide
<a class="tag-bgd-INSTLLN" href="#" data-value="INSTLLN">
2 - target the drop down elements you want to attach the event listener to.
const dropDownElements = document.querySelectorAll('.dropdown-content a')
3 - attach event listeners to the selected targets (PS. the e in the function stands for event, click event listener produces an event object)
dropDownElements.forEach((dropDownElement) => {
dropDownElement.addEventListener('click',(e)=>{
const filter = e.target.dataset.value;
})
})
4 - the rest is just adding the rest of the filter used in the demo js filter
dropDownElements.forEach((dropDownElement) => {
dropDownElement.addEventListener("click", (e) => {
const filter = e.target.dataset.value
var elements = document.querySelectorAll(".wk-date_ITEM")
elements.forEach((el) => {
var type = el.dataset.type.split(", ")
if (type.includes(filter)) {
el.classList.remove("hide-by-media")
} else {
el.classList.add("hide-by-media")
}
})
})
})
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>
I am working with a free responsive web template that I have edited to make a small portfolio site for a friend. The issue that I am having is that when I choose a specific image gallery and view in the Fancybox window, it will continue to click through all of the images, and not just the ones in that specific gallery.
I have been searching and found this solution (https://groups.google.com/forum/#!topic/fancybox/ncVsViD2v9o), but I don't really have a knowledge of javascript so I'm unsure if this would work for me or how to implement it into the template's code. I've included a portion of the html and what I believe is the related js below:
HTML
<!-- 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">Photography</li>
<li>All Images
</li>
<li>People
</li>
<li>Places
</li>
<li>Things
</li>
</ul>
</nav>
<!-- End Filter -->
</div>
<div class="span9">
<div class="row">
<section id="projects">
<ul id="thumbs">
<!-- Item Project and Filter Name -->
<li class="item-thumbs span3 people">
<!-- Fancybox - Gallery Enabled - Title - Full Image -->
<a class="hover-wrap fancybox" data-fancybox-group="gallery" title="John" href="_include/img/work/full/people-01-full.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/people-01.jpg" alt="Print Number 1–10">
</li>
<!-- End Item Project -->
<!-- Item Project and Filter Name -->
<li class="item-thumbs span3 things">
<!-- Fancybox - Gallery Enabled - Title - Full Image -->
<a class="hover-wrap fancybox" data-fancybox-group="gallery" title="Garden Wall" href="_include/img/work/full/things-07-full.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/things-07.jpg" alt="Print Number 1–22">
</li>
<!-- End Item Project -->
JS
BRUSHED.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;
});
}
}
Any insight would be greatly appreciated and please let me know if I need to give anymore information.
Thanks!
Your live link was really helpfull to try something.
Nice presentation, by the way.
So... The solution to your issue was, like I said in comments yesterday, to change the data-fancybox-group attribute... And you have to do it on click of a category link.
The pictures IN the selected category must NOT be in the FancyBox group "gallery"... But in a "selected" gallery. Only pictures with the same gallery name as the one that was clicked to trigger FancyBox will then be displayed.
Here is the code I added:
// find the clicked category
var fancyBoxClassToShow = $(this).attr("data-option-value");
// reset all data-fancybox-group (in case of a previous selection)
$("#thumbs").find(".item-thumbs").each(function(){
$(this).find("a").attr("data-fancybox-group","gallery")
});
// change all data-fancybox-group that IS a child of the clicked category
$("#thumbs").find(fancyBoxClassToShow).each(function(){
$(this).find("a").attr("data-fancybox-group","gallerySelected")
});
I added only these lines in your $optionLinks.click function, right above var $this = $(this);.
And that's it.
See CodePen here.
There is a pageA with 3 div(consider). also i'm having a link in another page. when users clicks the link they have to reach the 3rd div in pageA. How to do this?
In my code all div are hidden except the one which is selected at that
time. so there is no need for scrolling.
Demo
HTML:(PageA.html)
<div id="mws-navigation">
<ul id="link">
<li class="" data-related="a" id="a1"><i class="icon-book"></i>A</li>
<li data-related="b" class="" id="b1"><i class="icon-search"></i>B</li>
<li data-related="c" class="" id="c1"><i class="icon-calendar"></i>C</li>
</ul>
</div>
<!-- Main Container Start -->
<div id="mws-container" class="clearfix">
<!-- Inner Container Start -->
<div id="a" class="tab">
aaaa
</div>
<div id="b" class="tab">
bbbb
</div>
<div id="c" class="tab">
cccc
</div>
</div>
page B.html:
vvv// this link will be in other page(to reach C)
// what i have to give in herf="" to reach that particular div
JQuery:
$(function()
{
$('#link li').removeClass('actif');
$(this).find('li').addClass('actif');
$('.tab').hide();
$('#a').show();
document.getElementById('a1').className='active';
$('#link li').click(function(e){
$('#link li').removeClass('actif');
$(this).find('li').addClass('actif');
$('.tab').hide();
$('#'+$(this).attr('data-related')).show();
e.preventDefault();
});
});
Any suggestion?
Ok so I think you're saying you want to show and focus on a particular element based on what a user has clicked on coming from another page.
On pageB add a parameter to your querystring in your hrefs like so:
vvv
If you have server side access - java, php or something then I would suggest using that to handle the query string and add a class to your div on pageA
<div id="c" class="tab showAndFocus"> cccc</div>
var myElementToShow = $(".showAndFocus");
myElementToShow.show();
myElementToShow.focus();
OR
However, if you only have jquery/javascript to do this (i.e. there is no server side to help you work with the query string) then you can get access to the query string parameters as discussed here
var urlParams;
(window.onpopstate = function () {
var match,
pl = /\+/g, // Regex for replacing addition symbol with a space
search = /([^&=]+)=?([^&]*)/g,
decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
query = window.location.search.substring(1);
urlParams = {};
while (match = search.exec(query))
urlParams[decode(match[1])] = decode(match[2]);
})();
Once you have the query string you can grab the div you want to show pretty easily...
var myElementToShow = $("#"+urlParams.showdiv);
myElementToShow.show();
myElementToShow.focus();
You can read location.hash when pageA loads - in your jQuery load($) function
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