I'm trying to create a custom jquery cycle plugin which basically displays the contents of an <li> element upon click. The html is as follows:-
<ul class="ticker">
<li>Boo1</li>
<li>More boo1</li>
<li>Even more boo</li>
<a class="prev" href="#">previous</a>
<a class="next" href="#">next</a>
</ul>
so when the user clicks the next button, the next <li> shows and when he clicks the prev button, the previous <li> shows.
Achieving this has never been easy :( I'm still quite new to jquery so please pardon. Any help guys
I think this will solve your problem, you can see it working here http://jsfiddle.net/KvscH/
<ul class="ticker">
<li>Boo1</li>
<li>More boo1</li>
<li>Even more boo</li>
</ul>
<a class="prev" href="#">previous</a> -
<a class="next" href="#">next</a>
Js:
var ticker = $('ul.ticker');
ticker.children(':first').show().siblings().hide();
setInterval(function() {
ticker.find(':visible').fadeOut(function() {
$(this).appendTo(ticker);
ticker.children(':first').show();
});
},50000);
$('.next').live ('click', function () {
ticker.find(':visible').fadeOut(function() {
$(this).appendTo(ticker);
ticker.children(':first').show();
});
});
$('.prev').live ('click', function () {
ticker.find(':visible').fadeOut(function() {
ticker.find('li:last').insertBefore(ticker.find('li:first'));
ticker.children(':first').show();
});
});
Taking a wild stab in the dark:
DEMONSTRATION (I left previous button untouched, that's up to you)
The code (notice I left a section for you to complete):
var ticker = $('ul.ticker');
ticker.children(':first').show().siblings().hide();
startTicker();
$('.prev, .next').bind('click', function() {
if($(this).attr('class') == 'prev') {
clearInterval(myInterval);
/// for previous
/// do it
/// yourself
} else {
clearInterval(myInterval);
ticker.find(':visible').fadeOut(function() {
$(this).appendTo(ticker);
ticker.children(':first').show();
startTicker();
});
}
});
var myInterval;
function startTicker() {
myInterval = setInterval(function() {
ticker.find(':visible').fadeOut(function() {
$(this).appendTo(ticker);
ticker.children(':first').show();
});
},2000);
}
Okay, here is a potential solution for you, if I am understanding you correctly:
First off, setInterval is a "background function", in that it can run in the background while you run other functions. What you want to do first is move the stuff that you do inside of the setInterval method into its own function. Then, you will create a click event handler in which you call the that function. After that you can call setInterval and and it will run at the same time as you have your click-event listener running.
If you experience any issues with the interval being broken when your click-listener fires, you can also re-initialize your interval after calling the function in your click-listener.
Let me know if you need any further help/explanation.
Good Luck! :)
Take a look at this jsFiddle
HTML
<ul class="ticker">
<li>Boo1</li>
<li>More boo1</li>
<li>Even more boo</li>
</ul>
<a class="prev" href="#">previous</a>
<a class="next" href="#">next</a>
JS
var ticker = $('ul.ticker');
ticker.children(':first').show().siblings().hide();
function cycleFunc(direction) {
ticker.find(':visible').fadeOut(function() {
(direction == 'forward') ? $(this).appendTo(ticker) : $(this).prependTo(ticker);
ticker.children((direction == 'forward') ? ':first' : ':last').show();
})
}
var timer = setInterval(function() {
cycleFunc('forward');
}, 2000);
$('.next, .prev').click(function() {
clearInterval(timer)
var direction = ($(this).hasClass('next')) ? 'forward' : 'backward';
timer = setInterval(function() {
cycleFunc(direction);
}, 2000)
});
Removed the DOM manipulations just to keep track of the currently visible element.
I think they are unnecessary. My 2 cents.
Also made it like something someone would actually use.
HTML:
<div id='Test'>
<ul class="ticker">
<li>Boo1</li>
<li>More boo1</li>
<li>Even more boo</li>
</ul>
<a class="prev" href="#">previous</a>
<a class="next" href="#">next</a>
</div>
JS:
jQuery.fn.Custom_cycler = function(Options){
var Options = jQuery.extend({'Next': 'a.next', 'Previous': 'a.prev', 'List': 'ul.ticker'},Options||{});
var List = jQuery(Options.List, this);
var Index = 0;
var Size = List.children().size();
List.children().hide().first().show();
var Move = function(Event){
Event.preventDefault();
if(Event.data)
{
Index++;
}
else
{
Index--;
}
Index=(Index+Size)%Size;
jQuery(List.children().hide().get(Index)).show();
};
jQuery(Options.Next, this).bind('click', true, Move);
jQuery(Options.Previous, this).bind('click', false, Move);
return(this);
};
You use it like this:
jQuery('div#Test').Custom_cycler();
EDIT: Used the data parameter in the event handler to use only one function for both events which allowed me to use a closure for the Index/Size instead of jQuery(...).data.
Also removed some unnecessary variables from the closure.
And finally narrowed the context of the selection to avoid mistakenly manipulating external DOM tags when calling the function. It also executes faster because jQuery doesn't have to lookup the entire DOM.
Could be optimized further by calling hide() only on the previously shown element instead of all of them (easily infer-able from the value of Index).
Related
I am new to programming in Javascript .so please explain me can I use binding here.This menu is inspired by the left side menu found on YouTube. When clicking on the menu label and icon, the main menu appears beneath and the menu icon slides to the right side while the label slides up. To close the menu, the menu icon needs to be clicked again.
var menu = (function() {
function initiate() {
//[].slice.call I used by using call but i want to to by binding and I am not able to do.
[].slice.bind(null, document.querySelectorAll('.menu')).forEach(function(element, i) {
var titleclick = el.querySelector('div.d-striker'),
striker.addEventListener('click', function(event) {
if (!open) {
el.className += ' dr-menu-open';
open = true;
}
}, false);
icon.addEventListener('click', function(event) {
if (open) {
event.stopPropagation();
open = false;
el.className = el.className.replace(/\bdr-menu-open\b/, '');
return false;
}
}, false);
}
initiate();
})();
<div class="side">
<nav class="menu">
<div class="d-striker">
<span class="d-icon dr-icon-menu"></span><a class="dr-label">Account</a>
</div>
<ul>
<li><a class="d-icon dr-icon-user" href="#">icon</a></li>
<li><a class="d-icon dr-icon-cam" href="#">Videos</a></li>
<li><a class="d-icon dr-icon-download" href="#">Downloads</a></li>
<li><a class="d-icon dr-icon-settings" href="#">Settings</a></li>
</ul>
</nav>
</div>
bind() returns a bound function, but you need to call that function to get the array that's needed for forEach. Add parentheses to call the function.
[].slice.bind(null, document.querySelectorAll('.menu'))().forEach(function(element, i) {
^^
I have five slide shows on one page and I want to be able to cycle through all of them. The slideshow is made of an UL with each a different ID, so I want to create two functions for the arrows to cycle through the slides. And I want to pass the slide ID. My code:
$(document).ready(function() {
var slides = document.querySelectorAll('#slides li');
var slidesTotal = $('#slides li').length;
var currentSlide = 1;
function nextSlide() {
//$('a.nextSlideArrow').click(function() {
$('#slides .slide' + currentSlide).hide();
currentSlide++;
if(currentSlide > slidesTotal) {
currentSlide = 1;
}
$('#slides .slide' + currentSlide).show();
//return false;
//});
}
function previousSlide() {
//$('a.previousSlideArrow').click(function() {
$('#slides .slide' + currentSlide).hide();
currentSlide--;
if(currentSlide == 0) {
currentSlide = slidesTotal;
}
$('#slides .slide' + currentSlide).show();
//return false;
//});
}
});
<div id="slider-container">
<ul id="slides">
<?php
for ($i = 1; $i <= $amountImagesSlideshow[3]; $i++) {
echo '<li class="slide'.$i.'"><img src="'.$directories[3],$i.'.jpg" /></li>';
}
?>
</ul>
<div class="galleryPreviewArrows">
❮
❯
</div>
</div>
Now the funny thing is, if I remove the comments where the click is on the jQuery object and comment out the function, it will work. But not this way? I don't understand.
There is a difference between onclick event and functionality of href attribute.
When you write like this:
❮
It means, you are hyper referencing(trying to redirect) to some location whenever this anchor tag is clicked.
It doesn't mean you are doing only click action. It means, you are doing click + redirection.
href = click + redirection.
whereas, your need is only click event handling. Therefore, how you are handling through jquery.
$('a').on("click",function(){
----
----
})
This will work fine.
You shouldn't be using href to try to access a javascript function. That attribute is for navigation purposes. Also, binding to a jquery click even is the better way to handle your events so you adhere to separation of concerns design patterns.
If you need to put your function call in an attribute decorator, use the onclick attribute instead and don't evaluate the function by adding the parenthesis, just reference it.
<a onclick="previousSlide" class="previousSlideArrow">❮</a>
Anchor tag is for navigation which requires Href attribute. You should not use href for event handling. Instead:
<div class="galleryPreviewArrows">
❮
❯
</div>
It is strange..But writing that function outside document.ready works. It looks like that function should be defined before document is ready.
That may be the reson alert works always..which is a built-in function.
Also this is not the recommended way to bind event listner. Use jquery on/off to add/remove listners.
function nextSlide() {
//$('a.nextSlideArrow').click(function() {
alert('next');
//return false;
//});
}
function previousSlide() {
//$('a.previousSlideArrow').click(function() {
alert('prev');
//return false;
//});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="slider-container">
<div class="galleryPreviewArrows">
❮
❯
</div>
</div>
here is the HTML code, while clicking on clearfix class function called will happen and it will run the same function 4 times .
<div class="clearfix">
<ul id="dashboard-tab" class="nav nav-tabs pull-left">
<li class="active" isdashboardloaded="true">
<a data-toggle="tab" href="#dashboard_5" aria-expanded="true">DashLoadingLineChart</a>
</li>
<li class="" isdashboardloaded="true">
<a data-toggle="tab" href="#dashboard_6" aria-expanded="false">Zoom</a>
</li>
</ul>
</div>
JS function
$(document).on('click','.clearfix',function(){
var dashId=$('.dashboardTabContent.active').attr('id');
var dash_ids = bu.angular.pageScope.dashboardCollection.collection;
var dashBoardUrl=event.target.href;
$.each(dashObj.widgetObj,function(widgetId,widgetObj){
clearWidget(widgetId,widgetObj.mode);
var widget_refresh_interval = widgetObj.refresh_interval;
//widgetInterval[widgetId] = 0;
clearInterval(widgetInterval[widgetId]);
bu.angular.pageScope.$digest();
widgetWiseReload(widgetId,dashId)
getWidgetData(widgetId,dashId,widgetObj,data_sources);
});
});
i need to run this function only one time, but it is running more than 2 times .
Maybe you are attaching the function more than one time. Try this:
$(document).off("click", ".clearfix").on('click','.clearfix',function() {
$.each(dashObj.widgetObj,function(widgetId,widgetObj){
clearWidget(widgetId,widgetObj.mode);
var widget_refresh_interval = widgetObj.refresh_interval;
//widgetInterval[widgetId] = 0;
clearInterval(widgetInterval[widgetId]);
bu.angular.pageScope.$digest();
widgetWiseReload(widgetId,dashId)
getWidgetData(widgetId,dashId,widgetObj,data_sources);
});
});
This will detach the event before attaching it again, so if is called more than one time, it will be attached one time, actually.
Protip: Keep your indentation clean.
Protip 2: If this was the problem, then you should look why this code is called more than one time instead of using this hack.
// define a function of runOce
function runOnce(fn) {
var isDone = false;
return function(){
if(isDone){
return;
}
isDone = true;
fn();
};
}
// demo
function youWantRunFn(){
alert(0);
}
var changeYourFn = runOnce(youWantRunFn);
// now,changeYourFn only can run once
changeYourFn(); // alert 0
changeYourFn(); // nothing
Using Bootstrap
<ul class="nav nav-pills nav-stacked col-sm-2 hidden" id="menu">
<li role="presentation" id="LiNewsFeed">News Feed</li>
<li role="presentation" id="LiStatusUpdate">Update Status</li>
<li role="presentation" id="LiWriteWall">Post On Wall</li>
<li role="presentation" id="LiNotifications">Notifications</li>
<li role="presentation" id="LiLogOut">Logout</li>
</ul>
In Javascript, I am disabling some of the <li> like the following:
$('#LiNewsFeed').addClass('disabled');
The Item in the List actually LOOKS disabled, when when I click on it, it actually calls the javascript function, therefore, what I need is to disable the <a href> not just the <li>
I tried adding this after $(document).ready:
$(".nav li.disabled a").click(function () {
return false;
});
But it's not really doing anything.
What I need is to disable the <a href> directly after disabling <li> in my Js code, and not to depend on a click event...
Seems like there is no way to disable an <a href>, so I need a way around it
Any help would be appreciated.
use below code. check working example JSFIDDLE
$(".nav li.disabled a").each(function(){
$(this).attr('href','javascript:void(0);');
});
As you are disabling LI in javascript (runtime), you should use .on to bind events on disabled links:
$(".nav").on('click', 'li.disabled a', function () {
return false;
});
I would check on every link click if the parent has the disabled class.
$('.nav li a').click(function () {
if($(this).parent('li').hasClass('disabled')) {
return false;
}
return true;
});
EDIT, following more info from OP I would suggest the following:
$('.nav li a').each(function() {
var $this = $(this);
// store reference of 'href' attr in case link is re-enabled
$this.data('href', $this.attr('href'));
if ($this.parent('li').hasClass('disabled')) {
// remove href attribute disabling click
$this.removeAttr('href');
} else {
// restore href
$this.attr('href', this.data('href'));
}
});
This code should be run after you add/remove the disabled class on li elements.
EDIT 2 - Rather than you calling functions from the href of <a> links, you could do something like the following:
var events = {
'#LiNewsFeed': 'GetNewsFeed',
'#LiStatusUpdate': 'StatusUpdate'
'#LiWriteWall': 'WriteOnWall',
'#LiNotifications': 'GetNotifications',
'#LiLogOut': 'LogOut'
};
for (var selector in events) {
if (events.hasOwnProperty(selector)) {
try {
$(selector).click(function () {
// assuming function is global
if (typeof window[events[selector]] === 'function') {
// call function
window[events[selector]]();
}
// this is needed if the a element still has a href attr
return false;
});
} catch (e) {
console.log('Invalid Selector');
}
}
}
This way you can control the calling of the function, and check whether it should be called without altering the element, perhaps stick an
if (!$(this).parent('li').hasClass('disabled')) {
...
}
around the function call.
can you convert the a into span?
(code not tested)
$(".nav li.disabled a").replaceWith(function() { return "<span>" + this.innerHTML + "</span>"; });
this is my html code:
<body onload="fun1()">
<ul id="nav" class="nav" style="font-size:12px;">
<li>Tab1</li>
<li>Tab2</li>
<li>Tab3</li>
</ul>
</body>
<div id='home'></div>
this the script loading the page content in a 'home' div , and if i click 'tab1' that particular 'tab1.php' loading in 'home' div and when i click 'tab2' particular tab2.php is loading in 'home' div and when i click tab3 particular tab3.php is loading in home div,
<script>
function fun1(){
$("#home").load("tab1.php",{},function(){});
}
function fun2(){
$("#home").load("tab2.php",{},function(){});
}
function fun3(){
$("#home").load("tab3.php",{},function(){});
}
</script>
when i click on the tab1 page is loaded in home div and this home div has to refresh for every 5 seconds when tab2 page is loaded in home div and this home div has to refresh for 5 seconds and same as tab3
please check the 'onload' function is for body tag!
and i tried using setInterval(function() {}); like this :
function fun1(){
setInterval(function(){
$("#home").load("tab1.php",{},function(){});
},5000);
}
function fun2(){
setInterval(function(){
$("#home").load("tab2.php",{},function(){});
},5000);
}
function fun3(){
setInterval(function(){
$("#home").load("tab3.php",{},function(){});
},5000);
}
And the problem is when i called the page through ajax load() function than whole body of the page is loading, so i dont want to load whole page i want to refresh the page of particular div home div only, please suggest how to solve this problem.
please check onload() function i have used to call the default page tab1.php
I would organise the code like this:
<body>
<ul id="nav" class="nav" style="font-size:12px;">
<li>Tab1</li>
<li>Tab2</li>
<li>Tab3</li>
</ul>
</body>
<div id='home'></div>
JavaScript:
jQuery(function($) {
var $current,
timer;
// change current tab based on given anchor
function changeTab($element)
{
if (timer) {
clearInterval(timer); // clear old timer
}
$current = $element;
// set new timer
timer = setInterval(function() {
refreshCurrentTab();
}, 5000);
// and call immediately
refreshCurrentTab();
}
function refreshCurrentTab()
{
$('#home').load($current.prop('href'));
}
$('#nav').on('click', 'a', function(e) {
e.preventDefault();
changeTab($(this));
});
changeTab($('#nav .selected')); // initial tab
});
I suggest you to use .data() method of jQuery to provide required extra info:
<ul id="nav" class="nav" style="font-size:12px;">
<li>Tab1</li>
<li>Tab2</li>
<li>Tab3</li>
</ul>
As you are using jQuery then better to use unobtrusive way of writing scripts like this:
$('#nav a').on('click', function(e){
e.preventDefault();
$('.active').removeClass('active'); // removes the active class from other link
$(this).addClass('active'); // adds the active class to current cliked link
setInterval(function(){
$("#home").load($('.active').data('url'),{},function(){}); // populates the div with data-url of active class.
}, 5000);
});
$('#nav li:eq(0) a').trigger('click'); // triggers the first link's click.
Here's a very simple implementation of what you've requested. Contains comments, so you should be able to follow through it.
also, you can easily update this to auto-update using setInterval() function:
test.php single page demo
<?php
// Dummy Ajax Handler
if (!empty($_GET['load']))
{
switch ($_GET['load'])
{
case 'tab1':
echo "hello from tab 1";
break;
case 'tab2':
echo "hello from tab 2";
break;
case 'tab3':
echo "hello from tab 3";
break;
}
exit();
}
?>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
// When Page Loads
$(function()
{
// Load Tab 1 By Default
$('#home').load('test.php?load=tab1');
// Handle Nav Clicks
$('#nav li a').click(function()
{
// Load Requested Tab
$('#home').load('test.php?load=tab' + $(this).attr('data-tab'));
});
});
</script>
<ul id="nav" class="nav" style="font-size:12px;">
<li>Tab1</li>
<li>Tab2</li>
<li>Tab3</li>
</ul>
<div id="home"></div>
In html, I removed all javascript you have there. It is not good to mix html code with javascript code, it is less understandable.
<body>
<ul id="nav" class="nav" style="font-size:12px;">
<li>Tab1</li>
<li>Tab2</li>
<li>Tab3</li>
</ul>
</body>
<div id='home'></div>
in javascript:
// First we need to make onload, that we removed from html.
// So I make a function and bind it to window.onload, which is almost same as
// <body onload="bla()">
// Everything inside the function will then happen after html is loaded
// in browser, which is very important, because we cant manipulate with
// elements that doesn't exist yet.
window.onload = function() {
// there we need to put all code
};
Let's make some switch now. Do everything without refresh first. We have 3 tabs, so we need to make new content inside of home:
// first we need to add event onclick to our <a>
$("#m_blink").onclick(function() { });
$("#d_blink").onclick(function() { });
$("#k_blink").onclick(function() { });
// now add what should happen when you click on <a>
$("#m_blink").onclick(function() {
$("#home").load("tab1.php",{},function(){});
});
$("#d_blink").onclick(function() {
$("#home").load("tab2.php",{},function(){});
});
$("#k_blink").onclick(function() {
$("#home").load("tab3.php",{},function(){});
});
Now setInterval function is easy to write.
Two params, first is function you want to call, second is time in miliseconds.
setInterval(function(){
// do something
}, 5*1000);
So now first though is just do setInterval and put ajax inside, like that:
setInterval(function(){
$("#home").load("tab1.php",{},function(){});
}, 5*1000);
But the problem is, once user switch the tab, then after 5 seconds, interval will load data from tab1 again! How we solve the problem, easy. We will make variable currentTable that will hold the state which table user see. And with each table switch, we will change currentTable. Also we will use currentTable in setInterval, so function will always do what we want.
So now from scratch again, complete js code:
window.onload = function() {
var currentTable = "tab1.php"; // this is our initial state
// now I define function reloadTab, because we do that all the time
// and it is boring to write same code again and again
function reloadTab() {
$("#home").load(currentTable,{},function(){});
}
// onclicks - it is so easy now, we just change tab and call realoadTab
$("#m_blink").onclick(function() {
currentTable = "tab1.php";
reloadTab();
});
$("#m_blink").onclick(function() {
currentTable = "tab2.php";
reloadTab();
});
$("#m_blink").onclick(function() {
currentTable = "tab3.php";
reloadTab();
});
// setInterval - all we need is use reloadTab as first param
setInterval(reloadTab, 5*1000);
}; // end of window.onload
So thats it, all javascript that you need is the last part.
tr something like this
javascript
$(function(){
//adding click event
$('#nav li a').click(function(){
var url = this.id + '.php';
$("#home").load(url,{},function(){
// store your page id which is currently loaded with data attribute on #home element
$("#home").data('current_page',this.id);
});
})
// auto refresh function
setInterval(function(){
// retrieve page if which is currently loaded with data attribute on #home element
var current_page = $("#home").data('current_page');
var url= current_page + '.php';
$("#home").load(url);
},5000);
});
html
<body>
<ul id="nav" class="nav" style="font-size:12px;">
<li>Tab1</li>
<li>Tab2</li>
<li>Tab3</li>
</ul>
<div id='home' data-current_page='tab1'> </div>
</body>
EDITED [According to your code]
javascript
//default page
var page = 'tab1.php';
function fun1(){
page = "tab1.php";
$("#home").load("tab1.php",{},function(){});
}
function fun2(){
page = "tab2.php";
$("#home").load("tab2.php",{},function(){});
}
function fun3(){
page = "tab3.php";
$("#home").load("tab3.php",{},function(){});
}
function autorefresh(){
setInterval(function(){
$("#home").load(page,{},function(){});
},5000);
}
html
<body onload="autorefresh()">
<ul id="nav" class="nav" style="font-size:12px;">
<li>Tab1</li>
<li>Tab2</li>
<li>Tab3</li>
</ul>
<div id='home'></div>