Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
this.state('var', 5); // Программист: Состояние? Что за нахер? А если я хочу userState? Или varStack? По крайней мере я бы задал эти вопросы и предпочел бы модифицировать this по-человечески, а не "тру". Цитата:
|
...
Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
Цитата:
|
Цитата:
Забыл главное: jQuery используется на > 50% сайтов во всём мире. Чисто из любопытства: какие есть альтернативы? Мутулз — те же яйца, прототайп — вырвиглазное говнище... Цитата:
|
Ой, а я только сейчас заметил, что у меня получился вариант ну почти один в один как:
Цитата:
А лично моё мнение что FINoM усложняет реализацию. Я взялся за написание решение после того как попытался разложить твой FINoM скрипт и чуть голову не сломал. Реализация мне нужна сейчас, я делаю сложную анимацию и такой объект очень пригодится. Проброс переменных через аргументы функции для передачи состояния - в моём понимании это плохо тем, что переменные как бы летят через цепь, да ещё и меняют тип, говнокодом попахивает - фиг поймешь что в данную секунду записано и где это искать. Одна цепь - один объект, все переменные в одном месте - искать не нужно, даже отладка проще. |
Цитата:
Анекдот такой есть. Первую неделю после получки стипендии у студента в столовой действует правило правой руки: закрываются цены - выбираются блюда. Вторую неделю дествует правило левой руки: закрываются блюда - выбираются цены. Далее действует правило буравчика: покрутился-повертелся и ушел. ты не думаешь, что знание javascript, которое не просто знание jquery, лучше оплачивается? Да и вообще условия лучше. Цитата:
Цитата:
Цитата:
|
Цитата:
(казалось бы, фрилансер более поворотлив, но нет) Цитата:
Цитата:
Init.prototype.data = function(item,value) { if(value === undefined) {return this.data[item]} else {this.data[item] = value} }Примерно так. Хочешь, используешь функции, хочешь, просто пишешь this.data.x = 2; Цитата:
|
http://jsfiddle.net/XSGub/56/ — вот, вынес что мог в прототипы. Фигня в том, что когда вызывается runNext, он выполняется в контексте window. Заставлять писать кого-то runNext.call(this) — неправильно. A Function.prototype.bind слишком крупный, если хотим сделать кроссбраузерно.
|
Так что нужно обязательно замыкать callback в конструкторе. Есть идеи?
|
Цитата:
правда, если рассматривать кверю не как функцию ($(selector).method()), а как объект ($.css(element, prop)), то гибкость повышается... но этот пост вообще не об этом! /* что такое JavascriptMVC ? кто может вкратце обьяснить его суть? */ я погуглил насчёт альтернативы jquery и мне понравился qooxdoo. драг'н'дроп и другие плюшки их коробки.есть механизм поиска эл-ов по селектору (взят из Mootools). расскажите, что вы думаете об этом |
wait = function(first) { return new wait.Init(first); } wait.Init = function(first) { var self = this; this.callbackCaller = function() { self.callback.apply(self, arguments); } first.call(this, this.callbackCaller); } wait.Init.prototype = { deferred: [], callback: function() { this.args = [].slice.call(arguments); this.args.unshift(this.callbackCaller); if (this.deferred.length) { this.done = false; this.deferred[0].apply(this, this.args); this.deferred.shift(); } if (!this.deferred.length) { this.done = true; } }, wait: function(run) { if (this.done) { this.done = false; run.apply(this, this.args); } else { this.deferred.push(run); } return this; }, data: function(item, value) { if (arguments.length === 2) { this.data[item] = value; } else { return this.data[item]; } } } |
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
-------------------------- Пытаюсь разобраться в backbonejs, смотрю примеры, понимаю как они работают, но не понимаю главного: зачем они так работают и как строить хваленные масштабные приложения с помощью сабжа. Может есть какие-нибудь статьи или книга "для чайников"? |
backbone.js и javascriptMVC - близкие вещи, я сам не пробовал, но есть некто DjDiablo, который всячески советовал. Возможно, к этому приходишь, когда появляется желание покрыть код тестами. Наверное, это имеет смысл делать, когда у тебя скорее веб-приложение, чем сайт.
|
Цитата:
|
скорее всего ты слишком упрощаешь. А тесты должны помогать уменьшить количество ошибок при изменениях. Под веб-приложениям я понимаю что-то, что работает в пределах одной страницы, gmail, например. По твоему описанию непонятно, как у тебя. Можно плеер сделать в виде сайта, хотя лучше сделать без перезагрузки - музыка будет прерываться между страницами.
|
Да, это веб приложение на одной странице.
Цитата:
Цитата:
|
Цитата:
Цитата:
|
в продолжение... вот только как же ты их будешь использовать, если я даже для себя не уверен, не слишком ли это сложно. Хотя навреное надо.
Цитата:
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
Цитата:
|
Цитата:
Init.prototype.data = function(item,value) { if(value === undefined) {return this.data[item]} else {this.data[item] = value} } Цитата:
|
Цитата:
Цитата:
Цитата:
|
data не нужна.
|
Цитата:
|
я говорил о data как об аргументе для перехода от функции к объекту. Потому что этот data будет странно смотреться в твоей реализации.
Цитата:
wait(function() {...})... а у меня объект, потому что вызывается так: new AsyncChain(...).add(function() {...})... |
x-yuri, я тебя не понимаю.
Цитата:
Цитата:
|
нет, я хотел хранить состояние в цепочке. А передача объекта через всю цепочку - это решение в контексте твоего подхода.
И нету смысла делать так, как я сказал. Ты должен сам видеть необходимость. Если не видишь - делай по-своему. Еще раз, я тебе хотел сказать одну вещь: ты слишком упрощаешь, когда используешь функции, вместо объектов. Все. Необходимость хранить состояние - это всего лишь аргумент в пользу использования объектов. |
давайте все же расмотрим конкретный пример: ресайз картинок на клиенте с помощью flash.
Например, есть форма изменения юзерпика, в которой пользователь выбирает изображение. В результате появляется диалоговое окно, в котором пользователь указывает, как надо обрезать это изображение. Нажимает "Ok" диалогового окна, потом кнопку "Сохранить" формы. Получается что-то типа: var chain = new AsyncChain(); $('jsChangeUserpicForm-eUserpicField').addEvent('change', // input type="file" chain .setOptions({ onFailure: function() { // показать пользователю сообщение об ошибке this.fireEvent('complete'); }, onComplete: function() { new Button('jsChangeUserpicForm-eAttachFileLink') .enable(); $('jsChangeUserpicForm-eAttachFileThrobber') .addClass('sInvisible'); this.state('cropResizeUserpicDialog') && this.state('cropResizeUserpicDialog').close(); } }) .add(function() { new Button('jsChangeUserpicForm-eAttachFileLink') .disable(); $('jsChangeUserpicForm-eAttachFileThrobber') .removeClass('sInvisible'); }) .add(function(NEXT) { sendForm({ form: 'jsChangeUserpicForm', url: '/upload/userpic', onSuccess: function(userpicURL) { chain.state('userpicURL', userpicURL); NEXT(); }, onFailure: function() { chain.fireEvent('failure'); } }); }) .add(function(NEXT) { this.state('cropResizeUserpicDialog', new CropResizeUserpicDialog({ userpicURL: chain.state('userpicURL'), dstWidth: 100, dstHeight: 100, onOk: function(cropX, cropY, cropWidth, cropHeight, resizeWidth, resizeHeight) { this.state({ cropX: cropX, cropY: cropY, cropWidth: cropWidth, cropHeight: cropHeight, resizeWidth: resizeWidth, resizeHeight: resizeHeight }); NEXT(); }, onCancel: function() { chain.fireEvent('complete'); } })); }) .add(function() { this.state('cropResize', new CropResize()); this.state('cropResize').load(this.state('userpicURL'), { onSuccess: function() { NEXT(); }, onFailure: function() { chain.fireEvent('failure'); } }); }) .add(function() { this.state('cropResize') .crop( this.state('cropX'), this.state('cropY'), this.state('cropWidth'), this.state('cropHeight') ) .resize( this.state('resizeWidth'), this.state('resizeHeight'), ) .save({ url: '/upload/thumb', onSuccess: function() { NEXT(); }, onFailure: function() { chain.fireEvent('failure'); } }); }) .add(function() { if ($('jsChangeUserpicForm-eUserpicURLField')) { var eUserpicURLField = $('jsChangeUserpicForm-eUserpicURLField'); } else { var eUserpicURLField = new Element({ id: 'jsChangeUserpicForm-eUserpicField', type: 'hidden' }); eUserpicURLField.inject('jsChangeUserpicForm'); } eUserpicURLField.name = 'userpic-url'; eUserpicURLField.value = this.state('userpicURL'); $('jsChangeUserpicForm-eUserpicThumb').src = this.state('userpicURL'); }); ); дополнительные преимущества: 1) возможность научить addEvent запускать цепочки в ответ на событие; 2) предоставление интерфейса для работы с состоянием позволяет повторно использовать цепочку - для этого надо перед запуском цепочки очистить состояние; если пользователь сам придумывает, где хранить состояние, нету возможности его очистить; 3) возможность организовать аналогию блока finally из try-catch (событие complete). p.s. это я называю конкретным примером. Наличие кода необязательно в общем-то, но в твоем примере с гипотетическим парсером непонятно даже какие действия составляют цепочку, не говоря уже о данных, составляющих состояние цепочки. Т.е. не хватает важной информации. |
Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
chain.add(...).add(...).run()Запуск по событию: doc.addEventListener(event, chain.add(...).add(...).run);В первом случае мы сами вызываем функцию, во втором, передаем функцию для запуска после отлова события. Цитата:
Цитата:
chain.setOptions({ onComplete: function(){blabla()} }).add(function first(){}).add(function second(){}) писать chain.add(function first(){}).add(function second(){}).add(function() blabla()}) Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
chain.setOptions({ onComplete: function() { // выполняем завершающие действия } }).add(function() { this.fireEvent('complete'); }).add(function() { // делаем что-то еще }).add(function() { // делаем что-то еще }); chain .add(function() { runNext(true); }) .add(function(ignore) { if ( ! ignore) { // делаем что-то еще } runNext(ignore); }) .add(function(ignore) { if ( ! ignore) { // делаем что-то еще } runNext(ignore); }) .add(function(ignore) { if (ignore) { // выполняем завершающие действия } }); Цитата:
Цитата:
Цитата:
Цитата:
$('userpic').addEvent('change', // input type="file" function() { chain .add(function(runNext) { $('attach-file').addClass('disabled'); $('attach-file-throbber') .removeClass('invisible'); sendForm({ form: 'change-userpic-form', url: '/upload/userpic', onSuccess: function(userpicURL) { runNext(false, userpicURL); }, onFailure: function() { runNext(true); } }); }) .add(function(runNext, failure, userpicURL) { if (failure) { runNext(true); } var cropResizeUserpicDialog = new CropResizeUserpicDialog({ userpicURL: userpicURL, dstWidth: 100, dstHeight: 100, onOk: function(cropX, cropY, cropWidth, cropHeight, resizeWidth, resizeHeight) { runNext(false, false, userpicURL, cropResizeUserpicDialog, cropX, cropY, cropWidth, cropHeight, resizeWidth, resizeHeight); }, onCancel: function() { runNext(true); } })); }) .add(function(runNext, ignore, failure, userpicURL, cropResizeUserpicDialog, cropX, cropY, cropWidth, cropHeight, resizeWidth, resizeHeight) { if (ignore) { runNext(true); } if (failure) { runNext(false, true); } var cropResize = new CropResize(); cropResize.load(userpicURL, { onSuccess: function() { runNext(false, false, userpicURL, cropResizeUserpicDialog, cropX, cropY, cropWidth, cropHeight, resizeWidth, resizeHeight, cropResize); }, onFailure: function() { runNext(false, true); } }); }) .add(function(runNext, ignore, failure, userpicURL, cropResizeUserpicDialog, cropX, cropY, cropWidth, cropHeight, resizeWidth, resizeHeight, cropResize) { if (ignore) { runNext(true); } if (failure) { runNext(false, true); } cropResize .crop(cropX, cropY, cropWidth, cropHeight) .resize(resizeWidth, resizeHeight) .save({ url: '/upload/thumb', onSuccess: function() { runNext(false, false, userpicURL, cropResizeUserpicDialog); }, onFailure: function() { runNext(true); } }); }) .add(function(failure, userpicURL, cropResizeUserpicDialog) { if (failure) { // показать пользователю сообщение об ошибке } else { if ($('userpic-url')) { var usrpicUrl = $('userpic-url'); } else { var usrpicUrl = new Element({ id: 'userpic-url', type: 'hidden' }); usrpicUrl.inject('change-userpic-form'); } usrpicUrl.name = 'userpic-url'; usrpicUrl.value = userpicURL; $('eUserpicThumb').src = userpicURL; } $('attach-file').removeClass('disabled'); $('attach-file-throbber') .addClass('invisible'); cropResizeUserpicDialog && cropResizeUserpicDialog.close(); }); } ); p.s. ты либо специально скрываешь недостатки, либо... не специально. И даже если мое решение требуется в исключительных случаях... чем твое решение лучше существующих для ноды? |
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
Часовой пояс GMT +3, время: 14:57. |