Reputation: 139
so I'm trying to work with jquery and ajax and ran into a problem.
In short a drop down menu is created once a user is authenticated and logged in.
Ajax rewrites the menu holder with the correct menu options. The problem is that it works when the page is refreshed (CTRL+R), but not when the ajax rewrites the menu.
If I understand correctly this is because ajax writes after the page is loaded (DOM is complete) so because the menu and options weren't there (because the user hadn't successfully logged in) when the page DOM finished loading then the jquery can't find the new elements?
After reading around I saw this is usually because the .on Click is binded to an element and not the docment?
I've tried a hundred combinations now but still unsuccessful so I'm asking for some help to resolve this from any competent Jquery gurus out there :)
Here's the code...(I'm using jquery 1.10)
<script type="text/javascript">
function DropDowna(el) {
this.ddc = el;
this.placeholder = this.ddc.children('span');
this.opts = this.ddc.find('ul.dropdownmk > li');
this.val = '';
this.index = -1;
this.initEvents();
}
DropDowna.prototype = {
initEvents : function() {
var obj = this;
obj.ddc.on('click', function(event){
$(this).toggleClass('active');
return false;
});
obj.opts.on('click',function(){
var opt = $(this);
obj.val = opt.text();
obj.index = opt.index();
obj.placeholder.text(obj.val);
});
},
getValue : function() {
return this.val;
},
getIndex : function() {
return this.index;
}
}
$(function() {
var ddc = new DropDowna( $('#ddc') );
$(document).click(function() {
// all dropdowns
$('.wrapper-dropdown-3').removeClass('active');
});
});
</script>
The HTML
<div id="mmenuoptions">
<ul>
<li><a href="#" class="member">My Page</a></li><li><a href="#" class="member">Wish List (0)</a></li><li><a href="#" class="member">Help</a></li></ul>
</div>
The HTML gets rewritten by Ajax to
<div class="mymenuz">
<ul class="cbp-tm-menu">
<li>
<div id="ddc" class="wrapper-dropdown-3" tabindex="1">
<span>My Menu</span>
<ul class="dropdownmk">
<li><a href="#"><i class="icon-profile"></i>Option 1</a></li>
<li><a href="#"><i class="icon-edit-profile"></i>Option 2</a></li>
<li><a href="#"><i class="icon-store"></i>Option 3</a></li>
<li><a href="#"><i class="icon-purchases"></i>Option 4</a></li>
<li><a href="#"><i class="icon-items"></i>Option 5</a></li>
</ul>
</div>
</li>
<li><a href="#" class="member">Wish List (0)</a></li>
<li><a href="#" class="member">Help</a></li>
</ul>
</div>
And thanks to any and all for their help, input and time. This has been killing me :(
Upvotes: 1
Views: 2833
Reputation: 139
Ok, I solved this myself after some more hours of torture but thought I should share the answer in case other users run into similar problems validating on click controls with Jquery after an Ajax update.
Basically, the code is good (everything being relative and @Archer has a point about trimming the code being parsed by Ajax)...but there are 2 main problems.
Firstly, obj.ddc.on('click', function(event){ cannot fire because ddc is created AFTER DOM has completed. To get round this I bind the on click event to the document hence promising there will be a future div id called "ddc". So solution to problem one is
replace
obj.ddc.on('click', function(event){
with
$(document).on("click", "#ddc", function(e) {
Then problem two...Now the drop down menu is clickable and states active, it cannot retain the selection. Again this is because this.placeholder is defined before the Ajax update and no span tag exists when the DOM is loaded.
To get round this two changes. Again, obj.opts.on('click',function(){ needs to be redefined to work with the ajax injected HTML and the click bound once again at document level to.
$(document).on("click", "li", function() {
And then the placeholder needs to be defined. Created simply by adding obj.placeholder = $('.wrapper-dropdown-3 > span');
So the final Jquery
function DropDowna(el) {
this.ddc = el;
this.placeholder = this.ddc.children('span');
this.opts = this.ddc.find('ul.dropdownmk > li');
this.val = '';
this.index = -1;
this.initEvents();
}
DropDowna.prototype = {
initEvents : function() {
var obj = this;
$(document).on("click", "#ddc", function(e) {
$(this).toggleClass('active');
return false;
});
$(document).on("click", "li", function() {
/*obj.opts.on('click',function(){*/
var opt = $(this);
obj.val = opt.text();
obj.placeholder = $('.wrapper-dropdown-3 > span');
obj.index = opt.index();
obj.placeholder.text(obj.val);
});
},
getValue : function() {
return this.val;
},
getIndex : function() {
return this.index;
}
}
$(document).ready(function() {
var ddc = new DropDowna( $('#ddc') );
$(document).click(function() {
// all dropdowns
$('.wrapper-dropdown-3').removeClass('active');
});
})
Works perfectly and more importantly saved a bunch of time on rewriting code.
Thanks to @Archer for feedback during my problem.
Hope some of this logic and rewrites help anyone suffering from jquery / ajax updates and non-functioning links.
Upvotes: 1
Reputation: 9583
Try:
$(document).on('click',function() {
// all dropdowns
$('.wrapper-dropdown-3').removeClass('active');
});
Upvotes: 0