Ext JS Hash Map not being destroyed after window closes - javascript

Basically just want to create a new hashmap once the window is closed because it currently will still have the old values after closing and rendering a new window.
data: {
classCheck: false,
hashTable: new Ext.util.HashMap(),
countValid: 0
}
listeners: {
afterrender: function() {
var scope = this;
window.addEventListener('resize', function() {
scope.updateWindow(scope);
});
this.on('close', function(scope) {
this.getViewModel().data.hashTable = new Ext.util.HashMap();
window.removeEventListener('resize', scope.updateWindow);
});
},
},
renderer: function(value, cell_field1, cell_field2, cell_field3) {
var hashmap = this.up('classroom').getViewModel().data.hashTable;

JavaScript uses prototyping to implement class inheritance. The windows are instances of a window class, and due to the nature of prototyping the window instances reference the properties defined on the class until an instance explicitly sets them.
Ext.define('Fiddle.Class', {
boolean: true,
object: {},
constructor: function() {
/* 1. Instance Prototype
{ {
boolean: true,
object: {}
} }
*/
this.boolean = false;
this.object.key = false;
this.object = {};
/* 2. Instance Prototype
{ {
boolean: false, boolean: true,
object: { key: true } object: { key: false },
instance: null
} }
*/
// This returns true.
return this.object.key;
}
});
Therefore, the window instances need to set the values of properties that are objects or arrays during initialization, so that each instance gets its own copy. This can be defined on the class, and it is usually done in the constructor so that the data is available as early as possible.
Ext.define('Fiddle.window.Window', {
extend: 'Ext.window.Window',
data: null,
constructor: function(config) {
this.data = {
classCheck: false,
hashTable: new Ext.util.HashMap(),
countValid: 0
};
this.callParent(arguments);
}
});

Related

Using getter and setter on an object property that has his own properties

I'm fairly new to getters and setters and am looking for a way to listen for changes in an object to store the data immediately, without calling a Save() function everytime a value gets changed. This is how I do it right now:
var myObject = {
Data: {
enabled: true,
show: false
},
Save: function () {
//store myObject.Data to local storage
},
Load: function () {
//load data from local storage and assign it to myObject.Data
},
doSomething: function () {
myObject.Load();
if (myObject.Data.enabled) {
myObject.Data.show = true;
myObject.Save();
}
}
Now I would like to optimize this code so everytime a property in myObject.Data is changed, myObject.Save() is executed. The problem I'm experiencing is that it seems only possible to define a getter for a property that has just one value, but not for a property that is an object itself.
var myObj = {
_Data: {
a: 0,
b: 1,
c: 3
},
set Data (a) {
console.log(a);
}
};
myObj.Data.a = 2;
This obviously doesn't work since myObj.Data is not an object and doesn't have the same properties as myObj._Data.
Thanks in advance for any help.
You are likely interested in the Proxy object.
I used a very simple debounce function callHandler in order to avoid calling the onSet method dozens of times during array modifications. Otherwise, [1, 2, 3].splice(0, 1) would call the set handler once per item in the original array.
'use strict';
var myObject = {
Data: {
a: [1, 2, 3],
b: {c: ['test']}
},
Save: function() {
console.log('Save called');
},
}
function recursiveProxy(target, onSet) {
// For performance reasons, onSet will only be called one millesecond
// after the set handler has last been called.
var timeout;
function callHandler() {
clearTimeout(timeout);
timeout = setTimeout(onSet, 1);
}
var recursiveHandler = {
get: function(target, property) {
// If the property is something that could contain another object,
// we want to proxy it's properties as well.
if (typeof target[property] == 'object' && target[property] != null) {
return new Proxy(target[property], recursiveHandler);
}
return target[property];
},
set: function(target, property, value) {
console.log('Set called - queueing onSet');
callHandler();
target[property] = value;
return true;
}
}
return new Proxy(target, recursiveHandler);
}
myObject.Data = recursiveProxy(myObject.Data, myObject.Save);
myObject.Data.a.splice(0, 1);
myObject.Data.b.c[0] = 'test 2';
I believe you are looking for Defining a getter on existing objects using defineProperty
To append a getter to an existing object later at any time, use
Object.defineProperty().
var o = { a:0 }
Object.defineProperty(o, "b", { get: function () { return this.a + 1; } });
console.log(o.b) // Runs the getter, which yields a + 1 (which is 1)
For e.g:
var Data = {
enable: true,
show: false
};
Object.defineProperty(Data, 'doSomething', {
get: function() {
// get something;
},
set: function(something) {
// set something
}
});

Update data property / object in vue.js

is there a way I can programmatically update the data object / property in vue.js? For example, when my component loads, my data object is:
data: function () {
return {
cars: true,
}
}
And after an event is triggered, I want the data object to look like:
data: function () {
return {
cars: true,
planes: true
}
}
I tried:
<script>
module.exports = {
data: function () {
return {
cars: true
}
},
methods: {
click_me: function () {
this.set(this.planes, true);
}
},
props: []
}
</script>
But this gives me the error this.set is not a function. Can someone help?
Thanks in advance!
Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object, So you may create an object and add a new property like that:
data: function () {
return {
someObject:{
cars: true,
}
}
and add the property with the vm.$set method:
methods: {
click_me: function () {
this.$set(this.someObject, 'planes', true)
}
}
for vue 1.x use Vue.set(this.someObject, 'planes', true)
reactivity

What's the syntax to add a function other than an accessor?

I'm learning the JavaScript with Node. I like the idea of creating objects with factories, and after reading a lot on this subject, I chose to create objects with this code:
// ES6 only
'use strict';
// The base object, "object literal" syntax
let animal2 = {
// public member
animalType: 'animal',
// public method
describe() {
return `This is "${this.animalType}"`;
}
};
// factory function which serves 2 purposes:
// - encapsulation, that's where private things are declared thanks to closures
// - the "real" object creation, this prevents to use "new" which is not really Js-ish
let afc = function afc() {
// private member
let priv = "secret from afc";
return Object.create(animal2, {
// Object customisation
animalType: { value: 'animal with create'},
// object extension. The new objects created here get 3 new members:
// - a private member
// - a new property
// - a new method to access the private member
// new public member
color: { value: 'green' },
secret: {
get: function () { return priv; },
set: function (value) { priv = value; },
},
KO1() {
console.log("KO1");
},
KO2: function() {
console.log("KO2");
}
});
}
// creation of an animal instance
let tac = afc();
My problem is I can't figure out what's the syntax to add a function which can manipulate private data while not being just an accessor. I put here 2 examples which came to my mind (KOx), but as their names suggest, this syntax leads to: "KOx is not a function".
Object.create expects an object of property descriptors as its second argument. This is why you have to use {value: …} or {set: …, get: …} everywhere.
And in fact you'd have to do the same for a method - which is just a standard property with a function as its value:
…
KO3: {value: function() {
…
}},
…
However, I'd avoid using property descriptors when you don't need them. Object.assign is a better fit:
return Object.assign(Object.create(animal2, {
secret: {
get() { return priv; },
set(value) { priv = value; },
}
}), {
animalType: 'animal with create',
color: 'green',
KO1() {
console.log("KO1");
},
KO2: function() {
console.log("KO2");
}
});
Why don't just use the getter syntax?
return {
__proto__: animal2, // To be honest __proto__ is not a good thing to use
animalType: 'animal with create',
color: 'green',
get secret() { return priv; },
set secret(value) { priv = value; },
get KO3() { console.log("KO3"); },
// or just the following, if you would like it to be a regular member function
// KO3() { console.log("KO3"); },
};
Or without explicit __proto__:
const result = {
animalType: 'animal with create',
color: 'green',
get secret() { return priv; },
set secret(value) { priv = value; },
get KO3() { console.log("KO3"); },
};
Object.setPrototypeOf(result, animal2);
return result;

Is it possible to create read only members in JavaScript Object Literal Notation?

I have following JavaScript Object Literal Notiation object
var Parameters= {
modal_window:{
backdrop:true,
keyboard:true,
show:true,
remote:false,
type:{
normal:function(){
this.footer.button.accept.type='btn btn-primary';
this.header.type='modal-header';
},
success:function(){
this.footer.button.accept.type='btn btn-success';
this.header.type='modal-header alert alert-success';
},
info:function(){
this.footer.button.accept.type='btn btn-info';
this.header.type='modal-header alert alert-info';
},
error:function(){
this.footer.button.accept.type='btn btn-danger';
this.header.type='modal-header alert alert-error';
},
warning:function(){
this.footer.button.accept.type='btn btn-warning';
this.header.type='modal-header alert';
}
}
},
header:{
title:undefined,
type:this.window.type.normal.header
},
footer:{
button:
{
accept:{
title:'Accept',
click:undefined,
type:undefined
},
cancel:{
title:'Cancel',
click:undefined
}
}
}
};
Is it possible to make header.type and footer.button.accept.type read only variables which can be changed only through window.type.normal, window.type.success and etc.?
Clarifications:
I want to make some clarifications here. My Parameters.header.type
should be read only and should have default value. And when user
selects for example Parameters.modal_window.type.normal
Parameters.header.type must be changed.
Despite what everyone says, you can create read-only properties in modern browsers that supports Object.defineProperty.
var obj = {};
Object.defineProperty(obj, 'someProp', {
configurable: false,
writable: false,
value: 'initial value'
});
obj.someProp = 'some other value';
console.log(obj.someProp); //initial value
EDIT:
After reading your question again, I understand that you meant true private members or private variables. That can be accomplished by making use of closures and custom getters/setters.
Note: I simplified your object's structure for the sake of the example.
var Parameters = (function () {
var headerType = 'some value'; //private variable
return {
modal_window: {
type: {
normal: function () {
//custom logic
headerType = 'some new value'; //set private variable
}
}
},
header: {
get type() { return headerType; } //define a getter only
//for older browsers, you could just define a normal function
//which you would have to access like Parameters.header.type()
//type: function () { return headerType; }
}
};
})();
var header = Parameters.header;
console.log(header.type); //some value
header.type = 'some other val';
console.log(header.type); //some value
Parameters.modal_window.type.normal();
console.log(header.type); //some new value
Now that we know it is possible to enforce true privacy, I am not sure it's really worth it. Enforcing true privacy complicates the design and reduces testability (depending on the case). An approach that is far popular as well is to simply identify private members using a naming convention such as _myPrivateVar. This clearly indicates the itention and tells the programmers that they should treat that member like a private one.
You could make them functions, like this:
header:{
title:undefined,
type: function(){
return Parameters.modal_window.type.normal.header;
}
}
You can create a property and set it as non-writable. Your constructor would have to replace the values with the properties. If the variable that the property is returning is captured in a closure and not exposed to anything else, it will be as good as read-only. If it is not changed, you don't even need a closure, just use the value configuration option.
EDIT: As per your demand,
var Properties = function(obj) {
var makePropRecursive = function(prop) {
var old_prop = obj[prop];
delete obj[prop];
var prop_obj = {};
for (var attr in old_prop) {
if (old_prop.hasOwnProperty(attr)) {
Object.defineProperty(prop_obj, attr, {
value: old_prop[attr],
writable: false,
enumerable: true
});
}
}
Object.defineProperty(obj, prop, {
value: prop_obj,
writable: false,
enumerable: true
});
};
makePropRecursive('header');
makePropRecursive('footer');
return obj;
};
var props = new Properties({
modal_window:{
backdrop:true,
keyboard:true,
show:true,
remote:false,
type:{
normal:function(){
this.footer.button.accept.type='btn btn-primary';
this.header.type='modal-header';
},
success:function(){
this.footer.button.accept.type='btn btn-success';
this.header.type='modal-header alert alert-success';
},
info:function(){
this.footer.button.accept.type='btn btn-info';
this.header.type='modal-header alert alert-info';
},
error:function(){
this.footer.button.accept.type='btn btn-danger';
this.header.type='modal-header alert alert-error';
},
warning:function(){
this.footer.button.accept.type='btn btn-warning';
this.header.type='modal-header alert';
}
}
},
header:{
title:"Whatever",
type:"Type"
},
footer:{
button:
{
accept:{
title:'Accept',
click:undefined,
type:undefined
},
cancel:{
title:'Cancel',
click:undefined
}
}
}
});
console.log(props.header);
props.header = 17;
props.header.type = 18;
props.header.title = 19;
console.log(props.header);
props.header is unchanged: output shows
Object {title: "Whatever", type: "Type"}
Object {title: "Whatever", type: "Type"}
It's 3am and the recursive function isn't, so you can only "fix" one level of one object; also, it would be better if the values were copied onto this rather than returning obj; but it should not be too hard to polish it up.
If you need to have the values changeable, you can set up a private copy of the whole object inside the constructor, then make a getter (get: function(name) { return stuff.from.the.original.object }).
If you need to support IE 8 or earlier, you could create an accessor method that retrieves the value and then use a private variable to store the actual data. If you define your methods appropriately, the private variable could be set from them, but not set by the outside world. In IE8, there is no ability to define a read-only property so you'd have to use an accessor instead.
See Crockford's treatise on private member data: http://javascript.crockford.com/private.html for details on how to set up the private data that your accessor could be an interface for.
If you're willing to require IE9 or greater, then you could use a getter via Object.defineProperty() combined with a private variable in a closure. If there was no setter, then it couldn't be set from the outside world, but methods defined within the closure (described in Crockford's article) could still set the value of the private variable. You would have a read-only property that could also be set by a few of your own methods.
How about: Object.freeze()
You can find out more here: MDN Object.freeze
So:
Object.freeze(Parameters.modal_window.header);
...
Then in your your function that you want to be able to set them, you unfreeze them, change them, and re-freeze them.
You absolutely won't be able to change the frozen objects, by mistake anywhere else in your program.
This works in IE9+ chrome, firefox, and safari.
In newer versions of JavaScript, you can define how property access works:
var yourObj = function() {
var readOnly = "cannot be changed";
return {
get readOnly() { return readOnly; },
set readOnly(v) { return; },
specialSetter: function(something) {
if (something == "magic number") {
readOnly = "oops maybe it can";
}
}
};
}();
Now code can get the value like this:
var theValue = yourObj.readOnly;
without having to make a function call. However, if it tries to change the value:
yourObj.readOnly = "hello world";
then nothing will happen.
Either the setter or any other function can, when it wants to, still update the value that'll be returned when accessing the "readOnly" property. However, any attempt to just set the property directly will do nothing (unless the setter function decides it likes the value).
edit you'd want to make "specialSetter" be read-only probably, though nothing will be able to "break in" to the closure. Also, you might want to use Object.defineProperty to make "readOnly" not be writable, but I don't know whether that'd work out properly.
You can use the following revealing module pattern to hide variables and keep them from being changed but this wont stop anyone from changing the accessible "type" function.
Below in the code, the header property was changed to _header and made into a function. The property type was changed to _type and hidden by wrapping a return with an object notation to return "type" as a function instead of the property. Someone can change the type function to anything they want by over writing it, but they can't change the value of _type.
var Parameters = function () {
var _modal_window = function modal_window() {
var backdrop = true,
keyboard = true,
show = true,
remote = false;
return {
type: {
normal: function () {
this.footer.button.accept.type = 'btn btn-primary';
this.header.type = 'modal-header';
},
success: function () {
this.footer.button.accept.type = 'btn btn-success';
this.header.type = 'modal-header alert alert-success';
},
info: function () {
this.footer.button.accept.type = 'btn btn-info';
this.header.type = 'modal-header alert alert-info';
},
error: function () {
this.footer.button.accept.type = 'btn btn-danger';
this.header.type = 'modal-header alert alert-error';
},
warning: function () {
this.footer.button.accept.type = 'btn btn-warning';
this.header.type = 'modal-header alert';
}
}
};
}();
var _header = function header() {
var _type = 'This causes error';//this.window.type.normal.header;
return {
title: undefined, type: function () { return _type; }
};
}();
var _footer = function footer() {
return {
button:
{
accept: {
title: 'Accept',
click: undefined,
type: undefined
},
cancel: {
title: 'Cancel',
click: undefined
}
}
};
}();
return {
modal_window: _modal_window,
header: _header,
footer: _footer
};
}();

Setting correct this-value in requestAnimationFrame

I have an app-object constructer that looks like this:
var app = function(loadedsettings) {
return {
init: function() {
this.loop();
},
loop: function() {
this.update();
window.requestAnimationFrame(this.loop);
},
update: function() {
//loop through settings and call update on every object.
},
settings: [
//array of settings objects, all with update methods.
]
};
}
Then when I do:
var theApp = app(settings);
theApp.init();
I get:
Uncaught TypeError: Object [object global] has no method 'update'
because when requestAnimationFrame is called, the this-value inside the loop function is set to window.
Does anybody know how to call requestAnimatinFrame with the 'theApp' object set as the this-value?
You can create a bound function (with a fixed this), and pass that to requestAnimationFrame:
var app = function(loadedsettings) {
return {
init: function() {
this.loop();
},
loop: function() {
this.update();
window.requestAnimationFrame(this.loop.bind(this));
},
update: function() {
//loop through settings and call update on every object.
},
settings: [
//array of settings objects, all with update methods.
]
};
}
I think that a browser which supports requestAnimationFrame will also support Function.prototype.bind, but in case you come across one that doesn't, there are polyfills available.
You need to cache a reference to this:
var app = function(loadedsettings) {
var self = this;
return {
init: function() {
self.loop();
},
loop: function() {
self.update();
window.requestAnimationFrame(self.loop);
},
** snip **
...

Categories