I'm making a website that uses a Javascript sorter. In addition to the sorter, I also put in some custom javascript, to make certain div's clickable. My reasoning was that using the property just couldn't do all that we wanted it to do, so I stuck with divs, and used javascript to make them function.
Take a look here --
http://www.opohills.com/taipei-rentals.php
You can scroll down to where you see the search bar, and click on one of the apartments. When you go back click (1 bedroom), you'll see that clicking on the apartments doesn't work anymore.
I'm not quite sure what to make of this at all. The javascript for the clickability is at the bottom of the page.
What are your thoughts on this?
Here's my javasscript
<script type='text/javascript'>
$(".box_1").click(function(){
window.location=$(this).find("a").attr("href");
return false;
});
$(".box_2").click(function(){
window.location=$(this).find("a").attr("href");
return false;
});
$(".box_3").click(function(){
window.location=$(this).find("a").attr("href");
return false;
});
$(".apt2").click(function(){
window.location=$(this).find("a").attr("href");
return false;
});
</script>
Thoughts?
UPDATE
In accordance to the suggestions, I've updated the code by moving the javascript for clickability above jquery.quicksand, and initiated it only after the document was ready.
Even with these changes, I'm still having trouble getting it to work.
The latest version of the site can be seen here---
http://www.opohills.com/taipei-rentals.php
Your thoughts greatly appreciated
the script basically works for me (and should for you). your problem is probably that sometimes your dom is not ready:
$(document).ready(function() {
// your code here
});
2 more things.
1.) add "cursor: pointer;" to your css for the clickable boxes (usability)
2.) just trigger the click of your link:
$(".apt2").click(function(){
$(this).find("a").trigger('click');
return false;
});
When I'm using the chorme built in debuger on your website, if I create custome fields like ID on you "li" tags, they are deleted after a filter. I think quicksand is creating a cache during the page loading. You are creating you .click() event only after the initialisation of the quicksand library and it is possible that theses click events are deleted because quicksand replaces your li tags.
Try to initialize your click like
$(function() {
$("#ourHolder li").click(function() { window.location.href=$(this).find('a').attr('href')});
});
You should add an id="ourHolder" to your ul tag to optimize the script speed.
And only after this initialisation start your quicksand object initialisation. Move your
<script src="js/jquery.quicksand.js"></script>
<script src="js/sorter-settings.js"></script>
after the previous click functions.
So you can try to edit our file sorter-settings.js and replace by this code (based on the documentation available here (http://razorjack.net/quicksand/docs-and-demos.html) :
$(document).ready(function() {
// get the action filter option item on page load
var $filterType = $('#filterOptions li.active a').attr('class');
// get and assign the ourHolder element to the
// $holder varible for use later
var $holder = $('ul#ourHolder');
// clone all items within the pre-assigned $holder element
var $data = $holder.clone();
// attempt to call Quicksand when a filter option
// item is clicked
$('#filterOptions li a').click(function(e) {
// reset the active class on all the buttons
$('#filterOptions li').removeClass('active');
// assign the class of the clicked filter option
// element to our $filterType variable
var $filterType = $(this).attr('class');
$(this).parent().addClass('active');
if ($filterType == 'all') {
// assign all li items to the $filteredData var when
// the 'All' filter option is clicked
var $filteredData = $data.find('li');
}
else {
// find all li elements that have our required $filterType
// values for the data-type element
var $filteredData = $data.find('li[data-type=' + $filterType + ']');
}
// call quicksand and assign transition parameters
$holder.quicksand($filteredData, {
duration: 800,
easing: 'easeInOutQuad',
enhancement: function() {
$("#ourHolder li").click(function() { window.location.href=$(this).find('a').attr('href')});
}
}
);
return false;
});
});
Additinaly, I think that this code is useless on your html content.
<!--Begin Sorter-->
<script type='text/javascript'>
$(document).ready(function() {
$('#source').quicksand( $('#destination li') );
});
</script>
Related
I am currently learning JavaScript using O'Reilly's "Learning Web Application Development". In the example, we are constructing a website using HTML and CSS, which includes 3 tabs which should be able to be selected and become the "active" tab. The books claims that the following two ways of writing the tab code are equivalent:
1)
var main = function() {
"use strict";
var tabNumber;
for (tabNumber=1;tabNumber<=3;tabNumber++) {
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
$(tabSelector).on("click",function() {
$(".tabs span").removeClass("active");
$(tabSelector).addClass("active");
$("main .content").empty();
return false;
});
}
}
$(document).ready(main);
2)
var main = function() {
"use strict";
$(".tabs a span").toArray().forEach(function(element) {
$(element).on("click", function() {
console.print("this element: " + element);
$(".tabs span").removeClass("active");
$(element).addClass("active");
$("main .content").empty();
return false;
});
});
}
$(document).ready(main);
However, they do not output the same result. The version using forEach works correctly, so that when I click one of the tabs the attention moves to that tab and it becomes highlighted. However, in the version using a for loop, whenever I click any tab, the attention always moves to the last tab. To confirm what is happening, I printed out the name of the element inside the event listener with both methods, using 3 tabs total. And using the for loop, no matter which tab I click I am getting a response of
"this element: .tabs a:nth-child(3) span"
Could someone please help me explain why this is happening? Why is the output different using for or forEach? And why, using for, is it always passing the last element of tabs to the event listener?
Looks like there's a problem here:
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
$tabSelector.on("click",function(){
You've created a variable that doesn't have the $ at the beginning, then attached the event to a variable (not sure what it would refer to) with a $ at the beginning.
It should be changed to this, I believe:
$(tabSelector).on("click",function(){
In the for loop solution, you are setting tabSelector multiple times like so:
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
This selector is, in the end, going to be set to the last tabNumber, which is always going to be called when you make a reference to it:
$(tabSelector).addClass("active");
To avoid that, replace it by this, which will be different for each of them:
$(this).addClass("active");
JS Fiddle Demo
i have a div which is hidden initially and will be visible later depending on some click events results.
I have wrote this
$(document).ready(function () {
$('#<%=disable.ClientID %>').hide();
});
<div id="disable" runat="server">The following question is disabled</div>
But when i disable CSS it appears, when i don't disable css it gets invisible. how do i make this invisible even when css is disabled and visible later again
There is no way to make something invisible without CSS. But you can remove it:
$(document).ready(function () {
$('#<%=disable.ClientID %>').remove();
});
You would then need to readd all the mark up again should you wish to show it again.
Edit
You could do something like this:
$(document).ready(function () {
var item = $('#<%=disable.ClientID %>');
$(document).data('myElement', item.clone());
item.remove();
});
then you could re-add it
$(document).append($(document).data('myElement'));
If you are willing to write server code for this, then you could do this in the code-behind.
// c#
if(some condition...)
{
disable.Visible = false;
}
This will remove the div from the HTML output of the page.
I do not get you when talking about enabling and disabling css, but you can always manage the DOM elements via DOM manipulation. As you tagged jQuery:
$(document).ready(function () {
/* please try top avoid mix server side variables and javascript code */
$('#myTargetDiv').hide();
$('#myToggleButton').on('click',function(){
/* select the elements you want to hide / show with the click on this element */
var $elements = $('#myTargetDiv');
$elements.toggle();
});
});
Im kind of new to javascript, and I have tried for several hours now to make this fadeIn function to work.
First of all, look at my code here.
I have also included the following in my header:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
This is how I want the page to work,
When a user enters the site, the home selection will fadein
The menu is based on <ul> and <li> itmes for categories and in each category we have different comapnies. Each category have a <a href="category-id"> and each company have a <a href='company-id'> to the div tag made later in the body.
A user should be able to switch between the menu options, and each time the time should fade in.
So the problem as you see in my code, it works on page load, but I cant choose anything from the menu.
Any suggestions would be helpful
If I understood correctly you wanted it to function something like this :
$('#menu a').click(function () {
$("#content div").hide(); //Hide all content
var id = $(this).attr('href');
$(id).fadeIn(); // Show content for current tab
});
You didn't need this line (it is deleting the id) :
$("#menu li").attr("href", ""); //Reset id's
This is line I don't even know what it's for:
$(this).parent().attr("href", "current"); // Activate this google parent!
If you want to add a class to the current active menu item, use something like
$(this).parent().addClass('active');
Also you don't need to add '#' because you already had that in you href atrribute:
$($(this).attr('href')).fadeIn(); // Show content for current tab
You can check what kind of id you're getting by alerting it or logging it :
var id = $(this).attr('href');
alert(id);
$(id).fadeIn();
Are you sure with this line of Code?
$("#menu li").attr("href", "");
You do not override your ID here. You remove your link href.
you are resetting the "href" attribute. Thus, when you try to make a fadeIn the "href" attribute value is changed to "current".
Those two lines:
$("#menu li").attr("href", ""); //Reset id's
....
$('#' + $(this).attr('href')).fadeIn();
are wrong because $(this).attr('href') is equal to "" (empty string)
also you made a mistake because you did
$("#content div:last").fadeIn(); // Show first tab content
but the command and what you expect are not coherent. Here you are using fadeIn on the last tab content instead of the first.
You can try something like this: http://jsfiddle.net/546Jn/4/
$(document).ready(function () {
$("#content div").hide();
$("#content div:first").fadeIn(); // Show first tab content
$('#menu a').click(function () {
$("div#content div").hide(); // Hide all pages
$('div' + page).fadeIn(); // Show content for current tab
});
});
Check out the treatments menu on right hand side of this website. It has a set of <dt> tags with an <a> tag and a <ul> list of submenu <li> links inside. The top level link and sumbmenu links are grouped together using the rel attribute.
As you can see the submenu slides down when you click the top level link. What I'm trying to do is maintain state between page loads so that if any of the links in the submenus are clicked it will stay open. I am trying to use the rel attribute to do this.
Here is my code so far, I am getting a bit confused with the logic:
function initMenu() {
$('.menu ul:not(.active)').hide();
var checkCookie = $.cookie("nav-item");
if (checkCookie != "") {
$('.menu').each(function () {
var state = $(this).find('a:first-child').attr('rel');
if (state == checkCookie) {
alert(state);
$(this).next().slideToggle('normal');
}
})
}
$('.menu > a:first-child').click(function(e) {
e.preventDefault();
var navIndex = $(this).attr('rel');
$.cookie("nav-item", navIndex);
$(this).next().slideToggle('normal');
});
}
$(function() {
initMenu();
});
EDIT**
I have changed the first part of the code to this in order to try and use the active class. But what its doing is opening all the ul's instead of just the ul that contains the li with the active class.
$('.menu ul:not(.active)').hide();
$('.menu').each(function (){
if ($(this).children(".active")){
$(this).children('ul').slideToggle('normal');
}
});
Update *after update of original question*
Use for the if
if ($(this).find(".active").length){
$(this).children('ul').slideToggle('normal');
}
Original answer
One thing is with
if (state == checkCookie) {
alert(state);
$(this).next().slideToggle('normal');
}
this in this context refers to .menu and not the a link.
You should change it to
if (state == checkCookie) {
alert(state);
$(this).children('ul').slideToggle('normal');
}
The other is that the cookie plugin creates (by default) cookies that belong to the page that created them. So when you change a page it does not have access to a cookie created by another page.
Use the path option when saving $.cookie("nav-item", navIndex, {path: '/'});
The correct way
It would be best though not to rely on cookies for navigation as it will become problematic when a user starts using the back button ..
You should really pass the rel value to the url as the hash #relvalue and use that instead.
(hint: check out window.location.hash)
I want to separate these functions. They should both work separately on click events:
FIRST FUNCTION
$("ul.nav li").delegate("a", "click", function() {
window.location.hash = $(this).attr("href");
return false;
});
$(window).bind('hashchange', function(){
newHash = window.location.hash.substring(1);
if (newHash) {
ACTION A
});
$(window).trigger('hashchange');
});
SECOND FUNCTION
$("ul.subnav li").delegate("a", "click", function() {
window.location.hash = $(this).attr("href");
return false;
});
$(window).bind('hashchange', function(){
newHash = window.location.hash.substring(1);
if (newHash) {
ACTION B
});
$(window).trigger('hashchange');
});
This is what happend in ACTION A:
$mainContent
.find(".maincontent")
.fadeOut(200, function() {
$mainContent.hide().load(newHash + " .maincontent", function() {
$mainContent.fadeIn(200, function() {
$pageWrap.animate({
height: baseHeight + $mainContent.height() + "px"
});
});
$(".nav a").removeClass("active");
$(".nav a[href="+newHash+"]").addClass("active");
});
});
The Problem is that if I click the Link of the Second function always the the first function fires.
Details of what I'm trying to do:
First, I build my site on .php to serve poeple without JavaScript. Now I want to load the "maincontent" dynamically. So I found this script I'm using:
http://css-tricks.com/6336-dynamic-page-replacing-content/
It does do a great job if you only want to load "maincontents".
But my site has sub-navigation on some pages where I want to load the sub-content. In .php these sites use includes. So I get my content by: href="page2.php?page=sub1"
So, when I click on the sub-links now they load also dynamically but the script also on the whole maincontent loading area. So it doesn't really load content by .load() but the sub-content of the includes do appear.
So what I thought was just to separate this function. The first to simply load the maincontents and a second one for the sub-navigation to refresh only the sub-content area. I don't even understand how this script loads the include content dynamically since the link is the straight page2.php?page=sub1 link. All dynamic loaded content usually looks like "#index", without the ending ".php".
Some quick history:
I'm trying to get the best page structure. Deliver .php for non JavaScript user and then put some dynamic loading stuff over it. Always with the goal to keep the browser navigation and the browser links (for sharing) for each page in tact.
I'm not an jQuery expert. All I have learned so far was by trial and error and some logical thinking. But of course, I have a lack of fundamental knowledge in JavaScript.
So my "logical" question:
How can I tell the "nav" links to perform only their "$(window).bind"-Event and to tell the "subnav" links only to perfom their "$(window).bin"-event.
Is this the right thinking?
Since I've already been trying to solve it for nearly the last 18h, I'll appreciate any kind of help.
Thank you.
IMPORTANT:
With the first function I not just only load the maincontent but also I'm changing a div on the page with every link. So for any solution that might want to put it together in one, it won't work, cause they should do different things on different areas on the page. That's why I really need to call on the window.bind with each nav/subnav click.
Can anyone show me how?
Melros,
In your second function, you are binding to the event hashchange2, which is incorrect. Instead, you STILL want to bind to hashchange. Instead of:
$(window).bind('hashchange2', function() {
...
});
Try:
$(window).bind('hashchange', function() {
...
});
If you want to namespace your event subscriptions, you can suffix the ending of the event you are binding to with a period (.) and then the namespace:
$("#test").bind("click.namespace1", function() { });
$("#test").bind("click.namespace2", function() { });
Ok, it seems that you want to execute action A when a link inside .nav is clicked, and action B when a link inside .subnav is clicked.
You can just put these actions inside the event handlers. Furthermor, if .subnav is nested inside .nav, you have to restrict your selector:
// consider only direct children
$("ul.nav > li").delegate("a", "click", function() {
var href = $(this).attr("href");
if(window.location.hash !== href) {
Action A
window.location.hash = $(this).attr("href");
}
return false;
});
// consider only direct children
$("ul.subnav > li").delegate("a", "click", function() {
var href = $(this).attr("href");
if(window.location.hash !== href) {
Action B
window.location.hash = $(this).attr("href");
}
return false;
});
I don't think listening to the hashchange event will help you here, as this event is triggered in both cases and you cannot know which element was responsible (you probably can somehow, but why make it overly complicated?).
Here's by the way the solution I came to:
After understanding that the haschange-event doesn't have to do anything with it (as long as you don't want to make the subcontent bookmarkable too) I just added a new load function for the subcontent:
$(function(){
$("ul.linkbox li a").live('click', function (e) {
newLink = $(this).attr("href");
e.preventDefault();
$(".textbox").find(".subcontent").fadeTo(200,0, function() {
$(".textbox").load(newLink + " .subcontent" , function() {
$(".subcontent").fadeTo(200,1, function() {
});
});
$("#wrapper").css("height","auto");
$("ul.linkbox li a").removeClass("activesub");
$("ul.linkbox li a[href='"+newLink+"']").addClass("activesub");
});
});
});