Jasny Bootstrap offcanvas menu - ajax 'close' causing dismiss issue - javascript

Question Background:
JSFiddle - https://jsfiddle.net/k9K5d/200/embedded/result/
I am using Jasny Bootsrap to develop an 'off-canvas' slide out menu.
The Issue:
The menu slides out fine and also closes fine when the toggle button is pressed. The problem comes when closing the menu with an ajax call through code.
Within the menu I have a button (labeled 'Click') that makes an ajax call to append some data to a div. Within the Success method of the ajax call I am calling a Jasny 'hide' method that should dismiss the menu.
The menu does dismiss BUT often the 'body' of the view is closing before the menu slides, as shown by the red arrow:
The Code:
The Following shows my code for calling the data to be appened to a div, and then to close the off canvas menu:
$('#navBtn').click(function() {
var jsonData = {
"values" : ["Test1", "Test2"]
}
$.ajax({
type: 'POST',
dataType: 'json',
url: '/echo/json/',
data : { json: JSON.stringify( jsonData ) },
success: function(data)
{
var arraySize = data.values.length;
$('#arrayHolder').html(arraySize);
closeMenu();
}
});
});
function closeMenu()
{
$('.navmenu').offcanvas('hide');
}
I have provided a JSFiddle to display this: https://jsfiddle.net/k9K5d/200/
This issue appears on the second click of the ajax call 'Click' button.
Any help working out why the ajax call to the closeing code is causing this style would be great.

try to use .promise().done()
$('#arrayHolder').html(arraySize).promise().done(function(){
closeMenu();
});

Make your function like this. Work fine.
function closeMenu()
{
$('.navbar-toggle').click()
}

Related

When I click to open "sidr side menu" I´m also clicking on my sidr menu item

I followed the sidr documentation at: http://www.berriart.com/sidr/
And I already have my sidr side left menu working fine.
But on my mobile,only on android default browser, when I click in my link "Open Menu" I also click on my menu item "Menu 1", and so it opens my submenu items with my toggle effect. And I dont want this.
I just want to open my submenu items when I click in my Menu items, and not in my link to open the menu.
I found a solution, that is, if I put my sidr menu with some margin top, to not align with my link to open the menu, the problem is solved, like in my second image.
But I dont want to give that margin-top, so Im trying look for other solution.
Somebody there have exprience with this plugin and can give me a help??
(This only happens in mobile and on android browser that cames when you buy the smartphone, but I want to use this on mobile, and many users must use internet explorer which I think is the default browser for android.)
Like this image below, I have the problem, because the "Open Menu is aligned with "Menu 1" and so Im clicking on both!
Like this image below, I dont have the problem, because the "Open Menu is not aligned with "Menu 1" and so I only click on "Open Menu"!
This is my jQuery to start sidr plugin:
$(document).ready(function() {
$('#simple-menu').sidr({
name: 'sidr',
speed: 200,
side: 'left',
source: null,
renaming: true,
body: 'body'
});
});
$(document).ready(function() {
$('.sub-menu-sidr').hide();
$("#sidr li:has(ul)").click(function(){
$("ul",this).toggle('fast');
});
});
And here is my fiddle:
http://jsfiddle.net/y4CX4/1/
Easiest way to do that, IMHO is to prevent the first click on that link from happening, that is:
Define a variable to check if link was clicked, at click event check the value and prevent the event from propagating and then set the variable to something else, in order to allow all future clicks to happen naturally, for example:
var click = false;
$('#sidr > ul > li').first().find('a').first().click( function(e) { if ( click == false ) {
e.stopPropagation();
click = true;
} });
The next step would be to add a function that resets this variable when the menu gets closed by adding:
onClose : function() {
click = false;
}
An working example can be found here: http://jsfiddle.net/y4CX4/3/
Also make sure you use the same function in order to use the variable click properly ( in the fiddle you posted you used $(document).ready() two times for some reason ).
My solution to that problem is based on the top answer which helped me find the right way.
So I find all the links and prevent their default behavior until the menu is opened and then disable them again when the menu is closed.
var menuButton = $('.js-side-menu-toggle');
var sideMenuLinks = $('#sidr').find('a');
var canClick = false;
sideMenuLinks.on('click', function(e) {
if (!canClick) {
e.preventDefault();
}
});
menuButton.sidr({
onOpen: function() {
canClick = true;
},
onClose: function() {
canClick = false;
}
});
The tricky part here is that we need to change the plugin itself so that this code can work.
The problem is that the functions onOpen() and onClose() are called after the animation is done but not in it's callback function. That makes the functions to be called with the animation which is async and here is our issue.
Wrong:
// Close menu
if($body.is('body')){
scrollTop = $html.scrollTop();
$html.removeAttr('style').scrollTop(scrollTop);
}
$body.addClass('sidr-animating').animate(bodyAnimation, speed).removeClass(bodyClass);
$menu.animate(menuAnimation, speed, function() {
$menu.removeAttr('style').hide();
$body.removeAttr('style');
$('html').removeAttr('style');
sidrMoving = false;
sidrOpened = false;
// Callback
if(typeof callback === 'function') {
callback(name);
}
$body.removeClass('sidr-animating');
});
// onClose callback
onClose();
We just need to insert the onClose function inside the animation callback function in order to lock the links when the menu is closed and we should do the same with the on open code fragment.
Right:
// Close menu
if($body.is('body')){
scrollTop = $html.scrollTop();
$html.removeAttr('style').scrollTop(scrollTop);
}
$body.addClass('sidr-animating').animate(bodyAnimation, speed).removeClass(bodyClass);
$menu.animate(menuAnimation, speed, function() {
$menu.removeAttr('style').hide();
$body.removeAttr('style');
$('html').removeAttr('style');
sidrMoving = false;
sidrOpened = false;
// Callback
if(typeof callback === 'function') {
callback(name);
}
$body.removeClass('sidr-animating');
// onClose callback
onClose();
});

How to use Select2 inside a bootstrap popover

I wonder how I get my Select2 dropdown working inside of a Bootstrap popover. I know the issue is that the popover content is loaded after the popover-event-click is initiated, so that the JS-code for the Select2 wont work. I just don't know how to fix it.
Example:
http://hammr.co/8234009/6/problems.html
Try pressing "submit" on the fourth problem named "Aaaah!" and you'll get the popover visible. Then try pressing the "Alabama"-dropdown (which is the Select2 dropdown) and it wont work (since the JS isn't initiated because the popover content is loaded after the DOM).
Anyone knows how to make it work?
yes possible
thanks to
bootstrap popover callback modification
/* override bootstrap popover to include callback */
var showPopover = $.fn.popover.Constructor.prototype.show;
$.fn.popover.Constructor.prototype.show = function() {
showPopover.call(this);
if (this.options.showCallback) {
this.options.showCallback.call(this);
}
}
$(this).popover({
container:'#maincont',
placement:'right',
html : true,
title: function() {
return $('#'+pk).html();
},
content: function() {
return $('#'+pk).clone();
},
showCallback : function() {
$(".popover-content select").select2({
containerCss : {"display":"block"},
allowClear: true,
});
},
});

How can I write a function that relies on dynamic selectors?

I am writing a function to dynamically load jQuery UI accordian leaves with content. I know (think) the AJAX part works as I lifted it from another working AJAX loader I have, but the function as a whole does not work.
The code:
function load_leaf(link){
var link = link;
$.ajax({
cache : false,
type : 'POST',
async: false,
url : 'includes/'+ link +'.php?'+ new Date().getTime(),
dataType : 'text',
data: {
owner : '$user_id'
},
success: function(msg){
$("#" + link).html(msg);
console.log('Can\'t see me in Chrome, but ok in firefox !')
},
error: function() {
console.log($.makeArray(arguments));
},
complete: function() {
console.log($.makeArray(arguments));
}
});
};
$(function(){
$('.accordian').click(function(){
var link = this.getAttribute("link");
load_leaf(link);
});
});
For whatever reason this does not work. The break point seems to be this line
$("#" + link).html(msg);
Specifically the selector, as a hard coded selector works perfectly. The link variable is correctly filled i know this as i can alert the value correctly. The link is not the problem as i replaced the whole ajax function with a simple add class and it a still did not work, it also broke at the selector.
EDIT:
This is the div as printed by php:
<h3 class="accordian" id="'.$tab_id.'" link="'.$tab_link.'" >
'.$tab_name.'
</h3>
<div id="'.$tab_link.'"><p>Hi</p></div>
The html for the first one is:
<h3 class="accordian" id="accordian_manage.php" link="accordian_manage.php" >Manage Images</h3><div id="accordian_manage.php"><p>Hi</p></div>
Your ID has a period . in it, which jQuery interprets as a chained class selector.
You can either change your link/IDs, or use this hack:
$("[id='" + link + "']");
Live demo
I guess your problem is with Jquery is not finding the div to load the msg..Post the accordion div so that i could give you the proper selector

loading content into a div with jquery

Hey All - I am having a bit of trouble with a jquery function. I have a nav bar and I want when a user clicks on the nav bar to have the page load into a div (#content)
The code I have works for the first click, but when I try to click on another item it shows the loading image, but does not put the new content in the div (it leaves the old content). Any thoughts?
$(document).ready(function() {
$('.cat').live("click",function() {
var section = $(this).attr("id");
$.ajax({
type: "POST",
url: "../soccer/nav/" + section + ".php",
beforeSend: function() {
$('div#content').hide();
$('div#loading').show();
},
success: function(html){
$('div#loading').hide();
$("div#content").replacewith(html);
}
});
return false;
});
});
Any help would be greatly appreciated!
The problem is the .replacewith() method. You are actually replacing the #content div with the new content. Just use .html() instead.
You don't need $("div#content"). You can just do $("#content")
$("#content") means find the node with the id "content".
Try with:
$.post("../soccer/nav/" + section + ".php", null, function(data)
{
$('#loading').hide();
$("#content").html(data);
});
Try to use jQuery.Load event to make use of ajax and html populating at the same time.

load ajax content before showing tooltip

I wanted to create a drop down at a
certain position based on a users
click and
I wanted this to come in the form of a drop down also
the content in the drop down would be dynamically genereated through
ajax..
im using jquery-tools tooltip to do this but am facing some problem...
the ajax content is loading only after the second click ..
THIS IS THE CODE TO CREATE AN ARRAY of TOOLTIP OBJECTS
$(document).ready(function(){
var show = false;
var tips = new Array();
$(".replie").each(function(){
$(this).tooltip({ effect: 'fade', events: {widget:'click,'},position:"bottom right",onBeforeShow:function() {
this.getTrigger().fadeTo("slow", 0.8);
}})
tips.push($(this).tooltip(0));
});
AND THIS IS THE CODE TO CONTROL THE TOOLTIPS BEHAVIOR AND LOAD AJAX CONTENT
$(".replie").click(function(evt){
if(!evt){
evt=window.event;
}
var row =evt.target.parentNode.id[2];
var aid=evt.target.id;
var uid= <?php echo $uid ?>;
var tip;
$("#tip"+row).load("reply.php?uid="+uid+"&aid="+aid,function(){
$(this).hide()
});
if(tips[row].isShown)
{
tips[row].hide();
}
else
{
tips[row].show();
}
});
HOW DO I LOAD THE CONTENT AND THEN SHOW THE TOOLTIP .. ?
Use jQuery.ajax() function instead of jQuery.load() function. You can set a callback function on complete or success event. Inside that handler, trigger the tooltip function.
This is the documentation of jQuery.ajax(): http://api.jquery.com/jQuery.ajax/

Categories