JQuery Live() not working - asp.net

I have made an custom collapsible fieldset control in asp.net. I use jquery to add the toggle effects. The control works perfectly but when i am using my fieldsets inside an updatepanel, afer a postback i loose my jquery logic because of the document.ready.
Now i have read about the new Live() function of Jquery but i don't get it working. What do i do wrong? Has someone the answer??
Thanks a lot
My Jquery code is:
$(document).ready(function() {
$.fn.collapse = function(options) {
var defaults = { closed: false }
settings = $.extend({}, defaults, options);
return this.each(function() {
var obj = $(this);
obj.find("legend").addClass('SmartFieldSetCollapsible').live("click", function() {
if (obj.hasClass('collapsed')) {
obj.removeClass('collapsed').addClass('SmartFieldSetCollapsible'); }
$(this).removeClass('collapsed');
obj.children().next().toggle("slow", function() {
if ($(this).is(":visible")) {
obj.find("legend").addClass('SmartFieldSetCollapsible');
obj.removeAttr("style");
obj.css({ padding: '10px' });
obj.find(".imgCollapse").css({ display: 'none' });
obj.find(".imgExpand").css({ display: 'inline' });
}
else {
obj.css({ borderLeftColor: 'transparent', borderRightColor: 'transparent', borderBottomColor: 'transparent', borderWidth: '1px 0px 0px 0px', paddingBottom: '0px' });
obj.find(".imgExpand").css({ display: 'none' });
obj.find(".imgCollapse").css({ display: 'inline' });
}
});
});
if (settings.closed) {
obj.addClass('collapsed').find("legend").addClass('collapsed');
obj.children().filter("p,img,table,ul,div,span,h1,h2,h3,h4,h5").css('display', 'none');
}
});
};
});
$(document).ready(function() {
$("fieldset.SmartFieldSetCollapsible").collapse();
});

The problem is that you are doing more then just a plain selector for your live selection
From api.jquery.com
"DOM traversal methods are not fully supported for finding elements to send to .live(). Rather, the .live() method should always be called directly after a selecton"

if (obj.hasClass('collapsed')) {
obj.removeClass('collapsed').addClass('SmartFieldSetCollapsible'); }
$(this).removeClass('collapsed');
First you want to remove the class an add another class if it has the class collapsed, an then you remove the class collapsed. I don't know if it affects the working of the system but it is worth to try.
Does the function work if you just use .click (when the field aren't updated)?

Traversing is the issue. You can solve it with a simple selection.
var obj = $(this),
obj.find("legend").addClass('SmartFieldSetCollapsible');
$('legend.SmartFieldSetCollapsible').live('click.collapsible', function(e){

Related

Submitting form using Casperjs Error

I'm trying to scrape products with color and size variations.
Every variation is a form and to get the next variation I'm clicking on radio button and it is doing a form submit action on each click.
I have tried to click it using
1. “casper.getElementsInfo(element)[0].click();”
2. “document.querySelectorAll(element)[2].click();”
3. “casper.thenClick('element');”
4. “casper.evaluate(function(){document.querySelectorAll(element)[2].click();});”
After every click I'm doing a casper wait for 8 seconds !
So here is my problem Casperjs is getting error after clicking the next color/size
var casper = require('casper').create({
viewportSize: {
width: 1920,
height: 1080
},
pageSettings: {
loadImages: false,
loadPlugins: false
}
});
casper.then(function () {
self.thenOpen("https://scubapro.johnsonoutdoors.com/fins/fins/seawing-nova-fin-full-foot", function () {
casper.then(function () {
var varitoinCount = document.querySelectorAll('div#edit-attributes-field-swatch-taxonomy > div input').length;
var i = 0;
casper.repeat(varitoinCount + 1, function () {
try {
document.querySelectorAll('div#edit-attributes-field-swatch-taxonomy > div input')[i].click();
casper.log('we got to anhoter variatoin ...' + i);
} catch (error) {
console.log(error);
}
i++;
});
});
});
});
try {
casper.run();
} catch (e) {
consol.log("Error..... " + e);
}
(TypeError: undefined is not a constructor )
And btw when I'm doing the same thing in a console it works fine
You have to understand that accessing DOM is not possible in Casper environment. You should switch to browser environment to execute your DOM selectors by using Casper's evaluate method. Basically it used to get some information from within browser or to manually do some actions with javascript. To understand it you have a whole section dedicated for that in official documentation.
That being said, I amended your code to properly click on different color variation inputs.
var casper = require('casper').create({
viewportSize: {
width: 1920,
height: 1080
},
pageSettings: {
loadImages: false,
loadPlugins: false
}
});
casper
.start()
.thenOpen("https://scubapro.johnsonoutdoors.com/fins/fins/seawing-nova-fin-full-foot", function () {
var varitoinCount = this.evaluate(function() {
return document.querySelectorAll('div#edit-attributes-field-swatch-taxonomy > div input').length;
});
var i = 0;
this.repeat(varitoinCount + 1, function() {
this.evaluate(function(iterator) {
document.querySelectorAll('div#edit-attributes-field-swatch-taxonomy > div input')[i].click();
}, i);
i++;
})
});
try {
casper.run();
} catch (e) {
console.log("Error..... " + e);
}
However it still doesn't change the color since website(for some reason) needs to take 2 clicks to change the color and I suggest that you throw in some waitFor functions to be sure that color has changed.

Magnific Popup Iframe - How to show that the iframe is loading

I am loading content in the magnific popup using the iframe method.
It works just fine, except that it take awhile to load the iframe content. Until the content is loaded the iframe is just a blank dark and empty popup and the user has no clue as to what is happening.
Is there a way to make the iframe show a loading message or animation until the content arrives?
The .mfp-preloader css class is of no help because it is hidden behind the iframe.
I'm thinking the best was is to somehow hide the iframe until it has content.
Thanks
Thanks to Dmitry who pointed me in the right direction, here is the answer that worked for me:
The callback:
callbacks: {
beforeAppend: showIframeLoading
}
The showIframeLoading function:
var showIframeLoading = function() {
var curLength = 0;
var interval = setInterval(function() {
if ($('iframe').length !== curLength) {
curLength = $('.column-header').length;
$('.mfp-content').hide();
$('.mfp-preloader').show();
}
}, 50);
this.content.find('iframe').on('load', function() {
clearInterval(interval);
$('.mfp-content').show();
$('.mfp-preloader').hide();
});
};
You may use popup events to create custom actions, e.g.:
callbacks: {
beforeAppend: function() {
console.log('before iframe is added to DOM');
this.content.find('iframe').on('load', function() {
console.log('iframe loaded');
});
}
}
Instead of polling, how about if we just detect iframe and toggle the mfp-s-ready class from the container.
In case of images, mfp-s-ready is added to the mfp-container div when image has loaded. We can simply toggle that ourself for video (iframe) + use some custom css to our advantage.
callbacks: {
beforeAppend: function () {
if (this.currItem.type === 'iframe') {
$('.mfp-container').removeClass('mfp-s-ready');
}
this.content.find('iframe').on('load', function () {
$('.mfp-container').addClass('mfp-s-ready');
});
}
}
and add this CSS:
.mfp-container .mfp-content {
display: none;
}
.mfp-s-ready.mfp-container .mfp-content {
display: inline-block;
}
This will also support mixmode galleries with videos and images.

Deep link to a position in a page, using Meteor JS

I have a meteor app with multiple pages. I want to be able to deeplink to an anchor somewhere halfway the page.
Traditionally, in normal html, you'd make an somewhere in your page, and link to it via /mypage.html#chapter5.
If I do this, my meteor app won't scroll down to that spot.
What is the best approach around this?
#Akshat 's answer works for on the same page, but what if you want to be able to pass around a url w/ a "#" in it? I did it how the meteor docs did.
Template.myTemplate.rendered = function() {
var hash = document.location.hash.substr(1);
if (hash && !Template.myTemplate.scrolled) {
var scroller = function() {
return $("html, body").stop();
};
Meteor.setTimeout(function() {
var elem = $('#'+hash);
if (elem.length) {
scroller().scrollTop(elem.offset().top);
// Guard against scrolling again w/ reactive changes
Template.myTemplate.scrolled = true;
}
},
0);
}
};
Template.myTemplate.destroyed = function() {
delete Template.myTemplate.scrolled;
};
Stolen from the source to the meteor docs.
Are you using some kind of javascript router? Meteor Router?
You could use something like a javascript based scrolling method. One such example is with JQuery: (You can place this in your link/buttons click handler)
Template.hello.events({
'click #theitemtoclick':function(e,tmpl) {
e.preventDefault();
$('html, body').animate({
scrollTop: $("#item_id").offset().top
}, 600);
}
});
Then tag your html item where you would put your anchor with the id:
<h1 id="item_id">Section X</h1>
Currently, there's an issue in IronRouter where the hash is removed from the url. This is discussed here and here. Fortunately there is a fix even though it doesn't appear to be in the stable version.
My Iron Router solution with traditional anchor tags:
1) Apply the IronRouter fix above
2)
Router.configure({
...
after: function () {
Session.set('hash', this.params.hash);
},
...
});
3)
function anchorScroll () {
Deps.autorun(function (){
var hash = Session.get('hash');
if (hash) {
var offset = $('a[name="'+hash+'"]').offset();
if (offset){
$('html, body').animate({scrollTop: offset.top},400);
}
}
Session.set('hash', '');
});
}
Template.MYTEMPLATE.rendered = function (){
anchorScroll();
};
Unfortunately this has to be set in each template's .rendered() otherwise the anchor tag is not guaranteed to be in the DOM.
For better or worse this will scroll again with a code push.
Mike's Answer didn't quite work for me. The hash was returning empty in the onRendered callback. I nested the code in an additional Meteor.setTimeout
fyi I'm using Blaze.
Below worked like a charm :)
Template.myTemplate.onRendered(function() {
Meteor.setTimeout(function(){
var hash = document.location.hash.substr(1);
if (hash && !Template.myTemplate.scrolled) {
var scroller = function() {
return $("html, body").stop();
};
Meteor.setTimeout(function() {
var elem = $("a[name='" + hash + "']");
if (elem.length) {
scroller().scrollTop(elem.offset().top);
// Guard against scrolling again w/ reactive changes
Template.myTemplate.scrolled = true;
}
},
0);
}
},0);
});
Template.myTemplate.destroyed = function() {
delete Template.myTemplate.scrolled;
};

Jquery cookies, states of sliding panel problem

I have a little problem with my sliding panels, I have a Page with 2 sliding panels (right and left). These panels have a 'slide button' and you can reduce panels by clicking on it.
I use cookies to record state of panel, so when you change page panels stay collapsed or extended. But it doesn't work very well, in fact the state is recorded for the page. If I change page, panel will extend (default position) but if I go back on the page it will disapear. Is it possible to ignore the path in the cookie and use a cookie for all website?
Jquery code :
$('#rightfold').click(function () {
if ($('.menudroite').is(':visible')) {
$('.menudroite').hide("slide", { direction: "right" }, 400);
$.cookie('rightfold', 'collapsed');
$('.triggerdroite').animate({ backgroundColor: "#B2C9D1" }, 1000);
$('#rightfold').animate({ color: "#000000" }, 1000);
}
else {
$('.menudroite').show("slide", { direction: "right" }, 400);
$.cookie('rightfold', 'extended');
$('.triggerdroite').animate({ backgroundColor: "#6c7a7f" }, 1000);
$('#rightfold').animate({ color: "#d9f4ff" }, 1000);
}
});
$('#leftfold').click(function () {
if ($('.menugauche').is(':visible')) {
$('.menugauche').hide("slide", { direction: "left" }, 400);
$.cookie('leftfold', 'collapsed');
$('.triggergauche').animate({ backgroundColor: "#B2C9D1" }, 1000);
$('#leftfold').animate({ color: "#000000" }, 1000);
}
else {
$('.menugauche').show("slide", { direction: "left" }, 400);
$.cookie('leftfold', 'extended');
$('.triggergauche').animate({ backgroundColor: "#6c7a7f" }, 1000);
$('#leftfold').animate({ color: "#d9f4ff" }, 1000);
}
});
// COOKIES
var leftfold = $.cookie('leftfold');
var rightfold = $.cookie('rightfold');
// Set the user's selection for the left column
if (leftfold == 'collapsed') {
$('.menugauche').css("display", "none");
};
// Set the user's selection for the right column
if (rightfold == 'collapsed') {
$('.menudroite').css("display", "none");
};
Thanks for responses..
If you're using the JQuery cookie plugin I'm thinking of, you can set the cookie to be available everywhere like this.
$.cookie('leftfold', 'extended', {path: '/'});
I'm not entirely certain, but I think you want to set the cookie domain to / so that it can be used across the entire domain.
I'm not sure which cookie plugin you're using, so I can't give you the specifics on how to do that.

drop down list with jquery and blockui

I almost figure this out, can anyone tell me as to why my $.unblock never executes?
$(document).ready(function () {
$('#somedropdown').change(function () {
$.blockUI({
css: {
border: 'none',
padding: '15px',
backgroundColor: '#000',
'-webkit-border-radius': '10px',
'-moz-border-radius': '10px',
opacity: '.5',
color: '#fff'
}
});
var dropdownvalue = $('#somedropdown').val();
var xaml1obj = document.getElementById("Xaml1");
$.getScript(xaml1obj.Content.scriptableObject.InitializeSomething(dropdownvalue), function () { $.unblockUI(); });
});
});
The solution to this was to call unblock method from the managed code (C# to javascript).
In other words, when you make a selection you call block, do your work (i.e. call server, etc) and then call unblock at the end. The calls to block and unblock are made from managed code (c#) but the actual work is performed in the javascript (because this is jQuery)

Resources