How to put JavaScript DOM elements in object and access them? - javascript

I would like to place all of JavaScript DOM element queries in an object and access them throughout my script. Here's the current design pattern I'm using and I would like to stick to this format if possible:
(function ($) {
EXAMPLE = {
basicExample : function () {
config : {
logo : $('#logo'),
footer : $('footer'),
},
EXAMPLE.config.logo.hover(function () {
$(this).addClass('example');
}, function () {
$(this).removeClass('example');
});
}
EXAMPLE.basicExample();
})(jQuery);
Accessing the logo DOM element doesn't seem to work like this: EXAMPLE.config.logo

You did misplace the config part - not in your EXAMPLE object literal, but inside your basicExample function (where it acted as a labelled block statement with no-op expression statements inside, so it threw no error). Instead, it should be
(function ($) {
EXAMPLE = {
config : {
logo : $('#logo'),
footer : $('footer'),
},
basicExample : function () {
EXAMPLE.config.logo.hover(function () {
$(this).addClass('example');
}, function () {
$(this).removeClass('example');
});
}
};
EXAMPLE.basicExample();
})(jQuery);
However, you will need to place the initialisation into a DOM-ready handler, otherwise it might not find the elements. So either use
EXAMPLE = {
init : function($) {
EXAMPLE.config = {
logo : $('#logo'),
footer : $('footer'),
};
EXAMPLE.basicExample();
},
basicExample : function() {
this.config.logo.hover(function () {
jQuery(this).addClass('example');
}, function () {
jQuery(this).removeClass('example');
});
}
};
jQuery(EXAMPLE.init);
or just put everything in the handler, without any module pattern and extra basicExample function:
jQuery(function ($) {
var config = {
logo : $('#logo'),
footer : $('footer'),
};
config.logo.hover(function () {
$(this).addClass('example');
}, function () {
$(this).removeClass('example');
});
});

You are using object literal notation to define an object, and inside that object you define a constructor function, that needs to be used via new to be useful..I believe what you wanted is to create a namespace with a single object inside it.
try to remove the function and you should be able to access it, hence:
var EXAMPLE = {
basicExample : {
config : {
logo : $('#logo')
}
}
}

I would suggest declare a global object like this:
EXAMPLE = {
basicExample: function () {
this.config = {
logo: $('#logo'),
footer: $('footer')
};
return this;
},
applyHover: function () {
this.config.logo.hover(function () {
$(this).addClass('example');
}, function () {
$(this).removeClass('example');
});
}
};
And then call a .basicExample().applyHover() on document ready.
FIDDLE EXAMPLE

You have a comma at the end of the config.
config : {
logo : $('#logo'),
footer : $('footer'),
},
Should be:
config : {
logo : $('#logo'),
footer : $('footer')
},

You can do it like this:
var EXAMPLE = {
basicExample : {
config : {
logo : $('#logo')
}
}
}
EXAMPLE.basicExample.config.logo.hover(function () {
$(this).addClass('example');
}, function () {
$(this).removeClass('example');
});
JsFiddle
Or you can do what Artyom suggested.

EXAMPLE.basicExample is a function this is wrapping your config parameter. That is why it is not available to EXAMPLE.config. If you want the function EXAMPLE.basicEXAMPLE to define config as an element of EXAMPLE then do this:
EXAMPLE = {
basicExample : function () {
EXAMPLE.config = {
logo : $('#logo'),
footer : $('footer'),
},
EXAMPLE.config.logo.hover(function () {
$(this).addClass('example');
}, function () {
$(this).removeClass('example');
});
}
}

Related

Calling function inside another function globally Vanilla JS

Good evening community, I would like you to help me with this logic problem about the functions in vanilla JS.
There is a global function, inside this i made several functions, I would like to know how to access each one independently of the input order.
I have created an example, am I following the right way?
var FEGlobal = {
FEHomepage: {
Init: function () {
this.Cursor();
},
Cursor: function () {
mouseOver();
mouseOut();
},
},
FEMedia: {
Init: function () {
this.MouseOver();
this.MouseOut();
},
MouseOver: function () {},
MouseOut: function () {},
},
BEGlobal: { Init: function () {} },
};
My idea is to make a custom mouseOver / mouseOut functions, what i need to use before they are defined. So in the Cursor function () i wish to call them inside that funcion.
Cursor: function () {
const projectOriginal = document.querySelectorAll("#project__original");
projectOriginal.forEach((element) => {
element.addEventListener("mouseover", function mouseOver() {}, false);
element.addEventListener("mouseout", function mouseOut() {}, false);
});
}

Polymer this and Cytoscape this

So I have a problem and it's most likely because I still don't get JavaScript... Cytoscape has their own 'this' and Polymer has their 'this'
<div id="labelFld">{{node.label}}</div>
<div id="measureFld">{{node.measure}}</div>
<div id="timesignatureFld">{{node.time_signature}}</div>
<div id="voiceFld">{{node.voice}}</div>
<div id="beatFld">{{node.beat}}</div>
<div id="meventFld">{{node.event}}</div>
var cy;
cytoscape({
ready : function () {
Polymer: ({
...
properties : {
node : {
type : Object,
notify : true,
readOnly : true
}
},
...
// Fires when the local DOM has been fully prepared
ready : function () {
var self_node = this.node; // <- 'this' via Polymer
try {
cy = cytoscape({
container : this.$.rhythmgraph,
ready : function (e) {}
});
} catch (err) {
console.log(err);
}
// Assign handler to Cytoscape click event for node elements
cy.on('click', 'node', {
"nodedata" : self_node // <- Seems to pass by value, not reference
}, function (e) {
self_node = this.data(); // <- 'this' via Cytoscape
console.log(self_node);
// e.data.nodedata = this.data();
});
},
But in order to update my <div>{{node.label}}</div> I have to be able to do this.node.label = "N42" // Polymer but I can't do it in the cy.on('click','node', ... ) because I need this.data() // Cytoscape inside there.
Scope is really killing me on this.
EDIT
In the end, I created an Observer to watch and update:
self_node = this.selectedNode;
var poly = this;
Object.observe(self_node, function(changes) {
changes.forEach(function(change) {
if(change.type == "update") {
poly.selectedNode = {
"id": change.object.id,
... }
};
poly.notifyPath('selectedNode.id', change.object.id);
}
});}.bind(poly));
I find this a common gotcha among JS dev beginners. You'll have to bind the function to its proper this reference.
cy.on('click', 'node', {
"nodedata" : rhynode
}, function (e) {
e.data.nodedata = this.data();
console.log(e.data.nodedata);
}.bind(this)); // here
With ES2015, arrow functions would bind automatically to the proper this:
cy.on('click', 'node', {
"nodedata" : rhynode
}, (e) => {
e.data.nodedata = this.data();
console.log(e.data.nodedata);
});

Javascript functions in custom namespaces

It is possible to declare 2 more functions in main function like this ?
var jquery4u = {
init: function() {
jquery4u.countdown.show();
},
countdown: function() {
show: function() {
console.log('show');
},
hide: function() {
console.log('hide');
}
}
}
jquery4u.init();
and i receive the following error: Uncaught SyntaxError: Unexpected token ( on this line "show: function() {"
Remove the function from the right of the countdown (demo)
var jquery4u = {
init: function() {
jquery4u.countdown.show();
},
countdown: {
show: function() {
console.log('show');
},
hide: function() {
console.log('hide');
}
}
}
jquery4u.init();
Next time, use jsFiddle to make a demo and click the "JSHint" button.
Actually, none of this will work. Unless you make countdown an object or you treat its sub-functions as proper functions.
Why: Under countdown, you created an instance of object not a function.
var jquery4u = {
countdown: function() {
show = function() {
console.log('show');
}
hide = function() {
console.log('hide');
}
jquery4u.countdown.show();
}
}
The above code is a valid code so it is possible. Unfortunately it will not return anything.
The proper way to do this is in this format:
var jquery4u = {
countdown: {
show: function() {
console.log('show');
},
hide: function() {
console.log('hide');
}
}
}
This will work. You can try it out by calling:
jquery4u.countdown.show();

Creating a jQuery container to hold other functions

I am trying to create a simple class or a container to hold few JavaScript methods as shown below.
var Core = (function () {
var Error = {
alert: function() {
alert('Error => alert called');
},
display: function() {
alert('Error => display called');
}
};
var ajax = {
view: function(){
alert('Ajax => view called');
},
update: function(){
alert('Ajax => update called');
}
};
var call = function(){
Error.alert();
Error.display();
ajax.view();
ajax.update();
};
$(document).ready(function(){
call(); // This works fine.
}());
But for some reason I am not able to call these methods outside the container. For instance calling functions as shown below throws error.
$(document).ready(function(){
Core.Error.alert(); // This doesn't work.
Core.Call(); // This doesn't work.
});
Error: Uncaught TypeError: Cannot read property 'Error' of undefined
I can call the functions from within the container. I am new to the concept of jQuery plugins and would appreciate if someone can help me with this.
You can export these methods (read more about Module Pattern), like so
var Core = (function () {
...
return {
Error: Error,
Ajax: ajax,
Call: call
};
})();
Core.Error.alert();
Core.Call();
Example
Change it in:
var Core = {
error: {
alert: function () {
alert('Error => alert called');
},
display: function () {
alert('Error => display called');
}
},
ajax: {
view: function () {
alert('Ajax => view called');
},
update: function () {
alert('Ajax => update called');
}
},
call: function () {
Core.error.alert();
Core.error.display();
Core.ajax.view();
Core.ajax.update();
}
}
$(document).ready(function () {
Core.call(); // This works
}());
Working fiddle

How can i call that function inside that anonymous javascript? (TinyMce example)

How can i call test() inside that method? It's possible?
(function() {
tinymce.create('tinymce.plugins.WrImagerPlugin', {
init : function(editor, url) {
editor.addCommand('mceWrImagerLink', function() {
//--> how can i refer to test() here?
});
},
test: function () {alert('test');}
}
});
tinymce.PluginManager.add('wr_imager', tinymce.plugins.WrImagerPlugin);
})();
You can make test a regular function and assign it to the object, like this:
(function() {
function test() { alert('test'); }
tinymce.create('tinymce.plugins.WrImagerPlugin', {
init : function(editor, url) {
editor.addCommand('mceWrImagerLink', function() {
test();
});
},
test: test
});
tinymce.PluginManager.add('wr_imager', tinymce.plugins.WrImagerPlugin);
})();
Alternatively, you can keep a reference to the object:
(function() {
var wrImaergPlugin = {
init : function(editor, url) {
editor.addCommand('mceWrImagerLink', function() {
wrImagerPlugin.test();
});
},
test: function() { alert('test'); }
}
tinymce.create('tinymce.plugins.WrImagerPlugin', wrImagerPlugin);
tinymce.PluginManager.add('wr_imager', tinymce.plugins.WrImagerPlugin);
})();
Finally, in this specific case, you should be able to simply call tinymce.plugins.WrImagerPlugin.test().
You can also keep a reference to this in the init method that will be available in the addCommand closure:
(function() {
tinymce.create('tinymce.plugins.WrImagerPlugin', {
init : function(editor, url) {
var me = this;
editor.addCommand('mceWrImagerLink', function() {
//--> how can i refer to test() here?
me.test();
});
},
test: function () {alert('test');}
}
});
tinymce.PluginManager.add('wr_imager', tinymce.plugins.WrImagerPlugin);
})();

Categories

Resources