Widget.coffee
JQUERY STYLE
var attachTilesClick = function() {
_.each(selfDashboard.sections(), function(section) {
_.each(section.tiles(), function(tile) {
var theTile = $("#" + tile.uniqueId);
theTile.unbind("click");
theTile.click(function() {
if(tile.url) {
window.open(tile.url);
}
});
});
});
};
PROS and CONS
- Flexible and lightweight
- 3rd Party Friendly
- DOM-JS is separated
- Complicated query to locate the elements
- Code is still executed when element doesn't exist
- Initialize in public functions
- Codes for different features are mixed together
- Codes are hard to reuse
- Life-time management is hard in page with multiple components
EXTJS STYLE
Ext.define('KitchenSink.view.form.FieldTypes', {
extend: 'Ext.form.Panel',
xtype: 'form-fieldtypes',
frame: true,
title: 'Form Fields',
width: 400,
bodyPadding: 10,
layout: 'form',
items: [{
xtype: 'textfield',
name: 'textfield1',
fieldLabel: 'Text field',
value: 'Text field value'
}, {
xtype: 'hiddenfield',
name: 'hidden1',
value: 'Hidden field value'
},{
xtype: 'textfield',
name: 'password1',
inputType: 'password',
fieldLabel: 'Password field'
}, {
xtype: 'filefield',
name: 'file1',
fieldLabel: 'File upload'
}, {
xtype: 'textareafield',
name: 'textarea1',
fieldLabel: 'TextArea',
value: 'Textarea value'
}, {
xtype: 'displayfield',
name: 'displayfield1',
fieldLabel: 'Display field',
value: 'Display field <span style="color:green;">value</span>'
}, {
xtype: 'numberfield',
name: 'numberfield1',
fieldLabel: 'Number field',
value: 5,
minValue: 0,
maxValue: 50
}, {
xtype: 'checkboxfield',
name: 'checkbox1',
fieldLabel: 'Checkbox',
boxLabel: 'box label'
}]
});
PROS & CONS
- Powerful framework
- Included most common scenarios
- Feature Rich
- Predesigned Widgets
- Everything is in JavaScript
- No HTML, No CSS
- Hard to customize
- Extremely Heavy
- Extremely Intrusive
- Hard to debug
AGULAR JS
<html lang="en" ng-app>
<head>
<meta charset="utf-8">
<title>My HTML File</title>
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
<link rel="stylesheet" href="css/app.css">
<script src="bower_components/angular/angular.js"></script>
</head>
<body>
<p>Nothing here {{'yet' + '!'}}</p>
</body>
</html>
PROS AND CONS
- Very Powerful
- Extensible
- 3rd party friendly
- Code and DOM bounded
- Reusable
- Very heavy to use
- Learning curve is cliffy
- Hard to debug
Widget.coffee
WHY Widget.coffee
- Designed for Page
- Not for One-Page-Application
-
Light Weight
-
Non-intrusive
-
Easy to debug
- Simple to learn
FEatures
- DOM Binding
-
Life Cycle Management
- Relationship Management
- Event Binding
HTML
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="widget.js"></script>
<script type="text/javascript" src="sample_widgets.js"></script>
</head>
<body>
<div data-widget="Page">
<button data-action-handler='resetAll'>Reset All</button>
<hr>
<div data-widget="Timer" data-widget-part='timer'>
<div class="time">no record!</div>
<button class="toggle-button">start</button>
<button class="lap-button">lap</button>
<button class="reset-button">reset</button>
</div>
<hr>
<div data-widget="ScoreBoard">
<div>History</div>
<ol data-widget-part="scoreList"></ol>
<button data-action-handler="clean">Clean</button>
</div>
</div>
</body>
</html>
CoffeeScript
# sample_widget.coffee
class @Timer extends Widget
bindDom: ->
@timeSpan = @element.find('.time')
@toggleButton = @element.find('.toggle-button')
@lapButton = @element.find('.lap-button')
@resetButton = @element.find('.reset-button')
@scoreBoard = Widget.findWidgetByType('ScoreBoard')
enhancePage: ->
@toggleButton.click @toggle
@lapButton.click @lap
@resetButton.click @reset
initialize: ->
@running = false
@refreshButtonStatus()
@reset()
tick: =>
@time++
@refreshTime()
refreshTime: ->
@timeSpan.text("#{@time} ms")
toggle: =>
@controlTimer !@running
controlTimer: (running) ->
@running = running
@refreshButtonStatus()
if @running
@time = 0
@refreshTime()
@token = setInterval(@tick, 1)
else
if @token?
clearInterval(@token)
delete @token
refreshButtonStatus: ->
if @running
@toggleButton.text('Stop')
@lapButton.removeAttr('disabled')
@resetButton.attr('disabled', 'disabled')
else
@toggleButton.text('Start')
@lapButton.attr('disabled', 'disabled')
@resetButton.removeAttr('disabled')
lap: =>
@scoreBoard.addScore(@time)
reset: =>
delete @time
@timeSpan.text('no record!')
class @ScoreBoard extends Widget
bindDom: ->
@bindWidgetParts()
enhancePage: ->
@bindActionHandlers()
addScore: (score) ->
$('>/code>>li>>code>').text("#{score} ms").appendTo(@scoreList)
clean: ->
@scoreList.html('')
class @Page extends Widget
bindDom: ->
@scoreBoard = @findSubWidgetByType('ScoreBoard')
@bindWidgetParts()
enhancePage: ->
@bindActionHandlers()
resetAll: ->
@timer.controlTimer(false)
@timer.reset()
@scoreBoard.clean()
Debug
Widget.findWidgetByType('Timer').toggle()
Showcase
THANKS
TimNew
http://timnew.me
widget.coffee
By timnew
widget.coffee
- 95