プロトタイプ/ Scriptaculous:段落のグループ(< p>)をクリックして選択する
-
08-07-2019 - |
質問
段落のリスト(< p>
)が提供されます。ユーザーが段落Aをクリックすると、段落Aのクラスが「アクティブ化」に変わります。これで、ユーザーは段落Bを選択し、AとBの間のすべての段落がクラスを「有効化」に変更します。
Bを再度クリックすると、Aのみがクラス「アクティブ」のままになります。
Aをクリックして、クラス「アクティブ」を選択します。 AとBの間のすべての段落(AとBを含む)で削除されます。
「非アクティブ化」することはできません。 AとBの間の段落。AとBの間の選択は、常に選択された段落の中断されないリストである必要があります。
Prototype / Scriptaculousでこれを実現する方法についてのヒントを教えてください。アプリケーションはRailsに実装されているため、RJSのヒントはさらに評価されます!
解決 4
OK、その間に同僚の助けを借りて、この問題に対する独自の答えを思いつきました:
<script type="text/javascript">
// holds paragraph A (first selected paragraph)
var a_selected = null;
// holds paragraph B (second selected paragraph)
var b_selected = null;
// holds all 'active' paragraphs
var selected_paras = [];
function class_flipper_init() {
// reset paragraphs A and B
a_selected = null;
b_selected = null;
var paragraphs = $("#foobar p");
paragraphs.each(function(paragraph, index) {
// if user clicks on a paragraph
paragraph.observe("click", function(event) {
// if A and B are 'active': reset everything.
if(b_selected != null) {
selected_paras.each(function(i) {
toggleStyle(i);
})
a_selected = null
b_selected = null
return
}
// if A is 'active'
if(a_selected != null) {
// if A is 'active' and selected B is below A:
// select all paragraphs between A and B
if(a_selected < index) {
b_selected = index;
for (var i = a_selected + 1; i <= index; i++ ) {
toggleStyle(paragraphs[i])
}
}
// if A is 'active' and selected B is above A:
// select all paragraphs between A and B
else if(a_selected > index) {
b_selected = index;
for (var i = a_selected - 1; i >= index; i-- ) {
toggleStyle(paragraphs[i])
}
}
// if A == B
else {
toggleStyle(paragraph)
a_selected = null
}
}
// if A is selected
else {
a_selected = index;
toggleStyle(paragraph)
}
});
});
}
function toggleStyle(paragraph) {
// remove active class
if (paragraph.hasClassName("active")) {
paragraph.removeClassName("active");
selected_paras = selected_paras.without(paragraph)
}
// set active class
else {
paragraph.addClassName("active");
selected_paras.push(paragraph)
}
}
</script>
class_flipper_init()
は、ページ(または、私の場合は特定のパーシャル)がロードされるたびに呼び出されます。
「純粋」で書かれた解決策をためらわずに提出してください。 RJSまたはもっとエレガントなもの。 :-)
他のヒント
段落が「info」というラッパーdivにあると仮定します:(テストしていませんが、次のようになります)
$('info').select('P').each(function(element) {
Event.observe(element,'click',function(event){
flipIt(event)
})
})
function flipIt(evt) {
var element = evt.element();
if($(element).hasClassName('active')) {
$(element).removeClassName('active')
}
else {
$(element).addClassName('active')
}
}
これを試してください
<!DOCTYPE HTMP PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<%= javascript_include_tag :defaults %>
</head>
<body>
<style type="text/css">
.active {
background-color: maroon;
}
</style>
<div id="info">
<p>
1 ald fhasdfd sfhjfh afhd fhasjfhjsdah fadfhasd<br/>
fasdhfhsdf ajhajkfh dfhdasjf fhdasf asdf<br/>
asdfh hsdjkhf dhfasdfh asdjfkdhfjkasd<br/>
fsdhf jksdhf sdfjkh asfsdf asdfasdfasdh<br/>
</p>
<p>
2 ald fhasdfd sfhjfh afhd fhasjfhjsdah fadfhasd<br>
fasdhfhsdf ajhajkfh dfhdasjf fhdasf asdf<br/>
asdfh hsdjkhf dhfasdfh asdjfkdhfjkasd<br/>
fsdhf jksdhf sdfjkh asfsdf asdfasdfasdh<br/>
</p>
<p>
3 ald fhasdfd sfhjfh afhd fhasjfhjsdah fadfhasd<br>
fasdhfhsdf ajhajkfh dfhdasjf fhdasf asdf<br/>
asdfh hsdjkhf dhfasdfh asdjfkdhfjkasd<br/>
fsdhf jksdhf sdfjkh asfsdf asdfasdfasdh<br/>
</p>
<p>
4 ald fhasdfd sfhjfh afhd fhasjfhjsdah fadfhasd<br>
fasdhfhsdf ajhajkfh dfhdasjf fhdasf asdf<br/>
asdfh hsdjkhf dhfasdfh asdjfkdhfjkasd<br/>
fsdhf jksdhf sdfjkh asfsdf asdfasdfasdh<br/>
</p>
</div>
<%javascript_tag :defer => 'defer' do -%>
$('info').select('P').each(function(element) {
Event.observe(element,'click',function(event){
flipIt(event)
})
})
function flipIt(evt) {
var element = evt.element();
var all = $('info').select('P');
var first = -1;
var last = -1;
var clicked = 0;
for ( i=0;i<all.size();i++ ) {
if( all[i].hasClassName('active') && first == -1 )
first = i;
if( all[i].hasClassName('active') && first != i )
last = i;
if ( all[i] == element){
clicked = i;
}
}
if ( first == clicked && last == -1 ){
all[clicked].removeClassName('active');
return;
}
if ( first == -1 && last == -1 ) {
all[clicked].addClassName('active');
return;
}
if ( last < clicked && first != -1 ){
for (i=first;i<=clicked;i++)
all[i].addClassName('active');
return;
}
if (last == clicked && first != -1 ) {
for (i=first+1;i<=clicked;i++)
all[i].removeClassName('active');
return; }
}
<%end%>
</body>
</html>
以下のコードをテストしましたが、少し複雑ですが、希望どおりに動作します。その鍵は、Prototypeの $$を使用して達成される配列内の段落を保持することです関数。
<style type="text/css">
.activated {
background-color: yellow;
}
</style>
.
.
.
<div id="container">
<p>This is paragraph 1.</p>
<p>This is paragraph 2.</p>
<p>This is paragraph 3.</p>
<p>This is paragraph 4.</p>
<p>This is paragraph 5.</p>
<p>This is paragraph 6.</p>
</div>
<script type="text/javascript">
Event.observe(document, "dom:loaded", function() {
var paragraphs = $("#container p");
paragraphs.each(function(paragraph, index) {
paragraph.observe("click", function(event) {
// A clicked; toggle activated class on A
if (index == 0) {
toggleStyle(paragraphs[0]);
// A clicked; remove activated class from A + 1 through to B
// if present
for (var i = 1; i <= paragraphs.length; i++) {
if (paragraphs[i] && paragraphs[i].hasClassName("activated")) {
paragraphs[i].removeClassName("activated");
}
}
}
// A + 1 clicked; toggle activated class on A + 1
if (index > 0 && paragraphs[0].hasClassName("activated")) {
for (var i = 1; i <= index; i++) {
toggleStyle(paragraphs[i]);
}
}
});
});
});
function toggleStyle(paragraph) {
if (paragraph.hasClassName("activated")) {
paragraph.removeClassName("activated");
} else {
paragraph.addClassName("activated");
}
}
</script>
所属していません StackOverflow