I am trying to set up a set of global variables in my js app script that allows me to access them throughout my functions in the page and the site. For some reason I keep getting undefined in my console even though I know the objects are there.
This is my js snippet the js is quite long so I thought I would show you the important bit thats wrong(i think)
(function ($) {
"use strict";
var global = function() {
this.init();
};
global.prototype = {
// ------------------------------------
// Global variables
mainContainer : 'div#container',
tmbContainer : '.rsThumbsContainer',
tmbContainerT : '.rsThumbsContainer',
slider : '.collection #gallery-t-group',
body : 'body',
close : '<div class="close-button" id="close"><p class="icon-close"></p></div>',
socials : '.socialbar-vertical',
loader : '<div class="loader"></div>',
gallery : '.collection #gallery-t-group',
// ------------------------------------
// Initialise
init: function() {
var app = this;
this.testGlobals();
this.loadSlide();
this.fakingIt();
this.unloadSlide();
this.mobileNav();
this.loadThumbs();
this.royalSlider();
this.thumbsSwitch();
this.functionResize();
this.theSocialActivated();
this.theSliderActivated();
this.theSliderDeactivated();
this.slideEventChange();
console.log('======> new.global.js');
},
// ------------------------------------
// Functions
testGlobals: function () {
console.log(body);
}
}
$(document).ready(function () {
new global();
});
})(jQuery);
In my console I get
Uncaught ReferenceError: body is not defined
Is there a simple thing I am missing here.
Try replacing
testGlobals: function () {
console.log(body);
}
with
testGlobals: function () {
console.log(this.body);
}
or
testGlobals: function () {
console.log(global.body);
}
Related
I have Dialog which is in fragment. There I have:
<Button text="{i18n>buttonClose}" press="onCloseDialog"/>
and in controller there is:
openDialog: function () {
if (!this.pressDialog1) {
this.pressDialog1 = sap.ui.xmlfragment("mypackage.fragment.Dialog", this);
}
this.pressDialog1.open();
},
onCloseDialog: function () {
this.pressDialog1.close();
},
when I debug it in console it goes into openDialog function but when I try to close it doesn't go into onCloseDialog. I have also noticed that there is a warning in console:
event handler function "onCloseDialog" is not a function or does not exist in the controller.
Why it doesn't go into onCloseDialog function?
#Edit
openDialog is called like:
var controllerName = "mypackage.ProdE"
sap.ui.controller(controllerName, {
openDialog: function () {
if (!this.pressDialog1) {
this.pressDialog1 = sap.ui.xmlfragment("mypackage.fragment.Dialog", this)
this.getView().addDependent(this.pressDialog1);
}
this.pressDialog1.open();
},
onCloseDialog: function () {
this.pressDialog1.close();
});
the reason is pretty simple, your Dialog is not attached to your controller so it's not executing the onCloseDialog method you have implemented.
This is the correct way to handle dialog:
onOpenDialog: function(oEvent) {
if ( !this._oDialog ) {
this._oDialog = sap.ui.xmlfragment(this.getView().getId(), "mypackage.fragment.Dialog", this);
// This is important becuase your dialog will be attached to the view lifecycle
this.getView().addDependent(this._oDialog);
}
this._oDialog.open();
},
ondialogClose: function(oEvent) {
// Do cleaning stuff
this._oDialog.close();
}
My code is supposedly made to show two sprites of buttons (nothing terribly complex (or is it?), but nothing is appearing, not even the blue screen that is supposed to show with only creating the game variable and initiating it. All my code has been made from following the official Excalibur documentation, so what is happening?
The code:
var game = new ex.Engine({
width: 1024,
height: 768
});
function loadAssets()
{
var loader = new ex.Loader();
var resources = {
txGameTitle: new.ex.Texture("icons/GUI/final/"),
txStartButton: new.ex.Texture("icons/GUI/final/MenuPlayButton.png"),
txLoadButton: new.ex.Texture("icons/GUI/final/MenuLoadButton.png"),
txOptionsButton: new.ex.Texture("icons/GUI/final/"),
txExitButton: new.ex.Texture("icons/GUI/final/"),
txMenuBackground: new.ex.Texture("icons/GUI/final/"),
txMenuMusic: new.ex.Sound("icons/GUI/final/")
};
for (var loadable in resources)
{
if (resources.hasOwnProperty(loadable))
{
loader.addResource(resources[loadable]);
}
}
}
function startUp()
{
var StartButton = new ex.Actor.extend({
onInitialize: function (engine)
{
this.addDrawing(txStartButton.asSprite());
}
});
var LoadButton = new ex.Actor.extend({
onInitialize: function (engine)
{
this.addDrawing(txLoadButton.asSprite());
}
});
}
function init()
{
loadAssets();
startUp();
}
init();
game.start(loader).then(function () {
console.log("Game started!");
});
sorry for the bad formatting.
I think that could be because of a code error. I noticed that right at the end of the file
game.start(loader)
the loader variable is referenced but seems like it is not defined. There is the same variable which created inside loadAssets function, but it is a local one. Probably in order to use it, you need to define it above.
var loader;
function loadAssets() {
loader = ...
}
...other code
game.start(loader).then(...
Another variant is to define loader outside the loadAssets function.
var loader = new ex.Loader();
function loadAssets() {
var resources = {...
}
...other code
game.start(loader).then(...
I've got a file which needs to run on page load (randomise_colors.js), but also needs to be called by another file as part of a callback function (in infinite_scroll.js). The randomise_colors script just loops through a list of posts on the page and assigns each one a color from an array which is used on the front-end.
Infinite Scroll loads new posts in to the DOM on a button click, but because the randomise_colors.js file has already ran on page load, new content loaded is not affected by this so I need it to run again. I'm open to other suggestions if it sounds like I could be tackling the problem in a different way, I'm no JS expert.
Currently I'm getting Uncaught ReferenceError: randomise_colours is not defined referring this line of infinite_scroll.js:
randomise_colours.init();
I'm calling all files that need be loaded on document.ready in app.js
require(['base/randomise-colours', 'base/infinite-scroll'],
function(randomise_colours, infinite_scroll) {
var $ = jQuery;
$(document).ready(function() {
infinite_scroll.init();
randomise_colours.init();
});
}
);
This is infinite_scroll.js which initialises Infinite Scroll and features the callback. The callback function runs whenever new items are loaded in via AJAX using the Infinite Scroll jQuery plugin. I've put asterix around the area where I need to run the randomise_colors.init() function from randomise_colors.js.
define(['infinitescroll'], function() {
var $ = jQuery,
$loadMore = $('.load-more-posts a');
function addClasses() {
**randomise_colours.init();**
};
return {
init: function() {
if($loadMore.length >= 1) {
this.setUp();
} else {
return false;
}
},
setUp: function() {
this.initInfiniteScroll();
},
initInfiniteScroll: function() {
$('.article-listing').infinitescroll({
navSelector : '.load-more-posts',
nextSelector : '.load-more-posts a',
itemSelector : '.standard-post'
}, function(newItems) {
addClasses();
});
//Unbind the standard scroll-load function
$(window).unbind('.infscr');
//Click handler to retrieve new posts
$loadMore.on('click', function() {
$('.article-listing').infinitescroll('retrieve');
return false;
});
}
};
});
And this is my randomise_colors.js file which runs fine on load, but needs to be re-called again after new content has loaded in.
define([], function() {
var $ = jQuery,
$colouredSlide = $('.image-overlay'),
colours = ['#e4cba3', '#867d75', '#e1ecb9', '#f5f08a'],
used = [];
function pickRandomColour() {
if(colours.length == 0) {
colours.push.apply(colours, used);
used = [];
}
var selected = colours[Math.floor(Math.random() * colours.length)];
var getSelectedIndex = colours.indexOf(selected);
colours.splice(getSelectedIndex, 1);
used.push(selected);
return selected;
};
return {
init: function() {
if($colouredSlide.length >= 1) {
this.setUp();
} else {
return false;
}
},
setUp: function() {
this.randomiseColours();
},
randomiseColours: function() {
console.log('randomise');
$colouredSlide.each(function() {
var newColour = pickRandomColour();
$(this).css('background', newColour);
});
}
};
});
You would have to reference randomiseColours inside the infiniteScroll file. So you need to change your define function to the following:
define(['infinitescroll', 'randomise-colours'], function(infiniteScroll, randomise_colours)
Remember that when using require you need to reference all variables through the define function, otherwise they will not be recognised.
What is the proper way to make this code work?
$(function(){
var base = {
$wrapper: $('.homepage_main'),
$main: base.$wrapper.find('#primary').find('.home_slides').closest('[data-id="Colleague"]'),
$panel: base.$wrapper.find('#sidebar').find('.home_slides').closest('[data-id="Colleague"]'),
Template: {
$img: function () { return $('img'); }
},
Modal: {
$modalInterrupt: $('#searching_interruption'),
Suggestion: {
$self: $('#suggested_colleague'),
$loading: base.Modal.Suggestion.$self.find('.gif_loading'),
$paging: base.Modal.Suggestion.$self.find('.pagination'),
$itemContainer: base.Modal.Suggestion.$self.find('.request_items'),
$itemClone: base.Modal.Suggestion.$itemContainer.find('[data-id="Clonable"]').clone().removeAttr('data-id').removeClass('hide'),
$lblCount: base.Modal.Suggestion.$self.find('[data-id="SuggestCount"]'),
$listItems: function () {
return base.Modal.Suggestion.$itemContainer.find('.coll_panel_content:not([data-id="Clonable"])');
}
}
}
};
});
I'm getting Uncaught TypeError: Cannot read property '$wrapper' of undefined when you look at Google Chrome console.
Some fiddle
I tried pulling out the $wrapper and now I get new error:
Uncaught TypeError: Cannot read property 'Modal' of undefined
Another fiddle sample
I made this approach because it is more easy to manage. For example, if I have changed some class name or id on my html page, I just have to modify 1 specific variable in my jquery code and everything will be fine again. If you know a better approach, kindly share it to me.
You can't use the variable you're defining while you're defining it. So a shorter example would be:
var hi = "hi" + hi.length;
Because the variable isn't completely defined yet.
To make your code work, define the variables you need beforehand:
$(function(){
var $wrapper = $('.homepage_main'),
$modalSelf = $('#suggested_colleague'),
$itemContainer = $modalSelf.find('.request_items');
var base = {
$main: $wrapper.find('#primary').find('.home_slides').closest('[data-id="Colleague"]'),
$panel: $wrapper.find('#sidebar').find('.home_slides').closest('[data-id="Colleague"]'),
Template: {
$img: function () { return $('img'); }
},
Modal: {
$modalInterrupt: $('#searching_interruption'),
Suggestion: {
$loading: $modalSelf.find('.gif_loading'),
$paging: $modalSelf.find('.pagination'),
$itemClone: $itemContainer.find('[data-id="Clonable"]').clone().removeAttr('data-id').removeClass('hide'),
$lblCount: $modalSelf.find('[data-id="SuggestCount"]'),
$listItems: function () {
return $itemContainer.find('.coll_panel_content:not([data-id="Clonable"])');
}
}
}
};
});
If I have an element on the page like this ...
<span data-function="DoSomething">Click</span>
... and i put this in my page header ...
$(document).ready(function()
{
$('[data-function]').each(function()
{
var fName = $(this).attr('data-function');
$(this).click(fName);
});
});
... what goes in place of the comment produce the desired effect of executing the function called "DoSomething".
Note:
I no the code above wont work, my question is how to make this work (translate 'DoSomething' in to DoSomething();)
Any ideas guys?
The functions should be available. Try putting them in an Object, like this:
$(document).ready(function()
{
var fns = {
DoSomething: function() {/* ... */},
DoAnotherthing: function() {/* ... */}
};
$('[data-function]').each(function()
{
var fName = $(this).attr('data-function');
$(this).click(fns[fName]);
});
});
Here's a jsfiddle, demonstrating a way to keep everything local to one namespace and assigning handlers based on the data attribute of elements.
Try calling function with window object -
$(document).ready(function() {
$('[data-function]').each(function() {
var fName = $(this).attr('data-function');
if (typeof (window[fName]) === "function") {
$(this).click(window[fName]);
}
});
}
You can use something like
$(this).click(window[fName]);
Where window would be replaced by the appropriate expression if the function DoSomething is not defined in the global scope.
Maybe a little bit clean way:
http://jsfiddle.net/whsPG/
var myfuncs = {
alert : function() {
alert("An Alert");
},
changeName: function(obj) {
$(obj).text('Other Text');
}
};
$('[data-function]').on('click', function()
{
value = $(this).data('function');
if (myfuncs.hasOwnProperty(value)) {
myfuncs[value](this);
}
});