Skip to content

Instantly share code, notes, and snippets.

@mike-gusiev
Last active August 29, 2015 14:24
Show Gist options
  • Save mike-gusiev/b7407777c0b44445993a to your computer and use it in GitHub Desktop.
Save mike-gusiev/b7407777c0b44445993a to your computer and use it in GitHub Desktop.
CanJS tips
console.log('Static and public methods:');
var Todo = can.Construct({
count: 0
}, {
author: function () {return "Justin";}
});
console.log(Todo.count); //static property (can use without object)
//public method
var todo = new Todo();
console.log(todo.author());
//privat methods
console.log('\nPrivat Methods:');
var PrivateTodo = Todo({
isPrivate: function () {
return true;
}
});
var private = new PrivateTodo();
console.log(private.isPrivate()); //private: true
console.log(private.author()); //public: Justin
console.log('\nInit method:');
var Todo = can.Construct({
count: 0
}, {
init: function (name, author) {
this.name = name;
this.authorName = author;
this.constructor.count++;
},
author: function () {
return this.authorName;
}
});
var todo = new Todo('dishes', 'Justin');
console.log(Todo.count); //static: 1
console.log(todo.author()); //public: Justin
console.log('Observer pattern:');
var paginate = new can.Observe({offset: 0, limit: 100, count: 2000});
console.log( paginate.attr('limit') ); //public property: 100
paginate.attr('offset', 100); //changing public property
console.log( paginate.attr('offset') ); //public: 100
paginate.removeAttr('count');
console.log('\nStart listening property changes:');
paginate.bind('offset', function (ev, newVal, oldVal) {
console.log('New:', newVal, 'Old:', oldVal);
});
paginate.attr('offset', 200);
console.log('\nNested data:');
var user = new can.Observe({
name: {
first: 'Justin',
last: 'Meyer'
}
});
console.log( user.attr('name.first') ); //nested property: Justin
user.attr('hobbies', ['programming', 'party rocking']);
console.log(user.attr('hobbies.1')); //second item: party rocking
console.log('\nWorking with attr():');
console.log(user.attr()); //return user object
user.attr({limit: 200, count: 1000}); //adding multiply properties
console.log( user.attr() );
user.attr( {limit: 200}, true); //removes all values not present in the given object -> {limit: 200}
console.log( user.attr() );
console.log('\nAny changes binding:');
user.bind('change', function (ev, attr, how, newVal, oldVal) {
console.log('CHANGE:', attr, how, newVal, oldVal);
});
user.attr('count', 2000); //fires event: "CHANGE: count add 2000 undefined"
user.attr('count', 3000); //fires event: "CHANGE: count add 3000 2000"
user.removeAttr('count'); //fires event: "CHANGE: count remove undefined 3000"
console.log('\nBinding handlers and unbinding:');
var countHandler = function (ev, newVal, oldVal) {
console.log('the count has changed', newVal, oldVal);
}
user.bind('count', countHandler).attr('count', 3000); //fires 2 events! old global + new
user.unbind('count');
user.attr('count', 2000); //fires 1 evet (global): CHANGE: count set 2000 3000
console.log('\nEach function:');
var paginate = new can.Observe({
offset: 0,
limit: 100,
count: 1000
});
paginate.each(function (value, name) {
console.log(name, value);
});
console.log('\nObserve Lists:');
var hobbies = new can.Observe.List(['programming', 'basketball', 'party rocking']);
console.log(hobbies.attr(0)); //programming
hobbies.attr(0, 'eating mexicans');
console.log( hobbies.attr() );
var newindex = hobbies.indexOf('basketball');
console.log(newindex); //1
var lastElem = hobbies.pop(); //changes source array, deleting last elem
console.log(lastElem); //party rocking
console.log( hobbies.attr() );
hobbies.push('guitar'); //adding elem at the end, returns array.length
console.log( hobbies.attr() );
var firstElem = hobbies.shift(); //changes source array, deleting first elem
console.log(firstElem); //eating mexicans
console.log( hobbies.attr() );
hobbies.unshift('football'); //returns array.length
console.log( hobbies.attr() );
hobbies.splice(1, 1, 'flag football'); //removes second item and adds 'flag football' instead of it
console.log( hobbies.attr() );
console.log('\nDifferent types of events:');
hobbies
.bind('add', function (ev, newVals, index) {
console.log('ADD:', newVals, index);
})
.bind('remove', function (ev, newVals, index) {
console.log('REMOVE:', newVals, index);
})
.bind('set', function (ev, newVals, index) {
console.log('SET:', newVals, index);
})
.bind('length', function (ev, length) {
console.log('LENGTH:', length);
});
hobbies.pop(); //removes last item, fires 2 evets: remove and length
console.log('can.Model for persisting data:');
var Todo = can.Model({
findAll : 'GET /todos',
findOne : 'GET /todos/{id}',
create : 'POST /todos',
update : 'PUT /todos/{id}',
destroy : 'DELETE /todos/{id}'
}, {
});
//catching requests and return fake data
(function () {
var TODOS = [{
id: 1,
name: 'do the dishes'
}, {
id: 2,
name: 'mow the lawn'
}, {
id: 3,
name: 'iron my shirts'
}];
//findAll
can.fixture('GET /todos', function () {
return TODOS;
});
//findOne
can.fixture('GET /todos/{id}', function (request) {
return TODOS[ (+request.data.id)-1 ];
});
//create
can.fixture('POST /todos', function (request) {
var id = TODOS.length + 1;
TODOS.push( $.extend( {id: id}, request.data ));
return {id: id};
});
//update
can.fixture('PUT /todos/{id}', function (request) {
$.extend( TODOS[ (+request.data.id) - 1 ], request.data );
return {};
});
//delete
can.fixture('DELETE /todos/{id}', function (request) {
return {};
});
})();
Todo.findAll({}, function (todos) {
console.log('\nFind All:');
todos.each(function (todo) {
console.log(todo.name);
});
});
Todo.findOne({id: 1}, function (todo) {
console.log('\nFind One:');
console.log(todo.name);
})
var todo = new Todo({name: 'pick up milk'});
todo.save(function (todo) { //save = update or create
console.log('\nCreate new item and saving to the model:');
console.log(todo.name);
});
setTimeout(function () {
console.log('\nModel bindings methods: ');
var todo = new Todo({name: 'canjs understanding'});
todo.bind('name', function (ev, newVal, oldVal) {
console.log('name changed to:', newVal);
});
todo.attr('name', 'new name');
}, 1000);
setTimeout(function () {
console.log('\nBinding events on class and object:');
var staticReport = function (ev, todo) {
console.log('some todo was', ev.type, ' named', todo.name);
}
var instanceReport = function (ev) {
console.log('my todo was', ev.type, ' named', this.name);
}
Todo.bind('created', staticReport)
.bind('updated', staticReport)
.bind('destroyed', staticReport);
var todo = new Todo({name: 'learn model events'});
todo.bind('created', instanceReport)
.bind('updated', instanceReport)
.bind('destroyed', instanceReport);
todo.save(); //fires 2 create events. first from object, next from class
setTimeout(function () {
//updating
todo.attr('name', 'Learned model events');
todo.save(); //fires 2 update events
}, 500);
setTimeout(function () {
todo.destroy(); //fires 2 destroy events
}, 1000);
setTimeout(function () {
new Todo({name: 'Temp'}).save(); //fires only 1 event!!!
}, 1500);
}, 2000);
setTimeout(function () {
console.log('\ncan.Model.List derived from findAll:');
var globalTodos = {};
Todo.findAll({}, function (todos) {
globalTodos = todos;
});
setTimeout(function () {
globalTodos.bind('remove', function (ev, removed, index) {
console.log('removed', removed[0].name, 'at', index);
});
globalTodos[0].destroy();
}, 500);
}, 4000);
<!doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Can JS</title>
</head>
<body>
<ul id="todos"></ul>
<script src="js/jquery-1.11.3.min.js"></script>
<script src="js/can.custom.js"></script>
<script src="js/extra.js"></script>
<script src="js/main.js"></script>
</body>
</html>
<!-- todo.ejs -->
<script id="todoEJS" type="text/ejs">
<% for (var i =0; i < this.length; i++) { %>
<li><%= this[i].name %></li>
<% } %>
</script>
<!-- main.js -->
<script type="text/javascript">
//catching requests and return fake data
(function () {
var TODOS = [{
id: 1,
name: 'do the dishes'
}, {
id: 2,
name: 'mow the lawn'
}, {
id: 3,
name: 'iron my shirts'
}];
//findAll
can.fixture('GET /todos', function () {
return TODOS;
});
//findOne
can.fixture('GET /todos/{id}', function (request) {
return TODOS[ (+request.data.id)-1 ];
});
//create
can.fixture('POST /todos', function (request) {
var id = TODOS.length + 1;
TODOS.push( $.extend( {id: id}, request.data ));
return {id: id};
});
//update
can.fixture('PUT /todos/{id}', function (request) {
$.extend( TODOS[ (+request.data.id) - 1 ], request.data );
return {};
});
//delete
can.fixture('DELETE /todos/{id}', function (request) {
return {};
});
})();
var Todo = can.Model({
findAll : 'GET /todos',
findOne : 'GET /todos/{id}',
create : 'POST /todos',
update : 'PUT /todos/{id}',
destroy : 'DELETE /todos/{id}'
}, {});
Todo.findAll({}, function (todos) {
//var frag = can.view('todoEJS', todos); //byID
var frag = can.view('js/todo.ejs', todos); //byFilename
console.log(frag);
document.getElementById('todos')
.appendChild( frag );
});
</script>
console.log('\nDeferred object:');
var deferred = new can.Deferred();
deferred.then(function (value) {
console.log('I got', value);
});
deferred.resolve('A VALUE');
console.log('\nShowing template when all deferred objects are loaded:');
can.view.ejs('favorites', '<%= todo1.name %> & <%= todo2.name %>');
can.view('favorites', {
todo1: Todo.findOne({ id: 1 }),
todo2: Todo.findOne({ id: 2 })
})
.then(function (frag) {
document.body.appendChild( frag );
});
latest-video.hbs:
<script>
steal('modules/latest-video/', function(latestVideo){
latestVideo('#{{id}}',{
videoFeed: 'data/latest-video.json',
searchPage: '{{searchPage}}',
trailSize: 8
});
})
</script>
latest-video.js:
define(['can', 'scripts/base-cloudinary', 'jspath', 'src/markups/blocks/card/card.hbs!'], function(can, BaseCloudinary, JSPath, VideoItemTemplate){
return BaseCloudinary.extend({
init: function () {
this._super();
can.ajax({
url: this.options.videoFeed,
dataType: 'json',
success: this.proxy(this.onFeedLoaded)
});
this.initPropertes();
if (!this.options.searchPage) {
this.prepareSearchControls();
}
},
...
'.b-filter__select change': function ($select, event) {
var searchTag = $select.val();
this.currentTag = searchTag;
this.findVideo(searchTag, this.searchFilter);
},
'.b-search__icon click': function ($icon, event) {
this.onSearchClick();
},
'.b-search__input keypress': function ($input, event) {
var key = event.keyCode || event.which;
if (key == 13) {
this.onSearchClick();
}
},
})
});
//feedapp.js:
var FeedApp = can.Control.extend({
defaults: {
link: "http://api.massrelevance.com/MassRelDemo/kindle.json",
limit: 10,
interval: 10000
},
data: {},
timer: false,
lastAjax: true
}, {
init: function () {
this.data = new can.List();
this.view();
this.startRefresh();
},
view: function () {
var mainHTML = can.view("app/tpl/main.tpl", {
data: this.data
});
$(this.element).html(mainHTML);
},
...
addNew: function (newData) {
var self = this;
can.batch.start();
newData.map(function (item) {
self.data.unshift(item);
if(self.data.length > self.options.limit) self.data.pop();
});
can.batch.stop();
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment