does DOJO TabContainer have an event thats triggered when changing tabs?
I imagine it would but I couldn't find anything about it in the documentation. :(
SOLVED: It looks like I found a solution here:
Dijit TabContainer Events - onFocus
not the most searchable topic title :/
Connect aspect.after to TabContainer's selectChild method:
var tabContainer1 = registry.byId("tabContainer1");
aspect.after(tabContainer1, "selectChild", function() {
console.log("tab changed");
});
Or if you are interested in a particular tab, connect to its ContentPane's _onShow:
var contentPane1 = registry.byId("contentPane1");
aspect.after(contentPane1, "_onShow", function() {
console.log("[first] tab selected");
});
See it in action at jsFiddle: http://jsfiddle.net/phusick/Mdh4w/
From the docs;
var tabs = registry.byId('someTabs');
tabs.watch("selectedChildWidget", function(name, oval, nval){
console.log("selected child changed from ", oval, " to ", nval);
});
In addition to #phusick's answer, which is correct, all StackContainers, including the TabContainer publish on topics that you can subscribe to.
http://dojotoolkit.org/reference-guide/1.7/dijit/layout/StackContainer.html#published-topics
[widgetId]-addChild,
[widgetId]-removeChild
[widgetId]-selectChild
http://dojotoolkit.org/reference-guide/1.7/dojo/subscribe.html#dojo-subscribe
Here's a complete code sample that works in Dojo 1.8, I've tested it. It's not an event that fires just on changing tabs, I couldn't get any of their events in the API to fire, but at least it works on the Click event.
require(["dijit/registry", "dojo/on", "dojo/ready", "dojo/domReady!"], function (registry, on, ready) {
ready(function () { //wait till dom is parsed into dijits
var panel = registry.byId('mainTab'); //get dijit from its source dom element
on(panel, "Click", function (event) { //for some reason onClick event doesn't work
$('.hidden_field_id').val(panel.selectedChildWidget.id); //on click, save the selected child to a hidden field somewhere. this $ is jquery, just change it to 'dojo.query()'
});
});
});
//include this function if you want to reselect the tab on page load after a postback
require(["dijit/registry", "dojo/ready", "dojo/domReady!"], function (registry, ready) {
ready(function () {
var tabId = $('.hidden_field_id').val();
if (tabId == null || tabId == "")
return;
var panel = registry.byId('mainTab');
var tab = registry.byId(tabId);
panel.selectChild(tab);
});
});
Related
I have created a on change method for a select box of my project. On selecting particular option it is basically showing and hiding a div which is perfectly working fine. Now, my problem is when first time page is loading this show and hide not working for first default section of form. Can I make this onchange function also working when page load first time.
$('.contact-form').on('change', (e) => {
var selectedId = $(e.currentTarget).val();
var listofforms = $("#discount").data("display-for").split(",");
if (listofforms.indexOf(selectedId) !== -1) {
$("#discount").collapse('show');
}
else {
$("#discount").collapse('hide');
}
});
Here you go with a solution
function changeMethod(selectedId) {
var listofforms = $("#discount").data("display-for").split(",");
if (listofforms.indexOf(selectedId) !== -1) {
$("#discount").collapse('show');
}
else {
$("#discount").collapse('hide');
}
}
changeMethod($('.contact-form').val())
$('.contact-form').on('change', (e) => {
changeMethod($(e.currentTarget).val());
});
You need to move your code outside the change event, so I have kept your existing code within a method changeMethod.
Then call the method from to places
From you change event method
OnLoad of the JS file
Is it possible can I make my on change trigger on page load
Yes, you will just need to change your on change event from e.currentTarget to this as on page load e.currentTarget will be null, but this always points to the current element like:
$('.contact-form').on('change', function() {
var selectedId = $(this).val();
// Your other logic here
});
and to trigger this change event on page load, simply add .change() at last like:
$('.contact-form').on('change', function() {
var selectedId = $(this).val();
// Your other logic here
}).change(); //<---- here
I have a notification dropdown menu being fired by adding a CSS class via Javascript. However, I am certain that Turbolinks is causing it to not work properly, as it seems to only work on refresh.
There is a data-turbolinks="true" in the <body> tag of the document. If I change this to false I get normal operation.
If I put the data-turbolinks="false" in the <div> tag of the specific links it still does not work properly.
So I am thinking I will have to change the JaveScript so it is not affected by the Turbolinks. However, I am not sure how to go about this. This is for a Laravel 5.6 app.
/*--------------------------------------------------*/
/* Notification Dropdowns
/*--------------------------------------------------*/
$(".header-notifications").each(function() {
var userMenu = $(this);
var userMenuTrigger = $(this).find('.header-notifications-trigger a');
$(userMenuTrigger).on('click', function(event) {
event.preventDefault();
if ( $(this).closest(".header-notifications").is(".active") ) {
close_user_dropdown();
} else {
close_user_dropdown();
userMenu.addClass('active');
}
});
});
// Closing function
function close_user_dropdown() {
$('.header-notifications').removeClass("active");
}
// Closes notification dropdown on click outside the conatainer
var mouse_is_inside = false;
$( ".header-notifications" ).on( "mouseenter", function() {
mouse_is_inside=true;
});
$( ".header-notifications" ).on( "mouseleave", function() {
mouse_is_inside=false;
});
$("body").mouseup(function(){
if(! mouse_is_inside) close_user_dropdown();
});
// Close with ESC
$(document).keyup(function(e) {
if (e.keyCode == 27) {
close_user_dropdown();
}
});
I think the issue is that the script only selects the elements on the first page load, rather than on every page load. For example, calling $(".header-notifications") will attempt to find all the elements with a class of .header-notifications, however this is only run once, so when a new page is loaded with Turbolinks , the body gets replaced, and those selected elements no longer exist. Scripts are not executed again until a full page load, and so this script is only run once—.header-notifications elements are never reselected.
To fix this, the Turbolinks README recommends using event delegation:
When possible, avoid using the turbolinks:load event to add other event listeners directly to elements on the page body. Instead, consider using event delegation to register event listeners once on document or window.
So you add your event listeners to the document or window, then choose which elements it should run on with a selector, e.g.:
$(document).on(
"click", ".header-notifications-trigger a", function (event) { … }
)
This means that any time a .header-notifications-trigger a element is added to the page, the click event handler will be fired.
With that in mind, you may wish to update your script to something like:
/*--------------------------------------------------*/
/* Notification Dropdowns
/*--------------------------------------------------*/
// For convenience and to prevent unnecessary $() calls
var doc = $(document);
doc.on("click", ".header-notifications-trigger a", function (event) {
event.preventDefault();
var user_menu = $(this).closest(".header-notifications");
if (user_menu.is(".active")) {
close_user_dropdown();
} else {
close_user_dropdown();
user_menu.addClass('active');
}
});
// Closing function
function close_user_dropdown() {
$('.header-notifications').removeClass("active");
}
// Closes notification dropdown on click outside the container
var mouse_is_inside = false;
doc.on("mouseenter", ".header-notifications", function() {
mouse_is_inside = true;
});
doc.on("mouseleave", ".header-notifications", function() {
mouse_is_inside = false;
});
doc.on("mouseup", function(){
if(!mouse_is_inside) close_user_dropdown();
});
// Close with ESC
doc.on("keyup", function(e) {
if (e.keyCode == 27) {
close_user_dropdown();
}
});
I am running into an odd issue with codeschools jquery course where my on click handler is not working. The question we are trying to solve in 5.10 is:
For starters create an event handler using on, that targets the
.see-photos link within each .tour. When this is clicked, run a
function that will add a class of is-showing-photofy to the tour.
You'll probably want to save a reference to this outside of your event
handler, and use that in the click event handler.
My current code attempt is:
$.fn.photofy = function() {
this.each(function() {
var tour = $(this)
tour.on('click.see-photos', 'button', function() {
$(this).addClass('is-showing-photofy');
});
});
}
$(document).ready(function() {
$('.tour').photofy();
});
and the error message I am getting is:
Your `on` `click` handler should watch for clicks on the `.see-photos` element within the current tour
Can anyone point me in the right direction?
I was missing the following:
prevent default
var tour = $(This)
Final Code:
$.fn.photofy = function() {
this.each(function() {
var tour = $(this);
tour.on('click.photofy', '.see-photos', function(event) {
event.preventDefault();
tour.addClass('is-showing-photofy');
});
});
}
$(document).ready(function() {
$('.tour').photofy();
});
I have some 'static' HTML on my page:
<div id="DIVISIONS">
<ul class="nav nav-tabs" id="DIVISIONTABS">
#* <li> nodes will be injected here by javascript *#
</ul>
<div class="tab-content" id="DIVISIONTABPANES">
#* <div class="tab-pane"> nodes will be injected here by javascript *#
</div>
</div>
On page load, I create a tab 'framework', i.e. create the bootstrap tabs and tab content containers.
I trigger the process with:
$(window).bind("load", prepareDivisionTabs);
And "prepareDivisionTabs" does this:
function prepareDivisionTabs() {
// Retrieve basic data for creating tabs
$.ajax({
url: "#Url.Action("GetDivisionDataJson", "League")",
cache: false
}).done(function (data) {
var $tabs = $('#DIVISIONTABS').empty();
var $panes = $('#DIVISIONTABPANES').empty();
for (var i = 0; i < data.length; i++) {
var d = data[i];
$tabs.append("<li>" + NMWhtmlEncode(d.Name) + "</li>");
$panes.append("<div id=\"TABPANE" + d.DivisionId + "\" class=\"tab-pane\"></div>")
}
renderDivisionTabPaneContents(data);
}).fail(function (err) {
alert("AJAX error in request: " + JSON.stringify(err, null, 2));
});
}
For info, the "renderDivisionTabPaneContents" in the above does this:
function renderDivisionTabPaneContents(data) {
for (var i = 0; i < data.length; i++) {
var d = data[i];
renderDivisionTabPaneContent(d.DivisionId);
}
}
function renderDivisionTabPaneContent(id) {
var $tabPane = $('#TABPANE' + id);
$tabPane.addClass("loader")
$.ajax({
url: "/League/GetDivisionPartialView?divisionId=" + id,
cache: false
}).done(function (html) {
$tabPane.html(html);
}).fail(function (err) {
alert("AJAX error in request: " + JSON.stringify(err, null, 2));
}).always(function () {
$tabPane.removeClass("loader")
});
}
All good so far. My page loads, my tab contents are rendered, and when I click the different tabs, the relevant content is shown.
Now, rather than loading all content at the start, I want to load tab content just-in-time by using the 'shown' event of the tabs. To test this, I've wanted to just make sure I could get a javascript alert when the tab was shown. So, I create the following to trigger the attachment of tab shown events:
$(function () {
attachTabShownEvents();
})
which calls:
function attachTabShownEvents() {
$(document).on('shown', 'a[data-toggle="tab"]', function (e) {
alert('TAB CHANGED');
})
}
I'd therefore expect so see the "TAB CHANGED" alert after the change of tab. But ... I see no alerts.
Could anybody help me out here?
The correct event binding for tab change is shown.bs.tab.
$(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
alert('TAB CHANGED');
})
Update 11-01-2020 --- Bootstrap 4.5
This is still the correct answer however, this is a bit of additional helpful information found all the way at the bottom of the official bootstrap docs page at: https://getbootstrap.com/docs/4.5/components/navs/#tabs
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
e.target // newly activated tab
e.relatedTarget // previous active tab
})
You can determine which tab has been selected each time the code fires with e.target.
If you have unique IDs on your elements then you could do something like the following so code only runs when the appropriate tab is clicked.
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
switch (e.target.id){
case "mainTab":{
doMainTabStuff();
break;
}
case "configTab":{
doConfigTabStuff();
break;
}
}
})
<a data-toggle="tab" href="#some_special_tab_anchor">
<div id="some_special_tab_anchor" class="tab-pane fade">
special tab content
</div>
$( 'a[data-toggle="tab"]' ).on( 'shown.bs.tab', function( evt ) {
var anchor = $( evt.target ).attr( 'href' );
alert("TAB SHOWN = "+anchor);
// take action based on what tab was shown
if(anchor === "some_special_tab_anchor"){
// do my special thing :)
}
});
Use my Nuget package for lazyloading bootstrap tabs here, its very simple,
just add "lazyload" class to the "ul" element of bootstrap tabs, then add "data-url" equal to url to load to the any tabs anchor element (a). thats it.
https://www.nuget.org/packages/MT.BootstrapTabsLazyLoader.js/
'show' and 'shown' events didn't work for me. My solution is not exactly specifically OP's situation, but the general concepts are there.
I had the same issue with bootstrap forcing its own onclick events
on tabs (menu buttons and content panels). I wanted to lazy load stuff into a panel depending on what menu button was clicked, and some buttons show a panel on the current page, others were to load a page into an iframe.
At first, I stuffed data into a hidden form field tag, which was the same issue. The trick is to detect some sort of change and act on that. I solved the problem by forcing a change and using an alternate event listening on the buttons without having to touch bootstrap.
1) stash iframe target in button as data attribute:
$('#btn_for_iframe').attr('data-url',iframeurl);
2) bind alternate event onto fire off thingy,
and inside, swap out the iframe source
$('#btn_for_iframe').on('mouseup',function(){
console.log(this+' was activated');
$('#iframe').attr('src',$('#btn_for_iframe').attr('data-url'));
});
3) force 'change' event on panel shows, then load iframe src
$('#iframe_panel_wrapper').show().trigger('change');
or you can put the change trigger in the mouseup above.
$(document).ready(function(){
$(".nav-tabs a").click(function(){
$(this).tab('show');
});
$('.nav-tabs a').on('shown.bs.tab', function(event){
alert('tab shown');
});
});
I can't manage to find out how to initiate a click event by a user clicking on a dropdown. I want to populate the dropdown ONLY if the user clicks the dropdown which will be rare. In addition, it depends on several other values selected on the page. So basically, how do I fire off an event if a user just simply clicks on the dropdown to see the options.
I've tried, $('select').click but to no avail.
It works if you don't have any options. But if there are current options, no luck.
Try using the focus event instead, that way the select will be populated even when targeted using the keyboard.
$('select').on('focus', function() {
var $this = $(this);
if ($this.children().length == 1) {
$this.append('<option value="1">1</option><option value="2">2</option>');
}
});
View simple demo.
UPDATE
Here is a new version that uses unbind to only fire the event handler once. This way you are able to use your alert without adding any option elements to change the outcome of the condition as the previous solution required.
$('select').on('focus', function() {
var $this = $(this);
// run your alert here if it´s necessary
alert('Focused for the first time :)');
// add the new option elements
$this.append('<option value="1">1</option><option value="2">2</option>');
// unbind the event to prevent it from being triggered again
$this.unbind('focus');
});
Hope that is what you are looking for.
It should work. Here I've done it and its working.
$("select").on("click", function() {
$(this).append("<option>1</option><option>2</option>");
});
Updated: http://jsfiddle.net/paska/bGTug/2/
New code:
var loaded = false;
$("select").on("click", function() {
if (loaded)
return;
$(this).append("<option>1</option><option>2</option>");
loaded = true;
});
Getting the dropdown to automatically open after the click is trickier:
// Mousedown is used so IE works
$('#select_id').on('focus mousedown', function (e) {
var data;
$(this).off('focus mousedown');
$.ajax({async: false,
type: 'GET',
url: 'url that returns the options',
success: function (d) { data = d; }
});
$(this).find('option').remove().end().append(data);
// Prevent IE hang by waiting awhile
var t = new Date().getTime(); while(new Date().getTime() < t + 200) {}
return true;
});