Week 2 GUI And MVVM
Link to all source code (zipped)
- Example
1:
A Javascript Timer object. A reality check! We are learning about GUI, NOT
about AngularJS ... or, we are using AngularJS to learn about GUI!
- Notice the CSS450Timer.js file
- How to define a Javascript class (how to define a constructor)
- All instance methods are defined on the prototype property
[prototype is a default property on all Javascript objects]:
http://www.w3schools.com/js/js_object_prototypes.asp
- All instance variable references must proceed with "this"!! Be
careful!! Without "this", you will be defining and accessing a local
variable!
- Notice, we are passing a callback function to the timer
construction.
- The function.bind(this) syntax is a little strange, but
requestAnimationFrame() needs to know who is "this" when it wakes up
- Index.html:
- This is NOT an AngularJS example!! (why?)
- We can access to any HTML element at run time by its ID
- We can insert HTML code at runtime.
- Example 2:
A simple AngularJS timer
- Use the $interval parameter inthe controller. Simple.
- Need the mRun content to cancel an existing running timer
- index.html:
- The code can be in a separate file, clearer for illustration
purpose.
- Lesson:
- Timer is a pretty standard function
- enable nd disable should go in pair
- supply a service function
- Example 3:
A reusable module
- Goal: use timer as an example to learn about building a re-usable
GUI object, a Timer in this case.
- SimpleModule.js:
- directive keyword
- scope:
- Prevents outside from passing parameters into the directive
- "=" passes attribute in and binds (use when desire to binds
with variable)
- First: mBinded is two-way bound to
mCheckResult (from parent)
- "@" passes actual value (no binding invovles)
- Second: mFromMe is value "second"
- Scope keyword blocks out parent's scope
- try commenting the whole block out and see mFromParent
actually prints out parent's value
- Alternate: use $parent.mFromParent to explicitly see
parent's scope
- index.html
- when create the exApp. note, we specify that we need
SimpleModule
- my-tag is translated into myTag
- two instances of <my-tag>
- use attribute to modify the values of the directive
- Watch out:
- The "scope" of a directive
DOES NOT [seem to] get cleaned in-between re-run!!
- If you change scope's variable, good idea to quit and re-start
the browser
- Lesson:
- One example of reusable directive
- This is like we can parameterized the creation of some GUI
echo. Cool?
- Use alt-shift-I to see the "template" is expanded in the
browser.
- Example 4:
A reusable timer
- Now, create a re-usable timer module using directive: idea, create a
module that defines a directive, when using it, gives timer
functionality.
- Files:
- index.html (testing page)
- CSS450Tinmer.js: implements the timer module
- MyDriver.js: the testing module
- CSS450Timer: Almost identical to previous example, except ....
- Defines start/stop functions: to start and stop the timer
- Defines interval and callback
- MyDriver.js: the test driver module
- initialize the fast and slower timer control (one on and one
off)
- Define fn: the service function for slower timer
- Lesson:
- Not much, all seem reasonable
- EXCEPT: cannot start or stop timer after initialization
-
Example 5: Timer example complete
- MyDriver.js: added in timeCtrl() function
- $scope.$broadcast(): message to all references to $scope
- CSS450Timer.js:
- Bottom of file: $scope.$on() methods, to receive broadcast
messages
- Note:
- When broadcast "timer-ended" both fast and slow timer received
the message, they use mTimerIsOn flag (which is bounded to checkbox
result) to decide to switch on/off timer!
- Slow timer has a service function [fn], and the default counting
never happened.
- Fast timer does not have a service function, so it performs
default counting
- A useful timer should _NOT_ count, it should triggers and calls
the callback.
- Lesson:
- Familiar with module, and directive
- Example
6:
Integrating Timer with Mouse and Keyboard event handling
- Goal: to show our timer works in general
- First: organization
- create the "lib" folder will put all "general reusable" files in
here: CSS450Timer.js is here.
- Timer counting functionality is removed (who needs that?) [echo
is also stripped]
- Index.html: timer service decreases vertical slider
- If vertical slider reaches zero, switches off the timer and
hides timer echo
- Check out "ng-hide" :-)
- Lesson:
- Familiar with module, and director
- Appreciate convenience of two-way binding: mValue_2 [vertical
bar value]
- Control by user (via the slider bar)
- Program logic can control it also!
- We don't have to worry about consistency of the value!
- We now know how to create a GUI element (showing or otherwise)
that can be reused.
- Example
7:
Creating GUI element at run time!
- Layout to support calling of function to insert HTML code.
- Note:
- createSlider funciton
- We can use " " to quote or ' ' to quote
- Note: \" to escape double quotes inside double quotes
(min=\"0\")
- Script is moved to the end of the index.html
- Need to make sure when call createGUI(): after the corresponding
<div> are defined
- createSlider() is called _BEFORE_ the constructor for the
controller is activated
- This is important for the controller to know the models (mSimpleModel,
mLeftMode, and mRight Mode)!
- Lesson:
- OK. we can define function to insert GUI element.
- Big deal.
- Example 8: Reusable slider as a directive
- New library file: CSS450Slider.js
- Note: min/max: we only want their values in the template, that's
why {{min}} and {{max}}
- @: the parameter is accepted as a simple string (and values for
min and max)
- =: binds to the parameter (parameter is assumed to be either
a number, or a variable)
- Lesson:
- Not that difficult to create re-useable combo GUI elements
- NOT easy either, tricky and tons of potentials for bugs.
- Example 9: Working with multiple modules (Timer and Slider) in the same
app
- This is pretty lame. Just to show we can.
- Two timers, one drives the left, the other drives the right slider
bars.
- Cool. No?
- Example 10: A complete (and useless) Application
- Demonstrate the annoyance of not having two way binding.
- Structured as a MVC:
- Model: MyApp
- V: the GUI elements that echos input and output values
- C: the MyGUIController
- Notice: MyGUIController is the "container" controller, the container
of the entire interactive application
- Model is instantiate in MyGUIController
- Model:
(MyApplication) defined in MyApp
- Independent from any controller (Nothing UI specific!!)
- The model an receive an input value
- The model can compute a output value
- Would be nice, if we can bind the input and output to GUI
elements, which we are trying to do
- mInput and mOutputEcho are used to create the instance of
mApp
- Notice, MyUIController's variables and MyApplication's variables
are not binded! No binding :-(
- AngularJS data binding
- stops at the controller, does not binds with the model!
- Binding must be done explicitly!!
- No reason to pass the mOutput reference to the model, the values
are not bounded
- Example 11: Simple minded MVVM
- instead of Binding to the Controller's variables (mInput, and
mOutput)
- Defines an object specifically to support GUI View interface to the
Model
- Call this object ViewModel (kind of: for the convenience of
viewing the model)
- Now, binds GUI element to the ViewModel object
- Now, when model updates, through ViewModel, the View is updated
- This general philosophy of defining an intermediate "wrapper" for
the model to support GUI Vuew is referred to as MVVM or Model-View-ViewModel
- So? What's the big deal? ... simple concept but ...
- What if we have multiple instance of MyApp that needs to be
presented?
- Example 12: More general MVVM example
- Model is an array of MyApp
- We can now use mViewModel to interface to different part of the
Model
- Key:
- DO NOT access the model by accessing its instance variables (DO
NOT make assumptions on the model's internal representation)
- Only access the model via public methods, OR, access the
ViewModel, let ViewModel deal with the actual representation of the
Model.
- We are now ready to build graphical applications!
- Intro to working with WebGL
- Example 13: Some interaction with WebGL drawing
- MyGmae: is now our model.
- Separate out constructor (where GL is initialized)
- Defined a separate setColor and draw functions
- Design to support setting of color and re-drawing
- MainController: is the controller that over sees the entire
application
- Model is an instance of the MainController
- Supports a couple of CSS450Slider, and the timer (just to show
we can)
- X/Y Position: define element to the left and top
- Use <div> (commented out)
- Use <tr> <td>: table row above, and table column to the right