【问题标题】:Chaining button clicks with jQuery使用 jQuery 链接按钮点击
【发布时间】:2020-11-30 20:55:30
【问题描述】:

我正在尝试构建一个简单的网站,让您可以点击 6 个不同的按钮。每次单击按钮都应该触发特定内容的显示(作为 img 文件)。单击六个按钮中的每一个都会导致不同的内容。我已经设法通过 Javascript getElementById 实现了这部分。

但是,为了增加一点复杂性,我想实现顺序决策。这意味着单击按钮“1”然后单击按钮“2”(或 3-6)应该各自导致其他特定内容的显示。同样单击按钮“1”,然后单击“2”,然后再次单击“1”也应该显示特定内容。我的顺序决策应该被限制为只有两个按钮交互,直到决策结束。所以本质上,像 1 -> 2 -> 3 这样的事情不会发生,但 3 -> 6 -> 3 可能会发生。我希望我想做的事情不要太复杂。

无论如何,这是我为实现此目的而编写的一些代码,但我很确定我的切换功能不是正确的方法,因为我基本上只是将图片放在彼此之上并且没有顺序作出的任何决定。我认为要实现这一点,我需要链接点击,但我完全不知道如何实现这一点。非常感谢任何帮助。

a:link {
  color: white;
  text-decoration: none;
}
a:visited {
  color: white;
  text-decoration: none;
}
a:hover {
  color: white;
  text-decoration: none;
}
a:active {
  color: white;
  text-decoration: none;
}    

a.pos:link {
  color: black;
  text-decoration: none;
}
a.pos:visited {
  color: black;
  text-decoration: none;
}
a.pos:hover {
  color: white;
  text-decoration: none;
}
a.pos:active {
  color: black;
  text-decoration: none;
}        
    
a.button:link, a.button:visited {
  margin: auto;
  position: absolute;
  top: 0px;
  left: 0px;
  background-color: yellowgreen;
  width: 345px;
  line-height: 20px;
  height: 185px;
  border: 2px solid;
  border-color: white;
  text-align: center;
  border-radius: 100px;
  font-family: open sans;
  font-size: 9px;
  color: black;
  font-weight: 650;
  color: white;
  padding: 14px 25px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
}
    
a.button:hover, a.button:active {
  background-color: yellowgreen;
}       
    
body {margin:0;}

ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #333;
  position: fixed;
  top: 0;
  width: 100%;
}

li {
  float: left;
}

li a {
  display: block;
  color: white;
  text-align: center;
  padding: 20px 30px;
  font-family: open sans;
  text-decoration: none;
}

li a:hover:not(.active) {
  background-color: #111;
}

.active {
  background-color: #4CAF50;
}
    
h1 {
        color: whitesmoke;
        font-family: open sans;
        font-size: 300%;
    }
    
.table {
  margin: auto;
  position: relative;
  width:  450px;
  top: -1350px; 
  border: 6px solid #333333;
  border-radius: 250px;
  background: #737373;
  padding-top: 150px;
  padding-right: 50px;
  padding-left: 50px;
  padding-bottom: 150px;

}
    
#quattro {
    margin: auto;
    position: absolute;
    bottom: -25px;
    right: 250px;
    background-color: gold;
    width: 50px;
    line-height: 50px;
    height: 50px;
    border: 1px solid black;
    text-align: center;
    border-radius: 50px;
    font-family: open sans;
    font-size: 20px;
    font-weight: 650;
}

#uno {
    margin: auto;
    position: absolute;
    top: -25px;
    right: 250px;
    background-color: gold;
    width: 50px;
    line-height: 50px;
    height: 50px;
    border: 1px solid black;
    text-align: center;
    border-radius: 50px;
    font-family: open sans;
    font-size: 20px;
    font-weight: 650;
}

#duo {
    margin: auto;
    position: absolute;
    top: 25px;
    right: 10px;
    background-color: gold;
    width: 50px;
    line-height: 50px;
    height: 50px;
    border: 1px solid black;
    text-align: center;
    border-radius: 50px;
    font-family: open sans;
    font-size: 20px;
    font-weight: 650;
}

#tres {
    margin: auto;
    position: absolute;
    bottom: 25px;
    right: 10px;
    background-color: gold;
    width: 50px;
    line-height: 50px;
    height: 50px;
    border: 1px solid black;
    text-align: center;
    border-radius: 50px;
    font-family: open sans;
    font-size: 20px;
    font-weight: 650;
}

#cinqo {
    margin: auto;
    position: absolute;
    bottom: 25px;
    left: 10px;
    background-color: gold;
    width: 50px;
    line-height: 50px;
    height: 50px;
    border: 1px solid black;
    text-align: center;
    border-radius: 50px;
    font-family: open sans;
    font-size: 20px;
    font-weight: 650;
}
    
#seis {
    margin: auto;
    position: absolute;
    top: 25px;
    left: 10px;
    background-color: gold;
    width: 50px;
    line-height: 50px;
    height: 50px;
    border: 1px solid black;
    text-align: center;
    border-radius: 50px;
    font-family: open sans;
    font-size: 20px;
    font-weight: 650;
}

.imgrange1 {
    text-align: center;
    color: white;
    position: absolute;
    top: 400px;
    left: -400px;
    }
    
.imgrange2 {
    text-align: center;
    color: white;
    position: absolute;
    top: 400px;
    left: 320px;
    }

.centered {
  font-family: open sans;
  font-size: 150%;
  position: absolute;
  top: -3%;
  left: 50%;
  transform: translate(-50%, -50%);
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" href="css/style.css">
<style>
    
.myimgdivtoggle1 {
    display: none;

}
    
.myimgdivtoggle2 {
    display: none;

}

.myimgdivtoggle3 {
    display: none;

}
    
.myimgdivtoggle4 {
    display: none;

}

.myimgdivtoggle5 {
    display: none;

}
    
</style>
    
<script>
    
$(document).ready(function(){
    $('.togglebtn1').click(function(){
        $('.myimgdivtoggle1').toggle();
    });
});

$(document).ready(function(){
    $('.togglebtn2').click(function(){
        $('.myimgdivtoggle2').toggle();
    });
});
    
$(document).ready(function(){
    $('.togglebtn3').click(function(){
        $('.myimgdivtoggle3').toggle();
    });
});
    
$(document).ready(function(){
    $('.togglebtn4').click(function(){
        $('.myimgdivtoggle4').toggle();
    });
});

$(document).ready(function(){
    $('.togglebtn5').click(function(){
        $('.myimgdivtoggle5').toggle();
    });
});  

$(document).ready(function(){
    $('.togglebtn6').click(function(){
        $('.myimgdivtoggle6').toggle();
    });
}); 

</script>
    
</head>
<body>
<ul>
  <li><a class="active" href="index.html">Main</a></li>
  <li><a href="#news">News</a></li>
  <li><a href="#contact">Contact</a></li>
  <li><a href="#about">About</a></li>
</ul>

<div style="padding:20px;margin-top:30px;background-color:cadetblue;height:1500px;">
    <h1><center>TEST</center></h1>
    </div>
    <div class="table">
        <button type="button" class="togglebtn1" id="uno">1</button>  
        <div class="myimgdivtoggle1">
        <img src="1.JPG" class="imgrange1"/>
        </div>
        <button type="button" class="togglebtn2" id="duo">2</button>  
        <div class="myimgdivtoggle2">
        <img src="2.JPG" class="imgrange1"/>
        </div>
        <button type="button" class="togglebtn3" id="tres">3</button>  
        <div class="myimgdivtoggle3">
        <img src="3.JPG" class="imgrange1"/>
        </div>
        <button type="button" class="togglebtn4" id="quattro">4</button>  
        <div class="myimgdivtoggle4">
        <img src="4.JPG" class="imgrange1"/>
        </div>
        <button type="button" class="togglebtn5" id="cinqo">5</button>  
        <div class="myimgdivtoggle5">
        <img src="5.JPG" class="imgrange1"/>
        </div>
        <button type="button" class="togglebtn6" id="seis">6</button>  
        <div class="myimgdivtoggle6">
        <img src="6.JPG" class="imgrange1"/>
        </div>
</body>
</html>

【问题讨论】:

  • 您的情况是相当可行的,但是您应该确定约束条件,例如:哪些组合是可能的,哪些组合代表哪些内容等。然后您应该监听所有按钮的点击。每个按钮都应该有一个value 属性,它代表按钮所持有的值和一个id 属性来标识按钮。单击按钮时,应将该按钮的值添加到数组中。该数组将保存您单击的按钮的组合,例如:["3", "6", "3"]。您可以检查数组是否匹配任何已知的内容组合。
  • 感谢您的评论。不太清楚如何处理数组,因为我是新手,还没有工作过。我认为我的案子对于有专业知识的人来说是可行的,所以这是一种解脱,哈哈。你知道我可以阅读如何在我的代码中实现数组的任何资源吗?谢谢!

标签: javascript jquery decision-tree chaining


【解决方案1】:

虽然我无法为您提供可靠的解决方案,但我可以提供一个小示例,说明如何合并一个跟踪已单击按钮的数组,以及从按钮组合中获取某些内容的方法.

运行示例并尝试组合363254521165 以显示一些结果。我已尽力展示生成的输出是什么。

我建议你看看它,如果你有任何问题,请提出。我去看看你有没有。

$(document).ready(function() {
  /**
   * Select the buttons.
   * The $display and $clickedButtons are just to output
   * the values that are stored.
   */
  const $buttons = $('.button');
  const $display = $('#display');
  const $clickedButtons = $('#clicked-buttons');
  const $removeButton = $('#remove-button');

  /**
   * Array which tracks your clicked buttons.
   * If a button is clicked, the value of that button should be added to this array. 
   * The combination of the values will then later represent the key.
   */
  const values = [];

  /**
   * This is where any know combinations are stored.
   * The values in the values array will later be transformed into a single string to 
   * see if it matches any key in the combinations object below. 
   * If it does, it will give you a value, otherwise undefined.
   */
  const combinations = {
    "363": "https://www.fillmurray.com/200/200",
    "254": "https://www.fillmurray.com/220/220",
    "521": "https://www.fillmurray.com/240/240",
    "165": "https://www.fillmurray.com/300/300"
  };

  /**
   * Combines the values to form a single key and check if that key matches a combination. 
   * If there is a match the content should be anything other than undefined.
   */
  function tryCombination() {
    // This will output the current values from the array.
    $clickedButtons.text(values);
        
    // Transform the array into a single string.
    // This will be the key to select content.
    // ["1", "2", "3"] becomes "123".
    const key = values.join('');    

    // Check if key has a match in the combinations object.
    const url = combinations[key];
    if (url !== undefined) {
      // It does, show the content.
      $display.attr('src', url);
      $display.removeClass('hidden');
    } else {
      // It doesn't, empty the content.
      $display.removeAttr('src');
      $display.addClass('hidden');
    }
  }

  /**
   * Listen for the click event on all the buttons.
   * When clicked, get the value of that clicked button and add that to the values array. 
   * It then calls the tryCombination function to evaluate if the values in the values 
   * array make a valid combination.
   */
  $buttons.on('click', function() {
    // This is the currently clicked button.
    const $button = $(this);
    
    // Get the value of the button.
    const value = $button.val();
    
    // If there already are 3 previously clicked buttons,
    // then empty the array, so we can start a new combination.
    if (values.length === 3) {
      values.length = 0;
    }
    
    // Now add the newly clicked value.
    values.push(value);

    // Render and try the combination.
    tryCombination();
  });

  /**
   * Remove the last item in the values array.
   * Then retry to create a valid combination.
   */
  $removeButton.on('click', function() {
    // Remove the last item from the values array
    values.pop();

    // Render and try the new combination.
    tryCombination();
  })
});
.container {
  display: grid;
  grid-template-rows: auto auto;
  grid-template-columns: 200px 1fr;
  grid-gap: 1em;
  border: 1px solid #d0d0d0;
  background-color: #f7f7f7;
  padding: 1em;
  border-radius: 5px;
}

.buttons {
  grid-area: 1 / 1 / 2 / 3;
}

#display {
  grid-area: 2 / 1 / 3 / 2;
  width: 200px;
  height: 200px;
  background-color: #d0d0d0;
  border-radius: 5px;
}

#clicked-buttons {
  grid-area: 2 / 2 / 3 / 3;
  display: block;
  background-color: #d0d0d0;
  border-radius: 5px;
  padding: 1em;
  margin: 0;
}

#remove-button {
  grid-area: 1 / 2 / 2 / 3;
}

.hidden {
  opacity: 0;
  visibility: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="container">
  <div class="buttons">
    <button class="button" id="1" value="1" >1</button>
    <button class="button" id="2" value="2" >2</button>
    <button class="button" id="3" value="3" >3</button>
    <button class="button" id="4" value="4" >4</button>
    <button class="button" id="5" value="5" >5</button>
    <button class="button" id="6" value="6" >6</button>
  </div>
  <img id="display" class="hidden">
  <button id="remove-button">Remove last input</button>
  <code id="clicked-buttons"></code>
</div>

编辑

本着展示胜于讲述的精神;您的最后一条评论是关于数字的松散组合。这又增加了一层复杂性。

对象只能有作为字符串(或符号)的键来获取和设置值。但是在您的情况下,您需要一个以任意顺序表示键的数字数组,因此普通对象不再适用。

解决方案是Map 对象。这个对象可以有任何类型的键和值。所以我们可以在数字组合和它们所代表的图像之间建立联系(因此得名“地图”)。

下面的例子使用了这种方法。我编写了一个函数来检查一个数字数组是否与地图中的任何组合匹配。如果确实如此,它会返回一组图像,参考您之前的评论。

检查一下。我相信这个比较复杂,所以请再次随意提问。

/**
 * Create a Map instance.
 */
const combinations = new Map();

/**
 * Values and keys are added with the set() method.
 * This could still be improved with a loop setting each 
 * combination / images pair.
 */
combinations.set([3, 3, 6], ['https://www.fillmurray.com/200/200', 'https://www.fillmurray.com/200/200']);
combinations.set([2, 4, 5], ['https://www.fillmurray.com/220/220', 'https://www.fillmurray.com/220/220']);
combinations.set([1, 2, 5], ['https://www.fillmurray.com/240/240']);
combinations.set([1, 5, 6], ['https://www.fillmurray.com/300/300', 'https://www.fillmurray.com/300/300', 'https://www.fillmurray.com/300/300']);

const tryCombination = (key, combinations) => {
  /** 
   * Loop over every combination.
   * [combination, images] exposes the key-value pair, 
   * it's just a syntax to write fewer lines
   */
  for (const [combination, images] of combinations) {
    /**
     * Create an array for the matches. If a number of the
     * combination is in the given key, then that number
     * will be pushed to the matches list. In the end, 
     * if everything matches, we should have just as many
     * matches as numbers in the combination. That way
     * we know if a key is correct.
     */
    const matches = [];
    
    /**
     * We'll do some manipulation on the combination array,
     * so to keep it intact we make a copy and manipulate that instead.
     */
    const combinationCopy = Array.from(combination);
    
    /**
     * Count backwards through the combination array.
     * Backwards counting is necessary when you remove items
     * from the array while looping. I'd suggest you look
     * into that subject.
     */
    for (let i = combinationCopy.length - 1; i >= 0; i--) {
      /**
       * Get the current number we're looping over.
       */
      const number = combinationCopy[i];
      
      /**
       * If that number is in the key array..
       */
      if (key.includes(number)) {
        /**
         * ..then push that number to the matches array..
         */
        matches.push(number);
        
        /**
         * ..and remove it from the copied combination array.
         * We do this to prevent duplicate hits for cases
         * where you have multiple occurrences of the same number,
         * like [3, 3, 6]. When the first 3 hits, it will be removed.
         * Then we have [3, 6] and we know we only need one more
         * 3 and a 6.
         */
        combinationCopy.splice(i, 1);
      }
    }
    
    /**
     * Now if every number has been matched correctly, then
     * the amount of matches should be the same as the length
     * of the combination. If that is the case, return the 
     * images. Otherwise, do nothing.
     */
    if (matches.length === combination.length) {
      return images;
    }
  }
  
  /**
   * If there are no matches, just return false, notifying the
   * user that the combination is incorrect.
   */
  return false;
};

console.log(tryCombination([5, 4, 2], combinations)); // Hit!
console.log(tryCombination([5, 1, 6], combinations)); // Hit!
console.log(tryCombination([2], combinations)); // Fail!
console.log(tryCombination([5, 4, 4], combinations)); // Fail!
console.log(tryCombination([3, 6, 3], combinations)); // Hit!

【讨论】:

  • 哇,这真是令人印象深刻。谢谢你的帮助!我已经继续并添加了所有可能的组合,包括那些只单击一个按钮来执行文本结果的情况。我唯一的问题(现在:D)是:该脚本是否也能够输出图像,而不是输出文本?类似: const combination = { "363": "image1.jpg", "212": "image2.jpg" 等等?
  • 不客气。当然!我已将文本替换为应以相应组合显示的图像路径,并将显示 &lt;span&gt; 替换为 &lt;img&gt;。现在,当找到组合时,设置图像的src 属性并显示图像。
  • 太棒了!我将花几个小时来研究这一切是如何运作的,但感谢您到目前为止的时间。祝你有个美好的一天!!
  • 嘿,埃米尔!所以这很有帮助,从那以后我就一直在使用这个脚本。又出现了一个问题:是否可以在解锁组合后使代码显示多于 1 张图片,例如如果我输入 const combination = { "363": "image1.jpg & "image2.jpg" 以便组合显示一次给我两张图片?
  • 嘿@aaaRt。很高兴听到。这当然是可能的。目前组合"363" 的值是单个字符串。但该值也可以是字符串数组,例如["image1.jpg", "image2.jpg"]。然后,您无需设置单个图像的src,而是遍历数组并为数组中的每个图像设置图像的src。当然,对于数组中的每个图像,您都需要一个&lt;img&gt;。您可以动态创建这些元素,如果每个组合的图像数量有所不同,这可能是一个好主意。希望对您有所帮助。
猜你喜欢
  • 2011-06-24
  • 1970-01-01
  • 1970-01-01
  • 2019-07-12
  • 1970-01-01
  • 2020-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多