Calling a function that resides in the main page from a plugin? - javascript

I want to call a function from within plugin, but the function is on the main page and not the plugin's .js file.
EDIT
I have jQuery parsing a very large XML file and building, subsequently, a large list (1.1 MB HTML file when dynamic content is copied, pasted, then saved) that has expand/collapse functionality through a plugin. The overall performance on IE is super slow and doggy, assuming since the page/DOM is so big.
I am currently trying to save the collapsed content in the event.data when it is collapsed and remove it from the DOM, then bring it back when it is told to expand... the issue that I am having is that when I bring the content back, obviously the "click" and "hover" events are gone. I'm trying to re-assign them, currently doing so inside the plugin after the plugin expands the content. The issue then though is that is says the function that I declare within the .click() is not defined. Also the hover event doesn't seem to be re-assigning either....
if ($(event.data.trigger).attr('class').indexOf('collapsed') != -1 ) { // if expanding
// console.log(event.data.targetContent);
$(event.data.trigger).after(event.data.targetContent);
$(event.data.target).hide();
/* This Line --->*/ $(event.data.target + 'a.addButton').click(addResourceToList);
$(event.data.target + 'li.resource')
.hover(
function() {
if (!($(this).attr("disabled"))) {
$(this).addClass("over");
$(this).find("a").css({'display':'block'});
}
},
function () {
if (!($(this).attr("disabled"))) {
$(this).removeClass("over");
$(this).children("a").css({'display':'none'});
}
}
);
$(event.data.target).css({
"height": "0px",
"padding-top": "0px",
"padding-bottom": "0px",
"margin-top": "0px",
"margin-bottom": "0px"});
$(event.data.target).show();
$(event.data.target).animate({
height: event.data.heightVal + "px",
paddingTop: event.data.topPaddingVal + "px",
paddingBottom: event.data.bottomPaddingVal + "px",
marginTop: event.data.topMarginVal + "px",
marginBottom: event.data.bottomMarginVal + "px"}, "normal");//, function(){$(this).hide();});
$(event.data.trigger).removeClass("collapsed");
$.cookies.set('jcollapserSub_' + event.data.target, 'expanded', {hoursToLive: 24 * 365});
} else if ($(event.data.trigger).attr('class').indexOf('collapsed') == -1 ) { // if collapsing
$(event.data.target).animate({
height: "0px",
paddingTop: "0px",
paddingBottom: "0px",
marginTop: "0px",
marginBottom: "0px"}, "normal", function(){$(this).hide();$(this).remove();});
$(event.data.trigger).addClass("collapsed");
$.cookies.set('jcollapserSub_' + event.data.target, 'collapsed', {hoursToLive: 24 * 365});
}
EDIT
So, having new eyes truly makes a difference. As I was reviewing the code in this post this morning after being away over the weekend, I found where I had err'd.
This:
$(event.data.target + 'a.addButton').click(addResourceToList);
Should be this (notice the space before a.addbutton):
$(event.data.target + ' a.addButton').click(addResourceToList);
Same issue with the "li.resource". So it was never pointing to the right elements... Thank you, Rene, for your help!!

I guess you should pass your function to the plugin as some argument, so it can call it.
// inside your plugin:
$.yourPlugin = function(f) {
f();
}
// on the main page
$.yourPlugin(yourFunction);
Other possibility would be to call a global function by name, but a plugin shouldn't rely on your own global function to exist.
Or provide some more context to your question, as your current description is way too brief.

It seems to me, that this plugin should be responsible for adding the events at the first place and then it can re-add them when necessary.
But when these click and hover events are really external to plugin, then you might want to take a look at jQuery live events.

Related

Use .destroy(); with Waypoints but only on one object

I have two different objects I'm using to trigger two different Waypoints events which then trigger Velocity.js (a fade in/out library).
The first even (the one on secondary) should fire eternally, up and down and every time. The second however, on .process should only fire once and then never again until the page is reloaded.
When I insert .destroy(); in the second function, it shuts off all waypoints events for the entire page. Any idea why?
Page in reference: http://www.goodcorps.com/
if (document.documentElement.clientWidth > 990) {
$('.secondary').waypoint(function(direction) {
$('.intro').toggleClass('hidden');
}, {
offset: "0%",
});
$('.home .process').waypoint(function(direction) {
$('.illus.crosses svg g').velocity("transition.fadeIn", {
stagger: 50,
duration: 100,
});
$(this).destroy(); // here's my attempted location
}, {
offset: "20%",
});
} else {
$('.home .process').waypoint(function(direction) {
$('.illus.crosses svg g').velocity("transition.fadeIn", {
stagger: 50,
duration: 100,
});
$(this).destroy(); // here's my attempted location
}, {
offset: "50%",
});
}
The page you shared doesn't appear to contain the destroy calls you reference in your code sample, but if they were included you should have seen an uncaught TypeError "undefined is not a function". The reason: You're calling $(this).destroy() instead of this.destroy(). destroy is a function on a Waypoint instance. When you try to call it on a jQuery object, which $() will return, it should have blown up on you in the console because destroy is not a jQuery method. Am I missing something here?

Two problems with jquery script: z-index and setTimeout

have a side menu on the left side of the website. I want the submenu to slide open to the right with a neat animation. I have made the script:
jQuery(document).ready(function($){
$(".main-navigation ul li").mouseenter(function() {
if ($(this).children().length > 0) {
$(this).children("ul").css ({
"display" : "block",
}).animate({
left: '250px',
opacity: 1,
}, 500)
}})
.mouseleave(function() {
setTimeout(function() {
$(this).children("ul").css({
"display" : "none",
"left" : "0px",
"opacity": 0,
})
}, 1000);
});
});
Sliding works just fine. The menu shows up nicely.
There's two problems though. One is, that the menu z-index doesn't work. The submenu's ul has a negative index set in css but when it slides it goes OVER the main ul. I want it to go UNDER the menu so it doesn't show.
Second one is, the SetTimeout function doesn't seem to work. Once the mouse leaves the area the ul just stays there forever. Without the Settimeout function it disappears just nicely (instantly though, I want it to stay there awhile).
I have made a jsfiddle example
http://jsfiddle.net/r8vx07ae/4/
Problem with z-index:
An element can not appear behind its parent. Since the submenu exists as a child element of the menu, it will not be able to appear behind the menu, z-index is really only applicable to two elements which share the same parent.
Problem with setTimeout:
The issue is most likely being caused because the this variable is out of scope by the time that the timeout occurs. This has an easy fix: create a global variable (say subMenu) and set subMenu = this before the timeout occurs and replace this with subMenu in your timeout function. You may use additional variables or a dictionary/array if you have multiple submenus to prevent the variable from being overwritten if two submenus get opened one right after the other
It is because $(this) is losing its scope on setTimeout function. To overcome this issue, you can assign your $(this) scope into a variable like $this and then use it in your setTimeout function. Here is the code changes:
.mouseleave(function() {
var $this=$(this);
setTimeout(function() {
$this.children("ul").css({
"display" : "none",
"left" : "0px",
"opacity": 0,
})
}, 1000);
});
And here is your updated fiddle:
http://jsfiddle.net/r8vx07ae/5/
The problem with the setTimeout is the scope of this
When it runs, it is the window, not the menu.
jQuery(document).ready(function($){
$(".main-navigation ul li").mouseenter(function() {
/* see if the timer has run yet, if it has not, cancel it */
var hideTimer = $(this).data("timer");
if (hideTimer) window.clearTimeout(hideTimer);
if ($(this).children().length > 0) {
$(this).children("ul").css ({
"display" : "block",
}).stop().animate({
left: '250px',
opacity: 1,
}, 500)
}})
.mouseleave(function() {
/* store the children here to get rid of the "this" scope issue */
var ul = $(this).children("ul");
/* Store a reference to the timer so we can cancel it if they mouseover again */
$(this).data("timer", setTimeout(function() {
ul.css({
"display" : "none",
"left" : "0px",
"opacity": 0,
})
}, 1000));
});
});
This will not fix the z-index issue.
I guess this is from the usage of "this" inside the callback of setTimeout sadly i do not have any computer to test out...
See section "the this problem": https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers.setTimeout#The_%27this%27_problem
To solve it, save a reference of this before the call of setTimeout, and use the saved reference inside your callback

JavaScript taking extra time between calls

console.log("FADIG");
console.log(modal);
modalBG.delay(options.animationspeed).fadeOut(options.animationspeed);
console.log("background GONE!");
modal.animate({
"opacity": 0
}, 300, function () {
console.log("FADED OUT MODAL");
modal.css({
'opacity': 1,
'visibility': 'hidden',
'top': topMeasure
});
unlockModal();
});
That's my JavaScript code. I know that it finds the object named modal just fine. It then immediately spits out background GONE! then it takes about 10 seconds for me to see FADED OUT MODAL. Which means the animate didn't run for a good 10 seconds.
Any idea why this would be?
Super simple... I think a few animations were being queued, so I changed it to:
modal.stop().animate and all is well

JQuery Toggle auto-collapsing div on load. Don't want it to, can't figure out why

I didn't see any answer to this question out there, but I'm having this problem:
I made a JQuery menu UI, and it was working just fine.
When you click on the first link inside an list-item, the list-item is supposed to expand to show the rest of the links.
However! When the page loads, it seems the .toggle() which is connected to the first link is auto-collapsing that first link. I can't figure it out.
Again, to reitterate: The first link "a.cat" is being collapsed when the page loads. It didn't used to, and I'm not sure when, or if, I even changed it...).
Edit Here's the jsFiddle.
Anyhow, I hope that's clear enough. I'll check back regularly to answer questions.
And here's the JS, because S.O. requires it:
$("#sidebar ul li a.cat").toggle( function () {
$(this).stop(true).animate({
"color" : "#fff"
});
var growTo = (parseInt($(this).siblings("a.link").length) * nmMenu.linkHeight) + nmMenu.catHeight;
$(this).parent("li").stop(true).animate({
"height" : growTo + "px",
"padding-top" : "5px"
}, function () {
$(this).children("a").stop(true).animate({
"margin-left" : "20px"
});
});
}, function () {
$(this).siblings("a").andSelf().stop(true).animate({
"margin-left" : "0px"
}, function () {
$(this).siblings(" a:first").stop(true).animate({
"margin-bottom" : nmMenu.catMarginBottom + "px",
"color" : nmMenu.linkColor
});
$(this).parent("li").stop(true).animate({
"height" : nmMenu.catHeight + "px"
});
});

jQuery Animate() hover?

I'm using jQuery for the first time, specifically on my own website, and I'm using the animate function to make an email tab move down slightly when hovered upon (check it out in the top right: http://www.tommaxwell.me). However, I don't know how to make the animation pause after completing. I can make the first animation and the animation necessary to have it return to its original state, but I want it to return to its original state after the user moves their cursor away. Here's the code, and keep in mind I realize why it doesn't work, I just don't know a solution as I'm new to jQuery.
$("#emailme").hover(function(){
$("#emailme").animate({
paddingTop: "15px"
}, 100, function() {
$("#emailme").animate({
paddingTop: "10px"
}, 100)
});
});
The second argument to hover is the callback to invoke when the user moves their mouse away.
$("#emailme").hover(function() {
$(this).animate({
paddingTop: "15px"
}, 100);
}, function() {
$(this).animate({
paddingTop: "10px"
}, 100)
});
So the general idea is:
$('selector').hover(function(){
//stuff to do on mouse in
}, function(){
//stuff to do on mouse out
});
You should use the functions $element.mouseover(fn) and $element.mouseout(fn).
So it should be like this:
$("#emailme").mouseover(function(){
$(this).animate({
paddingTop: "15px"
}, 100);
}).mouseout(function(){
$(this).animate({
paddingTop: "10px"
}, 100);
});
This means that attach event handlers to two different events: when you move your mouse over the element it expands and when you move your mouse out it subtracts - just as you want it.

Categories

Resources