I'm trying to select a specific class (in this case page1, page2, page3 etc.)
I've written this code that works fine for a single class, i've tried using .match() to exclude the .plink class picked up in dis but can't get it working.
$(function(){
$("a.plink").click(function() {
var dis = $(this).attr("class"); // This is the problem line, I need it to contain 'page1' ONLY. Not 'page1 plink'.
$("#page1,#page2,#page3").hide();
$("#" + dis).show();
return false;
});
});
The HTML that is associated with this is:
<div id="page-links">
<a class="page1 plink" href="#">About</a>
<a class="page2 plink" href="#">History</a>
<a class="page3 plink" href="#">Backstage</a>
</div>
EDIT:
These are the DIV's being shown and hidden:
<div id="page1">
<?php include_once("page1.php");?>
</div>
<div id="page2">
<?php include_once("page2.php");?>
</div>
<div id="page3">
<?php include_once("page3.php");?>
</div>
Is there a simple way to achieve this without regular expression matching?
$(function(){
var pages = $('div[id^=page]');
$("a.plink").click(function() {
var dis = $(this).attr("class").replace(' plink', '');
pages.hide().filter('#' + dis).show();
return false;
});
});
This should be
$("." + dis).show();
for class and in your example there are all classes.
As you mentioned simple way so it could be
$("a.plink").click(function() {
$(".plink").hide();
$(this).show();
return false;
});
According to your question after edit
$("a.plink").click(function() {
$('div[id^="page"]').not('#page-links').hide();
pid=$(this).attr('class').split(' ')[0];
$('#'+pid).show();
return false;
});
Here is a fiddle.
The JavaScript code is not correct. With the "#" you select ids from the html-element.
As you have only classes, the right way is to do it with "."
So this would be correct:
$(function(){
$("a.plink").click(function() {
var dis = $(this).attr("class");
$(".page1,.page2,.page3").hide();
$("." + dis).show();
return false;
});
});
I didn't test it, but I think you have to change something with the var dis.
If you click on .page1, the variable dis would contain "page1 plink".
$("." + dis).show();
would be
$(".page1 plink").show();
So I recommend to split the two classes, as it should be like
$(".page1 .plink").show();
You are trying to associate functionality of a click by appending classes. It would make more sense to put id of the div you want to show in the href
html:
<div id="page-links">
<a class="plink" href="#page1">About</a>
<a class="plink" href="#page2">History</a>
<a class=" plink" href="#page3">Backstage</a>
</div>
<div id="page1">
Content 1
</div>
<div id="page2">
Content 2
</div>
<div id="page3">
Content 3
</div>
javascript:
jQuery(function ($) {
var pages = [];
function showPage(page) {
var i;
for(i = 0; i < pages.length; i++)
{
if(page === pages[i]) {
$(pages[i]).show();
} else {
$(pages[i]).hide();
}
}
}
// Store each href in a pages array and add handlers
$('.plink').each( function() {
var page = $(this).attr('href');
pages.push(page);
$(this).attr('href', '#');
$(this).click(function () {
showPage(page);
});
});
// show the first page
if(pages.length > 0) {
showPage(pages[0]);
}
});
Example:
http://jsfiddle.net/38qLB/
And just so I don't avoid the actual question, which is how do you select a class from a multi class element, you should follow this example of splitting up the class name Get class list for element with jQuery if you truly insist on using classes to make your link/div association
You don't really want to exclude the plink class, because that will bring you confusion and trouble when you need to add another class. Instead you want to extract just the pageX class:
// Regex for extracting pageXX
var reg = /^(.*\s)?(page\d+)([^\d].*)?$/;
dis = reg.exec(dis)[2];
I haven't testet this 100%, but put these two lines in right after var dis = $(this).attr("class"); and you should hopefully be good to go.
i down't know if i get your question right
to get all classes with class plink u can use
var klasses $("a.plink");
now u can loop true the items
var yourClasses = Array();
for(var klass in klasses)
{
var word = klass.attr('class').replace(" plink", "");
yourClasses.push(word);
}
now you have all the classes wich have the class plink
hope this was where u where looking for
If I was just doing a minor tweak to fix your existing structure I would do something like this:
$(document).ready(function() {
$('a.plink').click(function() {
var id = $.trim(this.className.replace('plink', ''));
/*adding a "page" class to each of the page divs makes hiding the visible one a bit easier*/
$('div.page').hide();
/*otherwise use the version from sheikh*/
//$('div[id^="page"]').not('#page-links').hide();
$('div#' + id).show();
});
});
The main change I would recommend to your existing markup would be to add a common "page" class to each of the page divs. Here is a fiddle
If I was starting on this from scratch I would probably take a slightly different approach in which I define an "active" class and toggle which elements have it rather than using show/hide on the divs. And that would end up looking something like this:
Markup:
<div id="page-links">
<a class="plink active" href="#page1">About</a>
<a class="plink" href="#page2">History</a>
<a class="plink" href="#page3">Backstage</a>
</div>
<div id="page1" class='page active'> </div>
<div id="page2" class='page'> </div>
<div id="page3" class='page'> </div>
CSS:
div.page
{
height: 300px;
display:none;
}
div.page.active
{
display:block;
}
a.plink
{
padding-left:5px;
padding-right:5px;
}
a.plink.active
{
background-color:#ddd;
}
div#page1
{
background-color:blue;
}
div#page2
{
background-color:green;
}
div#page3
{
background-color:red;
}
Script:
$(document).ready(function() {
$('a.plink').click(function() {
var id = $(this).attr('href');
$('.active').removeClass('active');
$(this).addClass('active');
$('div' + id).addClass('active');
});
});
Or the fiddle here.
Oh and to answer the title question rather than just the end behavior described...
var classes = this.className.split(' ');
var id;
for (var i = 0; i < classes.length; i++) {
if(classes[i].substring(4) === classes[i].replace('page', '')) {
id = classes[i];
break;
}
}
should end up with id containing the "page#" value associated with the link that was clicked regardless of its position in the list of classes.
Related
I'm trying to make a menu (with buttons) that open links.
when you hover on the buttons, a slideDown reveals more information on that link.
I've gotten all those features to technically work, however i can't get the animation speed to go any slower than instantly.
I'm really new to javascript and Jquery, and it took me 2-3 days to get the javascript and CSS to do what i have so far... and yeah it's probably bloated... but i'm still proud i got this done so far :D
PS, I know most menus are made w/ul's but I really like the way the buttons look and detested trying to put the list together. last time i tried used a seperate ul for the information and it kept styling the second list like the first because it was inside it... so annoying. I also tried vertical-link list w/CSS but still think flat 'buttons' are so boring. i really like the 3D esk of the actual html
HTML:
<div class="mainmenu">
<div id="homemenu">
<button id="home" class="mmbutton active">Home</button>
<div id="homesub" class="sub active">-just a bit about this page</div>
</div>
<div id="photosmenu">
<button id="photos" class="mmbutton">Photos</button>
<div id="photossub" class="sub inactive">-just a bit about this page
</div>
</div>
</div>
javascript/jquery:
$(function(){
var mmbutton = $('.mmbutton');
var start = "http://";
var address = "[my web address"; //add "http:
var about = "[web address]/aboutme.html";
var id = 0;
var rel = 0;
var mmsub = 0;
//<click link buttons:
$(mmbutton).click(function(){
var id = $(this).attr('id');
if (id === "home") {
location.replace(start+address);
}else if (id === "about") {
window.alert("I'm sorry I don't have this page set up yet. Thank you for visiting my page!");
//add additional buttons here under 'else if' unless its a subdomain
}else {
location.replace(start+id+'.'+address);//goes to any subdomain by id
}});
//>detect hover
$(mmbutton).hover(function(){
id = $(this).attr('id');
rel = '#'+id+'sub';
mmsub = '#'+id+'menu';
console.log('mouseenter'+rel);
$(rel).removeClass('inactive');
$(rel).stop().slideDown(500000);
}, function(){
console.log('mouseleave'+rel);
$(rel).addClass('inactive');
if ( $(this).hasClass('active')) {
$(rel).removeClass('inactive');
console.log('this is active');
}if ($(rel).hasClass('inactive')){
$(rel).stop().slideUp(500000);
}});});
relevante CSS:
.inactive {
display: none;
}
.sub {
transition-duration: 1s;
}
You can do it setting all that info divs to display:none and use slideToggle() function for that. Considering you want to keep the subdiv's opened when you're over them, one option is create a span element that include the button and the subdiv, and apply the hover to that span. So...
HTML:
<div class="mainmenu">
<div id="homemenu">
<span class="subcontainer">
<button id="home" class="mmbutton active">Home</button>
<div id="homesub" class="sub">-just a bit about this page</div>
</span>
</div>
<div id="photosmenu">
<span class="subcontainer">
<button id="photos" class="mmbutton">Photos</button>
<div id="photossub" class="sub">-just a bit about this page</div>
</span>
</div>
</div>
CSS:
.sub {
display: none;
/*transition-duration: 1s; IMPORTANT: REMOVE THIS!!*/
}
JQUERY:
$('span.subcontainer').hover(function() {
$(this).find('div.sub').slideToggle('slow');
});
IMPORTANT: Check that to make it work you have to remove the transition style you've created for .sub divs (it interfeers with the jquery function).
NOTE: I don't use the div.homemenu or div.photosmenu as the containers for the hover because div's normally have some styles pre-applied by default and can interfeer with the desired behaviour (for example, they normally have width=100% so the hover applies even when you're outside of the button or subdiv in the same line). span is normally more innocuous to use it just as a wrapper.
I hope it helps
Oh! i got it. i was trying to do too much (show off.../ using what im learning).
I removed the line that added and removed the class 'inactive' and just toggled the SlideUp and slideDown when i wanted it too. now i can adjust the animation speed:
(HTML remains unchanged)
CSS: removed the "transition-duration: 1s;"
JavaScript:
$(function(){
var mmbutton = $('.mmbutton');//any/all buttons
var activebut= 0; //detect button classes
var mmdiv = $("div[id$='menu']");//detect button sub info
var start = "http://";
var address = "[address]/index.html"; //add "http://" + [blog or games] + address
var about = "http://[address]/aboutme.html";
var id = 0;
var sub = 0;
var slidespeed= 450; //slideUP/slideDown animation speed //added var for speed
//<click link buttons: (unchanged)
$(mmbutton).click(function(){
id = $(this).attr('id');
if (id === "home") {
location.replace(start+address);
}else if (id === "about") {
location.replace(start+'[address]/aboutme/index.html')
//add additional buttons here under 'else if' unless its a subdomain
}else {
location.replace(start+id+'.'+address);//goes to any subdomain by id
}
});
//<hover display:
//<detect mouse ON button
$(mmbutton).hover(function(){
id = $(this).attr('id');
sub = '#'+id+'sub';
activebut= $(this);
if ( $(activebut).hasClass('active')) {
}else {
$(sub).stop().slideDown(slidespeed);
}
});
//<detect mouse off button AND div
$(mmdiv).mouseleave(function(){
if ( $(activebut).hasClass('active')) {
}else {
$(sub).stop().slideUp(slidespeed);
}
});
});
I am trying to toggle a div when its name is clicked.
I have multiple coupls like that in my page, and I want it to work as
"when <p id= "d2"> is clicked => <div id="d2"> is toggled".
I tried those functions:
$(document).ready(function(){
$("p").click(function(){
$("div#" + $(this).attr('id')).toggle();
});
});
function rgt() {
//document.body.innerHTML = "";
var id = "d" + this.id;
var situation = document.getElementById(id).style.display;
if (situation == "none") {
situation = "block";
}
else {
situation = "none";
}
}
function showHide(theId) {
if (document.getElementById("d" + theId).style.display == "none") {
document.getElementById("d" + theId).style.display = "block";
}
else {
document.getElementById("d" + theId).style.display = "none";
}
}
I can't make it Work!!! Why is it?
the browser says:"no 'display' property for null"...
I will be more than happy to solve it with simple jquery
Ensure Your id Attributes Are Unique
Assuming that your id attributes are unique, which they are required to be per the specification:
The id attribute specifies its element's unique identifier (ID). The
value must be unique amongst all the IDs in the element's home subtree
and must contain at least one character. The value must not contain
any space characters.
You should consider renaming your id attributes to d{n} and your paragraphs to p{n} respectively as seen below :
<button id='p1'>p1</button> <button id='p2'>p2</button> <button id='p3'>p3</button>
<div id='d1'><pre>d1</pre></div>
<div id='d2'><pre>d2</pre></div>
<div id='d3'><pre>d3</pre></div>
which would allow you to use the following function to handle your toggle operations :
$(function(){
// When an ID that starts with P is clicked
$('[id^="p"]').click(function(){
// Get the proper number for it
var id = parseInt($(this).attr('id').replace(/\D/g,''));
// Now that you have the ID, use it to toggle the appropriate <div>
$('#d' + id).toggle();
})
});
Example Using Unique IDs
You can see an interactive example of this approach here and demonstrated below :
Consider Using data-* Attributes
HTML supports the use of data attributes that can be useful for targeting specific elements through jQuery and associating them to other actions. For instance, if you create an attribute on each of your "p" elements as follows :
<button data-toggles='d1'>p1</button>
<button data-toggles='d2'>p2</button>
<button data-toggles='d3'>p3</button>
and then simply change your jQuery to use those as selectors :
$(function(){
// When an element with a "toggles" attribute is clicked
$('[data-toggles]').click(function(){
// Then toggle its target
$('#' + $(this).data('toggles')).toggle();
});
});
Is this you are looking?
$("#p1").on("click", function() {
$("#d1").toggle();
});
js fiddle: https://jsfiddle.net/Jomet/09yehw9y/
jQuery(function($){
var $toggles = $('.divToggle');
var $togglables = $('.togglableDiv');
$toggles.on('click', function(){
//get the div at the same index as the p, and toggle it
$togglables.eq($toggles.index(this)).toggle();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<p class="divToggle">Show Me 1</p>
<p class="divToggle">Show Me 2</p>
<p class="divToggle">Show Me 3</p>
<div class="togglableDiv">Weeee 1</div>
<div class="togglableDiv">Weeee 2</div>
<div class="togglableDiv">Weeee 3</div>
Minimal approach using classes. This solution assumes the order of the p elements in the dom are in the same order as the divs are in the order. They do not have to be contiguous, but the order does matter with this solution.
ids are not the droids you are looking for.
An id needs to be unique. If you want to classify something one would suggest to use classes. You can actually use serveral of them for some fancy stuff. How about something like this:
<p class="toggle one">one</p>
<div class="toggle one" style="display:none">content one</div>
Straight forward. Every element that is a switch or switchable gets the class toggle. Each pair of switch and switchable(s) gets an additional identifier (like one, two, ...).
Simple JScript Implementation:
Now how about not using JQuery to work with that? Sure it i$ handy, but it hides all that neat stuff one would eventually like to learn her/himself!
var myToggle = {};
(function(module) {
"use strict";
(function init() {
var elements = document.getElementsByClassName("toggle");
var element;
var i = elements.length;
while (i) {
i -= 1;
element = elements[i].className;
elements[i].setAttribute("onclick", "myToggle.swap(\"" + element + "\")");
}
}());
module.swap = function(element) {
var couple = document.getElementsByClassName(element);
var i = couple.length;
while (i) {
i -= 1;
if (couple[i].style.display === "none" && couple[i].tagName === "DIV") {
couple[i].style.display = "block";
} else if (couple[i].tagName === "DIV") {
couple[i].style.display = "none";
}
}
};
}(myToggle));
<p class="toggle one">one</p>
<div class="toggle one" style="display:none">content one</div>
<p class="toggle two">two</p>
<div class="toggle two" style="display:none">content two 1</div>
<div class="toggle two" style="display:none">content two 2</div>
var myToggle = {} is the object we use to keep our little program contained. It prevents that our code conflicts with other declarations. Because what if some plugin on our site already declared a function called swap()? One would overwrite the other!
Using an object like this ensures that our version is now known as myToggle.swap()!
It may be hard to follow how it got to that name. Important hint: something looking like this... (function() { CODE } ()) ...is called an immediately-invoked function expression. iffy! It's a function that is immediatly executed and keeps its variables to itself. Or can give them to whatever you feed it in the last ()-pair.
Everything else is as verbose as can be... no fancy regular expressions, hacks or libraries. Get into it!
Maybe this is not possible, however, i have like 50 unique divs like this:
<div id="nyc_data">
nyc
</div>
<div id="la_data">
la
</div>
<div id="san_data">
san
</div>
etc....
below is my jquery:
jQuery(document).ready(function()
{
var url=document.URL.split('#')[1];
url=url.toLowerCase();
if (url == "nyc_pics")
{
jQuery("#nyc_data").show();
jQuery("#la_data, #san_data").hide();
}
if (url == "la_pics")
{
jQuery("#la_data").show();
jQuery("#nyc_data, #san_data").hide();
}
if()
{
}
etc....
}
When this was 2 it was okay to write it out, but i can't possibly write a long jquery 50 times for each city or so. is there an efficient way to have a simple smaller jquery code?
Select all the divs first, with jQuery selector id ending with '_data' as [id$='_data'] and hide them all. This will hide your desired div as well.
Now get the desired div id from url, find it with jQuery and show.
If your uri is mySite.com/myPage#nyc_pics then var urlHash = document.URL.split('#')[1] will get "nyc_pics". After toLowercase().replace("pics", "data") this will be "nyc_data". Now, jQuery("#" + divToSHow) will be $("#nyc_data"), which will match your div. Then you can show that single div with .show()
jQuery(document).ready(function()
{
var urlHash = document.URL.split('#')[1];
var divToSHow = urlHash .toLowerCase().replace("pics", "data");
jQuery("div[id$='_data']").hide();
jQuery("#" + divToSHow).show();
});
You can use this CSS selector:
jQuery('div[id$="_data"]').show();
In your example:
jQuery(document).ready(function()
{
var url=document.URL.split('#')[1];
url=url.toLowerCase();
var currentId = '#' + url.split('_')[0] + "_data";
jQuery('div[id$="_data"]').hide();
jQuery(currentId).show();
}
It would be much easier/cleaner/faster if you just used jQuery to toggle a class on a parent element and let CSS do the work. Something like this:
window.onload = function() {
$('#all-the-things-btn').on('click', function() {
$('#my-parent-div').toggleClass('show-things');
});
};
#my-parent-div > div {
display: none;
}
#my-parent-div.show-things > div {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Toggle all the things!
<div id="my-parent-div" class="show-things">
<div id="1">stuff</div>
<div id="2">more stuff</div>
<div id="3">even more stuff</div>
</div>
i am trying to move a .details outside of .buttons
<div class="product-actions">product 1
<div class="buttons buttons_3 group">buttons
<a class="details" title="Détails" rel="nofollow" >link</a>
</div>
</div>
<div class="product-actions">product 2
<div class="buttons buttons_3 group">buttons
<a class="details" title="Détails" rel="nofollow" >link</a>
</div>
</div>
this do the trick
if ($('.product-actions').length )
{
$('.product-actions').prepend("<div id='new_details_location'></div>");
$(".details").prependTo("#new_details_location");
$('.buttons_3').attr('class','buttons buttons_2 group');
}
the problem is there is more than one product and all a.details get moved to the first product div instead of being prepend at the beginning of each div .product-actions:
http://jsfiddle.net/upKhq/2/
any idea?
Try this FIDDLE
$('.product-actions').each(function () {
$new = $(this).prepend("<div class='new_details_location'></div>");
$(".details", $(this)).prependTo($new);
$('.buttons_3', $(this)).attr('class', 'buttons buttons_2 group');
});
You made a few mistakes:
your selectors were not context sensitive and you were using id in prependTo which has to be unique, but you had 2 divs with the same id.
Did you mean to do this instead?
$('.product-actions').each(function() {
$elem = $("<div class='new_details_location'></div>");
$(this).find(".details").prependTo($elem);
$(this).prepend($elem);
});
$('.buttons_3').attr('class', 'buttons buttons_2 group');
http://jsfiddle.net/samliew/upKhq/4/
You can use each jquery method:
$('.product-actions').each(function() {
var self = $(this);
var new_location = $("<div id='new_details_location'></div>").prependTo(self);
self.find(".details").prependTo(new_location);
self.find('.buttons_3').attr('class','buttons buttons_2 group');
});
And you should not use the same id for two elements.
use .each, and use $(this) to refer to the current .product-actions element. Also you cant have multiple ids that are the same, only the first one would ever be used
if ($('.product-actions').length ) {
$('.product-actions').each(function() {
var newDetailLocation = $('<div></div>');
$(this).prepend(newDetailLocation);
$(".details",$(this)).prependTo(newDetailLocation);
$('.buttons_3',$(this)).attr('class','buttons buttons_2 group');
});
}
So i'm just starting to discover how awesome jquery is and how a basic function can drive me nuts to understand. I'm trying to highlight a div with a specific "id" generated via backend
<br/><br/><br/><br/>
<div id="id_1">
<h2>id_1 -
<a class="marker_id_1" href="#top" name="id_1" id="id_1">Top</a>
</h2>
</div>
<div id="id_1">
<h2>id_1 -
<a class="marker_id_1" href="#top" name="id_1" id="id_1">Bottom</a>
</h2>
</div>
<div id="id_2">
<h2>id_2 -
<a class="marker_id_2" href="#top" name="id_2" id="id_2">Top</a>
</h2>
</div>
<div id="id_2">
<h2>id_2 -
<a class="marker_id_2" href="#top" name="id_2" id="id_2">Bottom</a>
</h2>
</div>
So if I hover over the "id_1" Top , I want to highlight both the "id_1" Top and Bottom. Below is a link to that so it'll be easier to understand.
http://jsfiddle.net/4PgC6/66/
Thanks!!
You must not use same id for different element.
Using name you can do
$('a').hover(function() {
var name = this.name;
$('a[name='+ name +']').css('color', '#f00')
},function() {
var name = this.name;
$('a[name='+ name +']').css('color', 'blue')
});
DEMO
Using class
$('a').hover(function() {
var className = this.className;
$('a.' + className).css('color', '#f00')
},function() {
var className = this.className;
$('a.' + className).css('color', 'blue')
});
DEMO
if you want to use .on() for hover then use
$('a').on('hover', function(e) {
if (e.type == 'mouseenter') {
var divName = this.name;
console.log(divName);
$('div', 'td.' + divName).addClass('match-highlight');
} else {
var divName = this.name;
$('div', 'td.' + divName).removeClass('match-highlight');
}
});
DEMO
$('div').mouseenter(function() {
var hoveredid = $(this).attr('id');
$('[id='+hoveredid+']').each(function() {
$(this).addClass("highlighted");
});
}).mouseleave(function() {
var hoveredid = $(this).attr('id');
$('[id='+hoveredid+']').each(function() {
$(this).removeClass("highlighted");
});
});
As mentioned, id should be unique. But if it isn't I found accessing using '[id=' rather than '#' you are able to access all divs, since you are looking at id as an attribute. (See: http://jsfiddle.net/4PgC6/68/)
First of all you cant have same same ID for a and div. Id should be unique.
Use data for that instead. Like that:
and then read it in script like that:
$('a').hover(function() {
divID = $(this).data('id');
$('#'+divId).css('color', '#f00');
},function() {
divID = $(this).data('id');
$('#'+divId).css('color', 'blue');
});
http://jsfiddle.net/acrashik/4PgC6/69/