Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
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, время: 01:22. |