ExtJS react to user clicks on tab in tabpanel - javascript

(Yes, I know this is similar to How can I attach an react to user clicking on tabs in Ext.TabPanel, but it is a different question)
I have a tabpanel, the panels of which can be accessed either by clicking on a tab, or by clicking links in other tabs. One tab in the tabpanel has a menu for the user to select the desired subpanel. What I am trying to achieve is that clicking on the tab does not activate it - thus forcing the user to select an option from the menu. However, I still want the panel to activate when a link on another panel is clicked, or when a menu option is selected.
This is how I disable the panel:
'beforeactivate': function (component, eOpts) {
//to prevent loading tab content on tab/menu click
console.debug('tab disabler', arguments);
return false;
}
It works - just works too well, blocking everything. I have not been able to find a way to detect the difference between clicking the tab and, well, doing anything else at all.

Basically you already described the problem: you want to prevent activation of the tab only when the tab header is clicked, not altogether, so the beforeactivate event is not the way to go.
You can access the tab header (which is basically just a button in the tab bar) via the tab property on the panel and prevent the execution of its handler by stopping the propagation of the click event:
panel.tab.on({
'click': function(tab, e) {
e.stopEvent();
}
});
Note: the docs say you can also return false to achieve the same, however that does not seem to work.
This won't affect activation of the panel at all, but the interaction on the tab header.
Check out this fiddle for a working example.

Related

jQuery animations on back button

I have a page where multiple tabs (subpages) are accessed via jQuery show/hide functions. When one clicks on the logo all other tabs are hidden and the first one is shown.
I would like to attach the same show/hide flow as with $("#logo").click() to the back button. When someone would tap browser's back button the default action should be prevented and show/hide combination should be activated to display the first tab.
Does anyone has a solution?
window.onbeforeunload function does not work...
https://jsfiddle.net/hqkyxz3w/3/
This is usually done using URL's hash (that's everything after #) and window.history.pushState() method.
When the user clicks on a tab/logo:
Change location.hash to whatever you want.
Call window.history.pushState() to add state to browsers history. See https://developer.mozilla.org/en-US/docs/Web/API/History_API for more detailed explanation what parameters it requires.
Call your function that hides/shows appropriate tabs.
Then, when you press the browser's back button you want the tabs to change so you need to know when the URL's hash has changed.
See this answer how to listen to hash change events: On - window.location.hash - Change?
Check current hash and call the same function from bullet point 3 in the previous paragraph that hide/shows tabs.
Here is the half working version... I have used location.hash and history.pushState to change it on clicking the tab and then window.onpopstate to hide the page..
https://jsfiddle.net/hqkyxz3w/4/
The problem still exists because the onpopstate also fires when clicking the tab and not only when tapping back button.. Here is the example:
https://jsfiddle.net/hqkyxz3w/5/
$("#tab1").click(function(){
location.hash = 'something';
history.pushState({extraData: "something"}, '', 'new-hash');
$("#page1").show();
});
$("#logo").click(function(){
$("#page1").hide();
});
window.onpopstate = function() {
alert('How to exclude it on clicking page one?');
$("#page1").hide();
};

Stop navigation AFTER link has been clicked

I have a slider with some buttons (which are links).
The buttons have double function
If I click on an inactive button, the slider will slide to the appropriate slide and the button will turn active (so preventDefault() here)
If I click on an active button, the link will work (no preventDefault())
Now, when I click on another inactive link after an active link is clicked, the browser will still got to the active link's url.
So the question is: How can I abort/stop/cancel a link navigation, after the link was pressed? I.E. my browser is already working.
The question is not: How can I prevent the link to be followed, if I click on the link?
jQuery('a.button').on('click', function(e){
if ( jQuery(this).hasClass('active') ) {
// no preventDefault(), so link is followed
return;
}
e.preventDefault();
// how can I stop the link from above?
// ..
jQuery(this).addClass('active')
// do the slide thing
});
Sounds like what you're trying to do is window.stop().
https://developer.mozilla.org/en-US/docs/Web/API/Window/stop
The stop() method is exactly equivalent to clicking the stop button in
the browser. Because of the order in which scripts are loaded, the
stop() method cannot stop the document in which it is contained from
loading, but it will stop the loading of large images, new windows,
and other objects whose loading is deferred.

Determining causes of Bootstrap events being raised

I've got a Bootstrap accordion, and a button that expands all of the accordion panels. This works fine.
HTML:
<div class="btn btn-primary btn-sm" id="accordion-expand-all">Expand all</div>
JS:
$("#accordion-expand-all").click(function() {
$(".panel-collapse").each(function() {
if ($(this).hasClass("in") === false) {
$(this).collapse("toggle");
};
});
});
THE PROBLEM:
I'd like to make it so that when a user clicks on a panel's header, if the accordion panel is collapsed, then the panel expands... and the window scrolls down such that the accordion panel's header is positioned at the top of the page.
A naive approach would be to invoke some function like pageScrollToTop(expandedPanel) to the Bootstrap shown.bs.collapse event. But this conflicts with the "Expand All" button, which raises the shown.bs.collapse every time an accordion panel is expanded, and thus scrolling the page all over the place.
I know this is pretty unlikely, but when a shown.bs.collapse event is raised, is there a way of determining if it was raised by a user's click, versus being raised programmatically (as with the "Expand all" button)? If so, my website would know when and when not to call pageScrollToTop().
You could trigger a once only event after someone clicks an unexpanded accordion item. It's not quite what you were after (determining programmatically triggered vs user triggered event), but it should work.
$('a[data-toggle=collapse]').on('click', function(){
if($(this).is('.collapsed')) {
$(this.getAttribute('href')).one('shown.bs.collapse', function(){
$(document.body).stop().animate({scrollTop: $(this).offset().top});
});
}
});
Here's a demo: http://jsfiddle.net/97vju2b7/
As a workaround, I attached a click handler to the accordion panel-headers, and created a "mock" show.bs.collapse event which scrolls the page afterwards (I peeked at the bootstrap.js code base to figure out how to do this).
The buttons just iterate over the accordion panels and invoke $("#foo-panel").collapse("toggle"), which raises the real show.bs.collapse event.

Synchronizing top-nav mouseleave for a tab and its associated submenu

I'm trying to create a top-nav menu as follows:
The idea is that when you click a tab, the tab itself gets highlighted in black and an associated menu shows up beneath it. This works fine.
I also want the menu to disappear and the tab to be unhighlighted if the mouse leaves either the tab or the menu. This is where I'm running into trouble. At the moment, the JQuery I use to handle this is roughly as follows:
$('.item-support a').click(function(e){
// removeClass('curr') from all other tabs
$('.item-support').addClass('curr');
$('#submenu-support').fadeIn('fast');
$('.item-support').mouseleave(function(e) {
$('.item-support').removeClass('curr');
$('#submenu-products').fadeOut('fast');
});
}else{ // Click again
$('.item-support').removeClass('curr');
$('#submenu-support').fadeOut('fast');
}
return false;
});
$('#submenu-products').mouseleave(function(e) {
$('.item-support').removeClass('curr');
$('#submenu-products').fadeOut('fast');
});
// Similar code for the other tabs
The problem is that the mouseleave events for the tab and sub-menu are not synchronized. So, for example, if the mouse leaves the support tab and enters the submenu below it, the submenu vanishes. I've tried many different approaches to get around this and even have one that crudely works using pageX and pageY co-ordinates, but I'm looking for a more elegant solution. How do I get the tab and its associated submenu to work in tandem? Is there a way to bind the two divs together? Or make mouseleave recognize an exception when entering a certain div?
You can check if either element is hovered, and do something like this:
$('.item-support, #submenu-support').mouseleave(function() {
setTimeout(function() {
if (!$('.item-support').is(':hover') && !$('#submenu-support').is(':hover')) {
$('.item-support').removeClass('curr');
$('#submenu-support').hide();
}
}, 50);
});
You also shouldn't bind your mouseleave event in the callback of another event. Currently every time you click item-support, you are binding another mouseleave event to it.

Mozilla Extension: Multiple States between multiple tabs

I am creating a mozilla extension that converts the content of a webpage on click of the "convert button"(Label: Convert) in other language
and its label gets converted to English so that on click of that button(Label: English) the content gets converted into original form
I tried to set attribute "changedcontent" with each tab so that on event focus ,focussed tab reads its "changedcontent" attribute and set the label on button ("Convert" or "English")
problem arises where i need to switch between multiple tabs, plugin in the different tab should maintain different state depending on whether it is displaying changed content(should display button label: English)
or it is in its original form(should display button label: "Convert")
so when i click refresh button or click other link in the webpage. The label of the button which is "English" with converted content on the page should gets changed to "Convert"
so for this i have handled page unload event to track page refresh or link click, but since webpage may contain multiple frames/iframes this event is getting called multiple times.
If in the meantime i switch the tab, label of other tab gets converted from "English" to "Convert"
code of the unload event is:
window.addEventListener('unload', unloadingDocument, true);
function unloadingDocument()
{
var currentTab = gBrowser.selectedTab;
currentTab.setAttribute("changedcontent" , "false");//set the transliterated attribute back to false
var convertButton = document.getElementById("convert_button");
convertButton.setAttribute("label","Convert");
}
Please suggest how can i solve this problem and maintain different states of mozilla plugin between multiple tabs.
Thanks
You could use the Session Store API to have independent state between tabs.
-- EDIT:
So if you already have a way to know if a specific tab is "Translated or not", if you want the button to change to have the correct state when another tab is selected, you might want to check for the tabSelect event: Detecting tab selection
In this event you check your tab attribute to check if you have to change or not the label/behaviour of your button.
-- Edit 2 :
If when you click the "Convert" button you do your processing, and you set the attribute changedcontent of that tab to true. Then you have a load/unload listener to check for the refresh, to change the state back to false. Then if you change tabs, you would have the tabSelect event to change the button whenever you change tabs.
If you add this listener when you change changedcontent to true. Then when the event beforeunload is first called, you check if changedcontent is true, you change it to false and remove the listener.

Categories