How can I simplify this select function? - javascript

I don't know anything about javascript. I just found this snippet in the web when I was trying to find a solution on how to achieve what I need. Is there any way to simplify this since I will be adding around 40 elements that I need to show and hide.
var $selects = $('.filters select');
$selects.on('change', getValues).first().trigger("change");
function getValues() {
var vals = $selects.map(function() {
return this.value;
}).get();
if (vals.join('') === "a1b2c3") {
$(".box_wrapper").not(".a1b2c3").hide();
$(".a1b2c3").show();
$('html,body').animate({
scrollTop: $(".a1b2c3").offset().top},
'slow');
}
else if (vals.join('') === "d4e5f6") {
$(".box_wrapper").not(".d4e5f6").hide();
$(".d4e5f6").show();
$('html,body').animate({
scrollTop: $(".d4e5f6").offset().top},
'slow');
}
else{
$(".vid_box").hide();
}
}
I think I can simplify this further by getting the joined value from the select boxes and use it on the function above and since I am using the same value combination for the class. I just don't know how. Is that possible? Thanks in advance guys!

Perhaps something like this (air code):
var $selects = $('.filters select');
$selects.on('change', getValues).first().trigger("change");
function getValues() {
var vals = $selects.map(function() {
return this.value;
}).get();
var values = [ "a1b2c3", "d4e5f6" ];
var vj = vals.join('');
if (values.indexOf(vj) !== -1) {
$(".box_wrapper").not("." + vj).hide();
$("." + vj)).show();
$('html,body').animate({
scrollTop: $("." + vj)).offset().top
}, 'slow');
}
else {
$(".vid_box").hide();
}
}

I would suggest something like this.
var $selects = $('.filters select');
$selects.on('change', function() {
var value = $selects.map(function() {
return this.value;
}).get();
$(".box_wrapper").not("." + value).hide();
$(".box_wrapper." + value).show();
$('html, body').animate({
scrollTop: $("." + value).offset().top},
'slow');
});
$selects.first().trigger("change");

Here is my final code. Thanks #MJH for all the help.
var $selects = $('.filters select');
$selects.on('change', getValues).first().trigger("change");
function getValues() {
var $selects = $('.filters select');
$selects.on('change', getValues).first().trigger("change");
function getValues() {
var vals = $selects.map(function() {
return this.value;
}).get();
var vwarp = vals.join('');
if (vwarp == vwarp) {
$(".box_wrapper").not("." + vwarp).hide();
$("." + vwarp).show();
$('html,body').animate({
scrollTop: $("." + vwarp).offset().top},
'slow');
}
else{
$(".box_wrapper").hide();
}
}
Hope this helps!

Related

Jquery functions overriding each other

Question:
I have 2 jQuery function one is a search function and the other is a function to only show column values of a certain type. The problem is if I select a column value with the second function and hide the other rows then try to search those rows it resets and searches all rows.
Fiddle
Code:
Here are the 2 functions:
Search:
$(document).ready(function(){
$("#mySearch").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#myTable tr td:nth-child(1)").filter(function() {
$(this).parent().toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
Column:
$(function() {
$('select[name="CPUmenu"]').change(function(e) {
let socket = $(this).val();
$('tbody tr[data-socket]').show();
if (socket.length) {
$('tbody tr[data-socket!="' + socket + '"]').hide();
}
});
$('select[name="CPUmenu"]').trigger('change');
});
Expected result:
I was thinking that the function could only apply to rows that aren't hidden but I'm not sure what the code for that would be.
Update:
I saw the :hidden selector and thought i could use .not(:hidden)
I also plan to add more functions in future so need it to be able to scale.
If you need any more information please let me know.
Thanks
I dont really know what this would do but i think your search function should be like this:
$(document).ready(function(){
$("#mySearch").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#myTable tr td:nth-child(1)").filter(function() {
if ($(this).parent.css("display") == "block") {
$(this).parent().toggle($(this).text().toLowerCase().indexOf(value) > -1)
}
});
});
});
Here's the working fiddle.
You could add, remove a class when you filter the rows by column and then search based on class usage.
Search Function:
...
if($(this).parent().hasClass("filtered")){
$(this).parent().toggle($(this).text().toLowerCase().indexOf(value) > -1);
}
Column Function:
...
if (socket.length) {
$('tbody tr[data-socket!="' + socket + '"]').hide();
$('tbody tr[data-socket!="' + socket + '"]').removeClass("filtered");
$('tbody tr[data-socket="' + socket + '"]').addClass("filtered");
}
Quick fix, but sorry won't scale well :
$(function() {
$('select[name="CPUmenu"]').change(function(e) {
let socket = $(this).val();
$('tbody tr[data-socket]').removeClass('discarded').show(); /// <<<- here the trick
if (socket.length) {
$('tbody tr[data-socket!="' + socket + '"]').addClass('discarded').hide(); /// <<<-- here as well
}
});
$('select[name="CPUmenu"]').trigger('change');
});
$("#mySearch").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#myTable tr:not(.discarded) td:nth-child(1)").filter(function() {
$(this).parent().toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
Here is the working code:
$(function() {
$('select[name="CPUmenu"]').change(function(e) {
let socket = $(this).val();
$('tbody tr[data-socket]').show();
if (socket.length) {
$('tbody tr[data-socket!="' + socket + '"]').hide();
}
});
$('select[name="CPUmenu"]').trigger('change');
});
$(document).ready(function(){
$("#mySearch").on("keyup", function() {
var value = $(this).val().toLowerCase();
$('select[name="CPUmenu"]').trigger('change');
$("#myTable tr td:nth-child(1)").filter(function() {
if ($(this).parent().is(":visible")) {
$(this).parent().toggle($(this).text().toLowerCase().indexOf(value) > -1)
}
});
});
});

Updating interval dynamically - jQuery or Javascript

I have two "stopwatches" in my code (and I may be adding more). This is the code I currently use below - and it works fine. But I'd really like to put the bulk of that code into a function so I'm not repeating the same code over and over.
When I tried doing it though, I could get it working - I think it was because I was passing stopwatchTimerId and stopwatch2TimerId into the function and it may have been passing by reference?
How can I reduce the amount of code repetition here?
var stopwatchTimerId = 0;
var stopwatch2TimerId = 0;
$('#stopwatch').click(function () {
if ($(this).hasClass('active')) {
$(this).removeClass('active');
clearInterval(stopwatchTimerId);
}
else {
$(this).addClass('active');
stopwatchTimerId = setInterval(function () {
var currentValue = parseInt($('#stopwatch-seconds').val()) || 0;
$('#stopwatch-seconds').val(currentValue + 1).change();
}, 1000);
}
});
$('#stopwatch2').click(function () {
if ($(this).hasClass('active')) {
$(this).removeClass('active');
clearInterval(stopwatch2TimerId);
}
else {
$(this).addClass('active');
stopwatch2TimerId = setInterval(function () {
var currentValue = parseInt($('#stopwatch2-seconds').val()) || 0;
$('#stopwatch2-seconds').val(currentValue + 1).change();
}, 1000);
}
});
As you can see, it's basically the same code in each except for stopwatchTimerId and $('#stopwatch-seconds') (and the same vars with 2 on it for the other one).
This won't pollute global scope and also you don't need to do any if-else statements. Just add data-selector to your new elements :)
<input id="stopwatch" type="text" data-selector="#stopwatch-seconds"/>
<input id="stopwatch2" type"text" data-selector="#stopwatch2-seconds"/>
$('#stopwatch stopwatch2').click(function () {
var $element = $(this),
interval = $element.data('interval');
selector = $element.data('selector');;
if ($element.hasClass('active')) {
$element.removeClass('active');
if (interval) {
clearInterval(interval);
}
}
else {
$element.addClass('active');
$element.data('interval', setInterval(function () {
var currentValue = parseInt($(selector).val()) || 0;
$(selector).val(currentValue + 1).change();
}, 1000));
}
});
function stopwatch(id){
$('#' + id).click(function () {
if ($(this).hasClass('active')) {
$(this).removeClass('active');
clearInterval(window[id]);
}
else {
$(this).addClass('active');
window[id] = setInterval(function () {
var currentValue = parseInt($('#' + id + '-seconds').val()) || 0;
$('#' + id + '-seconds').val(currentValue + 1).change();
}, 1000);
}
});
}
$(function(){
stopwatch("stopwatch");
stopwatch("stopwatch2");
});
You could do something like this (code is not very nice, you can improve it):
var stopwatchTimerId;
$('#stopwatch').click(function () {
doStopWatch(1);
});
$('#stopwatch2').click(function () {
doStopWatch(2);
});
var doStopWatch = function(option){
var stopWatch = option===1?$('#stopwatch'):$('#stopwatch2');
if (stopWatch.hasClass('active')) {
stopWatch.removeClass('active');
clearInterval(stopwatchTimerId);
}
else {
stopWatch.addClass('active');
stopwatchTimerId = setInterval(function () {
var currentValue = option===1?(parseInt($('#stopwatch-seconds').val()) || 0):(parseInt($('#stopwatch2-seconds').val()) || 0);
if(option===1)
$('#stopwatch-seconds').val(currentValue + 1).change();
else
$('#stopwatch2-seconds').val(currentValue + 1).change();
}, 1000);
}
}
Try
var arr = $.map($("div[id^=stopwatch]"), function(el, index) {
el.onclick = watch;
return 0
});
function watch(e) {
var id = this.id;
var n = Number(id.split(/-/)[1]);
if ($(this).hasClass("active")) {
$(this).removeClass("active");
clearInterval(arr[n]);
} else {
$(this).addClass("active");
arr[n] = setInterval(function() {
var currentValue = parseInt($("#" + id + "-seconds").val()) || 0;
$("#" + id + "-seconds").val(currentValue + 1).change();
}, 1000);
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div id="stopwatch-0">stopwatch1</div>
<input type="text" id="stopwatch-0-seconds" />
<div id="stopwatch-1">stopwatch2</div>
<input type="text" id="stopwatch-1-seconds" />

How to check current window location against an array of values

Let's say we've got this HTML:
<div class="locationhash" data-position="0"></div>
<div class="locationhash" data-position="1000"></div>
<div class="locationhash" data-position="3000"></div>
<div class="locationhash" data-position="5000"></div>
<div class="locationhash" data-position="8000"></div>
where data-positions value, in normal conditions would equal to elements height from pages top in px.
Im retrieving elements with .locationhash, reading its data-position and pushing both values as an object into an array using this code. (works as intended, output in third code sample here)
var getSections = function() {
var pageSectionsArr = [];
var pageSections = (document).querySelectorAll('.locationhash');
Array.prototype.forEach.call(pageSections, function(section) {
var getSectionPos = section.getAttribute('data-position');
var pageSectionObj = {
pageSection : section,
pageSectionPos : getSectionPos
};
pageSectionsArr.push(pageSectionObj);
});
console.log(pageSectionsArr)
};
(function recalcSectionPos() {
$(window).resize(function() {
getSections();
});
})();
Output looks like this:
[ {div.locationhash, value of its data-position},
{div.locationhash, value of its data-position}, ... ]
Now i need to check on scroll wether current window.scrollTop() equals any of data-position values so:
$(window).scroll(function() {
var hFromTop = $(window).scrollTop()
//cant figure out what should i do next (jquery allowed)
});
Question: How could i check current window.scrolltop() against multiple values, while user is scrolling so i could make something happen when window.scroll top equals to a value
(I'm using this array because later im gonna read .locationhash's id in order to append it to url using location replace)
DEMO
$(document).ready(function () {
$(document).on("scroll", onScroll);
//smoothscroll
$('a[href^="#"]').on('click', function (e) {
e.preventDefault();
$(document).off("scroll");
$('a').each(function () {
$(this).removeClass('active');
})
$(this).addClass('active');
var target = this.hash,
menu = target;
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top+2
}, 500, 'swing', function () {
window.location.hash = target;
$(document).on("scroll", onScroll);
});
});
});
function onScroll(event){
var scrollPos = $(document).scrollTop();
$('#menu-center a').each(function () {
var currLink = $(this);
var refElement = $(currLink.attr("href"));
if (refElement.position().top <= scrollPos && refElement.position().top + refElement.height() > scrollPos) {
$('#menu-center ul li a').removeClass("active");
currLink.addClass("active");
}
else{
currLink.removeClass("active");
}
});
}
I followed #tushar gupta's advice, also wrapped it in a function checking wether scrolling ended
$(window).scroll(function() {
clearTimeout($.data(this, 'scrollTimer'));
$.data(this, 'scrollTimer', setTimeout(function() {
var hFromTop = $(window).scrollTop();
$.each(pageSectionsArr, function(obj) {
console.log(this + 'is sparta')
if (~~this.pageSectionPos <= hFromTop && ~~this.pageSectionPos + this.pageSection.offsetHeight > hFromTop) {
//console.log(this.pageSectionPos)
var sectionsId = this.pageSection.id
//console.log(sectionsId)
window.location.replace('#/'+sectionsId)
};
});
}, 250));
});

I want to enable auto slider and infinite loop in JavaScript

<script type="text/javascript">
$(document).ready(function() {
var acch = 1;
$('.controls ul a').click(function() {
var chno = $('.slider-container li').length;
switch($(this).attr('data-gallery')){
case 'slide-left':
if (acch < chno){
acch++;
startSlide(acch);
}
break;
case 'slide-right':
if (acch <= 1){
acch = 1;
}else{
acch--;
startSlide(acch);
}
break;
}
})
function startSlide(itemNo){
var sTo = '#slider-item-' + itemNo;
$('#home-top-content').scrollTo($(sTo), 300);
}
$('.backToTop').click(function() {
$('html, body').animate({scrollTop:0}, 'slow');
})
})
</script>
This is the script listed above i need to enable auto slide function and infinite loop
http://aphex.fresh-pixel.com/
This is the link to theme which i am using, you can see the problem in slider
I think this implemetation is better, since you can add any number of sildes in the design without any chage in the code.
<script type="text/javascript">
$(document).ready(function() {
$('.controls ul a').click(function() {
moveSliders($(this));
})
function startSlide(element){
$('#home-top-content').scrollTo(element, 300);
}
$('.backToTop').click(function() {
$('html, body').animate({scrollTop:0}, 'slow');
})
setInterval(function(){
moveSliders($('.controls ul').find('a.arrow-right'));
},6000);
function moveSliders(clickElement)
{
//Get li with class active if that count is zero put it as the first li
var currentActive = $('.slider-container li.slide-active');
var firstElement = $('.slider-container li:first');
var lastElement = $('.slider-container li:last');
if(currentActive.length == 0){
firstElement.addClass('slide-active');
currentActive = firstElement;
}
switch(clickElement.attr('data-gallery')){
case 'slide-left':
//Next
var nextElement = currentActive.next();
if(nextElement.length == 0)nextElement = firstElement;
$('.slider-container li.slide-active').removeClass('slide-active');
nextElement.addClass('slide-active');
startSlide(nextElement);
break;
case 'slide-right':
//previous
var previousElement = $('.slider-container li.slide-active').prev();
if(previousElement.length == 0)previousElement = lastElement;
$('.slider-container li.slide-active').removeClass('slide-active');
previousElement.addClass('slide-active');
startSlide(previousElement);
break;
}
}
})
</script>

selectable limit stop

I am trying to make this selectable script to have selecting limits. I want it to stop selecting when the limit of selection goes over the limit number that is 4.
http://jsfiddle.net/dw6Hf/51/
$(function() {
$(".selectable").selectable({
filter: "td.cs",
stop: function() {
var result = $("#select-result").empty();
var result2 = $("#result2");
$('.ui-selecting:gt(31)').removeClass("ui-selecting");
// alert($(".ui-selected").length);
$('#divmsg').html($(".ui-selected").length*2+ " box selected")
if ($(".ui-selected").length > 4) {
//alert("Selection of only 4 allowed");
$('#divmsg').html($('#divmsg').html() + ", Selection of only 4 allowed");
$(".ui-selected").each(function(i, e) {
if (i > 3) {
$(this).removeClass("ui-selected");
}
});
return;
}
$(".ui-selected", this).each(function() {
var cabbage = this.id + ', ';
result.append(cabbage);
});
var newInputResult = $('#select-result').text();
newInputResult = newInputResult.substring(0, newInputResult.length - 1);
result2.val(newInputResult);
}
});
});​
thank you
Ok now that i understand the requirements this one should give you what you asked for. Changing from stop to selectable means you can decide before it is "selected" not after which is when stop is fired.
fiddle
This works
$( "#selectable" ).selectable({
selecting: function(event, ui) {
if ($(".ui-selected, .ui-selecting").length > 4) {
$(ui.selecting).removeClass("ui-selecting");
}
}
});
duplicate of this
EDIT
something like this?
$(function() {
$(".selectable").selectable({
filter: "td.cs",
// do not allow selecting more than four items
selecting: function(event, ui) {
if ($(".ui-selected, .ui-selecting").length > 4) {
$(ui.selecting).removeClass("ui-selecting");
}
}
// do whatever you like with the selected
stop: function() {
var result = $("#select-result").empty();
var result2 = $("#result2");
$('#divmsg').html($(".ui-selected").length*2+ " box selected")
$(".ui-selected", this).each(function() {
var cabbage = this.id + ', ';
result.append(cabbage);
});
var newInputResult = $('#select-result').text();
newInputResult = newInputResult.substring(0, newInputResult.length - 1);
result2.val(newInputResult);
}
});
});?

Categories