Jquery call defined function from an outside function [duplicate] - javascript

This question already has answers here:
JavaScript Nested function
(8 answers)
Closed 6 years ago.
Hey all I have a jQuery function like so:
$.fn.sexyForm = function (style){
$('.sexyform').on('click',function(){
$(this).find('input').trigger('focus');
});
var $input = $('.sexyform');
****************************************************
************* MORE CODE HERE TAKEN OUT *************
****************************************************
function closeBox(element) {
//console.log("Closing", element);
//Get the element that needs to be closed
var $el = $(element);
//Grab the data we set on it
var originalData = $el.data('original-styles');
//console.log(originalData);
var style = $el.data('style');
//Reset the input
$el.find('input').animate({
left: originalData.startPosInput
})
$el.find('span').animate({
width: originalData.startWidth,
left: originalData.startPosPlace,
})
}
};
And I am trying to call that from another location like this:
function clearAll() {
console.log('hi');
$('.input3').val('');
$('.input3').removeClass('form-open');
closeBox($('.input3'));
$("span[data-id*='txt']").each(function(index) {
//enable ALL textboxes
$(this).css("pointer-events", "auto");
$(this).fadeTo("fast", 1.0);
$('#searchTop').text('above');
});
$('#schoolSelect').prop('selectedIndex', 0).selectric('refresh');
$('#roles').prop('selectedIndex', 0).selectric('refresh');
$('#clearBtn').focus();
}
The error comes from the closeBox($('.input3'));. I have tried doing the following:
$.fn.sexyForm.closeBox($('.input3'));
and that doesn't work as well. What am I missing?

I might not be understanding exactly what you're looking for #Stealth, but if you want to keep the closeBox function defined inside of sexyForm, an alternative would be to pass an object of some form. For example:
$.fn.sexyForm = function(style, BoxObj) {
// Code here...
BoxObj.closeBox = function(element) {
// Any other code...
}
}
And depending on where BoxObj is defined, you can optionally pass BoxObj as an argument to clearAll:
function clearAll(BoxObj) or () {
// Code here
BoxObj.closeBox($('.input3'));
// More code
}

closeBox is only defined inside sexyForm function scope and cannot be used outside, what you can try is to move it in upper scope
function close(element) {
//console.log("Closing", element);
//Get the element that needs to be closed
var $el = $(element);
//Grab the data we set on it
var originalData = $el.data('original-styles');
//console.log(originalData);
var style = $el.data('style');
//Reset the input
$el.find('input').animate({
left: originalData.startPosInput
})
$el.find('span').animate({
width: originalData.startWidth,
left: originalData.startPosPlace,
})
}
$.fn.sexyForm = function(style) {
$('.sexyform').on('click', function() {
$(this).find('input').trigger('focus');
});
var $input = $('.sexyform');
function closeBox(element) {
close(element)
}
};
function clearAll() {
console.log('hi');
$('.input3').val('');
$('.input3').removeClass('form-open');
close($('.input3'));
$("span[data-id*='txt']").each(function(index) {
//enable ALL textboxes
$(this).css("pointer-events", "auto");
$(this).fadeTo("fast", 1.0);
$('#searchTop').text('above');
});
$('#schoolSelect').prop('selectedIndex', 0).selectric('refresh');
$('#roles').prop('selectedIndex', 0).selectric('refresh');
$('#clearBtn').focus();
}

Related

JQuery not able to get dynamic HTML element [duplicate]

This question already has answers here:
jQuery .on() event doesn't work for dynamically added element
(3 answers)
Closed 4 years ago.
I have this problem in JQuery and I can't seem to get past this issue.
I have a dynamically generated list of Li elements, and for each Li element I want to attach an On Hover so that a dropdown shows below the Li element. The catch is the Li elements are generated dynamically.
I have tried using .on("hover"), but nothing triggeres the event. The following is my code.
//On Init
$( document ).ready(function() {
generateList();
$(".app").on("hover", function () {
console.log('test'); //Does not trigger
});
$(".app").on("mouseenter", function () {
console.log('test'); //Does not trigger
});
});
//Load JSON file to generate app listing
function generateList(){
//Load JSON file
$.getJSON('json/adapters.json', function (json) {
var listCol = 5;
var ul = $('#container-apps');
//Generate app list from adapters.JSON
json.adapters.forEach(function (adapter) {
//Count adapter for no result function
adapterCount += 1;
var link = adapter.link;
var git = adapter.git;
var img = adapter.image;
var name = adapter.name;
//Appending the HTML elements
//List element
var li = $("<li>").attr("class", "app").appendTo(ul);
var a = $("<a>").attr({
"href": "javascript:void(0);",
"target":"_blank",
"class":"app-link",
}).appendTo(li);
var image = $("<img>").attr("src", img).appendTo(a);
var label = $("<div>").attr("class", "item-name black-font").html(name).appendTo(a);
//Hover element
var hoverContainer = $("<div>").attr("class", "hoverContainer").appendTo(li);
var hoverUL = $("<ul>").appendTo(hoverContainer);
var hoverPageLi = $("<li>").appendTo(hoverUL);
var hoverPageA = $("<a>").attr({"href": link, "target":"_blank", "class":"app-link"}).html("SDK").appendTo(hoverPageLi);
var hoverGitLi = $("<li>").appendTo(hoverUL);
var hoverGitA = $("<a>").attr({"href": git, "target":"_blank", "class":"app-link"}).html("Github").appendTo(hoverGitLi);
});
//Generate dummy box for responsive
for (var i = 0; i < (listCol); i++) {
$('<li class="item flex-dummy"></li>').appendTo(ul);
}
});
}
$(function () {
$(".app").hover(){
console.log('test'); //Does not trigger
}
})
Try this syntax:
$("body").on("click", ".app", function(){
//do something
});

Understanding module design patterns in javascript

I am trying to understand module patterns in Javascript so that i can separate my code into different modules and use them where required.
var messageHandler = (function(){
var el;
var display = function(a){
if(a=='error'){
el = $('.error');
el.css('display','block');
}
else if (a==='success'){
el = $('.success');
el.css('display','block');
}
else if (a=='warning'){
el = $('.warning');
el.css('display','block');
}
else if (a=='danger'){
el = $('.danger');
el.css('display','block');
}
registerClick(el.find('.close'));
return this;
}
function registerClick(p_el){
p_el.bind('click',function(){
hide();
});
}
var hide = function(){
el.css('display','none');
}
return {
display: display,
hide: hide
}
})();
window.messageHandler = messageHandler;
messageHandler.display('warning');
So, I have four different classes in css for different types of messages.The close class is for a small cross button on the top right to close the message.
This works fine till i call the function only once.When i do this
messageHandler.display('warning');
messageHandler.display('success');
Now both the messages close button have been bind to the success close button because el gets overwritten.
How to achieve it keeping the code reusable and concise.
The problem here is that you have a closure variable el that you are overwriting every time display() is called. The hide() function uses whatever is the current value of el at the time it is called, so overwriting el is a problem.
If you want to have "static" functionality like this display() method, you need to avoid shared state.
As #Bergi points out in the comments, you can eliminate the shared el and modify hide() to take an element as input:
var messageHandler = (function(){
var el; // delete this
var display = function(a){
var el; // add this
function registerClick(el){
el.bind('click', function(){
hide(p_el);
});
}
function hide(el){
el.css('display','none');
}
You could also modify hide to make use of the current event properties, and then just have:
function registerClick(el){
el.bind('click', hide);
}
function hide(event){
$(event.target).css('display','none');
}
Cleaned up version including the auto-hide discussed in the comments:
var messageHandler = (function(){
var display = function(a){
var el = $('.' + a);
el.css('display', 'block');
var hideAction = function () { el.css('display', 'block'); };
var token = setTimeout(hideAction, 5000);
el.find('.close').bind('click', function () {
hideAction();
clearTimeout(token);
});
return this;
}
return {
display: display
}
})();

For loop doesn't loop values of an object - applies same handler to each element

I've written a function that is meant to provide an easy way of creating right-click (context) menus. Fine, but the functions you pass into it as click handlers don't get applied to the right menu items.
When I call the function, I pass it the click event and an object literal containing menu item names and their handler functions, like this:
context.menu(e,{
"Hello": function() {
alert("Hi");
},
"World": function() {
alert("Hello world!");
},
});
Supposedly, the object literal is looped through in a for loop and each handler function is applied to the corresponding menu item. However, it seems that the first handler function passed in is getting applied to all the menu items.
The function goes like this:
this.menu = function(e,options) {
e.preventDefault();
var x = e.clientX;
var y = e.clientY;
var id = math.floor(math.random()*8192);
id = "menu-"+id;
var menu = "<div class='menu-wrapper'></div>";
menu = $(menu);
menu.attr("id",id);
var i = 0;
for(var key in options) {
var option = $("<span class='menu-item' id='menu-item-"+i+"'>"+key+"</span>");
var fn = options[key];
option.appendTo(menu);
option.on("click",function() {
// $(this).css("background","yellow"); - just a test, not needed any more
fn.call();
});
i++;
}
menu.appendTo("body");
menu.css({
top: y,
left: x,
});
$(document).click(function() {
$("#"+id).remove();
});
$("#"+id).click(function(e) {
e.stopPropagation();
});
}
How do I change this so that the handlers get applied in the right places?
Live JSFiddle demo
UPDATE:
I've tried adding code (using typeof(options[key]);so it checks the type of the function you pass in but still no luck. console.log also gives me the right values so I don't know why it's not looping.
Common pitfall here. JS doesn't have block scope - your fn variable is being rewritten each iteration. Try wrapping it in a closure.
this.menu = function(e,options) {
e.preventDefault();
var x = e.clientX;
var y = e.clientY;
var id = math.floor(math.random()*8192);
id = "menu-"+id;
var menu = "<div class='menu-wrapper'></div>";
menu = $(menu);
menu.attr("id",id);
var i = 0;
for(var key in options) {
(function(key){ // start closure
var option = $("<span class='menu-item' id='menu-item-"+i+"'>"+key+"</span>");
var fn = options[key];
option.appendTo(menu);
option.on("click",function() {
// $(this).css("background","yellow"); - just a test, not needed any more
fn.call();
});
})(key); // end closure
i++;
}
menu.appendTo("body");
menu.css({
top: y,
left: x,
});
$(document).click(function() {
$("#"+id).remove();
});
$("#"+id).click(function(e) {
e.stopPropagation();
});
}

How can i optimize my Jquery code?

I've created some JavaScript using Jquery, for the page animation :
I trying to optimize it since i repeat the same thing for subtab1, subtab2, subtab3.
The same function is executed for all of them, and the only thing is changes is variable i iterating on?
Any suggestion?
<script type="text/javascript">
$(document).ready(function () {
var $defensivo = $('#defensivoimg');
var $equilibrado = $('#equilibradoimg');
var $activo = $('#activoimg');
var $defensivoSubTab = $('#subtab1');
var $equilibradoSubTab = $('#subtab2');
var $activoSubTab = $('#subtab3');
var $fundosdiponiveis = $('#fundosdiponiveis');
var $fundosdiponiveisTab = $('#tabs1');
$defensivo.live('click', function () {
$fundosdiponiveis.removeClass("subshow show").addClass("hide");
$defensivoSubTab.removeClass("hide");
$defensivoSubTab.show();
});
$equilibrado.live('click', function () {
$fundosdiponiveis.removeClass("subshow show").addClass("hide");
$equilibradoSubTab.removeClass("hide");
$equilibradoSubTab.show();
});
$activo.live('click', function () {
$fundosdiponiveis.removeClass("subshow show").addClass("hide");
$activoSubTab.removeClass("hide");
$activoSubTab.show();
});
});
</script>
For a while:
var $fundosdiponiveis = $('#fundosdiponiveis');
This is my default div.
var $defensivoSubTab = $('#subtab1');
var $equilibradoSubTab = $('#subtab2');
var $activoSubTab = $('#subtab3');
That divs apears when i clicking on one of the following tabs:
var $defensivo = $('#defensivoimg');
var $equilibrado = $('#equilibradoimg');
var $activo = $('#activoimg');
And that button hides and changes style"display" to none, on click, of my three #subtab's
var $fundosdiponiveisTab = $('#tabs1');
Any suggestion?
You could write a function that returns the proper function:
function createShowTabFunc(tab) {
return function () {
$fundosdiponiveis.removeClass("subshow show").addClass("hide");
tab.removeClass("hide");
tab.show();
}
}
Then assign your click handlers:
$defensivo.live('click', createShowTabFunc($defensivoSubTab));
$equilibrado.live('click', createShowTabFunc($equilibradoSubTab));
$activo.live('click', createShowTabFunc($activoSubTab));
Have a common class attribute to all the tab's and you just need to write $('.class').click() and in this get the id of the corresponding tab and according to the id fetched by attr function, you can have an if else to define your variables inside the if else and execute your code block.

How to add values on Javascript?

I'm a very beginner on this and wondering is there anyway that I can add these two values
maxScreenWidth: 480,
menuTitle: 'Menu:'
into this script.
function DropDown(el) {
this.mainNav = el;
this.initEvents();
}
DropDown.prototype = {
initEvents: function () {
var obj = this;
obj.mainNav.on('click', function (event) {
$(this).toggleClass('active');
event.stopPropagation();
});
}
}
$(function () {
var mainNav = new DropDown($('#mainNav'));
$(document).click(function () {
// all dropdowns
$('.dropdown-menu').removeClass('active');
});
});
thanks in advance.
In addition, this is the dropdown menu that I'm applying to my website.
http://tympanus.net/Tutorials/CustomDropDownListStyling/index2.html
I'm trying to apply this menu only for phone layout but it maintains its form no matter what screen size is. It is supposed be disappeared when it's more 480px but it isn't.
Thank you so much for your help.
If you want to add those properties, just add them like below:
function DropDown(el, width, title) {
this.mainNav = el;
this.maxScreenWidth = width; //added
this.menuTitle = title; //added
this.initEvents();
}
Now they are part of your constructor as passable arguments
Then when you call you constructor, just pass what those values should be
$(function () {
var mainNav = new DropDown($('#mainNav'), 480, 'Menu'); //See, pass them here.
$(document).click(function () {
// all dropdowns
$('.dropdown-menu').removeClass('active');
});
});
You can add this values as DropDown parameters as Christoper wrote, also you can create global variables:
var maxScreenWidth = 480;
var menuTitle = 'Menu:';
function DropDown(el) {
this.mainNav = el;
this.initEvents();
}
//...
But then, if you write it in your js file, other code could access and change your global variables (they are global after all :) ), so this technique exists:
(function ($) {
var maxScreenWidth = 480;
var menuTitle = 'Menu:';
function DropDown(el) {
this.mainNav = el;
this.initEvents();
}
//...
}(jQuery));
In the last example you'r creating function with 'private scope', so your 'private' variables ain't accessible from other js code. Also you should note that you couldn't access DropDown from other code in you application, only within this function.

Categories

Resources