I'm trying to create a "bar" that is highlight-able and will return a value which contains the number of div boxes that were highlighted. For example, when I highlight 5 divs, it should return 5. When I continue on, and highlight another 6 boxes, it should return 6. All of the highlighted results should be in an array var x = ["5", "6",...];
Here's a fiddle https://jsfiddle.net/aepxqztL/3/
$(document).ready(function() {
var $range = $('.range-bar').mousedown(function() {
$(this).toggleClass('highlight');
var flag = $(this).hasClass('highlight')
$range.on('mouseenter.highlight', function() {
$(this).toggleClass('highlight', flag);
});
});
$(document).mouseup(function() {
$('.range-bar').off('mouseenter')
})
});
Any help will be appreciated.
Here is an example using jQuery.each to calculate the highlighted divs upon mousedown event
function calculateArray(){
var x = [];
$("div.range-bar").each(function( index, value ) {
if($(this).hasClass("highlight"))
x.push(index);
});
return x;
}
var x = [];
$(document).ready(function() {
var $range = $('.range-bar').mousedown(function() {
$(this).toggleClass('highlight');
var flag = $(this).hasClass('highlight')
$range.on('mouseenter.highlight', function() {
$(this).toggleClass('highlight', flag);
});
x = calculateArray();
console.log(x);
});
$(document).mouseup(function() {
$('.range-bar').off('mouseenter')
})
});
See working demo: https://jsfiddle.net/aepxqztL/7/
It looks like you need to set 2 global vars (a range counter rangeVal and a data array dataSet) and then increment the rangeVal on mousedown on each box and then add it to the dataSet on mouseup and then reset rangeVal.
Eg.
var dataSet = []; //data array
var rangeVal = 1; //range counter
$(document).ready(function() {
var $range = $('.range-bar').mousedown(function() {
$(this).toggleClass('highlight');
var flag = $(this).hasClass('highlight')
$range.on('mouseenter.highlight', function() {
$(this).toggleClass('highlight', flag);
rangeVal++; //Increment on mousedown mouseenter in box
});
});
$('.range-bar').mouseup(function() {
$('.range-bar').off('mouseenter')
dataSet.push(rangeVal); //add range counter to data array
rangeVal = 1; //reset range counter
$('.results p').text(dataSet.join()); //display data array in results div
})
});
See this fiddle here: https://jsfiddle.net/pavkr/0vftp5ja/1/
The question is still a little vague but I think this is what you're looking for.
EDIT:
https://jsfiddle.net/pavkr/0vftp5ja/2/
Modified so that it saves the Start and End value as well as the Range value.
Related
My task is to take the 3 different color lists in the jsonObj and place them into a <ul>. They should only appear one at a time, every second. For the sake of the fiddle, I put it to every 5 seconds.
I haven't gotten to the 2nd or 3rd list of colors yet because while I can list out my 1st color list, they're appending outside of the listItem I've created for them. The code it spits it is:
var jsonObj = '{"one":["red","green","blue"], "two":["red","green","blue"], "three":["orange","purple","hotpink"]}',
object = JSON.parse(jsonObj),
cOne = object.one,
cTwo = object.two,
cThree = object.three,
i = 0,
timer;
$('body').append('<ul/>');
timer = setInterval(function() {
$.each(cOne, function() {
var list = $('body ul'),
listItem = $(list).append('<li>'),
html = $(listItem).append(cOne[i]);
if (i < cOne.length) {
i++;
$(cOne[i]).split("");
list.append(html);
} else if (i = cOne.length) {
i = 0;
}
});
}, 5 * 1000);
timer;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Also available at https://jsfiddle.net/ep76ba3u/
What it does:
<ul>
<li></li>
"red"
<li></li>
"blue"
</ul>
What it should look like:
<ul>
<li>red</li>
<li>blue</li>
</ul>
I've tried rearranging it all. I've tried using wrap, innerWrap. I've tried just using text() and a few other methods. I started working on it at 3am and its 5am now... brain is fried. Any idea how to get this moving is appreciated.
You can not append partial html, that's why this $(list).append('<li>') is immediately closing the <li>.
And you should not modify the markup in a loop. It's obnoxious and unperformant.
Check out this approach to your code:
var jsonObj = '{"one":["red","green","blue"], "two":["red","green","blue"], "three":["orange","purple","hotpink"]}',
object = JSON.parse(jsonObj),
iteration = 0,
timer;
$('body').append('<div id=container>');
//a few utilities, because I don't want to repeat myself all over the place:
var string = value => value == null ? "" : String(value);
var wrapInNode = nodeName => value => `<${nodeName}>${ string(value) }</${nodeName}>`;
//here I create a few utility-methods that will build my markup:
var li = wrapInNode('li');
var ul = wrapInNode('ul');
var header = wrapInNode('h4');
timer = setInterval(function() {
//building the complete markup and adding it at once
var blocks = [],
//how many rows should I show in this iteration
numRowsLeft = ++iteration,
//getting this result is just a nice sideeffect of using `every()` instead of `forEach()`
//to short-curcuit the loop
done = Object.keys(object)
.every(function(key) {
//this line makes the title to be added with as a distinct iteration and not with the first item,
//check out what happens when you remove it
--numRowsLeft;
var rows = object[key]
//shorten the Array to numRowsLeft, if necessary
.slice(0, numRowsLeft)
//wrap each item in a li-node with my predefined utility-function
.map(li);
numRowsLeft -= rows.length;
//building the markup for this block
blocks.push(header(key) + ul(rows.join("")));
//here I'm short circuiting the loop. to stop processing the other keys on Object
return numRowsLeft > 0;
});
$('#container').html(blocks.join(""));
if (done) {
clearInterval(timer);
}
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
And showing the header all the time while only adding the points:
var jsonObj = '{"one":["red","green","blue"], "two":["red","green","blue"], "three":["orange","purple","hotpink"]}',
object = JSON.parse(jsonObj),
iteration = 0,
timer;
$('body').append('<div id=container>');
var string = value => value == null ? "" : String(value);
var wrapInNode = nodeName => value => `<${nodeName}>${ string(value) }</${nodeName}>`;
var li = wrapInNode('li');
var ul = wrapInNode('ul');
var header = wrapInNode('h4');
timer = setInterval(function() {
var numRowsLeft = ++iteration,
blocks = Object.keys(object)
.map(function(key) {
var rows = object[key]
.slice(0, numRowsLeft)
.map(li);
numRowsLeft -= rows.length;
return markup = header(key) + ul(rows.join(""));
});
$('#container').html(blocks.join(""));
// If I'd had room to show even more rows, then I' done
if (numRowsLeft > 0) {
clearInterval(timer);
}
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
I feel compelled to put in an answer which should perform better by cache of the jQuery objects and processes the objects and each color in them, hitting DOM once for each color.
var jsonObj = '{"one":["red","green","blue"], "two":["red","cyan","darkblue"], "three":["orange","purple","hotpink"]}',
objects = JSON.parse(jsonObj);
// set timer values
var basetime = 1000;
var delaytime = basetime;
// cache the ul list
var myul = $('<ul/>').appendTo('body');
//process outer objects
$.each(objects, function(key, item) {
// process color array held in item
$.each(item, function(index, color) {
setTimeout(function() {
$('<li/>').text(color).css('color', color).appendTo(myul);
}, delaytime);
delaytime = delaytime + basetime;
});
});
Test it out here https://jsfiddle.net/MarkSchultheiss/yb1w3o73/
var jsonObj = '{"one":["red","green","blue"], "two":["red","green","blue"], "three":["orange","purple","hotpink"]}',
object = JSON.parse(jsonObj),
cOne = object.one,
cTwo = object.two,
cThree = object.three,
i = 0,
timer;
$('body').append('<ul>');
var i = 0;
timer = setInterval(function() {
if (i === cOne.length - 1) clearInterval(timer);
$('body ul').append('<li>');
$('body ul li').last().text(cOne[i]);
i++;
}, 1000);
I'm using Isotope to function as a categorical organizer of linked content in a fancy layout. I'm trying to push multiple values into an array so it'll display all items touched by the filters. The end result is, however, just displaying the latest item in the array instead of the sum total. Initially, I was pushing all my values into a string, then declaring x as the final result-- I realize this isn't the way to go about this, and have since modified it. Instead of a string, I'm pushing into an array, and hoping to join each value so they'll all be displayed. However, I'm still getting nothing more than the latest selected value. JS as it stands below.
// store filter for each group
var filters = {};
$('.filters').on('click', '.button', function() {
var filters = [];
// var filters = '';
var selected = $(this).data('selected');
var group = $(this).data('group');
var currentFilter = $(this).data('filter');
// toggle function along with having multiple selectors
if(selected == "0") {
filters.push($(this).data('filter'));
filters = filters.join(', ');
// filters = $(this).data('filter');
$(this).data('selected', "1");
$(this).addClass('is-checked')
}
else {
$(this).data('selected', "0");
$(this).removeClass('is-checked')
}
// set filter for Isotope
$grid.isotope({
filter: filters
});
// flatten object by concatting values
function concatValues(obj) {
var value = '';
for (var prop in obj) {
value += obj[prop];
}
return value;
}
});
}());
I've also set up a codepen for fiddling. Thanks for any suggestions that come. Even pointing me to documentation or tutorials I may have missed would be a great help. For now, I'm studying this jsfiddle that does what I'm shooting for, to see how I can modify my code to better suit what's going on here.
Last week I also spend crazy time with this. :) Luckly I found Desandro's codepen http://codepen.io/desandro/pen/owAyG/
Hope that helps.
$( function() {
// filter functions
var filterFns = {
greaterThan50: function() {
var number = $(this).find('.number').text();
return parseInt( number, 10 ) > 50;
},
even: function() {
var number = $(this).find('.number').text();
return parseInt( number, 10 ) % 2 === 0;
}
};
// init Isotope
var $container = $('.isotope').isotope({
itemSelector: '.color-shape',
filter: function() {
var isMatched = true;
var $this = $(this);
for ( var prop in filters ) {
var filter = filters[ prop ];
// use function if it matches
filter = filterFns[ filter ] || filter;
// test each filter
if ( filter ) {
isMatched = isMatched && $(this).is( filter );
}
// break if not matched
if ( !isMatched ) {
break;
}
}
return isMatched;
}
});
// store filter for each group
var filters = {};
$('#filters').on( 'click', '.button', function() {
var $this = $(this);
// get group key
var $buttonGroup = $this.parents('.button-group');
var filterGroup = $buttonGroup.attr('data-filter-group');
// set filter for group
filters[ filterGroup ] = $this.attr('data-filter');
// arrange, and use filter fn
$container.isotope('arrange');
});
// change is-checked class on buttons
$('.button-group').each( function( i, buttonGroup ) {
var $buttonGroup = $( buttonGroup );
$buttonGroup.on( 'click', 'button', function() {
$buttonGroup.find('.is-checked').removeClass('is-checked');
$( this ).addClass('is-checked');
});
});
});
This is the solution I ended up with.
I came up with a separate solution but this is a great pen. I wish I had seen it before.
$(document).ready(function() {
// init Isotope
var $grid = $('.grid').isotope({
itemSelector: '.element-item',
layoutMode: 'fitRows',
fitRows: {
gutter: 27
}
});
// store filter for each group
var filters = [];
$('.filters').on('click', '.button', function() {
var filterstring = '';
var selected = $(this).data('selected');
var currentFilter = $(this).data('filter');
// toggle function along with having multiple selectors
if (selected == "0") {
filters.push( currentFilter );
$(this).data('selected', "1");
$(this).addClass('is-checked')
} else {
$(this).data('selected', "0")
$(this).removeClass('is-checked')
var filtername = $(this).data('filter')
var i = filters.indexOf(filtername)
filters.splice(i, 1)
}
filterstring = filters.join(', ');
// set filter for Isotope
$grid.isotope({
filter: filters.join("")
});
});
});
I hacked an isotope combofilter with checkboxes, but here is the problem with the isotope items; They are disappearing when resizing browser window.
I dont why they are not displaying when I change the size of the browser!
Please so help!!
Normaly I use isotope V2. Here in JSFiddle, there is np with the window resizing however I used isotope v1..
I am driving crazy, when items disappeared I need to trigger by clicking a select button, then its going fine.
var $containerii;
var filters = {};
jQuery(document).ready(function () {
var $containerii = $('.isotope').isotope({
itemSelector: '.isotope-item'
});
getContent: '.isotope-item li'
var $filterDisplay = $('#filter-display');
$containerii.isotope();
// do stuff when checkbox change
$('#options').on('change', function (jQEvent) {
var $checkbox = $(jQEvent.target);
manageCheckbox($checkbox);
var comboFilter = getComboFilter(filters);
$containerii.isotope({ filter: comboFilter });
$filterDisplay.text(comboFilter);
});
});
function getContent() {
var items = document.getElementById("containerii")
}
function getComboFilter(filters) {
var i = 0;
var comboFilters = [];
var message = [];
for (var prop in filters) {
message.push(filters[prop].join(' '));
var filterGroup = filters[prop];
// skip to next filter group if it doesn't have any values
if (!filterGroup.length) {
continue;
}
if (i === 0) {
// copy to new array
comboFilters = filterGroup.slice(0);
} else {
var filterSelectors = [];
// copy to fresh array
var groupCombo = comboFilters.slice(0); // [ A, B ]
// merge filter Groups
for (var k = 0, len3 = filterGroup.length; k < len3; k++) {
for (var j = 0, len2 = groupCombo.length; j < len2; j++) {
filterSelectors.push(groupCombo[j] + filterGroup[k]); // [ 1, 2 ]
}
}
// apply filter selectors to combo filters for next group
comboFilters = filterSelectors;
}
i++;
}
var comboFilter = comboFilters.join(', ');
return comboFilter;
}
function manageCheckbox($checkbox) {
var checkbox = $checkbox[0];
var group = $checkbox.parents('.option-set').attr('data-group');
// create array for filter group, if not there yet
var filterGroup = filters[group];
if (!filterGroup) {
filterGroup = filters[group] = [];
}
var isAll = $checkbox.hasClass('all');
// reset filter group if the all box was checked
if (isAll) {
delete filters[group];
if (!checkbox.checked) {
checkbox.checked = 'checked';
}
}
// index of
var index = $.inArray(checkbox.value, filterGroup);
if (checkbox.checked) {
var selector = isAll ? 'input' : 'input.all';
$checkbox.siblings(selector).removeAttr('checked');
if (!isAll && index === -1) {
// add filter to group
filters[group].push(checkbox.value);
}
} else if (!isAll) {
// remove filter from group
filters[group].splice(index, 1);
// if unchecked the last box, check the all
if (!$checkbox.siblings('[checked]').length) {
$checkbox.siblings('input.all').attr('checked', 'checked');
}
}
}
If your using isotope v2, try this:
var $containerii = $('.isotope').isotope({
itemSelector: '.isotope-item',
isResizeBound: true
});
v1.5, this:
ADDENDUM
I don't see anything disappearing, just the col-md-10 shifting down when you resize your window. I changed the layout to avoid the shift and it seems to resize as it should.
jsfiddle
Thank you so much for helps and valuable responses. Finally I solved my problem by using trigger isotope on window resize at the end of the code.
$(window).on('resize', function () {
$containerii = $('.isotope');
triggerIsotope();
});
I have 2 multi selects in a page, and I need to transfer some of the option in first into second, while mantaining the search capabilities.
The problem is, that when I use the search input, it restores the selects to their original options...
Here is the jquery search function:
jQuery.fn.filterByText = function(textbox) {
return this.each(function() {
var select = this;
var options = [];
$(select).find('option').each(function() {
options.push({value: $(this).val(), text: $(this).text()});
});
$(select).data('options', options);
$(textbox).bind('change keyup', function() {
var options = $(select).empty().data('options');
var search = $.trim($(this).val());
var regex = new RegExp(search,"gi");
$.each(options, function(i) {
var option = options[i];
if(option.text.match(regex) !== null) {
$(select).append(
$('<option>').text(option.text).val(option.value)
);
}
});
});
});
};
Here is the js fiddle : http://jsfiddle.net/C2XXR/ !
*I believe the problem lies in the options variable, but have no idea on how to solve it *
Thanks!
I have updated the fiddle. http://jsfiddle.net/C2XXR/2/
I have updated the code for right and left transfer. You have to change the option array itself got the filter, adding them in the dom will not work. In the changed code one issue is once we add from right to left or left to right it is getting added in the last position of the target select.
Please check and let me know if this is what you want.
Below is the main changed function. Later you can create a common function i suppose. Code can be optimized more.
$('[id^=\"btnRight\"]').click(function (e) {
var selected = $(this).parent().prev('select');
var target = $(this).parent().next('select');
target.find('option[value="999"]').remove()
var options = selected.data('options');
var selectedVal = selected.find('option:selected').val()
var tempOption = [];
$.each(options, function(i) {
var option = options[i];
if(option.value != selectedVal) {
tempOption.push(option);
}
});
var targetOptions = target.data('options');
targetOptions.push({value: selected.find('option:selected').val(), text: selected.find('option:selected').text()});
target.data('options', targetOptions);
selected.find('option:selected').remove().appendTo('#isselect_code');
selected.data('options', tempOption);
});
$('[id^=\"btnLeft\"]').click(function (e) {
var selected = $(this).parent().next('select');
var target = $(this).parent().prev('select');
var options = selected.data('options');
var selectedVal = selected.find('option:selected').val()
var tempOption = [];
$.each(options, function(i) {
var option = options[i];
if(option.value != selectedVal) {
tempOption.push(option);
}
});
if( tempOption.length == 0 )
{
// add 999 here
}
var targetOptions = target.data('options');
targetOptions.push({value: selected.find('option:selected').val(), text: selected.find('option:selected').text()});
target.data('options', targetOptions);
selected.find('option:selected').remove().appendTo('#canselect_code');;
selected.data('options', tempOption);
});
the problem with your code is that after you click btnRight or btnLeft your collection of options for each select is not updated, so try after click on each button to call your filterByText as the following :
$('[id^=\"btnRight\"]').click(function (e) {
$(this).parent().next('select').find('option[value="999"]').remove()
$(this).parent().prev('select').find('option:selected').remove().appendTo('#isselect_code');
$('#canselect_code').filterByText($('#textbox'), true);
$('#isselect_code').filterByText($('#textbox1'), true)
});
$('[id^=\"btnLeft\"]').click(function (e) {
$(this).parent().next('select').find('option:selected').remove().appendTo('#canselect_code');
$('#canselect_code').filterByText($('#textbox'), true);
$('#isselect_code').filterByText($('#textbox1'), true)
});
I have a fiddle here: my fiddle. What I am trying to do is create a list of items from a separate group of lists. I cannot seem to get a grasp on what I am doing wrong, but here is whats happening:
I have a group of lists based on tabular data
Each list has the name of the column and a selection checkbox
If I select an item, it needs to be added to the selected columns area (vertical list)
There are 14 unique tabular items with checkboxes
(PROBLEM -->) When I select an item, it gets added 14 times in the selected columns section
code
(html):
I tried ti insert HTML but is not working right. Please look at the fiddle listed above.
(jquery):
var dte = // drag table elements
{
init: function() {
var chkbx = $('.group input[type="checkbox"]:checkbox');
//var chkbx = $('#accordion');
for (var i = 0, ii = chkbx.length; i < ii; i++) {
$(chkbx).bind("click", dte.adjustList);
}
},
adjustList: function(event) {
var list = [];
var str = '';
var eleval = event.currentTarget.value;
var eleid = event.currentTarget.id;
if (eleval == 1) {
list.push(eleid);
str = '<li>' + eleid + '</li>';
}
$('#vertical ul').append(str);
/*
//var ele = event.currentTarget.id;
var allVals = [];
var str = '';
//var obj = $("#"+ele);
var ele = $('#accordion');
$(obj+': checked').each(function(){
allVals.push($(this.val()));
dte.list.push($(this.val()));
str += '<li>'+$(this.val())+'</li>';
});
$('#verticle').text(str);
alert('List: ' + toString(list));
*/
}
};
dte.init();
init: function() {
$('.group input:checkbox').bind("click", dte.adjustList);
},
you only need to bind once based on your selector.
init: function() {
var chkbx = $('.group input[type="checkbox"]:checkbox');
$(chkbx).bind("click", dte.adjustList);
},
fiddle
I have edited your fiddle, I removed the for loop. Here is the link updated fiddle
You only need to bind the click event once.
You are binding events multiple time. You can do something like this:
init:function(){
$('.group input[type="checkbox"]:checkbox').bind('click',dte.adjustList);
},
Edited your fiddle:
http://jsfiddle.net/emphaticsunshine/tPAmc/