【问题标题】:Prototype/Scriptaculous: Selecting groups of paragraphs (<p>) by clicking on themPrototype/Scriptaculous:通过单击选择段落组 (<p>)
【发布时间】:2009-03-10 10:16:51
【问题描述】:

给出了段落列表 (&lt;p&gt;)。一旦用户点击段落A,段落A的类别就变为“激活”。现在用户选择段落 B 并且 A 和 B 之间的所有段落都将其类更改为“已激活”。

通过再次单击 B,只有 A 保持“活动”类。

点击 A 后,A 和 B 之间的所有段落(包括 A 和 B)上的“活动”类都会被删除。

不应“停用” A 和 B 之间的任何段落。A 和 B 之间的选择应该始终是所选段落的不间断列表。

谁能给我一个关于如何使用 Prototype/Scriptaculous 实现这一点的提示?该应用程序是在 Rails 中实现的,因此任何 RJS 中的提示都将更加感激!

【问题讨论】:

    标签: javascript ruby-on-rails dom prototypejs scriptaculous


    【解决方案1】:

    假设您的段落位于名为“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')
        }
    }
    

    【讨论】:

    • 一个很好的起点,但它只是切换每个段落的激活状态; Javier 的要求有点复杂。
    • 不过,非常感谢 Diodeus 的起点!我将尝试在 RJS 中实现它并使用它...希望同时其他人为我的问题中更复杂的部分提出解决方案。 :)
    • 你说得对,约翰。我今天没有时间把它全部完成。
    【解决方案2】:

    试试这个

    <!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>
    

    【讨论】:

    • 感谢 cobranet!您可以将答案的所有代码格式化为代码吗?这将使您的答案更具可读性。
    【解决方案3】:

    我已经测试了下面的代码,它可以满足您的需求,尽管它有点复杂。它的关键是将段落保存在一个数组中,这是使用 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>
    

    【讨论】:

    • 我有一个指向 Prototype 的 $$ 函数的文档的链接,但不幸的是 Markdown 编辑器已经吞下了它!这是prototypejs.org/api/utility#method-$$
    • 嗨,约翰,非常感谢您的提交!不过我有一个问题:第 20 行的“索引”变量在哪里定义,分别。它来自哪里?
    • “index”变量是传递给“each”方法的迭代器函数的一部分。见prototypejs.org/api/enumerable/each
    • 如果我点击第 5 段,2、3、4 也会被选中。这是 OP 想要的吗?
    【解决方案4】:

    好的,与此同时,在同事的帮助下,我想出了一个自己的答案来解决这个问题:

    <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 或更优雅的方式编写的解决方案。 :-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-25
      • 2020-03-24
      • 2019-08-25
      • 1970-01-01
      • 2013-02-09
      • 1970-01-01
      相关资源
      最近更新 更多