Call function inside RequireJS - javascript

Is it possible to create an object inside RequireJS?
Because, in this way, FunctionA is visible inside the Click event:
require(["library1", "library2"], function (obj1) {
$('#loginButton').click(function () {
functionA();
});
functionA() {
obj1.value;
}
});
But if i do something like this, it doesn't work:
var library = new library();
require(["library1", "library2"], function (obj1) {
$('#loginButton').click(function () {
library.functionA();
});
});
function library() {
this.functionA = function () {
obj1.value;
}
}
or
var library = new library();
$('#loginButton').click(function () {
library.functionA();
});
functionA() {
require(["library1", "library2"], function (obj1) {
this.functionA = function () {
obj1.value;
}
});
}
Is this possible?

I'm not sure why your explicit example is not working. However, I would suggest ensuring that you make jQuery a dependency in your require statement.
The following is using dojo, which uses an AMD environment like RequireJS. I just wanted to make sure that I was able to load multiple modules for my example and RequireJS has not modules with it like dojo does.
I was able to get your second example working by fixing the dependencies.
var library = new library();
require(["dojo/dom", "jquery"], function(dom, $) {
$('#button').click(function() {
library.functionA();
});
});
function library() {
this.functionA = function() {
console.log("hello");
}
}
<script>
var dojoConfig = {
parseOnLoad: false,
isDebug: true,
async: 1,
packages: [{
name: "jquery",
location: "//code.jquery.com",
main: "jquery-1.11.3.min"
}]
};
</script>
<!-- Include the dojo 1.10.4 CDN -->
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
<main>
<button id="button" type="button">Click me</button>
</main>

Related

Javascript cannot call THIS in code

I'm am using module js syntax and I have some code like this:
var myModule = {
settings: {
myage: 25
},
init: function() {
//init code here
},
someFunction1: function(param1) {
//function code here
},
someFunction2: function() {
myModule.someFunction1(myparam);
}
}
The above will work fine but if I tried:
someFunction2: function() {
this.someFunction1(myparam);
}
It will not find the function.
Can't I use this.someFunction1... ?
this is who called the function.
myModule.someFunction2() will have this=myModule
someFunction2 = myModule.someFunction2; someFunction2() will have this=window
(you didn't show how you're calling it though)

CollapseSidebar is not a function

I am writing a script for a project, it has a function to collapse or open the sidebar on click on hamdurger icon but when I click it gives me error
TypeError: this.CollapseSidebar is not a function
The following is my code:
(function($) {
'use strict';
var Prtm = {
Constants: {
LEFTMARGIN:'315px',
COLLAPSELEFTMARGIN: '63px',
},
PrtmEle:{
BODY: $('body'),
SIDEBAR: $('.prtm-sidebar'),
SIDENAV: $('.sidebar-nav'),
MAIN: $('.prtm-main'),
HEADER: $('.prtm-header'),
CONTENTWRAP: $('.prtm-content-wrapper'),
CONTENT: $('.prtm-content'),
PRTMBLOCK: $('.prtm-block'),
FOOTER: $('.prtm-footer'),
HAMBURGER: $('.prtm-bars'),
},
Init:function(){
this.BindEvents();
},
BindEvents:function(){
this.PrtmEle.BODY.on('click',this.PrtmEle.HAMBURGER,function(){
this.CollapseSidebar();
});
},
CollapseSidebar: function(){
this.PrtmEle.HAMBURGER.toggleClass("prtm-sidebar-closed is-active");
this.PrtmEle.BODY.toggleClass("prtm-sidebar-closed is-active");
this.PrtmEle.SIDEBAR.toggleClass('collapse');
},
};
Prtm.Init();
})(jQuery);
When I change this.CollapseSidebar to Prtm.CollapseSidebar it works properly. What I am doing wrong here and how it can be resolved?
Why it do not work? Because a function() binds its own this.
One thing you can do is to use Arrow function which do not bind its own this - like this:
BindEvents:function(){
this.PrtmEle.BODY.on('click',this.PrtmEle.HAMBURGER,() => {
this.CollapseSidebar();
});
}
Inside you click function this will refer to the window - so either you can create a temporary variable like the below or use the arrow function:
BindEvents:function() {
let $this = this;
this.PrtmEle.BODY.on('click',this.PrtmEle.HAMBURGER,function() {
$this.CollapseSidebar();
});
}

Vue.js: Passing anonymous functions in props object

I'm trying to extend the select2 example to be more practically useful. So far I've added multiselect functionality, and trying to allow custom select2 configuration.
https://jsfiddle.net/5ytm3LL6/
It appears that function properties of props objects are being stripped when handed to component.
What is a solution for a parent to give widget component configuration with js functions?
I'm somewhat confused, because the embedded version actually shows params being transferred properly in the built-in console output, while jsfiddle browser console output does not. However, both versions do not pass the functions to select2 widget.
Vue.component('select2', {
props: ['options', 'value', 'params'],
template: '<select><slot></slot></select>',
mounted: function () {
var vm = this, params = $.extend({}, this.params || {});
console.log(this.params, params);
params.data = this.options;
$(this.$el).val(this.value).select2(params).on('change', function () {
vm.$emit('input', $(vm.$el).val());
});
},
watch: {
value: function (value) {
var $el = $(this.$el);
if (!_.isEqual($el.val(), value)) {
$el.select2('val', value);
}
},
options: function (options) {
$(this.$el).select2({ data: options });
}
},
destroyed: function () { $(this.$el).off().select2('destroy'); }
});
new Vue({
el:'#app',
data: function () {
return {
value: 'a',
options: [{id:'a', label:'A'}, {id:'b', label:'B'}],
params: {
test: 'TEST',
formatSelection: function (item) {return item.label;},
formatResult: function (item) {return item.label;}
}
};
}
});
<link rel="stylesheet" type="text/css" href="https://unpkg.com/select2/dist/css/select2.css"></style>
<script src="https://unpkg.com/lodash"></script>
<script src="https://unpkg.com/jquery"></script>
<script src="https://unpkg.com/select2"></script>
<script src="https://unpkg.com/vue"></script>
<div id="app">
<select2 v-model="value" :options="options" :params="params"></select2>
</div>
I see js functions you have passed being printed in console log. I have updated your fiddle and put following logs in select2 compoent:
console.log(params.formatResult);
console.log(params.formatSelection);
Which prints following:
function (item) {return item.label;}
function (item) {return item.label;}

How to have both observer and on init for ember js properties

New ember rules states that we need to use the below pattern
propObserver: Ember.observer(function () {
//code
})
instead of
propObserver: function() {
//code
}.observers('someProp')
Before updating ember we could do the below
propObserver: function () {
//code
}.observes('someProp').on('init')
How to achieve this cascading?
Now i know we can do this separately
propObserver: Ember.observer('someProp', function () {
//code
})
propObserver: Ember.on('init', function () {
//code
})
From the 2.0.0 docs: http://guides.emberjs.com/v2.0.0/object-model/observers/#toc_observers-and-object-initialization
propObserver: Ember.on('init', Ember.observer('someProp', function() {
// code
}))

How to test this with Jasmine test (Behaviour Driven Development)?

I've just developed this JavaScript/Backbone module as a part of a web page I am developing. I would like to create a Jasmine test for it, but I am brand new to Jasmine, therefore I am not sure what should I be testing in this class. What should be the "skeleton" of the test? In order to avoid redundancy in tests, what parts will you test?
editdestinationview.js:
define([
'common/jqueryex',
'backbone',
'marionette',
'handlebars',
'text!education/eet/templates/editdestination.hb',
'text!common/templates/validationerror.hb',
'lang/languageinclude',
'common/i18nhelper'
], function ($, Backbone, Marionette, Handlebars, templateSource, errorTemplateSource, i18n) {
'use strict';
var errorTemplate = Handlebars.compile(errorTemplateSource),
EditDestinationView = Marionette.ItemView.extend({
initialize: function (options) {
this._destinationTypes = options.destinationTypes;
},
onRender: function () {
this.stickit();
this._bindValidation();
},
_bindValidation: function () {
Backbone.Validation.bind(this, {
valid: this._validAttributeCallback,
invalid: this._invalidAttributeCallback,
forceUpdate: true
});
},
_validAttributeCallback: function (view, attr) {
view.$('#error-message-' + attr).remove();
},
_invalidAttributeCallback: function (view, attr, error) {
view.$('#error-message-' + attr).remove();
view.$('#destinationTypes').parent('div').append(errorTemplate({
attr: attr,
error: error
}));
},
template: Handlebars.compile(templateSource),
ui: {
saveAnchor: '#ed_eetSaveDestinationAnchor',
deleteAnchor: '#ed_eetDeleteDestinationIcon'
},
triggers: {
'click #ui.saveAnchor': 'click:saveDestination',
'click #ui.deleteAnchor': 'click:deleteDestination'
},
bindings: {
'select#destinationTypes': {
observe: 'destinationTypeId',
selectOptions: {
collection: function () {
return this._destinationTypes;
},
labelPath: 'description',
valuePath: 'destinationTypeId',
defaultOption: {label: i18n.EDUCATION_EET_SELECT_INTENDED_DESTINATION, value: null}
}
}
}
});
return EditDestinationView;
});
Thanks everyone!
UPDATE:
After thinking a lot about it, I think that I should try these aspects:
-Triggers: Check if they can be clicked.
-"_validAttributeCallback" and "_invalidAttributeCallback": Check if they behave accordingly to the code.
-Template: Spy on it to check if it is performing it's mission. (Optional test)
So, the test skeleton will be:
define([
'education/eet/views/editdestinationview'
], function (EditDestinationView) {
describe('description...', function () {
beforeEach(function () {
//EditDestinationView.triggers
});
describe('blablabla', function () {
beforeEach(function () {
// ...
});
it('blablabla', function () {
// blablabla
});
});
});
});
Any help on how to test this please?
One common pattern is to use two describe statements, one for the class and one for the method being tested, and then an it statement for each thing you want to test about that method. The rspec people have a convention (which I use in my JS tests) of using a '#' on the method describe for an instance method, and a "." for a describe of a static method.
Now, if you adopt all of the above, and you want to test (for instance) that your View's click-handling method triggers a certain event on the View's Model, it would look something like this:
define([
'education/eet/views/editdestinationview'
], function (EditDestinationView) {
describe('EditDestinationView', function () {
var view;
beforeEach(function () {
// do setup work that applies to all EditDestinationView tests
view = new EditDestinationView({model: new Backbone.Model()});
});
describe('#handleClick', function () {
beforeEach(function () {
// do setup work that applies only to handleClick tests
});
it('triggers a foo event', function () {
var wasTriggered;
view.model.on('foo', function() {
wasTriggered = true;
});
view.handleClick();
expect(wasTriggered).toBe(true);
});
});
});
});
P.S. Instead of creating a fake "foo" handler like I did, most people use a mocking library like Sinon. Using that library our "it" statement could instead be:
it('triggers a foo event', function () {
var triggerStub = sinon.stub(view.model, 'trigger');
view.handleClick();
expect(triggerStub.calledOnce).toBe(true);
expect(triggerStub.args[0][0]).toBe('foo');
//NOTE: args[0][0] == first arg of first call
});

Categories