Jump to content

filter div elements by classname


Recommended Posts

Hi

My users enter a lot of skills by skill families, and because these are stored as fields and I can't transpose the data easily within Caspio, when I want a user to view or edit their record, I need to customise the details pages. All the in-built Caspio features rely on filtering by columns and I haven't found a way to do this by row (and certainly not an option that doesn't involve a lot of page calculations and long load times). So I've been needed to use JS.

A great solution appears to be filtering by div class element (I've added the original code from W3 schools below). The only problem, the buttons submit the page when the user clicks rather than just filtering. I tried adding code to stop that, but that didn't work. If I add the code just to a plain HTML data page, it works as expected, but it doesn't work for any other datapage type.

Any ideas on why the code causes the page to submit and any ideas how to stop the filters from submitting yet still allow for a page submission?

<html>
<style>
.filterDiv {
  float: left;
  background-color: #2196F3;
  color: #ffffff;
  width: 100px;
  line-height: 100px;
  text-align: center;
  margin: 2px;
  display: none;
}

.show {
  display: block;
}

.container {
  margin-top: 20px;
  overflow: hidden;
}

/* Style the buttons */
.btn {
  border: none;
  outline: none;
  padding: 12px 16px;
  background-color: #f1f1f1;
  cursor: pointer;
}

.btn:hover {
  background-color: #ddd;
}

.btn.active {
  background-color: #666;
  color: white;
}
</style>
<body>

<h2>Filter DIV Elements</h2>

<div id="myBtnContainer">
  <button class="btn active" onclick="filterSelection('all')"> Show all</button>
  <button class="btn" onclick="filterSelection('cars')"> Cars</button>
  <button class="btn" onclick="filterSelection('animals')"> Animals</button>
  <button class="btn" onclick="filterSelection('fruits')"> Fruits</button>
  <button class="btn" onclick="filterSelection('colors')"> Colors</button>
</div>

<div class="container">
  <div class="filterDiv cars">BMW</div>
  <div class="filterDiv colors fruits">Orange</div>
  <div class="filterDiv cars">Volvo</div>
  <div class="filterDiv colors">Red</div>
  <div class="filterDiv cars">Ford</div>
  <div class="filterDiv colors">Blue</div>
  <div class="filterDiv animals">Cat</div>
  <div class="filterDiv animals">Dog</div>
  <div class="filterDiv fruits">Melon</div>
  <div class="filterDiv fruits animals">Kiwi</div>
  <div class="filterDiv fruits">Banana</div>
  <div class="filterDiv fruits">Lemon</div>
  <div class="filterDiv animals">Cow</div>
</div>

<script>
filterSelection("all")
function filterSelection(c) {
  var x, i;
  x = document.getElementsByClassName("filterDiv");
  if (c == "all") c = "";
  for (i = 0; i < x.length; i++) {
    w3RemoveClass(x[i], "show");
    if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
  }
}

function w3AddClass(element, name) {
  var i, arr1, arr2;
  arr1 = element.className.split(" ");
  arr2 = name.split(" ");
  for (i = 0; i < arr2.length; i++) {
    if (arr1.indexOf(arr2[i]) == -1) {element.className += " " + arr2[i];}
  }
}

function w3RemoveClass(element, name) {
  var i, arr1, arr2;
  arr1 = element.className.split(" ");
  arr2 = name.split(" ");
  for (i = 0; i < arr2.length; i++) {
    while (arr1.indexOf(arr2[i]) > -1) {
      arr1.splice(arr1.indexOf(arr2[i]), 1);     
    }
  }
  element.className = arr1.join(" ");
}

// Add active class to the current button (highlight it)
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
  btns[i].addEventListener("click", function(){
    var current = document.getElementsByClassName("active");
    current[0].className = current[0].className.replace(" active", "");
    this.className += " active";
  });
}
</script>

</body>
</html>

 

image.thumb.png.7997d7329d0ea231e384ff4c0aa11968.png

Link to comment
Share on other sites

Thanks for the suggestion Kronos - it doesn't solve the problem though. My code adds the buttons, and the filter function works once, but before you can read the output, the page submits, which given I'm not hitting submit, it's in effect "auto" submitting. I've set the page to reload, so I could probably workaround this by getting the button to pass a parameter and to read this on reload, but seeing the answer, then the page reloading (along with all the calculations and lookups repeating) this would be such a poor ux.

I've also tried and failed to modify the code Ned used in his live stream for instant filtering of results, to see if I might be able to use the basic constructs in a details page to show by group but I've had even less success. 

 

Link to comment
Share on other sites

I've managed to get the script to work by stopping the submit function. I added the following to the start of my script in footer. Works as is for the display only page; I think for the input version, adding a condition should get the code to work.

And I can now conditionally group my items by a logic that makes sense for my user rather than a fixed amount (previously I was using a collapsible every 5 items and couldn't use the overarching grouping)

 

document.addEventListener('BeforeFormSubmit', function () {

event.preventDefault();
      }
);
 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...