I'm trying to disable top menu on jQuery UI Tabs - so the tabs would be operated with next/prev buttons only.
Disable option form the doc does not seams to work as expected.
Please see my example here: Live Demo
jQuery code:
$(document).ready( function() {
$(function() {
var $tabs = $('#tabs').tabs();
$(".ui-tabs-panel").each(function(i){
var totalSize = $(".ui-tabs-panel").size() - 1;
if (i != totalSize) {
next = i + 2;
$(this).append("<a href='#' class='next-tab mover' rel='" + next + "'>Next Page »</a>");
}
if (i != 0) {
prev = i;
$(this).append("<a href='#' class='prev-tab mover' rel='" + prev + "'>« Prev Page</a>");
}
});
$('.next-tab, .prev-tab').click(function() {
$tabs.tabs('select', $(this).attr("rel"));
return false;
});
});
});
Any ideas how can I disable top menu, but keep the structure, style etc.. ?
How about just enable the tab to be selected just before selecting it, and then disable the tabs again?
So, at the initialisation, all tabs are disabled:
var $tabs = $('#tabs').tabs({
disabled: [0, 1, 2]
});
And when selecting the tab, enable it before selecting it, and then disable all tabs again:
$tabs.tabs('enable', tabIndex)
.tabs('select', tabIndex)
.tabs("option","disabled", [0, 1, 2]);
See it in action: http://jsfiddle.net/william/y6QeV/21/.
EDIT: You can simply disable just the old tab:
var newTabIndex = $(this).attr("rel");
var oldTabIndex = $tabs.tabs('option', 'selected');
$tabs.tabs('enable', newTabIndex)
.tabs('select', newTabIndex)
.tabs('disable', oldTabIndex);
Example: http://jsfiddle.net/william/y6QeV/22/.
Related
I use stackoverflow often so thanks to all who contribute - its been very helpful.
I am not an avid programmer and use jquery at its most basic level. I hope someone can help.
I would like to dynamically change the href url of '.nexttab' controls so that the user can move onto the next html page.
The below is my (juvenile) code.
$(function() {
$("#tabs").tabs();
$(".nexttab").click(function() {
var selected = $("#tabs").tabs("option", "selected");
$("#tabs").tabs("option", "selected", selected + 1);
var href = $(this).attr('href');
var lasttab = $(this).ui.panel('id');
if(lasttab == 'tabs-7'){
$('.nexttab').attr('href', href.replace('#','http://google.com.au'));
}
});
$(".prevtab").click(function() {
var selected = $("#tabs").tabs("option", "selected");
$("#tabs").tabs("option", "selected", selected - 1);
});
});
html is here
<div id="control-arrows">
< Back | Continue >
</div>
How can I identify the correct panel or tab (which is always the last) and then make the url change ?
Thank you,
Sarah
I have build a jQuery widget for Footer bar. This bar contain some click-able event. I want to write unit test to verify the functionality. For testing I am using qunit. I want to create test unit for these functionality:-
Check bar is loaded
Check on close button bar should be minimized
On next click on close button bar again get maximized
Can someone help me to write correct test modules.
Here is my footer bar widget code :-
// widget for footer bar
(function($){
$.widget("ui.footerbar", {
options: {
id: null, //id for the DOM element
offset:0, // relative to right edge of the browser window
width: '100%', // width of the chatbox
boxClosed: function(id) {}, // called when the close icon is clicked
},
init: function(elem) {
this.elem = elem;
},
widget: function() {
return this.uiFooterbar
},
_create: function(){
var self = this,
options = self.options,
offset = options.offset,
title = options.title || "No Title",
// footerbar
uiFooterbar = (self.uiFooterbar = $('<div></div>'))
.appendTo(document.body)
.attr('id', 'stickybar'),
// close button tab
uiFooterbarClosebox = (self.uiFooterbarClosebox = $('<div></div>'))
.addClass('vmchat_bar_button'
)
.attr('id', 'hide_bar')
.appendTo(uiFooterbar),
uiFooterbarClose = (self.uiFooterbarClose = $('<input>'))
.attr('id', 'closebtn')
.attr('type', 'button')
.appendTo(uiFooterbarClosebox)
.toggle(function () { alert('click1');
$('#stickybar').effect("size", { to: {width: 36}, origin: ['bottom','right'] }, 1000, function (){$('#stickybar').css("left", "97%")});
}, function () {alert('click2');
$('#stickybar').effect("size", { to: {width: self.options.width}, origin: ['bottom','left'] }, 100, function (){$('#stickybar').css("left", 0)});
});
//chatroom tab
uiFooterbarchatroomtab = (self.uiFooterbarchatroomtab = $('<div></div>'))
.addClass('vmchat_bar_button'
)
.attr('id', 'chatroom_bt')
.appendTo(uiFooterbar),
uiFooterbarchatroomContent = (self.uiFooterbarchatroomContent = $('<div class="inner_bt"></div>'))
.appendTo(uiFooterbarchatroomtab)
uiFooterbarchatroomIcon= (self.uiFooterbarchatroomIcon = $('<div id="chatroom_icon"></div>'))
.appendTo(uiFooterbarchatroomContent)
uiFooterbarchatroomText= (self.uiFooterbarchatroomText = $('<div id="chatroom_text"></div>'))
.appendTo(uiFooterbarchatroomContent)
.text('Chatroom')
.click(function(){
alert('open comman chat room');
})
//userlist tab
uiFooterbarUserlisttab = (self.uiFooterbarUserlisttab = $('<div></div>'))
.addClass('vmchat_bar_button'
)
.attr('id', 'user_list')
.appendTo(uiFooterbar),
uiFooterbarUserlistContent = (self.uiFooterbarUserlistContent = $('<div class="inner_bt"></div>'))
.appendTo(uiFooterbarUserlisttab)
uiFooterbarUserlistIcon= (self.uiFooterbarUserlistIcon = $('<div id="usertab_icon"></div>'))
.appendTo(uiFooterbarUserlistContent)
uiFooterbarUserlistText= (self.uiFooterbarUserlistText = $('<div id="usertab_text"></div>'))
.appendTo(uiFooterbarUserlistContent)
.text('Private Chat')
.click(function(){
alert('open comman chat room');
})
self._setWidth(self.options.width);
self.init(self);
},
destroy: function () {
this.element.remove();
// if using jQuery UI 1.8.x
$.Widget.prototype.destroy.call(this);
// if using jQuery UI 1.9.x
//this._destroy();
},
_setWidth: function(width) {
this.uiFooterbar.width(width + "px");
}
});
}(jQuery));
For testing I have created these modules:-
Testing bar is loaded and visible
var el;
var body = document.body;
function bar(){
return el.footerbar("widget");
}
(function($){
module("core");
test("init", function(){
el = $("#qunit-fixture").footerbar();
ok( bar().is(':visible'), 'bar is open');
});
})(jQuery);
Testing correct Number of tabs
(function($){
var el, widget, elems;
module("html", {
setup: function() {
el = $("#qunit-fixture").footerbar();
widget = el.footerbar("widget");
}
});
test("check close button", function(){
expect(4);
elems = widget.find('.vmchat_bar_button');
equal( elems.length, 3, 'There are three Tabs' );
equal(widget.find('input[id="closebtn"]').parents('div').attr("id"),'hide_bar','close button is present');
equal(widget.find('div[id="chatroom_text"]').parent().hasClass('inner_bt'),true,'chatroom tab is present');
equal(widget.find('div[id="usertab_text"]').parent().hasClass('inner_bt'),true,'user list tab is present');
});
})(jQuery);
Testing bar get minimize/maximize on close button click
(function($){
module("event");
test("footerbaropen", function(){
// inject widget
el = $("#qunit-fixture").footerbar();
el.footerbar({})
equal(bar().css('left'),'0px' ,'bar is open');
// fire click event on close button
bar().find("#closebtn").trigger("click");
equal(bar().css('left'),'97%' ,'bar is closed'); // this is not working
});
})(jQuery);
Top two test seems to be working fine but in third test when click event is triggered bar does not get minimized in this block. Its status get changed when it exit out.
What should I do to get changed status of footer bar, if it is minimized or if it is active?
Problem is $('#stickybar').effect.
Your test is running before your footer bar complete this effect.
I want to display jquery mobile alternate button's with different color. The code which I am using now is only able to change the button theme to 'e' but I want 'theme b'. What can be the problem? Below is the code.
$(document).delegate('[data-role="page"]', 'pagecreate', function(e) {
var db = openDatabase("Database", "1.0", "PhoneGap Demo", 200000);
db.transaction(function(tx) {
tx.executeSql("SELECT id FROM DEMO", [],
function(tx, results) {
var len = results.rows.length,
i;
//If no result Found
for (i = 0; i < len; i++) {
var test = results.rows.item(i).id % 2; //to get the alternate row's
if (test == 0) {
var id = "color" + results.rows.item(i).id;
$("#" + id).attr('data-content-theme', 'e').removeClass('ui-body-d').addClass('ui-body-e').trigger('create'); // Change to theme e
}
}
});
});
});
I am changing the button theme as per the id of dynamically populated buttons.
If you could post some HTML code it would help a lot.
You could try the following to see whether it solves the issue:
$("#" + id).attr('data-content-theme', 'b').removeClass('ui-body-a ui-body-b ui-body-c ui-body-d ui-body-e').addClass('ui-body-b').trigger('create');
I am using Primefaces 3.2 with jsf 2 and glassfish 3.1.2.
I have a p:dataTable of users containing avatars of the user. Whenever the user moves the mouse over the avatar a p:overlayPanel appears with more information (lazy loaded) on the user, and disappears when the user moves the cursor away - like this:
<p:overlayPanel for="avatar" dynamic="true" showEvent="mouseover" hideEvent="mouseout" ...>
This works very well - as long as the user is "slowhanded". Whenever an user moves the cursor fast above many avatars many of the overlayPanels stay visible.
For example when the user has the cursor over the position where user avatars are displayed and uses the scroll wheel of his mouse to scroll the usertable down or up.
I believe that the overlaypanel starts to load the information dynamically (dynamic="true") from the server when showEvent="mouseover" is dispatched and displays the overlaypanel after the response from the server arrives.
This way it is not possible to detect whether the cursor is already away when the overlaypanel becomes visible - so the hideEvent="mouseout" is never dispatched.
Is there a way to make the primefaces overlaypanel appear directly on mousover, showing a loading gif and update the content into the overlaypanel when the response comes from the server.
Is this a good appraoch or does anyone know any other way to solve this nasty problem?
Thanks Pete
As my first answer is already very long and contains valid information, I decided to open a new answer presenting my final approach.
Im now using Primefaces inheritance pattern making the code alot cleaner. Also I noticed that replacing/overwriting the whole bindEvents function isnt necessary, as we can remove the old event handlers. Finally this code fixs the latest issue experienced: A hide event before ajax arrival.
PrimeFaces.widget.OverlayPanel = PrimeFaces.widget.OverlayPanel
.extend({
bindEvents : function() {
this._super();
var showEvent = this.cfg.showEvent + '.ui-overlay', hideEvent = this.cfg.hideEvent
+ '.ui-overlay';
$(document).off(showEvent + ' ' + hideEvent, this.targetId).on(
showEvent, this.targetId, this, function(e) {
var _self = e.data;
clearTimeout(_self.timer);
_self.timer = setTimeout(function() {
_self.hidden = false;
_self.show();
}, 300);
}).on(hideEvent, this.targetId, this, function(e) {
var _self = e.data;
clearTimeout(_self.timer);
_self.hidden = true;
_self.hide();
});
},
_show : function() {
if (!this.cfg.dynamic || !this.hidden) {
this._super();
}
}
});
Im sorry for the poor formatting: Eclipses fault ;)
Wow, finally after a long debuging session and testing various approaches i recognized that the problem isnt the ajax request but the event handlers itself:
.on(hideEvent, this.targetId, this, function(e) {
var _self = e.data;
if(_self.isVisible()) {
_self.hide();
}
});
As you can see, the widget is just hidden if its visible before. If your moving your mouse out too fast, now two things can happen:
The widget isnt visible at all
The animation is still going on
In this case the event is discarded and the panel stays visible. As animations are queued, one simply has to remove the if statement to fix the issue. I did this by replacing the whole bindEvents method:
PrimeFaces.widget.OverlayPanel.prototype.bindEvents = function() {
//mark target and descandants of target as a trigger for a primefaces overlay
this.target.data('primefaces-overlay-target', this.id).find('*').data('primefaces-overlay-target', this.id);
//show and hide events for target
if(this.cfg.showEvent == this.cfg.hideEvent) {
var event = this.cfg.showEvent;
$(document).off(event, this.targetId).on(event, this.targetId, this, function(e) {
e.data.toggle();
});
}
else {
var showEvent = this.cfg.showEvent + '.ui-overlay',
hideEvent = this.cfg.hideEvent + '.ui-overlay';
$(document).off(showEvent + ' ' + hideEvent, this.targetId).on(showEvent, this.targetId, this, function(e) {
var _self = e.data;
if(!_self.isVisible()) {
_self.show();
}
})
.on(hideEvent, this.targetId, this, function(e) {
var _self = e.data;
_self.hide();
});
}
//enter key support for mousedown event
this.bindKeyEvents();
var _self = this;
//hide overlay when mousedown is at outside of overlay
$(document.body).bind('mousedown.ui-overlay', function (e) {
if(_self.jq.hasClass('ui-overlay-hidden')) {
return;
}
//do nothing on target mousedown
var target = $(e.target);
if(_self.target.is(target)||_self.target.has(target).length > 0) {
return;
}
//hide overlay if mousedown is on outside
var offset = _self.jq.offset();
if(e.pageX < offset.left ||
e.pageX > offset.left + _self.jq.outerWidth() ||
e.pageY < offset.top ||
e.pageY > offset.top + _self.jq.outerHeight()) {
_self.hide();
}
});
//Hide overlay on resize
var resizeNS = 'resize.' + this.id;
$(window).unbind(resizeNS).bind(resizeNS, function() {
if(_self.jq.hasClass('ui-overlay-visible')) {
_self.hide();
}
});
};
Execute this code on load and the issue should be gone.
As your replacing the js code nevertheless, you can use this oppurtunity to implement quite a nice feature. By using timeouts in the event handlers one can easily implement a little delay not just improving usability (no more thousands of popups appear) but also reducing network traffic:
$(document).off(showEvent + ' ' + hideEvent, this.targetId).on(showEvent, this.targetId, this, function(e) {
var _self = e.data;
_self.timer = setTimeout( function(){
if(!_self.isVisible()) {
_self.show();
}
}, 300);
})
.on(hideEvent, this.targetId, this, function(e) {
var _self = e.data;
clearTimeout(_self.timer);
_self.hide();
});
Ofcourse you can use a global variable to control the delay time. If you want a more flexible approach youll have to overwrite the encodeScript method in the OverlayPanelRender to transmit an additional property. You could access it then with _self.cfg.delay. Notice though that youll have to replace the component model OverlayPanel too providing it with an extra attribute.
At the same time I thank you for this brilliant solution I take the opportunity to update it for Primefaces 5.2. In our application the code broke after that upgrade.
Follows the updated code for Primefaces 5.2:
PrimeFaces.widget.OverlayPanel.prototype.bindTargetEvents = function() {
var $this = this;
//mark target and descandants of target as a trigger for a primefaces overlay
this.target.data('primefaces-overlay-target', this.id).find('*').data('primefaces-overlay-target', this.id);
//show and hide events for target
if(this.cfg.showEvent === this.cfg.hideEvent) {
var event = this.cfg.showEvent;
this.target.on(event, function(e) {
$this.toggle();
});
}
else {
var showEvent = this.cfg.showEvent + '.ui-overlaypanel',
hideEvent = this.cfg.hideEvent + '.ui-overlaypanel';
this.target
.off(showEvent + ' ' + hideEvent)
.on(showEvent, function(e) {
clearTimeout($this.timer);
$this.timer = setTimeout(function() {
$('.ui-overlaypanel').hide();
$this.hidden = false;
$this.show();
}, 500);
})
.on(hideEvent, function(e) {
clearTimeout($this.timer);
$this.timer = setTimeout(function() {
// don't hide if hovering overlay
if(! $this.jq.is(":hover")) {
$this.hide();
}
}, 100);
});
}
$this.target.off('keydown.ui-overlaypanel keyup.ui-overlaypanel').on('keydown.ui-overlaypanel', function(e) {
var keyCode = $.ui.keyCode, key = e.which;
if(key === keyCode.ENTER||key === keyCode.NUMPAD_ENTER) {
e.preventDefault();
}
})
.on('keyup.ui-overlaypanel', function(e) {
var keyCode = $.ui.keyCode, key = e.which;
if(key === keyCode.ENTER||key === keyCode.NUMPAD_ENTER) {
$this.toggle();
e.preventDefault();
}
});
};
I also added an extra feature which allows the user to move the mouse over the overlay without hiding it. It should hide when you move the mouse out of it then which I accomplished through:
<p:overlayPanel .... onShow="onShowOverlayPanel(this)" ...>
function onShowOverlayPanel(ovr) {
ovr.jq.on("mouseleave", function(e) {
ovr.jq.hide();
});
}
Hope you enjoy!
It's been a long time, but in case anyone bumps into this problem, a showDelay attribute was added to the overlayPanel to solve this problem starting from Primefaces 6.2. However, it is not in the official documentation for some reason.
I'm a begginer jQuery dev, and I'm using the jQuery UI dialog to show up properties of an object (whatever).
var $dialog = $('<div></div>')
.html('This dialog will show every time!')
.dialog({
autoOpen: false,
title: 'Properties'
});
So this is the dialog, and let's say I have a FOR structure in which I add properties (p tags) and for some of those properties I want a button.
var dialogHtml = "";
var dialog_buttons = {};
for (var key in d.properties){
var str;
var str = '<p>' + something + '</p>';
if (condition){
dialog_buttons[key] = function()
{ functionName(key); };
}
dialogHtml = dialogHtml + str;
}
$dialog.dialog( "option", "buttons", dialog_buttons );
$dialog.dialog('open');
And somewhere else I have the function:
function functionName(key){
// something something
}
This is where I have the problem: the key variable that's passed to the function... when the button is called the key is the last value from the iteration.
Let's say we have keys 1, 2, 3, 4 then when the button is clicked, the key parameter will be 4.
I want when I click a button from the dialog, to know which button was pressed.
Can anybody help me?
Thanks!
Using the event data from the click event (see here)
$('#btn').click(function(e) {
functionName(e.target);
});
Explanation of Event.Target