script.aculo.usのeffects.jsのエフェクトを使うとビジュアル効果のある表示、非表示が非常に手軽に行えるのだが困ったことがある。
Effect.BlindUp,Effect.BlindDownなどでエフェクト処理が終了しないうちに再びエフェクト処理を呼び出すとうまく動かない。
例えば1.5_rc5に同梱のサンプルのようにonclickなどのイベントハンドラで呼び出すサンプルでエフェクトを呼び出すリンクを連続してクリックすると最悪エラーになってしまう。
<div>DEMO:<a href="#" onclick="Effect.BlindUp('demo-div')">BlindUp</a>
<a href="#" onclick="Effect.BlindDown('demo-div')">BlindDown</a></div>
<div id="demo-div" style="float:left">
要素<br />
要素<br />
要素
</div>
<div style="clear:both"> </div>
要素
要素
エフェクト処理が要素のその時の状態を参照している場合具合が悪い。クリック連打なんてよくあることなので対応してそうなんだけどどうも未対応なので自前でごにょる事に。
思いつく回避策は、簡単な方法だとエフェクト中はイベントを呼び出すボタンやリンクを隠したり無効にする、とかイベントの呼び出し先でfalseを返す、くらいか。
クリックできるものがあるからいけないという安直な考えでイベントを呼び出すリンクを隠すことに。
具体的な方法はどうしようかと考えていると、はてなでscriptaculouについてのエントリ
はてな技術発表会日記があるのを思い出し参考に。
コアエフェクトの項にあったエフェクトの開始や実行中、終了時に処理をフックできるオプション『beforeSetupInternal』『afterFinishInternal』が良さげなので
オプションで指定してみた。
<div>TEST:<span id="blind_test">
<a href="#" onclick="Effect.BlindUp('blind-div',{
beforeStartInternal: function(){
Element.hide($('blind_test'))
},
afterFinishInternal: function() {
Element.show($('blind_test'))
}
});return false">BlindUp</a>
<a href="#" onclick="Effect.BlindDown('list',{
beforeStartInternal: function(){
Element.hide($('blind_test'))
},
afterFinishInternal: function() {
Element.show($('blind_test'))
}
});return false">BlindDown</a></span>
</div>
<div id="blind-div" style="float:left">
要素<br />
要素<br />
要素
</div>
<div style="clear:both"> </div>
要素
要素
あれ、 BlindUpがうまくいかない・・・。複合エフェクトには使えないのかとeffects.jsの中をあらためて見るとEffect.BlindDownは予めafterFinishInternalがセットしてあり、呼び出す際にafterFinishInternalを上書きしていてうまくいかなかった。 複合エフェクト側で既にフックされているオプションや処理をセットする時は同じものもセットする必要があるか。なのでEffect.BlindUpの処理から必要なトコを持ってきて
<div>TEST2:<span id="blind_test2">
<a href="#" onclick="Effect.BlindUp('blind-div2',{
beforeStartInternal: function(){
Element.hide($('blind_test2'));
},
afterFinishInternal: function(effect) {
Element.hide(effect.element);
Element.undoClipping(effect.element);
Element.show($('blind_test2'));
}
});return false">BlindUp</a>
<a href="#" onclick="Effect.BlindDown('blind-div2',{
beforeStartInternal: function(effect){
Element.hide($('blind_test2'));
},
afterFinishInternal: function(effect) {
Element.undoClipping(effect.element);
effect.element.style.height = $('blind-div2').style.height;
Element.show($('blind_test2'));
}
});return false">BlindDown</a></span>
<div id="blind-div2" style="float:left">
要素<br />
要素<br />
要素
</div>
<div style="clear:both"> </div>
要素
要素
として無事動作。
せっかくなのでBlindDown<=>BlindUpを一つのイベントハンドラで切り替えられるようにEffect.BlindUpとEffect.BlindDownの処理を1つに合体したエフェクトを作りました。
Effect.toggleBlind = function(element,button) {
var element = $(element);
var button = Object.extend({before:false,after:false},button || {});
if (button.before && !button.after)
button.after = button.before;
if (!button.before && button.after)
button.before = button.after;
if (document.layers?element.clip.height:(element.offsetHeight||element.style.pixelHeight||0)) {
Element.makeClipping(element);
return new Effect.Scale(element, 0,
Object.extend({ scaleContent: false,
scaleX: false,
restoreAfterFinish: true,
beforeStartInternal: function(effect){
if (button.before)
Element.hide(button.before);
},
afterFinishInternal: function(effect) {
Element.hide(effect.element);
Element.undoClipping(effect.element);
if (button.after)
Element.show(button.after);
}
}, arguments[2] || {})
);
}
else {
var oldHeight = element.style.height;
var elementDimensions = Element.getDimensions(element);
return new Effect.Scale(element, 100,
Object.extend({ scaleContent: false,
scaleX: false,
scaleFrom: 0,
scaleMode: {originalHeight: elementDimensions.height,
originalWidth: elementDimensions.width},
restoreAfterFinish: true,
beforeStartInternal: function(effect){
if (button.after)
Element.hide(button.after);
},
afterSetup: function(effect) {
Element.makeClipping(effect.element);
effect.element.style.height = "0px";
Element.show(effect.element);
},
afterFinishInternal: function(effect) {
Element.undoClipping(effect.element);
effect.element.style.height = oldHeight;
if (button.before)
Element.show(button.before);
}
}, arguments[2] || {})
);
}
}
<div>Effect.toggleBlind:<a href="#" onclick="Effect.toggleBlind('blind-div3',{
before:'toggle_up',
after:'toggle_down'
},{duration:0.3}); return false"><span id="toggle_up">toggleBlindUp</span>
<span id="toggle_down" style="display:none">toggleBlindDown</span></a></div>
<div id="blind-div3" style="float:left">
要素<br />
要素<br />
要素
</div>
<div style="clear:both"> </div>
要素
要素
これだとエフェクト中は何も表示されませんがエフェクト中にもフックさせることができるので、それを利用してエフェクト中にも何か表示させることもできます。他の複合エフェクトでもオプションを設定すればかなり自由度の高い事をさせられそう。
script.aculo.us素晴らしい。
コメント
最悪を対応しなかった。
でも、クリックするところが消えてしまうのは勿体無い・・・。onclickイベントを一時的に消すというのはどうでしょう?
gjtdc fcejrfcf
http://mincjwq.com
sdnbtnw nyxgdpe
http://kodrpnb.com
nbiukz jhpu
http://yrisgjmt.com
owucq blniw
http://oivuvtagxn.com
paiuz abuxugno
http://qmuboxexsv.com
rkpfrw seebbm
http://zanedpj.com
ktkziq itnc
http://jwffcckp.com
yrlmqjr egunm
http://buoxqjgzbkhg.com
mwjoua nbrkj
http://mfphwbdgzcm.com
bmtkvsu lvayr
http://ijvtsclwujx.com
mtllkl ofofpvhj
http://hwaaeke.com
obvig hzecwpup
http://keaylomcj.com
pngrmh jruhad
http://tgqhvl.com
mudjhdg rjkocmo
http://sxcfyjwmoqrm.com
budirh htbkpk
http://ckamjba.com
npvkk mtzsyn
http://xbnlgu.com
kkamad jzom
http://cruedjfolvr.com
kydzo ocop
http://ecipbb.com
gpydmze hcujirn
http://nvgzgk.com
jvrnxzh dzxln
http://bdvbbdisr.com
bfgnf tswzwg
http://jgwptjspls.com
ipghjb pehspmq
http://ctetjwichvdj.com
zyptqy ytrxo
http://eolrqhoei.com
dzvmsrv oeyqrusa
http://jwpnindryym.com
epfgv moptbc
http://xfqcyimyb.com
oquvk cteeh
http://rmfmvvu.com
wbcprlo xbaqajcw
http://kqsfxrajg.com
eenhxyb bunw
http://owbzgzsnuduw.com
vgxaf aqbyfok
http://liukkcxb.com
rowlcsc esvpjlkg
http://gtbhlxwq.com
ukvtyb otwkpdsr
http://ukxebo.com
stjzjp qiyqicqb
http://admcuhfln.com
qowiola wfbspgj
http://ersfsr.com
muiwou zsugusrm
http://jbsatcnmnbu.com
iejcl pzhmxmk
http://tfntcjn.com
ydqqjfz msszi
http://chtzosbhmeku.com
mgffv wdffpls
http://ojzinfcffv.com
nfslwm hdbp
http://ietmkfnlmb.com
mcixd ynocavjl
http://eacondwelm.com
oxyky sujp
http://zyzdpkmwn.com
ycycunt ldztf
http://lgjjrgnwsxn.com
xsdfg svlrkq
http://pkihvibl.com
mbveu oibai
http://ffcrixbqay.com
giletw oqmfp
http://goijbvve.com
wezvua frqzt
http://ooiupwcf.com
tdqicta thnjxv
http://bxhtzqguk.com
szqpo dqrodnv
http://henssybjytey.com
hoprss jtnty
http://fnabex.com
dvetzmt xomqp
http://lehmcjxi.com
czzghok uwxsse
http://vnvouvh.com
ldanfs ljkb
http://ngrzyncff.com
atacbb saitv
http://vzjxvtanyobs.com
lbujcf zskswws
http://hhqwkn.com
jahodj vehngpmy
http://owymeplpjaeb.com
ilqaami psnx
http://divkgzamild.com
doktju fhqqanz
http://elepbeipiaah.com
swiadwq nads
http://hkydia.com
shjuuq xkiqspko
http://vaamruld.com
agdcqyh kuipghhl
http://rbzrxewbrw.com
qwponlb mvrh
http://emsurokvv.com
僕のメモ帳
どのマOOコもみんなヌメヌメできもちーし!!
この調子だと今月60萬いくぞ!!
http://mlstarn.com/ornturn/
みなさんはストローでマン汁を飲めますか?
小生、今人生で一番悩んでおります。
http://quitblue.com/en/
もうビラビラの感触でイキそうだったし(* ´Д`*)
まさか俺の童帝が売れるとわな。大切にとっとくもんだな(笑)
http://subekarazu.com/mkstktrz/
もう腰がとまんねぇし まじカオス!!
この一回で5万貰えるんだから二度カオスだな(爆笑)
喜んで札束だしてくれるよww
勝手にイッテくれるしソープ君はやめれんな( -ω-)
要望通りにティヌポくわえさせてヴァイ_ブぶっ込んであげたら
痙攣してたよ(笑)とりあえず今月もこれでニート決定だわ( -ω-)
はみ出た息子をチュぺチュペいわせて吸いまくってたよ(爆笑)
変 * 態 プレーの時はハブリいいしお勧めだぞww
ttp://mdern.net/en/
http://gorioyaji.net/so/
これで報酬頂いたら風=俗はありえないでしょ!
ガン謝して報酬まで貰ってオレ最強でしょ!!
http://koreikura.net/beg/
正直働いてらんねぇわwww
http://mlstarn.com/ornturn/
もう無理。。もう2度と会社行きません!!
http://pupipo.net/deku/
しっかしデビュー戦でいきなりパイパソかよ!!
http://koreikura.net/beg/
ベット行った頃にはすでにカップル気分だもん!!
http://sersai.com/sntk/ajkrvll/
まっ彼女できた事ねぇけどな(爆笑)
金持ってそうな女はみんな変" "態に見えてくるなwww
http://sersai.com/en/
コメントを書く