Global variable in javascript doesn't work as expected - javascript

here is the code, I have a menu global variable inside the function. I want to use it outside it, but then I get an "undefined reference error...·
This is the only javascript code I have, so there's no interference with another variables or functions.
Thanks in advance.
$(function() {
menu = $('nav#menu').mmenu(
{
navbars: [
{
position: "top",
height : 1,
content : [
'',
'<img src="imagenes/wheel32.png" /><p class="navbartxt">bicimap.uy</p>',
]
},
{
position: "bottom",
content: [
'<a class="fa fa-envelope"></a>',
'<a class="fa fa-twitter"></a>',
'<a class="fa fa-facebook"></a>'
]
}
],
extensions: ["multiline"],
onClick: {
close: false
},
navbar:{
title: "Inicio"
},
offCanvas: {
zposition : "next"
}
});
});
I need to put this inside the function to get it working
var API = $("#menu").data( "mmenu" );
menu.on( 'click', 'a[class^="fa fa-twitter"]', function() {
$('#twitter').show();
var API = $("#menu").data( "mmenu" );
API.close();
return false;
});

I'm lacking some context here (I'm assuming there's more we don't see?)
But you may be executing the latter snippet, menu.on( 'click'… before the code inside $(…) has run (on dom ready); so menu would be undefined.
If you're just getting started, it's worth looking into your browser's developer tools and learning about break points and logging.
You'll need to make sure that you use menu only after it's been set, likely by delaying all your invocation to be on ready.
Execution Order
The $ is called and the function is provided as the first and only argument. The function itself is not called.
API is defined by the result of $("#menu") This may or may not be found yet depending upon where in the html file you've added this script.
The data method is invoked on the result of that
You try to call on on menu, which is still undefined
sometime later, the function you passed to $ is called, and menu ends up being defined, to late to be useful

If your closure/anonymous function is happening asynchonously, its possible that the work has not been done by the time the rest of your code is computed. I would need more context to determine that.

This is the solution I found, maybe it's not the best because it could bring problems. For some reason the ready function doesn't work as is shown above, maybe some assets are being expected.
menu = null;
$(function() {
menu = $('nav#menu').mmenu(
{
navbars : [{
position: "top",
height : 1,
content : [
'<img src="imagenes/wheel32.png" /><p class="navbartxt">bicimap.uy</p>',
]
},
{
position: "bottom",
content: [
'<a class="fa fa-envelope"></a>',
'<a class="fa fa-twitter"></a>',
'<a class="fa fa-facebook"></a>'
]
}
],
extensions: ["multiline"],
onClick: {
close: false
},
navbar:{
title: "Inicio"
},
offCanvas: {
zposition : "next"
}
});
});
$( window ).load(function() {
var API = $("#menu").data( "mmenu" );
menu.on( 'click', 'a[class^="fa fa-twitter"]', function() {
$('#twitter').show();
var API = $("#menu").data( "mmenu" );
API.close();
return false;
}
);
});

Related

AngularJS, AngularConfirm - Update Confirmation Dialog once function is completed

I am trying to figure out how to make the following $ngConfirm box update after a function is completed.
After submit is clicked, the following appears (the cog is spinning):
$scope.inProgress = function(){
$ngConfirm({
theme: 'modern',
icon: "fa fa-cog fa-spin fa-.5x fa-fw",
title: 'File is downloading Please wait.',
content: "",
buttons: {
}
});
};
After this box is displayed, the function doSomething() gets called. Once that function returns, I would like to update the display to the following (the cog stops):
$scope.Complete = function(){
$ngConfirm({
theme: 'modern',
icon: "fa fa-cog fa-.5x fa-fw",
title: 'Spreadsheet Generated!',
content: "File size is {$scope.fileSize}, Do you want to save it?",
buttons: {
'Yes, save my file': {
downloadStuff();
$ngConfirm('Spreadsheet saved to "Downloads" folder.');
},
'No, take me back': {
action: function(){
$ngConfirm('Download has been cancelled.');
}
}
}
});
};
And this is the way I currently have it set up in the submit() function inside my controller:
$scope.submit = function() {
$scope.inProgress();
$scope.doSomething();
$scope.Complete();
};
Using the above code, my application displays both elements layered over eachother. I am stuck trying to figure out how to make $scope.inProgress() update with the details inside $scope.Complete() once $scope.doSomething() returns.
Could someone offer me some advice on what changes I need to make? I've tried to tinker with $scope.inProgress at the end of the submit function, but I always end up displaying a new confirm box or not actually changing something.
My current idea is something along the lines of
$scope.ConfirmationControl = function() {
$scope.inProgress(){
storageService.doSomethingCool().then(
$scope.inProgress() = //updated elements
)
}
}
Does that make sense? Am I close or thinking about this totally wrong?
Thank you in advance for your help! :)
Angular Confirm
There is an example of how to change content on the site. https://craftpip.github.io/angular-confirm/#quickfeatures. Under the Features header you can click on the button labeled "Dialogs" to see an example. Basically you will need to put everything in the content: option with some scope variables. When doSomething() is done, set a $scope variable ($scope.somethingWasDone in this case) and in your dialog have the ng-if. Below is an untested example.
$scope.inProgress = function(){
$scope.title = 'File is downloading. Please wait.';
$ngConfirm({
scope: $scope,
icon: "fa fa-cog fa-spin fa-.5x fa-fw",
content: '<h2>{{title}}</h2>' +
'<div ng-if="somethingWasDone">' +
'<div>File size is 250kb, do you want to save it?</div>' +
'<button ng-click="downloadStuff()">Yes</button>' +
'<button ng-click="cancel()">No</button>' +
'</div>'
});
};
// when your doSomething function is done
$scope.doSomething().then(function(result) {
$scope.title = 'Spreadsheet Generated!';
$scope.somethingWasDone = true;
});

Using the $dropdown service (AngularStrap)

I'm having trouble using the AngularStrap $dropdown service. As the following plunk shows, I'm able to have it responding to events correctly, but I did not understand how to populate it using programmatic means (i.e., from a directive).
Here is the initialization snippet:
var dropdown = $dropdown(element, {
content: "Hello",
show: false,
trigger: "manual"
});
I tried to mimic the way a popover (also given in the plunk as a reference) is filled, unsuccessfully. I also tried to set the content property with the value of $scope.dropdown (see here), with no satisfactory outcome.
A complementary (but not blocking) issue also occured with the first call to dropdown.hide(), that irremediably causes a TypeError: Cannot read property 'off' of undefined, whereas the first popover.hide() runs silently. It might be an AngularStrap bug, but also a misuse.
Thanks by advance for the kind help!
Here is a working plunk that shows the context menu
http://plnkr.co/edit/tNAX7liFSNh71XcOUecs
var dropdown = $dropdown(element, {
show: false,
trigger: "manual",
html: true
});
dropdown.$scope.content = [
{
"text": "<i class=\"fa fa-globe\"></i> Display an alert",
"click": "alert(\"Holy guacamole!\")"
},
{
"divider": true
},
{
"text": "Separated link",
"href": "#separatedLink"
}
];
element.on("contextmenu", function(event) {
event.preventDefault();
console.log("dropdown right click");
scope.$apply(function() {
scope.dropdown_show = true;
});
});
However, I am still trying to get the 'click' working.

Javascript callback method is not called?

I am trying to create a reusable Header object with a right button. I'm having problems on my callback method on the button click. It's never called.
My object:
myHeader:function(params)
{
opt = {
title: "Title", //header tittle
fs: PrecApp.DEFAULT_HEADER_FONTSIZE, //font size
ignoreStack :true, //ignore stack
height: "70", //header height
rightButton: {
show :false, //show right button
background: "none", //background for right button
text: "Button", //text for right button
width: "auto",
height:"auto",
color:"black",
fontize:1,
extraCss: null,
onClick:function(){}
}
}
for (i in params) opt[i] = params[i];
if (opt.rightButton.show){
var right = $("#header .right");
right.click(opt.rightButton.onClick);
}
}
And in my html :
function updateLayout(){
PrecAppComponents.myHeader({
title:"My Title",
fs:1.5,
height:50,
rightButton:{
show:true,
background:"#ffff00",
text:"Right",
width:70,
height:30,
fontsize:1.1,
extraCss: {"float":"left", "font-size":"0.5em"},
onClick: PrecAppComponents.toggleDarkOverlay(true)
}
}
Everything else is working fine. If i replace
right.click(opt.rightButton.onClick);
with
right.click(function(
console.log("clicked")
));
It works fine. What am I doing wrong?
It looks like your onClick option is calling a function. Unless that call is returning another function, this won't work:
onClick: PrecAppComponents.toggleDarkOverlay(true)
You'd have to change it to something like:
onClick: function() {
PrecAppComponents.toggleDarkOverlay(true);
}
// or with bind, perhaps
onClick: PrecAppComponents.toggleDarkOverlay.bind(PrecAppComponents, true);
Try encapsulation in an anonymous function:
right.click(function(){opt.rightButton.onClick();});
Seems like PrecAppComponents.toggleDarkOverlay(true) does not return a function to be called as an event handler - you execute it immediately. You will need to use
function(e) {
PrecAppComponents.toggleDarkOverlay(true);
}
or
PrecAppComponents.toggleDarkOverlay.bind(PrecAppComponents, true)

Executing the content of string variable as line of code in javascript?

I have something like
"_onmouseover" : "this.className=this.className.replace(' hover',
'')";
I'm trying to execute it like
buttonObject.onmouseover = function( ) {
window [ this.someObject.__onmouseover ] () ; };
And I don't know how it is possible.
Let me tell you guys my scenario. I am creating this plugin to generate four types of dialogue messages in a jquery dialogue box. Those being 'Warning', 'Error', 'Note' and 'Confirm'. So lets say there are 4 spans in dom which should trigger these four.
<span id='DialogueWarning'> Warning </span>
<span id='DialogueError'> Error </span>
<span id='DialogueNote'> Note </span>
<span id='DialogueConfirm'> Confirm </span>
Now lets hadle the click to show the dialogue
jQuery('#DialogueWarning').click(function(){
var dialogue = new Dialogue({
"type":"Warning",
"message":"Are you sure you want to close this window without saving your changes?",
"buttons":
[
{
"text":"Close without saving",
"_onmouseover": "this.className+=' hover'",
"_onmouseout":"this.className=this.className.replace(' hover', '')",
"bClass":"e_customButton"
},
{
"text":"Don't Close",
"_onmouseover": "this.className+=' hover'",
"_onmouseout":"this.className=this.className.replace(' hover', '')",
"bClass":"e_customButton"
}
],
"closeOnBackgroundClick" : true
});
});
See the "_onmouseover" and _onmouseout thingy, I need those. Is there any way I can pass those in another way
If you need an eval, I bet you have some problems in your application's design.
E.g. you can avoid such things:
// ...
var eventHandlers = {
"_onmouseover" : "this.className=this.className.replace(' hover', '')"
};
// ...
eval(eventHandlers._onmouseover);
and just do it like
var eventHandlers = {
_onmouseover: function(e) {
this.className=this.className.replace(' hover', '');
}
};
buttonObject.onmouseover = eventHandlers._onmouseover;
Some articles to read:
# 1
# 2
# 3
Why does it have to be a string in the first place?
If you had something like:
var someObject = {
_onmouseover: function() {
this.className = this.className.replace(' hover', '');
}
}
You could execute it like:
buttonObject.onmouseover = someObject.__onmouseover;
If you need this to be the button object, you might do something like this:
buttonObject.onmouseover = function() {
someObject.__onmouseover.call( buttonObject );
};
You can use Function . demo
buttonObject.onmouseover = Function(window [ this.someObject.__onmouseover ] );

JQuery can't find variable from separate javascript file

I am using the cakephp framework and I created 2 separate javascript files and placed them into my webroot/js folder. The first javascript file contains modal dialog variables that contain the settings for the dialog boxes. The second javascript file contains other click event handlers that post data to an action and then open up the dialog.
The problem I am having is that the second file calls a variable from the first file using
$variablename and I get an error saying varaibleName is not defined.
Some code is below to show you what I mean.
From the first file:
var $editSel = $("#editSel_dialog").dialog(
{
autoOpen: false,
height: 530,
width: 800,
resizable: true,
modal: true,
buttons:
{
"Cancel": function()
{
$(this).dialog("close");
}
}
});
From the second file:
$('.neweditSel_dialog').live('click', function()
{
$.ajaxSetup({ async: false });
var selected = [];
$("#[id*=LocalClocks]").each(function()
{
if(false != $(this).is(':checked'))
{
var string = $(this).attr('id').replace('LocalClocks', '');
string = string.substring(10);
selected.push(string);
}
});
if(0 === selected.length)
{
$selError.dialog('open');
$selError.text('No Local Clocks Were Selected')
}
else
{
$.post('/LocalClocks/editSelected', { "data[Session][selected]": selected }, function(data)
{
});
$editSel.load($(this).attr('href'), function ()
{
$editSel.dialog('open');
});
}
return false;
});
This was working when I was using jquery-1.4.2.min.js, but I am using jquery1.7 now.
I also ended up putting the first file with all the variables inside of $(document).ready(function(){}); I tried putting the second file inside of a document.ready() function but that made no difference.
Any help would be great.
Thanks
You are dealing with an issue in scope. In javascript:
function foo() {
var greet = "hi";
}
function bar() {
console.log(greet); // will throw error
}
However:
var greet;
function foo() {
greet = "hi";
}
function bar() {
console.log(greet); // will log "hi"
}
You must define your variable in a common parent of both functions that need to access it. Unfortunately, since you do not use any modeling convention or framework, that is the window object (why are global variables bad?).
So, you must define var $whateveryouneed before and outside of both $(document).readys.
Also, keep the declaration and definition seperate. Your definition instantiates a jQuery object, so you must encapsulate it inside a $(document).ready() (use $(function() {}) instead):
var $editSel;
$(function () {
$editSel = $("#editSel_dialog").dialog(
{
autoOpen: false,
height: 530,
width: 800,
resizable: true,
modal: true,
buttons:
{
"Cancel": function()
{
$(this).dialog("close");
}
}
});
});
I don't think you can guarantee the order in which handlers will be fired, which means that the document ready may be fired in different order than you expect. Is the variable you are trying to access in the second file a global variable? Try to think about your variables scope as I would have thought this is the issue.
You cannot guarantee that one file will be loaded before the other. And you cannot guarantee that document.ready in one file will fire before the other.
Therefore, I suggest you wrap your code in functions and call them in a single document.ready handler in the order you need.
For example:
function initVariables(){
window.$editSel = ... // your code from the first file here
}
function initHandlers(){
// your code from the second file here
}
And then:
$(document).ready(function() {
initVariables();
initHandlers();
});
You'll notice that I used the global window object to expose your variable. It would be even better if you used a common namespace for them.

Categories