use intro.js on bootstrap dropdown element - javascript

I cannot figure out how to use intro.js on dropdown elements.
I found a similar question with no answer there: IntroJS Bootstrap Menu doesnt work
If you want to reproduce the error, follow these steps:
http://recherche.utilitaire.melard.fr/#/carto
You have to click on "Aide" (The green button on the top right), the problem occurs for the second step. on the change event, I do:
$scope.ChangeEvent = function (e) {
if (e.id === 'step2') {
document.getElementById('step1').click();
}
console.log("Change Event called");
};
When debugging, everything is working like a charm until that function end: _showElement
After that, I get lost in JQuery events, and the dropdown is closed...
If you want to reproduce, just add a breakpoint at the end of the _showElement function and you will understand what I mean...

Here a clearer solution
function startIntro(){
var intro = introJs();
intro.setOptions({
steps: [
{
element: "#mydropdown",
intro: "This is a dropdown"
},
{
element: '#mydropdownoption',
intro: "This is an option within a dropdown.",
position: 'bottom'
},
]
});
intro.onbeforechange(function(element) {
if (this._currentStep === 1) {
setTimeout(function() {
$("#mydropdown").addClass("open");
});
}
});
intro.start();
};
$(document).ready(function() {
setTimeout(startIntro,1500);
});
Note the setTimeout with no second argument (milliseconds) allows you to queue the function on event loop and run it after all events were processed (including the click closing the dropdown), also, it is better to add the class open to the dropdown if you want to set it to open state

In your template i.e. in
/views/nav/body-create.html
You have a code where ng-disabled is based on !currentPath.name. And the value of currentPath.name is null. Try inspecting the value on the following element. You will see that it is null.
<button class="dropdown-toggle btn btn-sm btn-default no-radius" ng-disabled="!currentPath.name">
Niveau{{currentPath.level?": "+currentPath.level:""}} <strong><b class="caret"></b>
</strong>
</button>
Make sure you have proper name or use different condition - I am not sure what you are trying to do with the condition.
Proof: Inspect the above element in chrome debugger at your recherche.utilitaire.melard.fr/#/carto link. Type the following in console and hit enter.
$scope.currentPath.name='Hello You';
And your "Niveau" menu starts working.

I found a workaround, it's quite ugly, but does the job:
$scope.ChangeEvent = function (e) {
if (e.id === 'step2') {
document.getElementById('step1').click();
setTimeout(function () {
document.getElementById('step2').style.display = 'block';
}, 500);
}
console.log("Change Event called");
};
I set the display attribute to block just after the click event I added in the change event
When clicking executing the click on the element 1, I noticed that jquery set the state of the style.display of the element 2 to '', so I wait a bit after clicking in order to set it back to 'block', I know it's ugly, but I didn't find anything better at the time

This happens because of the fixed position..
By using CSS, change the position for the parent item from fixed to absolute and it works perfectly.
For example:
position of .sidebar is fixed, leave it like that.
change position for .sidebar.introjs-fixParent to absolute.
Hope it helps you

Related

Jquery Content Slider: Add an error class to a navigation menu that corresponds to empty section

I have a form that is broken up into a Jquery Content slider (i.e. vertical tabs).
This breaks the form into manageable chunks for the user to fill in.
At the moment, if the user forgets to fill in a field, an error class is applied to that section of the form. However, if that section is not visible, the user won't see the error styling.
I want to add the error class to the corresponding part of the vertical tab navigation menu. How can I do this?
The Jquery code that is used to flip between the sections is as follows:
$(".taptabs li").live('click', function() {
$(this).parent().parent().parent().$('.pages .page').hide().eq($(this).index()).show().addClass("animated").addClass(mode).addClass("fadeInLeft");
});
(Taptabs is the name of the navigation list. Each section of the form has a class of page Each section is also in the HTML element of <section> ).
I thought this would work to make the error message appear on the navigation:
$(".changing-room").submit(function () {
var isFormValid = true;
$("input.required").each( function () {
if ( $.trim( $(this).val() ).length === 0 ) {
$(this).parent().addClass("error");
var menulink = $(this).closest('section').index();
$('.tapnav li').index(menulink).addClass('error');
isFormValid = false;
}
});
});
In this code, when an Input is left empty, the closest Section tag is located (This section tag holds that particular section of the form). The index of that section tag is calculated and then it is applied to the corresponding LI of the Nav menu. However, it doesn't seem to work, it actually breaks all the code!
Here is a JS Fiddle
Two possibilities I guess. One is you don't let them go to the next tab until they finished their work on the current tab. That's option #1 below. Option #2 as you state is to style the tab somehow so they can see they need to return to it. See #2 below.
#1:
In your click event (use .on() not .live()) wrap the containing code in this:
if(!$('.error').length){
//All the code you have in your event now should be here - that is, there are no errors they can proceed.
} else {
//else is optional. Here you could do whatever you want to tell the user - "no, you can't move on because you have a validation issue. Here is a suggestion:
alert('You have errors! ' + someerrorvar);
}
#2
Again, as above use a .on() event instead of .live() because .live() is no more.
I'm going to make an assumption that there's a class that indicates a certain tab is the active tab. We'll call that class 'tater' for lack of a true class name. If so, just use that thusly:
//At the beginning of your event, before you pull the switch
$('.tater').addClass('incomplete');
Then use incomplete to style that tab as desired.
Final Thoughts:
I would go with #1. It's clear to the user that, hey, something's not right here and we need to fix it. Be sure and put the validation text clearly in the user's face.
I figured this out:
$(".MY-WRAPPER-CLASS").submit(function () {
var isFormValid = true;
$("input.required").each(function () {
if ($.trim($(this).val()).length === 0) {
$(this).parent().addClass("error");
var menulink = $(this).closest('section').index(); //Note 1
$('.tapnav li').eq(menulink).addClass('error'); //Note 2
isFormValid = false;
}
else {
$(this).parent().removeClass("error");
}
});
});
Note 1: We use .closest() to find the parent <section> tag of the empty form element.
We then use .index() to find the index value of the section.
It is then assigned to a variable called menu link.
Note 2: We then use .eq() to target the menu link that has the same index value as the section.

toggling between two classes jQuery = works but extra click

Sort
$(".sort").click(function (event) {
$(this).toggle(function() {
$(this).toggleClass("sortUp","sortDown");
}, function() {
$(this).toggleClass("sortDown","sortUp");
});
});
it works but I need to click once before it works.
so -
click (nothing happens), click (sortUP), click (sortDown)
I would like to remove first click.
Thank you community for the help !
Firstly, you're using toggleClass incorrectly. You appear to want to toggle sortDown and sortUp on each click. That's done with toggleClass("sortDown sortUp").
Secondly, you need your class .sort to either have sortUp or sortDown set in its class property when you load the page. e.g. <a href="#" class="sort sortDown">. This makes sure you can reason about your code (i.e. it's always true that exactly one of sortUp, sortDown are set on your div).
Thirdly, $(this).click(function() { /* code */ }) means "when somebody clicks, do /*code*/". You've wrapped your
$(this).click(function() { $(this).toggleClass("sortUp sortDown"); })
which sets up the click behaviour, in a $(".sort").click(function () { which means you are requiring an initial click on "sort" just to start the behaviour.
So the correct version is:
Sort
$(document).ready(function () {
$(".sort").click(function() {
$(this).toggleClass("sortUp sortDown");
});
});
if you dont' want to begin with a sortUp or sortDown class, do this:
Sort
$(".sort").click(function (event) {
if($(this).hasClass("sortUp") || $(this).hasClass("sortDown")){
$(this).toggleClass("sortUp sortDown");
}else{
$(this).addClass("sortUp");
}
});
It looks like you are adding the click events on the first click, also if you want to switch between sortUp and sortDown you can simply specify them both. As long as the element starts with one or the other (not both and not neither), it will swap them each time.
$(".sort").click(function() {
$(this).toggleClass('sortUp sortDown');
});
You can see this running on JSFiddle.

checkbox running script onclick before actually setting the checked flag

I have a combobox with checkboxes. I am using jQuery to add a Click event to all of the checkboxes. When the checkbox is checked, a script is supposed to run and check an attribute of the checked box to determine it's type and then perform functions accordingly:
function () {
$('.RcbTag').find('input[type="checkbox"]').click(function () {
var evtCB = $(this);
var id = $(this).closest(".rcbSlide").siblings(".RcbTag").attr("id");
var rcbObject = $find(id);
rcbObject.get_items().forEach(
function (item, index) {
if (item.get_attributes().getAttribute('GUIDType') == 'group' &&
item.get_checked()) {
alert("Checked");
}
});
});
The problem right now is that it appears that the script is running before the checkbox is actually flipped to "checked". So in this example, it looks to see if the item attribute is 'group' and if it's checked. This always returns false, but will return true when I uncheck it. So I'm missing some order of events here. How do I fix this?
I think you're mixing jQuery click handlers and the Telerik code. Let's try and just stick with the Telerik-sanctioned events and I think everything will work like you're expecting.
On your RadComboBox, add an event handler declaritively like this:
OnClientItemChecked = "ComboBoxRowClick"
Then declare the JS function as you have it now (except we want to name it and not keep it anonymous):
function ComboBoxRowClick(sender, args) {
if (args.get_item().get_attributes().getAttribute('GUIDType') == 'group' &&
args.get_item().get_checked()) {
alert("Checked");
}
}
For more info on the client side functions from Telerik, you can check this link: http://www.telerik.com/help/aspnet-ajax/listboxitem-client-api.html
Also, you might run into this small annoyance where you have to click in the little checkbox itself, and not anywhere on the row (as one might expect). You can find a workaround for that one here: http://www.msigman.com/2010/07/telerik-radlistbox-fix/
try using change instead of click? that way you will catch changes made via keybord as well. and it will solve ypur problem.

check for ('div')mouseenter on ('a')mouseleave

my problem is following:
I got a trigger(a) and a popup(div). The div doesn't lie nested inside the anchor.
When I hover over a, I want the div to show up.
When I go from a to the div, I want it to stay visible.
When I leave the div, I want it to close.
When I hover over a and leave without entering the div, I want the div to close.
I got most of that figured out, but now I'm struggeling with requierement no. 2.
When checking for mouseleave on a, I check if there is a mouseenter on the div. If it is, I want to abort the mouseleave. If not, I want to close the div.
What am I doing wrong? Is this even the right way to do this?
Here's the markup:
<a href="#" class="popup_toggle" style='display:block;width:50px;height:50px;border:1px solid red;position:relative;'>Toggle</a>
<div class="popup_div" style='position:absolute;top:50px;left:0px;border:1px solid blue;display:none;'>Popup</div>
Here's the jQuery:
$('.popup_toggle').mouseenter(function() {
var element = $(this).next('.popup_div');
$.data(this, 'timer', setTimeout(function() {
element.show(100);
}, 500));
});
$('.popup_toggle').mouseleave(function() {
clearTimeout($.data(this, 'timer'));
if($('.popup_div').mouseenter==true)
{
return false;
}
else
{
$('.popup_div').hide(100)
};
});
What you're trying to do is fairly simple. When entering the trigger, identify the panel (layer, popup, whatever), save reference to each other using .data() and have the event handlers check if the related targets are either the trigger (from the panel view) or the panel (from the trigger view). I threw something together. Have a look at the console log to see how this works… http://jsfiddle.net/rodneyrehm/X5uRD/
That will most likely not work...no. I would suggest that you add a mouseenter and mouseleave callback to you <div> element as well and have them set a global variable that tells your other callbacks how to handle their events, i.e. "if global variable is true, don't hide the popup on mouseleave, otherwise hide popup" or something like this.
The other approach would be to check whether the mouse is inside the popup when the mouseleave callback tries to hide the popup. That might be much more work than it is worth though.
I believe the problem with your implementation is that the mouseenter on the div will fire shortly after the mouseleave from the a.
This would give you something like:
$('.popup_toggle').mouseenter(function() {
// Clear any pending "hide" timer
// Set a show timer
});
$('.popup_toggle').mouseleave(function() {
// Clear any pending "show" timer
// Set a hide timer
});
$('.popup_div').mouseenter(function() {
// Clear any pending "hide" timer
});
Note that you'll have to make sure that you access the same timer from both the .popup_toggle event and the .popup_div event. You may want to consider using Ben Alman's doTimeout plugin to help with this. It (usually) results in much clearer code than manually working with setTimeout/clearTimeout.

jQuery Checkbox/Target _Blank

I have the following jQuery on my website:
$(function() {
$('#newtab').toggle(function() {
$('a').attr('target', '_blank');
},
function() {
$('a').removeAttr('target');
});
});
The code is for a checkbox that toggles the target of links on my page (when checked, links open in a new tab (target="_blank"), otherwise, they open in the same page.
I have two issues:
I want to make it so only links in a particular div are affected by the toggle (I essentially just don't want links in my menu to be affected by it).
When clicking the checkbox, the check is never shown for some reason. I have <input type="checkbox" id="newtab" /><label for="newtab">Open links in new tab</label>
on my page which shows the checkbox (unselected). When I click on it, it changes the target attribute, but the checkbox never appears to be selected; it still shows the empty box. Clicking the checkbox again removes the target attribute as expected.
Thanks.
This should solve your problem: http://jsfiddle.net/UJMgQ/2/
$(function () {
$('#newtab').click(function () {
if ($(this).is(':checked')) {
$('#wanted a').attr('target', '_blank');
} else {
$('#wanted a').removeAttr('target');
}
});
});
To limit the a's that are selected just change #wanted to what ever div(container) the a's you want are in. It works like a css selector.
For part 1: $('.divYouWant a').attr(...) will limit it, just like a CSS selector would.
For part 2: According to the docs of toggle() "The implementation also calls .preventDefault() on the event, so links will not be followed and buttons will not be clicked if .toggle() has been called on the element.". If you don't want that, either use .click(), or just set $('#newtab').checked equal to one in the selected function, and 0 for the unselected function.
Try: $('#mydiv').find('a').attr('target', '_blank');
I think toggle wants you to return true to make the click event propagate to the checkbox. Not sure, but checking the docs may be in order here...
Nevermind, docs say that toggle prevents propagation. Perhaps use something like $.change() instead, and use the value of the checked property to set the values you want.

Categories

Resources