Давно не писал, ибо пребываю сейчас в экстремальном непроходящем дебаге ))
О нем и будет короткая моя речь ))
Недавно вышла новая весрия флеш плеера, о чем было уже писано переписано, все дружно обновились, я полагаю ). В куче мы могли также качать дебаг-версию.
И тут я вспомнил, что FlashTracer – милый плагин под файрФокс, позволяющий выводить трейс из флешек в режиме браузера, перестал откликаться, если я использую 9-ю версию дебаггера.
Как оказалось, такая проблема постигла не только меня. Решение найдено, спасибо Silin-у, подсказал верную мысль )
Дело в том, что я мануально поменял путь к файлу flashlog.txt, вытащив его из длинной цепочки C:\Documents and Settings\user\Application Data\Macromedia\Flash Player\Logs немного поближе.
Так вот флешки, опубликованные под версию плеера НИЖЕ 9-ки спокойно отдавали свои логи в этот файл В ЛЮБОМ дебаг плеере (тут конечно участие принял другой полезный аддон для FF – FlashSwitcher). Зато флешки, требующие как минимум 9-ю версию – тихо сдавали свои логи все по тому же длинному адресу по умолчанию, оставляя указанный мной flashlog.txt без должного внимания. Импичмент, понимаешь.
Так что пришлось смириться с адресом по умолчанию, но зато браузерный дебаг мой снова стал чистым и шелковистым. Вот веть какая штука.
PS. Кажется меня приняли в мксня-аггрегатор. Тут и проверим )) Ответсвенность то какая ))
Popularity: 3% [?]
апреля 10, 2008
В сети море полезных фреймворков, классов и решений различных задач.
Однако очень многие из них имеют существенный недостаток – УЖАСНАЯ, если вообще присутствующая документация.
Недавно я прикоснулся к магии SWFAddress, библиотеке AS+JS, решающей проблему deep linking для FLASH и AJAX.
Для таких как я (гуманитариев и не-программистов) предлагаю свой опыт по освоению СВФАдреса.
Нет. Документацию на русский язык я переводить не буду. Не вижу в этом смысла. Документация более чем минималистическая. С тем же успехом ее можно было бы вообще не писать. В прочем + от нее все же есть – сводная таблица всех доступных в классе методов.
Первое что следует сделать – это скачать библиотеку. Настоятельно рекомендую качать 7-мегабайтовый архив с примерами и документацией. Потому что, как выяснилось в процессе, если бы я ограничился скачиванием только классов — меня бы постигла неудача, и я бы так и не понял в чем дело. А непоняток-ошибок на пути встретилось некоторое количество )
Первая ошибка. Исторически сложилось так, что я работал над сайтом, к которому намеревался прикрутить SWFAddress на завершающем этапе. Собираетесь использовать дип линкинг – сразу работайте с SWFAddress. Дело в том, что любое изменение адресной строки браузера (А это именно то, зачем нам вообще нужен дип линкинг) вызывает событие SWFAddress.onChange. То есть фактически и переключение разделов из флеш сайта (конечно если оно должно вести к изменению в адресной строке) , и переключение разделов извне (навигация по кнопкам ВПЕРЕД НАЗАД ,навигация по якорям на хтмл-странице и т.д.) вызывает это событие. В сущности на нем как раз и будет строиться обработка события переключения между разделами.
Ошибка вторая. Я доверился заявлению Flash CS3 Support. Фактически же, если публиковать ролик на странице с помощью AC_RunActiveContent.js, которое генерируется Flash IDE – дип линкинг не работает. Изменения в адресной строке – да, но ролик не реагирует на навигацию из браузера. Я дошел до этого знания случайно. Потеряв веру в свой мозг, я просто взял рабочий пример, и заменил в нем флешку на свою – и все заработало. Путем исключений я нашел камень преткновения. Каким то образом AC_RunActiveContent.js из примера отличается от того, что генерируется FLASH CS3 IDE. Так что пользуйтесь скриптом из примеров. Что касается работы с SWFObject и UFO – не проверял. У вас есть отличная возможность сделать это за меня, а потом отписаться здесь, если пожелаете.
Теперь о некоторых тонкостях и внутренностях. В архиве есть коды для всех трех версий AS. Мои опыты ставились на AS2.0
1. Класс написан как TopLevel-класс, или для тех кто не понимает этого словосочетания, – он не создает экземпляров. Пример такого класса -Math, все функции в нем вызываются подобным образом: Math.sin(), Math.round() и т.д. То же справедливо и для SWFAddress.
2. Адресная строка.
Для решения задачи дип линкинга, к существующему URL добавляется якорь # за которым следует строка, которую разработчик волен генерить сам, по своим правилам, и сам же по своим правилам ее и разбирает. Есть два режима. setStrict(true) – в конце адреса жестко добавляется слеш (/) и setStrict(false) – никаких слешей без ведома разрабочика.
3. Основные полезные методы.
В классе присутствует набор методов для разбора строки. Весьма удобно.
К примеру в адресной строке имеем
http://flashsite.com/#news?page=&img=2
SWFAddress.getValue():String - вернет значение строки аккурат после # со всеми Вашими изысками (парами имя=значение)
SWFAddress.getPath():String - вернет значение строки аккурат после # без дополнительных параметров
news
SWFAddress.getQueryString():Array - вернет строку с дополнительными параметрами
SWFAddress.getParameterNames():Array - вернет массив с именами дополнительных переменных
page,img
SWFAddress.getParameter(value:String):String - вернет значение дополнительного параметра указанного в value
getParameter(«page») // 1;
getParameter(«img») // 2;
Для того чтобы изменить адресную строку из FLASH существует метод setValue(value:String) – помните, что вызов этого метода автоматически приведет к вызову события onChange, так что фактически переключение между разделами сводится к замене значения адресной строки и последующей обработке события.
Остальные методы описывать не стану, они весьма просты и даже данных документации хватит для их освоения.
4. События.
Я уже говорил о событии onChange. Должен отметить, что событие это вызывается сразу же, при первом же упоминании класса, равно как и событие onInit. Большого смысла в событии onInit я не уловил. В самом начале оно вызывается и тут же за ним вызывается onChange. Возможно есть смысл для более четкой структуризации, и отделении инит-процедур от собственно обработки переключений между разделами.
Более подробно поговрим о событии onChange, хотя в случае с onInit все работает абсолютно так же, за исключением значения cвойств SWFAddressEvent: path=null; value=null; type=init;
События доступны в двух ипостасях:
SWFAddress.onChange = function():Void
{
trace("SWFAddress.onChange");
}
В данном случае мы просто определяем статичную функцию onChange.
Второй вариант – подписать любой свой объект на событие. Во многом это удобнее, чем описывать вложенные функции с обработчиком события.
К примеру мне удобно подписать экземпляр класса, который напрямую работает с SWFAddress. Для этого я сначала создаю функцию обработчик:
public function onChange():Void \
{
trace("Class's onChange");
}
И далее подписывась на событие с помощью метода класса SWFAddress – addEventListener(type:String,listener:Function);
Поскольку в этом учавствует стандартный mx.utils.EventDispatcher, нужно подписаться так, чтобы наша функция onChange знала кто в доме хозяин – то есть надо жестко определить this. Делается это при помощи mx.utils.Delegate.create().
Итак подписка на событие для нашего экземпляра будет выглядеть так
SWFAddress.addEventListener("change",Delegate.create(this,onChange));
Теперь мы можем из тела функции onChange обращаться ко всем свойствам и методам нашего экземпляра. Ура.
Продвинемся дальше. В том случае, если мы подписываемся на событие, в качестве параметра в наш обработчик приходит экземпляр SWFAddressEvent, который несет в себе ценную информацию 
Модифицируем наш обработчик.
public function onChange(evt:SWFAddressEvent):Void
{
//вернет путь после # из адресной строки БЕЗ параметров
trace("path:"+evt.path);
//вернет путь после # из адресной строки С параметрами
trace("value:"+evt.value);
}
Также событие несет информацию о своем типе (type=»change» или «init»), target (это всегда отсылка на SWFAddress) а также массив parameters («ассоциативный») с параметрами из queryString. Если в адресной строке есть news?param=value, то значение param можно получить так : SWFAddressEvent.parameters.param
Какие замечены баги.
1. Самый неприятный. В опере любое переключение между страницами ИЗ браузера (навигация вперед назад, якоря) вызывает полную перезагрузку страницы. Не очень то красиво, особенно если это флеш сайт с какими то особенными переходами между страницами. К счастью внутренние флешовые переходы проходят как обычно.
2.Если вручную вставить адрес в браузерной строке в FireFox – адресная строка перестает изменяться, когда переключаешься между разделами. Вроде как адреса заносятся в history, навигация вперед.назад работает, но это не отображается в адресной строке. В принципе – я лично замечал вообще странное поведение адресной строки в Фоксе, и без дип линкинга, например иногда в ней просто невозможно перенабрать адрес.
Работоспособность проверена на:
- Mozzilla FireFox 2.0.0.12
- Opera 9.10
- IE 6.0
- Safari (win) 3.0.3
В завершении могу только дать ссылку на первый свой опыт с SWFAddress, где вы можете потестировать работоспособность библиотеки в разных браузерах. Будет полезно, если здесь вы запостите свои баг репорты, ну или зададите вопросы о том, что осталось непонятным. Цель этого топика – сделать эту бесспорно полезную опцию более доступной всем категориям разработчиков )) Поэтому -включайтесь )
http://kvadra.net/samples/goodpeople/_flash/#chillout/two?pgid=2t&imgid=36
Popularity: 62% [?]
февраля 26, 2008
Многие наверное помнят, что флеш-проектор может запускать exe-шники и bat-файлы, если они лежат в папке fscommand?
На этом стояли неcколько лет производители CD-презентаций, инсталляторов с флеш оболочкой и иже с ними…
Но вот недавно я пробился несколько часов, и удивлению моему не было предела – бат файлы отказывались запускаться, тогда как я РУКУ мог дать на отсечение что раньше мне это удавалось.
Краем глаза я успевал заметить, что дос-окно отчаянно пытается мне что-то сказать… Полчаса скоростных нажатий спасительной PrintScreen – и я узнал, что по какой то причине CMD.EXE ответственный за запуск батников, принимает адрес текущего каталога в т.н UNC-формате.
И вот сегодня мне в приватное сообщение приходит ссылка от @st@l@vist@ (Грандиозное ему спасибо за это) .Нашелся умелец, который не остановился как я, и все понял до конца )))
Вот статья в оригинале.
По традиции – мой вольный перевод.
В начале статьи читаем увлекательный рассказ, как автор поймал баг и, так же как и я, пытался поймать скриншот ). Эту часть я опущу.
Далее по тексту (с сокращениями).
Почему Flash пытается запустить CMD.EXE, когда его попросили запустить BAT файл? CMD.EXE – это системное приложение Windows, отвечающее за бат-ники, и ОС запускает копию CMD.EXE (Именно поэтому мы видим уродское дос-окно).
Поскольку CMD.EXE не понимает UNC путей и не может определить директорию, из которой батник запущен – он устанавливает значение по умолчанию, т.е папку Windows, в которой естественно нет тех файлов, которые мы хотим запустить.
BAT файлы продолжают работать под Windows 98 and ME, но перестают работать под XP и Vista, потому что эти ОСи используют разные приложения для запуска батников (command.com до XP, и CMD.EXE, начиная с XP). Flash CS3 не генерирует UNC путей на старых ОСях.
Если Adobe не вернет использование DOS путей вместо UNC – остается одно решение – использовать альтернативный процессор для запуска батников. И именно такой процессор совершенно безвозмездно был создан автором статьи (Тимом)
Вот маленький exe-шник. (52 кило)
http://www.northcode.com/free/proxy/proxy.exe
Надо сказать, что с exe-шниками все работает как раньше. Так вот. Пишете свой батник. Запускаете из него хоть мп3 хоть пдф, хоть черта лысого. Рядом кладете этот proxy.exe и называете его так же как и батник – только расширение exe оставляете. Все. Из флеш-проектора запускаем не батник – а прокси – вуаля. Нет уродского черного-дос окна, и все работает )) Слава Тиму Освободителю )
Вот еще ссылочка на первоисточник мануала: http://www.northcode.com/blog.php/2007/08/07/…Proxy
На последок – пара полезностей. Для тех кто вообще ни понял что такое батник )))
*.bat – файл – это такая инструкция с ДОС-командами – что запустить и откуда запустить.
Хотите больше знать о ДОС-командах? Гугл в помощь ) Изучаем MS-DOS )))
Popularity: 39% [?]
февраля 1, 2008
Отличное, а главное, очень полезное он-лайн приложение – трейс битмапа в вектор. Очень приличный конвертер.
| Input: |
JPG, GIF, PNG, BMP, TIFF |
| Output: |
EPS, SVG, PNG |
Сделано на флексе.
http://vectormagic.stanford.edu/
И посмотрите сравнение результатов VM, Adobe LiveTrace и Corel.
http://vectormagic.stanford.edu/vectorize/comparisons
Popularity: 4% [?]
декабря 15, 2007
На волнах фриланса частенько попадаются жадные купцы.
Денежку пожалеют, и разработчику не заплатят.
Особенно озадачивает разработчика сей факт, когда он, наивный, отдал результат работы в жадные купцовы руки.
Лучшая защита – работать только с теми, кто у вас в local-trust )))
Но вот еще небольшая подмога. Класс Permission.
Для работы с ним, конечно понадобиться свой родной домен, на который вы сможете положить скромный crossdomain.xml. В нем укажите доступ для того домена, на котором будет лежать результат вашей работы. Ну а если не знаете где именно, будет лежать разрешайте доступ всем. Хуже не будет.
Далее. Кладем у себя мальнький текстовый файл, в котором будут записаны две переменных allow=1 и message=ЗАПЛАТИ ДЕНЕГ!!!
Пока allow=1 флешка будет работать как положено.
Но как только вам покажется, что денег больше не видать – меняйте allow=0.
Теперь все будут поверх флешки периодически читать ваш душещипательный message.
Конечно, по завершении работ, в случае благополучной оплаты – лучше убрать эту мышеловку из кода, и отправить финальный , стерильный вариант.
Использование:
Просто заводим новый экземпляр Permission и передаем в конструкторе путь к текстовому файлу.
var my_permission:Permission = new Permission("my_domain.net/my_permission.txt");
Код классa: ru.decafe.utils.Permission
/**
* class ru.decafe.utils.Permission
* @author Mikhail Ivanchuk
* @version 0.1
*/
import ru.decafe.utils.Cache;
class ru.decafe.utils.Permission {
private var theURL:String = "";
private var accessor:LoadVars;
private var blinker:Number;
private var alert_mc:MovieClip;
private var message:String = "";
public function Permission(url:String) {
theURL = url;
accessor = new LoadVars();
}
public function loadAccess():Void {
var refer:Permission = this;
var _key:String = theURL.indexOf("?")==-1?"?":"&";
accessor.load(theURL+Cache.disable(_key+"nocache="));
accessor.onLoad = function (success:Boolean) {
var mode:String = "demo";
if (success && this.allow == "1") {
mode = "allow";
}
trace("mode: "+mode+"\n"+this.message);
if (mode=="demo") {
refer.message = this.message;
refer.blinker = setInterval(refer,"alert",10000);
}
}
}
private function alert():Void {
alert_mc = _level0.createEmptyMovieClip("alrt",_level0.getNextHighestDepth());
var txt:TextField = alert_mc.createTextField("txt",0,0,0,150,60);
txt.background = true;
txt.multiline = true;
txt.wordWrap = true;
txt.backgroundColor = 0xDEDEDE;
txt.border = true;
txt.borderColor = 0;
txt.html = true;
txt.condenseWhite = true;
txt.htmlText = "
<span style="font-family: Arial;">"+message+"
";
alert_mc.counter = 100;
alert_mc.onEnterFrame = function () {
this.counter--;
if (this.counter<0) this.removeMovieClip();
}
}
}
</span>
+ Cache.as, который необходим для работы класса Permission: ru.decafe.utils.Cache
Popularity: 8% [?]
декабря 6, 2007
Мало мальски серьезное приложение обязательно грузит в себя некие внешние данные.
В случае работы на просторах сети эти данные попадают в кеш.
Иногда эта особенность сильно мешает. К примеру мы делаем галерею которая постоянно пополняется. Адреса изображений заносятся в XML файл, который мы и грузим первым делом в нашу галерею. Единожды загрузившись – этот файл надолго попадает в кеш и наша галерея ничего и знать не знает об обновлениях.
Сценарий 2:
Мы пишем клиентскую часть игры для он-лайн казино. Все процессы связанные с логикой игры происходят на жутко засекреченном сервере, наш клиент только отображает красиво все эти процессы. В определенный момент отправляет серверу данные о действиях игрока, в ответ получая XML с состоянием дел: Баланс игрока, комбинацию карт (или символов, если это слот-машина) ну и много всего разного.
Несмотря на то что мы не запрашиваем реально существующий XML, все равно результат заносится в кеш, и по следующему подобному запросу мы получим старые данные. В итоге – игрок выиграл 100000, но не знает, что это случилось.
Самый простой способ это приклеить Math.random() к запросу. Тогда браузер воспримет такой запрос как абсолютно новый и радостно вернет нам нужные данные в самом свежем виде. Но, полагаться на Math.random() всегда я бы не стал.
И я не стал. Как раз когда мне довелось писать кучу игр для казино, возник вопрос о железной защите от кеша. В итоге родился шизофренический метод, который позже я перелопатил в класс с одним единственным статичным методом. Базируется он на самой непостоянной субстанции – времени.
Однако на этом мы успокаиваться не будем. Иногда нам нужно чтобы свежие данные приходили не так часто. Допустим у меня есть сайт-портфолио, состоящий из нескольких html-страниц. На каждой имеется флеш-галерея работ. Если я буду отключать кеш для каждой загрузки – то мой посетитель будет упорно грузить свежие данные при каждом возвращении на страницу. Выход – обновляться скажем только каждый час, или день.
В общем хватит слов. Класс элементарный – и все будет ясно из его кода.
Метод один Cache.disable(key:String, level:Number);
key – это строка, которую нужно приклеить к запросу. Или банальный «?» («&» если в запросе уже есть пары имя=значение), или что-то сокровенное вроде «?nocache=».
level – уровень защиты от кеша. Передаем одну из констант:
Cache.MONTH, Cache.DAY, Cache.HOUR, Cache.MINUTE, Cache.FULL
код класса:
/**
* class Cache
* @author Mikhail Ivanchuk
* @version 0.1
*/
class ru.decafe.utils.Cache {
public static var MONTH:Number = 1;
public static var DAY:Number = 2;
public static var HOUR:Number = 3;
public static var MINUTE:Number = 4;
public static var FULL:Number = 5;
public static function disable(key:String, level:Number):String {
if (level == undefined) level = Cache.FULL;
var browser:Boolean = (_level0._url.substr(0,4) == "http");
// timestamp
var timestamp:Date = new Date();
var timestampY:Number = timestamp.getYear();
var timestampMN:Number = timestamp.getMonth();
var timestampD:Number = timestamp.getDate();
var timestampH:Number = timestamp.getHours();
var timestampM:Number = timestamp.getMinutes();
var timestampS:Number = timestamp.getSeconds();
var timestampMS:Number = timestamp.getMilliseconds();
var timestampMT:Number = Date.UTC(timestampY,timestampMN,timestampD,timestampH,timestampM,timestampS,timestampMS);
//date string
var dateString:String = timestampY.toString(16) +timestampMN.toString(16);
if (level <= Cache.MONTH) return (browser?(key+dateString):"");
dateString += timestampD.toString(16);
if (level <= Cache.DAY) return (browser?(key+dateString):"");
dateString += timestampH.toString(16);
if (level <= Cache.HOUR) return (browser?(key+dateString):"");
dateString += timestampM.toString(16);
if (level <= Cache.MINUTE) return (browser?(key+dateString):"");
dateString += timestampS.toString(16)+timestampMS.toString(16)+timestampMT.toString(16);
// random
var addition:String = (Math.floor(Math.random()*1024)).toString(16);
return (browser?(key+dateString+addition):"");
}
}
Popularity: 11% [?]
декабря 6, 2007