Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #37500 > unrolled thread
| Started by | luserdroog <luser.droog@gmail.com> |
|---|---|
| First post | 2019-10-04 21:43 -0700 |
| Last post | 2019-10-05 23:38 -0700 |
| Articles | 13 — 4 participants |
Back to article view | Back to comp.lang.javascript
A very small MVC prototype, for real this time... but need help... of course luserdroog <luser.droog@gmail.com> - 2019-10-04 21:43 -0700
Re: A very small MVC prototype, for real this time... but need help... of course luserdroog <luser.droog@gmail.com> - 2019-10-05 12:52 -0700
Re: A very small MVC prototype, for real this time... but need help... of course "Evertjan." <exxjxw.hannivoort@inter.nl.net> - 2019-10-05 22:52 +0200
Re: A very small MVC prototype, for real this time... but need help... of course luserdroog <luser.droog@gmail.com> - 2019-10-05 23:26 -0700
Re: A very small MVC prototype, for real this time... but need help... of course "Evertjan." <exxjxw.hannivoort@inter.nl.net> - 2019-10-06 11:39 +0200
Re: A very small MVC prototype, for real this time... but need help... of course Silvio <silvio@internet.com> - 2019-10-06 16:42 +0200
Re: A very small MVC prototype, for real this time... but need help... of course luserdroog <luser.droog@gmail.com> - 2019-10-06 11:22 -0700
Re: A very small MVC prototype, for real this time... but need help... of course "Evertjan." <exxjxw.hannivoort@inter.nl.net> - 2019-10-06 22:25 +0200
Re: A very small MVC prototype, for real this time... but need help... of course Jonas Thörnvall <jonas.thornvall@gmail.com> - 2019-10-06 14:15 -0700
Re: A very small MVC prototype, for real this time... but need help... of course luserdroog <luser.droog@gmail.com> - 2019-10-06 14:25 -0700
Re: A very small MVC prototype, for real this time... but need help... of course luserdroog <luser.droog@gmail.com> - 2019-10-12 14:15 -0700
Re: A very small MVC prototype, for real this time... but need help... of course "Evertjan." <exxjxw.hannivoort@inter.nl.net> - 2019-10-12 23:53 +0200
Re: A very small MVC prototype, for real this time... but need help... of course luserdroog <luser.droog@gmail.com> - 2019-10-05 23:38 -0700
| From | luserdroog <luser.droog@gmail.com> |
|---|---|
| Date | 2019-10-04 21:43 -0700 |
| Subject | A very small MVC prototype, for real this time... but need help... of course |
| Message-ID | <476ce5c1-2d43-48cb-a935-3803c0195a1f@googlegroups.com> |
Upon rereading the helpful suggestions from Michael Haufe, I noticed this
link which I had missed before,
https://gist.github.com/mlhaufe/c841b2269b0099c3c52648717f9551cc
containing the very Model, View, and Controller classes in a short and
sweet, barebones implementation. I read through it, copied it by hand
into my notebook, and then retyped the handwritten copy to really get
a good sense of it all. So, I'd like to try to build up a very simple
usage example.
Suppose for simplicity that the model is just represented by a simple
integer and the only modifications are increment and decrement.
I want the page to display the current value and have clickable plus
and minus signs, buttons or divs or whatever.
In the following, incomplete solution, I instantiate a Model and specify
the member functions: setValue, inc, dec; all of which call this.notify()
after modifying the value.
The I instantiate a a View and set its model. And provide override the
default update function with a new function which queries the model and
modifies the DOM.
But I don't quite see how to stitch up the click handlers. And what do
I do with the Controller? Should my 'inc' and 'dec' functions go into
the controller object?
$ for f in eg.html app.js mvc.js; do echo ----- $f ------ ; cat $f ; done ;
----- eg.html ------
<!doctype html>
<html lang=en><meta charset=utf-8>
<script type=module src=app.js> </script>
<main>
<div class=turtle >?</div>
<div class=inc >+</div>
<div class=dec >-</div>
----- app.js ------
let qs = (sel,ctx)=> (ctx || document).querySelector( sel );
import {Model, View, Controller} from './mvc.js';
let turtle = new Model();
turtle.setValue = function( value ){ this.value = value; this.notify() };
turtle.inc = function(){ ++this.value; this.notify() };
turtle.dec = function(){ --this.value; this.notify() };
let panel = new View();
panel.setModel( turtle );
panel.update = function(){
qs('.turtle').innerHTML = this.getModel().value;
}
function main(){
turtle.setValue( 0 );
}
document.addEventListener('DOMContentLoaded', main );
----- mvc.js ------
class Model {
_observers = []
observe( observer ){ this._observers.push( observer ) }
unobserve(observer){ this._observers=this._observers.filter(o=> o!==observer)}
notify( data ){ this._observers.forEach(o=> o.update(data) ) } }
class View {
_subViews = []
update(){}
getModel(){ return this._model }
setModel( model ){ this._setModelAndController( model, this._controller ) }
getDefaultController(){ return new Controller }
getController(){ if( !this._controller )
this.setController(this.getDefaultController())
return this._controller}
setController(controller){this._setModelAndController(this._model,controller)}
_setModelAndController( model, controller ){
if( this._model !== model ){
if( this._model ) this._model.unobserve( this )
if( model ) model.observe( this )
this._model = model
}
if( controller ){ controller.setView( this ); controller.setModel( model ) }
this._controller = controller
}
getSubViews(){ return new Array( this._subViews ) }
addSubView( subView ){
var prev = subView.getSuperView()
if( prev ) prev.removeSubView( subView )
this._subViews.push( subView )
subView.setSuperView( this )
}
removeSubView( subView ){
this._subViews=this._subViews.filter(s=>{if(s===subView) s.setSuperView(null)
return s !== subView })
}
setSuperView( superView ){ this._superView = superView }
getSuperView(){ return this._superView }
destroy(){
if( this._model ) this._model.unobserve( this )
this._subViews.forEach(s=> s.destroy() )
} }
class Controller {
getModel(){ return this._model }
setModel( model ){ this._model = model }
getView(){ return this._view }
setView( view ){ this._view = view } }
export { Model, View, Controller }
[toc] | [next] | [standalone]
| From | luserdroog <luser.droog@gmail.com> |
|---|---|
| Date | 2019-10-05 12:52 -0700 |
| Message-ID | <0ab03e1a-bb5c-4294-b78f-ed6452e0ab0f@googlegroups.com> |
| In reply to | #37500 |
On Friday, October 4, 2019 at 11:43:28 PM UTC-5, luserdroog wrote:
> let turtle = new Model();
> turtle.setValue = function( value ){ this.value = value; this.notify() };
> turtle.inc = function(){ ++this.value; this.notify() };
> turtle.dec = function(){ --this.value; this.notify() };
Small improvement. I can avoid repeating 'this.notify()' if all modifications
are routed through 'setValue()'.
let turtle = new Model();
turtle.setValue = function( value ){ this.value = value; this.notify() }
turtle.inc = function(){ this.setValue( this.value + 1 ) }
turtle.dec = function(){ this.setValue( this.value - 1 ) }
[toc] | [prev] | [next] | [standalone]
| From | "Evertjan." <exxjxw.hannivoort@inter.nl.net> |
|---|---|
| Date | 2019-10-05 22:52 +0200 |
| Message-ID | <XnsAADFE8B7FA177eejj99@194.109.6.166> |
| In reply to | #37502 |
luserdroog <luser.droog@gmail.com> wrote on 05 Oct 2019 in
comp.lang.javascript:
> turtle.inc = function(){ this.setValue( this.value + 1 ) }
why not skip the setValue definition and do:
turtle.inc = function(){ this.value = ++this.value;this.notify(); };
--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
[toc] | [prev] | [next] | [standalone]
| From | luserdroog <luser.droog@gmail.com> |
|---|---|
| Date | 2019-10-05 23:26 -0700 |
| Message-ID | <c305cdfb-b07c-43ba-8488-b6305aefd83d@googlegroups.com> |
| In reply to | #37503 |
On Saturday, October 5, 2019 at 3:53:18 PM UTC-5, Evertjan. wrote:
> luserdroog <luser.droog@gmail.com> wrote on 05 Oct 2019 in
> comp.lang.javascript:
>
> > turtle.inc = function(){ this.setValue( this.value + 1 ) }
>
> why not skip the setValue definition and do:
>
> turtle.inc = function(){ this.value = ++this.value;this.notify(); };
>
It seems more DRY to call 'notify' in just one place.
[toc] | [prev] | [next] | [standalone]
| From | "Evertjan." <exxjxw.hannivoort@inter.nl.net> |
|---|---|
| Date | 2019-10-06 11:39 +0200 |
| Message-ID | <XnsAAE07682CB95Beejj99@194.109.6.166> |
| In reply to | #37505 |
luserdroog <luser.droog@gmail.com> wrote on 06 Oct 2019 in
comp.lang.javascript:
> On Saturday, October 5, 2019 at 3:53:18 PM UTC-5, Evertjan. wrote:
>> luserdroog <luser.droog@gmail.com> wrote on 05 Oct 2019 in
>> comp.lang.javascript:
>>
>> > turtle.inc = function(){ this.setValue( this.value + 1 ) }
>>
>> why not skip the setValue definition and do:
>>
>> turtle.inc = function(){ this.value = ++this.value;this.notify(); };
>>
>
> It seems more DRY to call 'notify' in just one place.
I more meant why tou needed a setValue function.
So:
turtle.inc = function(){ this.value = ++this.value; };
--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
[toc] | [prev] | [next] | [standalone]
| From | Silvio <silvio@internet.com> |
|---|---|
| Date | 2019-10-06 16:42 +0200 |
| Message-ID | <5d99fd5a$0$1711$e4fe514c@newszilla.xs4all.nl> |
| In reply to | #37507 |
On 10/6/19 11:39 AM, Evertjan. wrote:
> luserdroog <luser.droog@gmail.com> wrote on 06 Oct 2019 in
> comp.lang.javascript:
>
>> On Saturday, October 5, 2019 at 3:53:18 PM UTC-5, Evertjan. wrote:
>>> luserdroog <luser.droog@gmail.com> wrote on 05 Oct 2019 in
>>> comp.lang.javascript:
>>>
>>>> turtle.inc = function(){ this.setValue( this.value + 1 ) }
>>>
>>> why not skip the setValue definition and do:
>>>
>>> turtle.inc = function(){ this.value = ++this.value;this.notify(); };
>>>
>>
>> It seems more DRY to call 'notify' in just one place.
>
> I more meant why tou needed a setValue function.
>
> So:
>
> turtle.inc = function(){ this.value = ++this.value; };
>
this.value = ++this.value ???
[toc] | [prev] | [next] | [standalone]
| From | luserdroog <luser.droog@gmail.com> |
|---|---|
| Date | 2019-10-06 11:22 -0700 |
| Message-ID | <ec21c9e0-f03f-4d7f-815d-c0c7baaf59ae@googlegroups.com> |
| In reply to | #37507 |
On Sunday, October 6, 2019 at 4:39:06 AM UTC-5, Evertjan. wrote:
> luserdroog <luser.droog@gmail.com> wrote on 06 Oct 2019 in
> comp.lang.javascript:
>
> > On Saturday, October 5, 2019 at 3:53:18 PM UTC-5, Evertjan. wrote:
> >> luserdroog <luser.droog@gmail.com> wrote on 05 Oct 2019 in
> >> comp.lang.javascript:
> >>
> >> > turtle.inc = function(){ this.setValue( this.value + 1 ) }
> >>
> >> why not skip the setValue definition and do:
> >>
> >> turtle.inc = function(){ this.value = ++this.value;this.notify(); };
> >>
> >
> > It seems more DRY to call 'notify' in just one place.
>
> I more meant why tou needed a setValue function.
>
> So:
>
> turtle.inc = function(){ this.value = ++this.value; };
>
The Model needs to call 'notify' after any change to the value.
It seemed convenient to combine these into a single action.
I get the feeling that I'm not seeing the point you're trying
to make.
[toc] | [prev] | [next] | [standalone]
| From | "Evertjan." <exxjxw.hannivoort@inter.nl.net> |
|---|---|
| Date | 2019-10-06 22:25 +0200 |
| Message-ID | <XnsAAE0E42916C31eejj99@194.109.6.166> |
| In reply to | #37509 |
luserdroog <luser.droog@gmail.com> wrote on 06 Oct 2019 in
comp.lang.javascript:
> On Sunday, October 6, 2019 at 4:39:06 AM UTC-5, Evertjan. wrote:
>> luserdroog <luser.droog@gmail.com> wrote on 06 Oct 2019 in
>> comp.lang.javascript:
>>
>> > On Saturday, October 5, 2019 at 3:53:18 PM UTC-5, Evertjan. wrote:
>> >> luserdroog <luser.droog@gmail.com> wrote on 05 Oct 2019 in
>> >> comp.lang.javascript:
>> >>
>> >> > turtle.inc = function(){ this.setValue( this.value + 1 ) }
>> >>
>> >> why not skip the setValue definition and do:
>> >>
>> >> turtle.inc = function(){ this.value = ++this.value;this.notify(); };
>> >>
>> >
>> > It seems more DRY to call 'notify' in just one place.
>>
>> I more meant why you needed a setValue function.
>>
>> So:
>>
>> turtle.inc = function(){ this.value = ++this.value; };
>>
>
> The Model needs to call 'notify' after any change to the value.
> It seemed convenient to combine these into a single action.
> I get the feeling that I'm not seeing the point you're trying
> to make.
>
Repeat: why you need a setValue function???
--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
[toc] | [prev] | [next] | [standalone]
| From | Jonas Thörnvall <jonas.thornvall@gmail.com> |
|---|---|
| Date | 2019-10-06 14:15 -0700 |
| Message-ID | <4234af8c-f975-486d-a5df-a146a48a6918@googlegroups.com> |
| In reply to | #37510 |
Den söndag 6 oktober 2019 kl. 22:25:49 UTC+2 skrev Evertjan.:
> luserdroog <luser.droog@gmail.com> wrote on 06 Oct 2019 in
> comp.lang.javascript:
>
> > On Sunday, October 6, 2019 at 4:39:06 AM UTC-5, Evertjan. wrote:
> >> luserdroog <luser.droog@gmail.com> wrote on 06 Oct 2019 in
> >> comp.lang.javascript:
> >>
> >> > On Saturday, October 5, 2019 at 3:53:18 PM UTC-5, Evertjan. wrote:
> >> >> luserdroog <luser.droog@gmail.com> wrote on 05 Oct 2019 in
> >> >> comp.lang.javascript:
> >> >>
> >> >> > turtle.inc = function(){ this.setValue( this.value + 1 ) }
> >> >>
> >> >> why not skip the setValue definition and do:
> >> >>
> >> >> turtle.inc = function(){ this.value = ++this.value;this.notify(); };
> >> >>
> >> >
> >> > It seems more DRY to call 'notify' in just one place.
> >>
> >> I more meant why you needed a setValue function.
> >>
> >> So:
> >>
> >> turtle.inc = function(){ this.value = ++this.value; };
> >>
> >
> > The Model needs to call 'notify' after any change to the value.
> > It seemed convenient to combine these into a single action.
> > I get the feeling that I'm not seeing the point you're trying
> > to make.
> >
>
> Repeat: why you need a setValue function???
>
>
>
> --
> Evertjan.
> The Netherlands.
> (Please change the x'es to dots in my emailaddress)
To not have a static model, isn't setValue part of the user interface "guessing wildly"
[toc] | [prev] | [next] | [standalone]
| From | luserdroog <luser.droog@gmail.com> |
|---|---|
| Date | 2019-10-06 14:25 -0700 |
| Message-ID | <3be9b304-8c70-41fb-aa81-1858c1bb145a@googlegroups.com> |
| In reply to | #37510 |
On Sunday, October 6, 2019 at 3:25:49 PM UTC-5, Evertjan. wrote:
> luserdroog <luser.droog@gmail.com> wrote on 06 Oct 2019 in
> comp.lang.javascript:
>
> > On Sunday, October 6, 2019 at 4:39:06 AM UTC-5, Evertjan. wrote:
> >> luserdroog <luser.droog@gmail.com> wrote on 06 Oct 2019 in
> >> comp.lang.javascript:
> >>
> >> > On Saturday, October 5, 2019 at 3:53:18 PM UTC-5, Evertjan. wrote:
> >> >> luserdroog <luser.droog@gmail.com> wrote on 05 Oct 2019 in
> >> >> comp.lang.javascript:
> >> >>
> >> >> > turtle.inc = function(){ this.setValue( this.value + 1 ) }
> >> >>
> >> >> why not skip the setValue definition and do:
> >> >>
> >> >> turtle.inc = function(){ this.value = ++this.value;this.notify(); };
> >> >>
> >> >
> >> > It seems more DRY to call 'notify' in just one place.
> >>
> >> I more meant why you needed a setValue function.
> >>
> >> So:
> >>
> >> turtle.inc = function(){ this.value = ++this.value; };
> >>
> >
> > The Model needs to call 'notify' after any change to the value.
> > It seemed convenient to combine these into a single action.
> > I get the feeling that I'm not seeing the point you're trying
> > to make.
> >
>
> Repeat: why you need a setValue function???
>
>
To combine two actions which should always be performed together:
storing the new value and notifying observers that a new value
has been stored.
In my current playpen, I've moved it into the Model class so I don't
have to repeat it in each model.
[toc] | [prev] | [next] | [standalone]
| From | luserdroog <luser.droog@gmail.com> |
|---|---|
| Date | 2019-10-12 14:15 -0700 |
| Message-ID | <4f2e5a14-ac85-46ff-b30d-4a33d6f71120@googlegroups.com> |
| In reply to | #37510 |
On Sunday, October 6, 2019 at 3:25:49 PM UTC-5, Evertjan. wrote: > luserdroog <luser.droog@gmail.com> wrote on 06 Oct 2019 in > comp.lang.javascript: > > > > > The Model needs to call 'notify' after any change to the value. > > It seemed convenient to combine these into a single action. > > I get the feeling that I'm not seeing the point you're trying > > to make. > > > > Repeat: why you need a setValue function??? > Since this exchange, I've learned about getters and setters. Is that what you were suggesting? To hook my function on property access with a setter?
[toc] | [prev] | [next] | [standalone]
| From | "Evertjan." <exxjxw.hannivoort@inter.nl.net> |
|---|---|
| Date | 2019-10-12 23:53 +0200 |
| Message-ID | <XnsAAE6F30983C45eejj99@194.109.6.166> |
| In reply to | #37532 |
luserdroog <luser.droog@gmail.com> wrote on 12 Oct 2019 in comp.lang.javascript: > On Sunday, October 6, 2019 at 3:25:49 PM UTC-5, Evertjan. wrote: >> luserdroog <luser.droog@gmail.com> wrote on 06 Oct 2019 in >> comp.lang.javascript: >> >> > >> > The Model needs to call 'notify' after any change to the value. >> > It seemed convenient to combine these into a single action. >> > I get the feeling that I'm not seeing the point you're trying >> > to make. >> > >> >> Repeat: why you need a setValue function??? >> > > Since this exchange, I've learned about getters and setters. Is that > what you were suggesting? To hook my function on property access with > a setter? I am not suggesting you learned something I'm not suggesting anything, I am just asking. "To hook my function on property access" What does "to hook A on B" mean? Why would you need that? -- Evertjan. The Netherlands. (Please change the x'es to dots in my emailaddress)
[toc] | [prev] | [next] | [standalone]
| From | luserdroog <luser.droog@gmail.com> |
|---|---|
| Date | 2019-10-05 23:38 -0700 |
| Message-ID | <c63e99c9-07bb-498e-b568-1f730aa89bd8@googlegroups.com> |
| In reply to | #37500 |
On Friday, October 4, 2019 at 11:43:28 PM UTC-5, luserdroog wrote:
> Upon rereading the helpful suggestions from Michael Haufe, I noticed this
> link which I had missed before,
>
> https://gist.github.com/mlhaufe/c841b2269b0099c3c52648717f9551cc
>
> containing the very Model, View, and Controller classes in a short and
> sweet, barebones implementation. I read through it, copied it by hand
> into my notebook, and then retyped the handwritten copy to really get
> a good sense of it all. So, I'd like to try to build up a very simple
> usage example.
>
> Suppose for simplicity that the model is just represented by a simple
> integer and the only modifications are increment and decrement.
>
> I want the page to display the current value and have clickable plus
> and minus signs, buttons or divs or whatever.
>
[snip]
I think I have it worked out a little better. The model has the function
'setValue' which calls the Model class's 'notify' function.
The view modifies the DOM in response to an 'update' from the model.
The controller has functions named to match DOM element classes and
a single click handler function routes all click events to their
respective controller functions.
>
> $ for f in eg.html app.js mvc.js; do echo ----- $f ------ ; cat $f ; done ;
> ----- eg.html ------
<!doctype html>
<html lang=en><meta charset=utf-8>
<script type=module src=app.js> </script>
<main>
<div class=turtle >?</div>
<div class=plus >+</div>
<div class=minus >-</div>
> ----- app.js ------
let qs = (sel,ctx)=> (ctx || document).querySelector( sel );
import {Model, View, Controller} from './mvc.js';
function main(){
turtle.setValue( 0 );
}
var turtle = new Model();
turtle.setValue = function( value ){ this.value = value; this.notify() };
turtle.inc = function(){ this.setValue( this.value + 1 ) };
turtle.dec = function(){ this.setValue( this.value - 1 ) };
var panel = new View();
panel.setModel( turtle );
panel.update = function(){ qs('.turtle').innerHTML = this.getModel().value; }
var control = panel.getController();
control.plus = function(){ this.getModel().inc() }
control.minus = function(){ this.getModel().dec() }
function click( e ){
if( typeof( control[ e.target.className ] ) == 'function' )
control[ e.target.className ]()
}
document.addEventListener('DOMContentLoaded', main );
document.addEventListener('click', click );
> ----- mvc.js ------
> class Model {
> _observers = []
> observe( observer ){ this._observers.push( observer ) }
> unobserve(observer){ this._observers=this._observers.filter(o=> o!==observer)}
> notify( data ){ this._observers.forEach(o=> o.update(data) ) } }
>
> class View {
> _subViews = []
> update(){}
> getModel(){ return this._model }
> setModel( model ){ this._setModelAndController( model, this._controller ) }
> getDefaultController(){ return new Controller }
> getController(){ if( !this._controller )
> this.setController(this.getDefaultController())
> return this._controller}
> setController(controller){this._setModelAndController(this._model,controller)}
> _setModelAndController( model, controller ){
> if( this._model !== model ){
> if( this._model ) this._model.unobserve( this )
> if( model ) model.observe( this )
> this._model = model
> }
> if( controller ){ controller.setView( this ); controller.setModel( model ) }
> this._controller = controller
> }
> getSubViews(){ return new Array( this._subViews ) }
> addSubView( subView ){
> var prev = subView.getSuperView()
> if( prev ) prev.removeSubView( subView )
> this._subViews.push( subView )
> subView.setSuperView( this )
> }
> removeSubView( subView ){
> this._subViews=this._subViews.filter(s=>{if(s===subView) s.setSuperView(null)
> return s !== subView })
> }
> setSuperView( superView ){ this._superView = superView }
> getSuperView(){ return this._superView }
> destroy(){
> if( this._model ) this._model.unobserve( this )
> this._subViews.forEach(s=> s.destroy() )
> } }
>
> class Controller {
> getModel(){ return this._model }
> setModel( model ){ this._model = model }
> getView(){ return this._view }
> setView( view ){ this._view = view } }
>
> export { Model, View, Controller }
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.javascript
csiph-web