I'm trying to extend the widget's init method to make a simple console.log when the page is loaded, but it doesn't work, what can be a correct way to do this?
odoo.define('lliege_pdt_main.pdt_maps', function (require) {
var Widget = require('web.Widget');
var pdt_maps = Widget.extend({
init: function (parent) {
console.log("test");
this._super(parent);
},
});
return pdt_maps;
});
In your case you do not want to inherit the widget in the classical sense. You want to modify the parent itself. This can be done with include instead of extend:
var pdt_maps = Widget.include({
init: function (parent) {
console.log("test");
this._super(parent);
},
});
Don't forget to debug in assets debug (gorilla) mode. Here is the official documentation on patching a JS class like this.
Related
If a function is defined inside the config object that is passed to Ext.application(), is there a way to override this function definition. Also, another point to note is that application is created inside Ext.onReady(function(){...
Here is an example
Ext.onReady(function() {
Ext.application({
name: 'TestApplication',
customFunction: function(obj) {
//Some function definition.. .. ..
}
});
launch: function() { window.appl = this; }
...
});
This code is from a js file that I can't change and I need to override the definition of customFunction from another js file that loads later in the sequence.
The only way I'm able to achieve this is using Ext.onReady in my file as well.
Ext.onReady(function() {
appl.customFunction = function (obj) {
//My own definition
}
});
Now my question is, is this a proper way to do this? Or is there a better/elegant way?
Is it OK to have multiple Ext.onReady functions in the code?
We have a JS framework that lets us set up "modules". Each module is added by calling the addModule method and passing a literal object that contains required properties about the module as well as optional methods. Example:
framework.addModule({
id: "test-module",
init: function () {
//stuff to do when initializing like set up jQuery bindings
$("div").click(function () {
// need access to literal object so I can call:
something.utility1();
});
},
utility1: function () {
something.utility2();
},
utility2: function () {
// need access to literal object so I can call:
}
});
I'm trying to figure out the easiest way to make the object itself available to any code, at any level, inside the object (in place of "something").
The best I've been able to do is to add a this: this property to the object and then inside of methods I can put var module = this, which works but requires that variable to be added to each module. I'd like to see if there's another way that wouldn't require adding a variable to each method. Thanks.
Thanks for the comments and, zzzzBov, thanks for your suggestions.
However, it looks like the below code will work best for my needs. The devs on my team are writing a lot of these modules and I need the solution to be clear to them. Having to call $.proxy could make it less clear. I was hoping to avoid having to put var module = this in each method, so it would be cleaner, but it seems that it's not possible without it.
framework.addModule({
id: "test-module",
init: function () {
var module = this;
$("div").click(function () {
module.utility1();
});
},
utility1: function () {
var module = this;
module.utility2();
},
utility2: function () {
}
});
If anyone has a cleaner solution, let me know.
jQuery has a proxy method which will bind the function to a specific context. This would turn your event binding into:
$('div').click($.proxy(this, 'utility1'));
Alternatively, instead of using an object literal to instantiate the module object, you could instantiate an anonymous function:
framework.addModule(new function () {
this.id = 'test-module';
this.init = function () {
$('div').click($.proxy(this, 'utility1'));
};
this.utility1 = function () {
...more code...
};
this.utility2 = this.utility1;
});
I am starting to play with require js / modular development for the first time and am liking what I see.
What I am trying to achieve is basically only load certain custom jQ modules when needed. My main goal is page performance. At present I am only loading require.js (which in turns loads jQ async) then other jQ code/plugins only fire on user interaction.
Would the following code be considered good/bad practice? Is there anything anyone would change? (super basic example below)
MAIN.JS
require.config({
paths: {
"jquery": "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min"
}
});
require(["jquery"], function($) {
// overlay plugin
$("a").on("click", function(e){
var self = this;
require(["overlay"], function (overlay) {
overlay.init(self);
});
e.preventDefault();
});
});
OVERLAY.JS
define(function () {
return {
init: function(self) {
$.ajax({
url: self.href,
success: function (data) {
$("#results").html($(data).filter('#details').html());
},
dataType: 'html'
});
$('#results').fadeIn();
}
}
});
Cheers,
Adi.
Your method of loading overlay is a correct use of require, however a couple of things:
Overlay.js should list jQuery as a dependency. Ensure your modules have all the code they need to run. In this case it's fine (as you're grabbing jQuery in the require) but say you used document.addEventListener to attach your click then you're no longer sure jQuery will be available for use by the $.ajax. It's nice to know your modules ask for everything they need rather than getting it by luck.
One rule I try to follow is to keep all my DOM related stuff in main. So for example:
Overlay
// Example code, and not complete
define(function(require) {
var $ = require('jquery');
return {
init: function(elements) {
this.trigger = $(elements.trigger);
this.target = $(elements.target);
this.trigger.on('click', this.someEvent.bind(this));
},
someEvent: function() {
this.getAjax();
}
}
});
And then in main.js just pass in the DOM elements
require(['overlay'], function(overlay) {
overlay.init({
trigger: 'a',
target: '#results'
})
});
Keeping the DOM elements separate and in one place makes updating them breeze. You could also pass in an options object for other things (such as class names) much like a jQuery plugin does.
Finally, in your example code your $('#results').fadeIn(); is outside the success callback and would run immediately.
I'm writing a browser extension for a site that uses Backbone.js. Its pertinent code looks like the following (names have been changed to protect the innocent):
var BigContainer = BigContainer || {};
(function($, exports) {
var Thing = Backbone.View.extend({
...
useful_func: function() {
// Does something I need to call
},
...
});
(function($, exports) {
BigContainer.BaseView = Backbone.View.extend({
...
render: function() {
this.local_thing = new Thing({
el: '.local_thing'
});
}
...
});
I am also inserting some code in a <script> block to listen for postMessage() calls I make from my extension's injected javascript file. I would like to be able to call useful_func from there, but can't figure out how, or if I'm even supposed to (and if not, then how I can arrive at the same result).
As an example, I've tried the following references, all of which show up as undefined:
BigContainer.BaseView.$local_thing
BigContainer.BaseView.local_thing
Thing
document.getElementsByClassName('local_thing')[0].useful_func
Importantly, since I'm writing an extension for a site I don't own, I can't modify the site's Backbone.js code to help myself out. I need to work with what's there.
With the line BigContainer.BaseView = Backbone.View.extend({, you are defining a new View type called BaseView, but it is only the definition. What you need is the actual instance of the view in your code. That would be somewhere where you do new BaseView (in this case, it's the following:)
// Where view is created
(function($, undefined) {
BigContainer.OtherThing = {
...
create: function(config, params) {
this.view = new BigContainer.BaseView(...);
}
...
})
With that found, you would do something like this:
// Your code, reach into that instance and its subview, and call 'usefulFunc'.
BigContainer.OtherThing.view.local_thing.useful_func();
I've been reading alot about the advantages of using the jQuery.Widget Factory for my plugins. One of the capabilities touted is how the jQuery.widget creates a namespeace for your widget. This is attractive, as I can maintain my current namespacing (naturally) within the jQuery context.
THE PROBLEM:
I keep getting "$(".myWidget").namespace.newWay is not a function" error.
For the following element...
<div class="myWidget"></div>
THIS EXAMPLES CODE WORKS:
While nice...this is NOT what I am trying to achieve...as I still want my namespace to be honored.
var workingVersion = {
_init: function () { /* Do Something*/ }
};
$.widget("ui.workingVersion", workingVersion);
$(document).ready(function () {
$('.myWidget').workingVersion();
});
HOWEVER, MY CODE FAILS:
var namespace = namespace || { };
;namespace.newWay = (function ($, window, document, undefined) {
return function (options) {
var self = this;
this._create = function () {
// Do something
},
this._init = function() {
// Do something
},
this.publicFunction = function () {
// Do something
};
};
})(jQuery, window, document);
$(document).ready(function () {
$.widget("ui.namespace.newWay", namespace.newWay); //<-- Namespace does get appended
$('.myWidget').namespace.newWay({ type: 'testing' }); //<-- But still fails here
});
MY QUESTION IS:
Why does it fail?
RELATED READING:
Understanding jQuery UI widgets: A tutorial
Tips for Developing jQuery UI 1.8 Widgets
This answer comes a bit late, maybe, but I was struggling with the same thing and had to do some reading.
$() in General
The $() instance is a no-namespace shortcut list to different functions spread out over different namespaces. You can add more functions to this shortcut list by writing:
$.fn.myFunction = function() {
...
};
Which then will be accessed by calling
$("...").myFunction();
If you add two functions by the same name the latter one will overwrite the first one.
Widgets
When you create a widget with a namespace it's created with it's namespace, as you would expect, but to $() it's added without it's namespace, as a simplified shortcut to your real widget-with-shortcut. This is done using $.widget.bridge(). You can therefore create your own namespaced link to $() by writing like this:
$.widget.bridge("namespace_myFunction", $.namespace.myFunction );
And then access your widget like this:
$("#myDiv").namespace_myFunction();
To use a widget directly with it's original namespace you can instead invoke it like this:
$.namespace.myWidget(
{
option1: "",
option2: ""
},
$("#div")
);
Hope this will clarify a little...