jQuery 选项卡的键盘导航
如何为具有历史记录的 jQuery 选项卡制作键盘导航左/上/右/下(如照片库)功能? http://dl.dropbox.com/u/6594481 中没有键盘功能的演示/tabs/index.html
所需功能:
- 从第一层到最后一层的嵌套 ajax 选项卡
- 在键盘上
top/down
进行选择并 CSS 显示active
键盘上左/右
更改后/前
活动
嵌套ajax选项卡的内容选项卡是 - 一个额外选项,使
活动
嵌套ajax具体嵌套ajax选项卡级别上“cursor-on”上的选项卡
阅读更多详细问题以及示例图片 https://stackoverflow.com/questions/2975003/jquery-tools-to-make-keyboard-and-cookies-feature-for-ajaxed-tabs-with -历史
/**
* @license
* jQuery Tools @VERSION Tabs- The basics of UI design.
*
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
*
* http://flowplayer.org/tools/tabs/
*
* Since: November 2008
* Date: @DATE
*/
(function($) {
// static constructs
$.tools = $.tools || {version: '@VERSION'};
$.tools.tabs = {
conf: {
tabs: 'a',
current: 'current',
onBeforeClick: null,
onClick: null,
effect: 'default',
initialIndex: 0,
event: 'click',
rotate: false,
// 1.2
history: false
},
addEffect: function(name, fn) {
effects[name] = fn;
}
};
var effects = {
// simple "toggle" effect
'default': function(i, done) {
this.getPanes().hide().eq(i).show();
done.call();
},
/*
configuration:
- fadeOutSpeed (positive value does "crossfading")
- fadeInSpeed
*/
fade: function(i, done) {
var conf = this.getConf(),
speed = conf.fadeOutSpeed,
panes = this.getPanes();
if (speed) {
panes.fadeOut(speed);
} else {
panes.hide();
}
panes.eq(i).fadeIn(conf.fadeInSpeed, done);
},
// for basic accordions
slide: function(i, done) {
this.getPanes().slideUp(200);
this.getPanes().eq(i).slideDown(400, done);
},
/**
* AJAX effect
*/
ajax: function(i, done) {
this.getPanes().eq(0).load(this.getTabs().eq(i).attr("href"), done);
}
};
var w;
/**
* Horizontal accordion
*
* @deprecated will be replaced with a more robust implementation
*/
$.tools.tabs.addEffect("horizontal", function(i, done) {
// store original width of a pane into memory
if (!w) { w = this.getPanes().eq(0).width(); }
// set current pane's width to zero
this.getCurrentPane().animate({width: 0}, function() { $(this).hide(); });
// grow opened pane to it's original width
this.getPanes().eq(i).animate({width: w}, function() {
$(this).show();
done.call();
});
});
function Tabs(root, paneSelector, conf) {
var self = this,
trigger = root.add(this),
tabs = root.find(conf.tabs),
panes = paneSelector.jquery ? paneSelector : root.children(paneSelector),
current;
// make sure tabs and panes are found
if (!tabs.length) { tabs = root.children(); }
if (!panes.length) { panes = root.parent().find(paneSelector); }
if (!panes.length) { panes = $(paneSelector); }
// public methods
$.extend(this, {
click: function(i, e) {
var tab = tabs.eq(i);
if (typeof i == 'string' && i.replace("#", "")) {
tab = tabs.filter("[href*=" + i.replace("#", "") + "]");
i = Math.max(tabs.index(tab), 0);
}
if (conf.rotate) {
var last = tabs.length -1;
if (i < 0) { return self.click(last, e); }
if (i > last) { return self.click(0, e); }
}
if (!tab.length) {
if (current >= 0) { return self; }
i = conf.initialIndex;
tab = tabs.eq(i);
}
// current tab is being clicked
if (i === current) { return self; }
// possibility to cancel click action
e = e || $.Event();
e.type = "onBeforeClick";
trigger.trigger(e, [i]);
if (e.isDefaultPrevented()) { return; }
// call the effect
effects[conf.effect].call(self, i, function() {
// onClick callback
e.type = "onClick";
trigger.trigger(e, [i]);
});
// default behaviour
current = i;
tabs.removeClass(conf.current);
tab.addClass(conf.current);
return self;
},
getConf: function() {
return conf;
},
getTabs: function() {
return tabs;
},
getPanes: function() {
return panes;
},
getCurrentPane: function() {
return panes.eq(current);
},
getCurrentTab: function() {
return tabs.eq(current);
},
getIndex: function() {
return current;
},
next: function() {
return self.click(current + 1);
},
prev: function() {
return self.click(current - 1);
}
});
// callbacks
$.each("onBeforeClick,onClick".split(","), function(i, name) {
// configuration
if ($.isFunction(conf[name])) {
$(self).bind(name, conf[name]);
}
// API
self[name] = function(fn) {
$(self).bind(name, fn);
return self;
};
});
if (conf.history && $.fn.history) {
$.tools.history.init(tabs);
conf.event = 'history';
}
// setup click actions for each tab
tabs.each(function(i) {
$(this).bind(conf.event, function(e) {
self.click(i, e);
return e.preventDefault();
});
});
// cross tab anchor link
panes.find("a[href^=#]").click(function(e) {
self.click($(this).attr("href"), e);
});
// open initial tab
if (location.hash) {
self.click(location.hash);
} else {
if (conf.initialIndex === 0 || conf.initialIndex > 0) {
self.click(conf.initialIndex);
}
}
}
// jQuery plugin implementation
$.fn.tabs = function(paneSelector, conf) {
// return existing instance
var el = this.data("tabs");
if (el) { return el; }
if ($.isFunction(conf)) {
conf = {onBeforeClick: conf};
}
// setup conf
conf = $.extend({}, $.tools.tabs.conf, conf);
this.each(function() {
el = new Tabs($(this), paneSelector, conf);
$(this).data("tabs", el);
});
return conf.api ? el: this;
};
}) (jQuery);
/**
* @license
* jQuery Tools @VERSION History "Back button for AJAX apps"
*
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
*
* http://flowplayer.org/tools/toolbox/history.html
*
* Since: Mar 2010
* Date: @DATE
*/
(function($) {
var hash, iframe, links, inited;
$.tools = $.tools || {version: '@VERSION'};
$.tools.history = {
init: function(els) {
if (inited) { return; }
// IE
if ($.browser.msie && $.browser.version < '8') {
// create iframe that is constantly checked for hash changes
if (!iframe) {
iframe = $("<iframe/>").attr("src", "javascript:false;").hide().get(0);
$("body").append(iframe);
setInterval(function() {
var idoc = iframe.contentWindow.document,
h = idoc.location.hash;
if (hash !== h) {
$.event.trigger("hash", h);
}
}, 100);
setIframeLocation(location.hash || '#');
}
// other browsers scans for location.hash changes directly without iframe hack
} else {
setInterval(function() {
var h = location.hash;
if (h !== hash) {
$.event.trigger("hash", h);
}
}, 100);
}
links = !links ? els : links.add(els);
els.click(function(e) {
var href = $(this).attr("href");
if (iframe) { setIframeLocation(href); }
// handle non-anchor links
if (href.slice(0, 1) != "#") {
location.href = "#" + href;
return e.preventDefault();
}
});
inited = true;
}
};
function setIframeLocation(h) {
if (h) {
var doc = iframe.contentWindow.document;
doc.open().close();
doc.location.hash = h;
}
}
// global histroy change listener
$(window).bind("hash", function(e, h) {
if (h) {
links.filter(function() {
var href = $(this).attr("href");
return href == h || href == h.replace("#", "");
}).trigger("history", [h]);
} else {
links.eq(0).trigger("history", [h]);
}
hash = h;
window.location.hash = hash;
});
// jQuery plugin implementation
$.fn.history = function(fn) {
$.tools.history.init(this);
// return jQuery
return this.bind("history", fn);
};
})(jQuery);
$(function() {
$("#list").tabs("#content > div", {effect: 'ajax', history: true});
});
How to make Keyboard
navigation left/up/right/down (like for photo gallery) feature for jQuery Tabs with history? Demo without keyboard feature in http://dl.dropbox.com/u/6594481/tabs/index.html
Needed functions:
- on keyboard
top/down
make select and CSS showactive
nested ajax tabs from 1-st to last level - on keyboard
left/right
changeback/forward
content ofactive
nested ajax tabs tab - an extra option, make
active
nested ajax tab on 'cursor-on' on concrete nested ajax tabs level
Read more detailed question with example pictures in https://stackoverflow.com/questions/2975003/jquery-tools-to-make-keyboard-and-cookies-feature-for-ajaxed-tabs-with-history
/**
* @license
* jQuery Tools @VERSION Tabs- The basics of UI design.
*
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
*
* http://flowplayer.org/tools/tabs/
*
* Since: November 2008
* Date: @DATE
*/
(function($) {
// static constructs
$.tools = $.tools || {version: '@VERSION'};
$.tools.tabs = {
conf: {
tabs: 'a',
current: 'current',
onBeforeClick: null,
onClick: null,
effect: 'default',
initialIndex: 0,
event: 'click',
rotate: false,
// 1.2
history: false
},
addEffect: function(name, fn) {
effects[name] = fn;
}
};
var effects = {
// simple "toggle" effect
'default': function(i, done) {
this.getPanes().hide().eq(i).show();
done.call();
},
/*
configuration:
- fadeOutSpeed (positive value does "crossfading")
- fadeInSpeed
*/
fade: function(i, done) {
var conf = this.getConf(),
speed = conf.fadeOutSpeed,
panes = this.getPanes();
if (speed) {
panes.fadeOut(speed);
} else {
panes.hide();
}
panes.eq(i).fadeIn(conf.fadeInSpeed, done);
},
// for basic accordions
slide: function(i, done) {
this.getPanes().slideUp(200);
this.getPanes().eq(i).slideDown(400, done);
},
/**
* AJAX effect
*/
ajax: function(i, done) {
this.getPanes().eq(0).load(this.getTabs().eq(i).attr("href"), done);
}
};
var w;
/**
* Horizontal accordion
*
* @deprecated will be replaced with a more robust implementation
*/
$.tools.tabs.addEffect("horizontal", function(i, done) {
// store original width of a pane into memory
if (!w) { w = this.getPanes().eq(0).width(); }
// set current pane's width to zero
this.getCurrentPane().animate({width: 0}, function() { $(this).hide(); });
// grow opened pane to it's original width
this.getPanes().eq(i).animate({width: w}, function() {
$(this).show();
done.call();
});
});
function Tabs(root, paneSelector, conf) {
var self = this,
trigger = root.add(this),
tabs = root.find(conf.tabs),
panes = paneSelector.jquery ? paneSelector : root.children(paneSelector),
current;
// make sure tabs and panes are found
if (!tabs.length) { tabs = root.children(); }
if (!panes.length) { panes = root.parent().find(paneSelector); }
if (!panes.length) { panes = $(paneSelector); }
// public methods
$.extend(this, {
click: function(i, e) {
var tab = tabs.eq(i);
if (typeof i == 'string' && i.replace("#", "")) {
tab = tabs.filter("[href*=" + i.replace("#", "") + "]");
i = Math.max(tabs.index(tab), 0);
}
if (conf.rotate) {
var last = tabs.length -1;
if (i < 0) { return self.click(last, e); }
if (i > last) { return self.click(0, e); }
}
if (!tab.length) {
if (current >= 0) { return self; }
i = conf.initialIndex;
tab = tabs.eq(i);
}
// current tab is being clicked
if (i === current) { return self; }
// possibility to cancel click action
e = e || $.Event();
e.type = "onBeforeClick";
trigger.trigger(e, [i]);
if (e.isDefaultPrevented()) { return; }
// call the effect
effects[conf.effect].call(self, i, function() {
// onClick callback
e.type = "onClick";
trigger.trigger(e, [i]);
});
// default behaviour
current = i;
tabs.removeClass(conf.current);
tab.addClass(conf.current);
return self;
},
getConf: function() {
return conf;
},
getTabs: function() {
return tabs;
},
getPanes: function() {
return panes;
},
getCurrentPane: function() {
return panes.eq(current);
},
getCurrentTab: function() {
return tabs.eq(current);
},
getIndex: function() {
return current;
},
next: function() {
return self.click(current + 1);
},
prev: function() {
return self.click(current - 1);
}
});
// callbacks
$.each("onBeforeClick,onClick".split(","), function(i, name) {
// configuration
if ($.isFunction(conf[name])) {
$(self).bind(name, conf[name]);
}
// API
self[name] = function(fn) {
$(self).bind(name, fn);
return self;
};
});
if (conf.history && $.fn.history) {
$.tools.history.init(tabs);
conf.event = 'history';
}
// setup click actions for each tab
tabs.each(function(i) {
$(this).bind(conf.event, function(e) {
self.click(i, e);
return e.preventDefault();
});
});
// cross tab anchor link
panes.find("a[href^=#]").click(function(e) {
self.click($(this).attr("href"), e);
});
// open initial tab
if (location.hash) {
self.click(location.hash);
} else {
if (conf.initialIndex === 0 || conf.initialIndex > 0) {
self.click(conf.initialIndex);
}
}
}
// jQuery plugin implementation
$.fn.tabs = function(paneSelector, conf) {
// return existing instance
var el = this.data("tabs");
if (el) { return el; }
if ($.isFunction(conf)) {
conf = {onBeforeClick: conf};
}
// setup conf
conf = $.extend({}, $.tools.tabs.conf, conf);
this.each(function() {
el = new Tabs($(this), paneSelector, conf);
$(this).data("tabs", el);
});
return conf.api ? el: this;
};
}) (jQuery);
/**
* @license
* jQuery Tools @VERSION History "Back button for AJAX apps"
*
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
*
* http://flowplayer.org/tools/toolbox/history.html
*
* Since: Mar 2010
* Date: @DATE
*/
(function($) {
var hash, iframe, links, inited;
$.tools = $.tools || {version: '@VERSION'};
$.tools.history = {
init: function(els) {
if (inited) { return; }
// IE
if ($.browser.msie && $.browser.version < '8') {
// create iframe that is constantly checked for hash changes
if (!iframe) {
iframe = $("<iframe/>").attr("src", "javascript:false;").hide().get(0);
$("body").append(iframe);
setInterval(function() {
var idoc = iframe.contentWindow.document,
h = idoc.location.hash;
if (hash !== h) {
$.event.trigger("hash", h);
}
}, 100);
setIframeLocation(location.hash || '#');
}
// other browsers scans for location.hash changes directly without iframe hack
} else {
setInterval(function() {
var h = location.hash;
if (h !== hash) {
$.event.trigger("hash", h);
}
}, 100);
}
links = !links ? els : links.add(els);
els.click(function(e) {
var href = $(this).attr("href");
if (iframe) { setIframeLocation(href); }
// handle non-anchor links
if (href.slice(0, 1) != "#") {
location.href = "#" + href;
return e.preventDefault();
}
});
inited = true;
}
};
function setIframeLocation(h) {
if (h) {
var doc = iframe.contentWindow.document;
doc.open().close();
doc.location.hash = h;
}
}
// global histroy change listener
$(window).bind("hash", function(e, h) {
if (h) {
links.filter(function() {
var href = $(this).attr("href");
return href == h || href == h.replace("#", "");
}).trigger("history", [h]);
} else {
links.eq(0).trigger("history", [h]);
}
hash = h;
window.location.hash = hash;
});
// jQuery plugin implementation
$.fn.history = function(fn) {
$.tools.history.init(this);
// return jQuery
return this.bind("history", fn);
};
})(jQuery);
$(function() {
$("#list").tabs("#content > div", {effect: 'ajax', history: true});
});
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
以下是我将键盘功能添加到您的代码中的方法。
但是,我想补充一点,在查看几乎相同的 您在此问题前两天发布的问题,该网站的建立是为了帮助您发现代码中的问题,而不是为您编写所有代码。如果您希望有人编写所有代码,请雇用某人来完成,否则您可能必须学习如何自己完成(根据需要需要我们提供故障排除帮助)。
不管怎样,我设置了这个演示来帮助您入门。希望有足够的评论让您能够理解我在做什么,并且可以从那里开始。
Here is how I would add the keyboard functionality to your code.
But, I want to add that after looking at pretty much the same question you posted two days prior to this one, that this site is set up to help you find problems in your code, not to write it all for you. If you want someone to write all the code, hire someone to do it or you'll probably have to learn how to do it yourself (with troubleshooting help from us as needed).
Anyway, I set up this demo to help you get started. Hopefully there are enough comments that you can understand what I was doing and you can take it from there.
您可以使用以下方法将操作绑定到按键:
快速谷歌搜索为我提供了以下关键代码列表:http://www.cambiaresearch.com/c4/702b8cd1-e5b0-42e6-83ac-25f0306e3e25/Javascript-Char-Codes-Key-Codes.aspx
You can bind actions to key presses by using
A quick google search got me this list of key codes: http://www.cambiaresearch.com/c4/702b8cd1-e5b0-42e6-83ac-25f0306e3e25/Javascript-Char-Codes-Key-Codes.aspx