How to get the "this" from parent function - javascript

I am building a simple tab system with angularjs, but I'm having trouble referring to this in the parent function. I know I might be misunderstanding some fundamentals, so please educate me:
js:
$scope.tabs = {
_this: this, // doesn't work
open: function(elem) {
$scope.tabsOpen = true;
if(elem)
$scope[elem] = true;
},
close: function() {
$scope.tabsOpen = false;
},
about: {
open: function() {
$scope.aboutOpen = true;
_this.notification.close(); // doesn't work
$scope.tabs.notification.close(); // works
},
close: function() {
$scope.aboutOpen = false;
}
},
notification: {
open: function() {/*etc*/},
close: function() {/*etc*/}
},
message: {
open: function() {/*etc*/},
close: function() {/*etc*/}
},
}

How about:-
$scope.tabs = getTab();
function getTab(){
var tab = {
open: function(elem) {
$scope.tabsOpen = true;
if(elem)
$scope[elem] = true;
},
close: function() {
$scope.tabsOpen = false;
},
about: {
open: function() {
$scope.aboutOpen = true;
tab.notification.close(); // Should work
},
close: function() {
$scope.aboutOpen = false;
}
},
notification: {
open: function() {/*etc*/},
close: function() {/*etc*/}
},
message: {
open: function() {/*etc*/},
close: function() {/*etc*/}
},
}
return tab ;
}
This way you don't rely on what this context would be which is anyways determined by the execution context, not where it is defined. Here you are just using a local tab object created in the local scope while calling the function getTab and instead of doing _this.notification.close(); you can just do tab.notification.close();, where tab is really the this that you are looking for there. A simple Demo

Related

Odoo V12 JavaScript Framework

I have an issue with Odoo V12 Javascript Framework.
I don't know whather the javascript is loaded or there is another issue:
odoo.define('titi.Home',['web.core','web.Dialog','web.Class'], function(require) {
"use strict";
var core = require('web.core'),
Dialog = require('web.Dialog'),
Class = require('web.Class');
var TitiHouse = Dialog.extend({
template: 'titi.her_house_name',
events: {
'click a#titi_s_house_name a': '_onClick',
},
init: function(parent, params) {
var self = this;
var options = _.extend({
size: 'large',
buttons: [{
text: params.titi_s_house_name,
click: self._onClick,
classes: 'btn-secondary',
}],
}, params || {});
self._super(parent, options);
},
_onClick: function(event) {},
willStart: function() {
console.log('Will start .....');
},
start: function() {
console.log('Start !!!');
},
});
return TitiHouse;
});
When can I execute this javascript file in template?
Or how to execute that script in template?
There are a couple of things that could be contributing to the problem:
1 - You are not calling the super methods of the Dialog widget in willStart or start. Try making these:
...
willStart: function() {
console.log('Will start .....');
return this._super.apply(this, arguments);
},
start: function() {
console.log('Start !!!');
return this._super.apply(this, arguments);
},
...
2 - You are not extending the events, you are overridding them. You need to make your events param:
events: _.extend({}, Dialog.prototype.events, {
'click a#titi_s_house_name a': '_onClick',
}),
Try changing these and see if it helps.

Overriding JS function

this is an original function from Framework I'm working with. It's a Python-based framework with a little bit Javascript. and as I do not really know much about JS I want to ask a question.
How can I override init: function (parent, options) part.
in that function, I need to change just one thing.
line 57
link
display_order: ORDER.ASC to ORDER.DESC
so i need somehow to call this functions in super and change arguments
var Thread = Widget.extend({
className: 'o_mail_thread',
events: {
"click a": "on_click_redirect",
"click img": "on_click_redirect",
"click strong": "on_click_redirect",
"click .o_thread_show_more": "on_click_show_more",
"click .o_thread_message_needaction": function (event) {
var message_id = $(event.currentTarget).data('message-id');
this.trigger("mark_as_read", message_id);
},
"click .o_thread_message_star": function (event) {
var message_id = $(event.currentTarget).data('message-id');
this.trigger("toggle_star_status", message_id);
},
"click .o_thread_message_reply": function (event) {
this.selected_id = $(event.currentTarget).data('message-id');
this.$('.o_thread_message').removeClass('o_thread_selected_message');
this.$('.o_thread_message[data-message-id=' + this.selected_id + ']')
.addClass('o_thread_selected_message');
this.trigger('select_message', this.selected_id);
event.stopPropagation();
},
"click .oe_mail_expand": function (event) {
event.preventDefault();
var $message = $(event.currentTarget).parents('.o_thread_message');
$message.addClass('o_message_expanded');
this.expanded_msg_ids.push($message.data('message-id'));
},
"click .o_thread_message": function (event) {
$(event.currentTarget).toggleClass('o_thread_selected_message');
},
"click": function () {
if (this.selected_id) {
this.unselect();
this.trigger('unselect_message');
}
},
},
init: function (parent, options) {
this._super.apply(this, arguments);
this.options = _.defaults(options || {}, {
display_order: ORDER.ASC,
display_needactions: true,
display_stars: true,
display_document_link: true,
display_avatar: true,
shorten_messages: true,
squash_close_messages: true,
display_reply_icon: false,
});
this.expanded_msg_ids = [];
this.selected_id = null;
},
If you're unable or not interested in changing the source code, you can pass
{display_order: ORDER.DESC} as the options parameter when creating this class.

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();

return true for click event and continue

Hi I have a popup window control what I'm trying todo is get it to continue the click event if the user chooses the yes button. How do you continue the click event for the 'yes' button, I'm trying to make it return true but it doesn't continue for the click it just return false.
<script type="text/javascript">
$(document).ready(function() {
$('.delete-question').click(function(e) {
ret = false;
_this = this;
$('#pop-up-1').popUpWindow({
modal: true,
blurClass: '.main-container',
action: "open",
buttons: [{
text: "Yes",
click: function () {
this.close();
ret = true;
}
}, {
text: "No",
click: function () {
this.close();
}
}]
});
return ret;
})
});
</script>
You can't do it directly, but you can emit the click event once it is needed, e.g. something like this (not tested):
<script type="text/javascript">
// global flag to track the popup state
var popupReturn = false;
$(document).ready(function() {
$('.delete-question').click(function(e) {
// when true (after Yes click only) go on returning true
if (popupReturn) {
popupReturn = false;
return true;
}
else {
_this = this;
$('#pop-up-1').popUpWindow({
modal: true,
blurClass: '.main-container',
action: "open",
buttons: [{
text: "Yes",
click: function () {
// set global flag to true
popupReturn = true;
// emit click event where it knows that popupReturn is true
$(_this).click();
this.close();
}
}, {
text: "No",
click: function () {
this.close();
}
}]
});
return false;
}
})
});
</script>
You can't return from asynchronous event like in your case, because your "modal" is not really modal in sense that it doesn't pause code execution until use clicks a button.
This is where callback come handy. I would wrap the modal code into helper plugin and use it like this:
$.fn.confirmable = function(options) {
options = $.extend({
close: $.noop,
dismiss: $.noop
}, options);
this.each(function() {
$(this).popUpWindow({
modal: true,
blurClass: '.main-container',
action: "open",
buttons: [{
text: "Yes",
click: function() {
this.close();
options.close();
}
}, {
text: "No",
click: function() {
this.close();
options.dismiss();
}
}]
});
});
};
$('.delete-question').confirmable({
close: function() {
// ok pressed do something
},
dismiss: function() {
// cancel pressed
}
});
It means that your workflow needs to transform to asynchronous callback/promise-based.

Working with React TransitionGroups

I'm trying to get a simple "drawer" component working to test React's TransitionGroups. What I have so far below and on JSBin. If you try to run it, it works but I'm getting the error:
Uncaught TypeError: Cannot read property 'componentWillLeave' of undefined
What am I doing wrong here?
var DrawerInner = React.createClass({
componentWillEnter: function(cb) {
var $el = $(this.getDOMNode());
var height = $el[0].scrollHeight;
$el.stop(true).height(0).animate({height:height}, 200, cb);
},
componentWillLeave: function(cb) {
var $el = $(this.getDOMNode());
$el.stop(true).animate({height:0}, 200, cb);
},
render: function() {
return <div className="drawer" ref="drawer">{this.props.children}</div>;
}
});
var Drawer = React.createClass({
getInitialState: function() {
return {
open: false
};
},
componentWillMount: function() {
this.setState({
open: this.props.open
});
},
componentWillReceiveProps: function(props) {
this.setState({
open: props.open
});
},
open: function() {
this.setState({
open: true
});
},
close: function() {
this.setState({
open: false
});
},
toggle: function() {
this.setState({
open: !this.state.open
});
},
render: function() {
return (
<ReactTransitionGroup transitionName="test" component={React.DOM.div}>
{this.state.open && <DrawerInner key="content">{this.props.children}</DrawerInner>}
</ReactTransitionGroup>
);
}
});
Looks like this is a bug in ReactTransitionGroup. I've just put up a fix ReactTransitionGroup: Fix moving from falsey child.

Categories

Resources