:contains case sensitive not working appropriately - javascript

I have added the code to overwrite the contains method however I am still not getting the right result. I have created a JFiddle to show the problem. http://jsfiddle.net/zjAyX/ I have also tried the code that works with the jQuery 1.8 which is the version of jQuery I'm using. Where do I place the code?
$(function() {
$.extend($.expr[":"], {
"containsIN": function(elem, i, match, array) {
return (elem.textContent || elem.innerText || "").toLowerCase().indexOf((match[3] || "").toLowerCase()) >= 0;
}
});
$("#searchInput").keyup(function () {
//split the current value of searchInput
var data = this.value.split(" ");
//create a jquery object of the rows
var jo = $("tbody").find("tr");
if (this.value == "") {
jo.hide();
return;
}
//hide all the rows
jo.hide();
//Recusively filter the jquery object to get results.
jo.filter(function (i, v) {
var $t = $(this);
for (var d = 0; d < data.length; ++d) {
if ($t.is(":contains('" + data[d] + "')")) {
return true;
}
}
return false;
})
//show the rows that match.
.show();
}).focus(function () {
this.value = "";
$(this).css({
"color": "black"
});
$(this).unbind('focus');
}).css({
"color": "#C0C0C0"
});
});

Use :containsIN() instead of contains() in your condition.
jo.filter(function (i, v) {
var $t = $(this);
for (var d = 0; d < data.length; ++d) {
if ($t.is(":containsIN('" + data[d] + "')")) {
return true;
}
}
return false;
})
Demo: Fiddle

Related

JQUERY, highlight a column if contains numbers in sequence

I'm struggling in how to make this simple code work: i only want to check the values of every column and see if they are sequential (like 0 to 7 for example), and if so, highlight that column (class = "snaked" ).
So i marked every cell which belongs to the first row (class = "vstarter") and i tried out this :
function is_colsnake() {
ognicella.filter(".vstarter").each(
function() {
var cella = $(this);
var pos = cella.index();
var colonna = ognicella.filter(":nth-child(" + (pos + 1) + ")")
var col = [];
var issnake = false;
colonna.each(
function() {
col.push(parseInt($(this).text()));
});
col.each(
function() {
var start = parseInt($(this).text()) ;
var next = parseInt($(this).next().text()) ;
var prev = parseInt($(this).prev().text()) ;
var ix = $(this).index() ;
if (ix == 0) {
if (next == start + 1) {
issnake = true;
} else {
issnake = false;
}
} else if (start != prev + 1) {
issnake = false;
}
});
if (issnake) {
colonna.each(function() {
$(this).addClass("snaked");
})
} else {
colonna.each(function() {
$(this).removeClass("snaked");
})
}
})
};
However it isn't working. Would you please help?

How to put a condition in jQuery's map function?

I am trying to put a condition in jQuery's map function. My issue is that I don't want the same number in the map function value. When it is the same I want to display an alert box. My map function code is like this:
var rankbox= $('input[type=text][class = cate_rank]').map(function() {
return this.value;
}).get();
If I get a value like 1,2,3,4,5 it's ok, but if I get a value like 1,2,3,2,5, I want to display an alert box. Is it possible?
How to put a condition in jQuery's map function?
function change_rank() {
var rankbox= $('input[type=text][class = cate_rank]').map(function() {
if() {
} else { }
return this.value;
}).get();
var vals = []
$('input[type=text][class = cate_rank]').each(function(){
if($(this).val() && (typeof vals[$(this).val()] == 'undefined')){
vals[$(this).val()] = 1;
var last_val = $(this).val();
}else if($(this).val() && (typeof last_val != 'undefined') && parseInt(last_val) > parseInt($(this).val())){
alert('Whooah! Something went terribly wrong! Inputs don\'t have values ordered incrementally!');
}else{
alert('Whooah! Something went wrong! We got two inputes with same value!');
}
});
Check this,
var rankbox= $(".test").map(function() {
return this.value;
}).get();
var sorted_arr = rankbox.slice().sort();
var results = [];
for (var i = 0; i < rankbox.length - 1; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
results.push(sorted_arr[i]);
}
}
var rankbox= $(".test").map(function() {
if($.inArray(this.value, results) > -1){
alert(this.value+" is duplicate");
}
return this.value;
}).get();
I took reference of this link
If you are Looking to check dup you can try this:
var x=[1,2,3,2,5]
var has=!x.every(function(v,i) {
return x.indexOf(v) == i;
});
console.log(has);//true means dup found else not found.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
you can try with a object. check this:
function change_rank() {
var temp = {};
var rankbox= $('input[type=text][class = cate_rank]').map(function() {
if(temp[this.value]==undefined) {
temp[this.value] = this.value;
} else {
alert('the same value');
}
return this.value;
}).get();

setInterval only running on 4 of my 5 elements

I have to make some table-cells blink based on their values, and apparently IE8 is still a thing, so I'm working on the fix for that..
Here's my function for adding the blink-effect:
function blinkForIE(element) {
setInterval(function () {
if (element.hasClass('IEBlink')) {
element.removeClass('IEBlink');
}
else {
element.addClass('IEBlink');
}
}, 100);
}
the class:
.IEBlink
{
background-color:red;
}
This works for 4 of my 5 cells that should be blinking. I've debugged and checked taht the correct elements are getting passed to the blinkForIE-method and it adds the setInterval-thing for the first 4 elements but not the 5th..
Anyone knows why this might be happening? (I'm not sure what info might be needed, so if you need something else please comment and I'll add it when I can.)
EDIT: still not sure what you guys need to see, but here's all the jquery
var threshold = 100; //---THIS can be changed to what ever our threshold-difference should be.
$(document).ready(function () {
var itemsIndex;
var locationIndex;
var locations = [""];
$('#<%= gvKeying.ClientID %> tbody tr.GridHeader th').each(function () {
if ($(this).html() === 'Items') {
itemsIndex = $(this).index() + 1; //Find the column index of the Items column (+1 for nth-child usage)
}
else if ($(this).html() === 'KeyingLocation') {
locationIndex = $(this).index() + 1; //And the same for KeyingLocation-column.
}
});
$('#<%= gvKeying.ClientID %> tbody tr td:nth-child(' + locationIndex + ')').each(function () {
if ($(this).html() === ' ') {
//Do nothing.
}
else {
locations.push($(this).html()); //Add all locations to an array
}
});
locations = unique(locations); //Make them unique
locations.shift(); //This just removes the first empty element.
for (var i = 0; i < locations.length; i++) { //Loop through all locations
var values = [];
var valuesToBlink = [];
$('#<%= gvKeying.ClientID %> tbody tr').each(function () {
if ($(this).find('td:nth-child(' + locationIndex + ')').html() === locations[i]) {
values.push($(this).find('td:nth-child(' + itemsIndex + ')').html()); //Make an array with all the values.
}
});
values = getTop5(values); //We just want the top 5 highest values.
var firstBlinkVal = -1;
for (var j = 0; j < values.length - 1; j++) { //Loop through the values.
if (firstBlinkVal > -1 && compare(values[j], values[j + 1]) > -1) {
firstBlinkVal = Math.min(firstBlinkVal, compare(values[j], values[j + 1]));
}
else if(compare(values[j], values[j + 1]) > -1){
firstBlinkVal = compare(values[j], values[j + 1]);
}
}
if (firstBlinkVal > -1) {
for (var j = 0; j < values.length; j++) {
if (values[j] >= firstBlinkVal) {
valuesToBlink.push(values[j]);
}
}
}
$('#<%= gvKeying.ClientID %> tbody tr').each(function () { //Loop through all rows.
if ($(this).find('td:nth-child(' + locationIndex + ')').html() === locations[i]) { //If this row is the current location,
var temp = $(this).find('td:nth-child(' + itemsIndex + ')').html(); //get the value for this row.
if (jQuery.inArray(temp, valuesToBlink) > -1) { //if we want this to blink,
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0) {
blinkForIE($(this).find('td:nth-child(' + itemsIndex + ')')); //make it blink for IE
}
else {
$(this).find('td:nth-child(' + itemsIndex + ')').addClass('blink_me'); //make it blink for everything else.
}
}
}
});
}
});
function blinkForIE(element) {
var x = element.html();
console.log(x);
setInterval(function () {
if (element.hasClass('IEBlink')) {
element.removeClass('IEBlink');
}
else {
element.addClass('IEBlink');
}
}, 100);
}
//This just compares two values and returns true if the diff is over our threshold.
function compare(val1, val2) {
if (Math.abs(val1 - val2) > threshold) {
return Math.max(val1, val2);
}
return -1;
}
//Returns a sorted array of the top5 highest values in the input-array.
function getTop5(values) {
values.sort(function (a, b) { return b - a });
while (values.length > 5) {
values.pop();
}
values.sort(function (a, b) { return a - b });
return values;
}
//Makes the values of the input unique.
function unique(list) {
var result = [];
$.each(list, function (i, e) {
if ($.inArray(e, result) == -1) result.push(e);
});
return result;
}
You should call only 1 setInterval function, passing all cells to be animated.
function blinkForIE(elements) {
setInterval(function(){
elements.forEach(function(e){$(e).toggleClass('IEBlink')})
}, 100);
}
resp.
function blinkForIE($elements) {
setInterval(function(){
$elements.toggleClass('IEBlink')
}, 100);
}
(elements is Array, $elements is jQuery object)
The problem is, that setInterval must not execute the callback function, if there is no idle time slot at the execution time. It happens, when there are many executions within a small time interval.
You can troubleshoot this also using different offsets:
setTimeout(function(){setInterval(callback, 100)}, i*15)

Can this function be re-written recursively or more cleanly?

This function match sets an attribute (collapsed) to true or false depending on
the value of a string :
function match(children) {
var data = $scope.treeData
for (var i = 0; i < data.length; i++) {
var s = data[i]
for (var i2 = 0; i2 < s.children.length; i2++) {
var s2 = s.children[i2]
for (var i3 = 0; i3 < s2.children.length; i3++) {
for (var i4 = 0; i4 < s2.children[i3].children.length; i4++) {
var text = "";
if ($scope.searchText == undefined) {
text = ""
} else {
text = $scope.searchText
}
if (s2.children[i3].children[i4].label
.toLowerCase() === text.toLowerCase()) {
s2.children[i3].collapsed = false
}
}
}
}
}
}
Excluding the bad use of variable names i3,i2 etc is there a cleaner method ?
As the inner most loop requires access to the outer loop can recursion still be used ?
Update :
Data structure :
[{"label":"test","collapsed":false,"children":[{"label":"test","collapsed":false,"children":[],"$$hashKey":"002"}],"$$hashKey":"001"}]
Update 2 :
Using a recursive function but the string 'test' is not being matched :
http://jsfiddle.net/U3pVM/19196/
fiddle src :
<div ng-app>
<h2>Todo</h2>
<div ng-controller="TodoCtrl">
</div>
</div>
function TodoCtrl($scope) {
var json = [{"label":"test","collapsed":false,"children":[{"label":"test","collapsed":false,"children":[],"$$hashKey":"002"}],"$$hashKey":"001"}]
var searchText = 'test'
function match(node, searchText){
angular.forEach(node.children, function(idx, child){
node.collapsed = child.label.toLowerCase === searchText.toLowerCase
console.log(node.collapsed)
if(child.children.length > 0){
match(child, searchText);
}
});
}
match(json, searchText);
}
Please try this :
function match2(obj) {
if (obj.children) {
for (var i = 0; i < obj.children.length; i++) {
match2(obj.children[i]);
}
}
else {
var text = $scope.searchText ? $scope.searchText : "";
if (obj.label
.toLowerCase() === text.toLowerCase()) {
obj.collapsed = false
}
}
Your JSFiddle is very nearly there. I made a couple of changes for this working JSFiddle.
First, you were passing an array into match and not an object. I changed your json variable to be json instead by removing the outer [], but you could also have fixed this by passing in json[0].
The other change was that you had the two parameters, child and idx, were the wrong way round.
function match(node, searchText){
angular.forEach(node.children, function(child, idx){
node.collapsed = child.label.toLowerCase === searchText.toLowerCase
console.log(node.collapsed)
if(child.children.length > 0){
match(child, searchText);
}
});
}
Here's another way of doing it, using some:
function match (node, searchText) {
node.collapsed = node.children.some(function(child) {
return child.label.toLowerCase === searchText.toLowerCase;
});
angular.forEach(node.children, function(child, idx){
match(child, searchText);
})
}
I think something like this may work for you. I don't know anything about angular there might be something there that would make it easier.
var searchText = ($scope.searchText == undefined) ? "": $scope.searchText;
match($scope.treeData, searchText);
function match(node, searchText){
$.each(node.children, function(idx, child){
node.collapsed = child.label.toLowerCase === searchText.toLowerCase
if(child.children.length > 0){
match(child, searchText);
}
});
}

Can this jQuery be done in vanilla JS?

I've got this working on mobile devices, but because of the 32kb gzip-ed of jQuery I wonder if it's possible to create this code
$(document).ready(function() {
$('body').addClass('js');
var $menu = $('#menu'),
$menulink = $('.menu-link'),
$wrap = $('#wrap');
$menulink.click(function() {
$menulink.toggleClass('active');
$wrap.toggleClass('active');
return false;
});
});
can be written in no library dependany vanilla JavaScript.
Can it be done? Where would I start?
JQuery uses javascript/DOMscripting to create its framework. Everything JQuery does, can be done in basic scripting. For example $('body').addClass('js') can be written as:
document.querySelector('body').className += ' js';
And $menulink.toggleClass('active'); as something like
var current = $menulink.className.split(/\s+/)
,toggleClass = 'active'
,exist = ~current.indexOf(toggleClass)
;
current.splice(exist ? current.indexOf(toggleClass) : 0,
exist ? 1 : 0,
exist ? null : toggleClass);
$menulink.className = current.join(' ').replace(/^\s+|\s+$/,'');
That's why JQuery wrapped this kind of code.
This jsfiddle contains a working example using javascript without a framework. Besides that it demonstrates how to program your own element wrapper.
Where to start? You'll have to dive into javascript I suppose. Or check this SO-question
For modern browsers only.®
document.addEventListener('DOMContentLoaded', function() {
document.body.classList.add('js');
var wrap = document.getElementById('wrap');
var menuLinks = Array.prototype.slice.call(document.getElementsByClassName('menu-link'));
var toggleActive = function(element) {
element.classList.toggle('active');
};
menuLinks.forEach(function(menuLink) {
menuLink.addEventListener('click', function(e) {
menuLinks.forEach(toggleActive);
toggleActive(wrap);
}, false);
});
}, false);
var toggleClass = function (el, className) {
if(el) {
if(el.className.indexOf(className)) {
el.className = el.className.replace(className, '');
}
else {
el.className += ' ' + className;
}
}
};
document.addEventListener('DOMContentLoaded', function () {
document.body.className += ' js';
var $menu = document.querySelector('#menu'),
$menulink = document.querySelectorAll('.menu-link'),
$wrap = document.querySelector('#wrap');
$menulink.addEventListener('click', function (e) {
toggleClass($menulink, 'active');
toggleClass($wrap, 'active');
e.preventDefault();
});
});
There's always classList (workaround for incompatible browsers included).
Absolutely. Since jQuery is a subset of JavaScript (written entirely in JavaScript) any function you like can be duplicated. It's a matter of how much effort you want to put into it. Below is how I would duplicate the limited subset of jQuery in your post and it's reasonably cross-browser compatible (if a wee bit long...).
var Vanilla;
if (!Vanilla) {
Vanilla = {};
}
//execute this now to have access to it immediately.
(function () {
'use strict';
Vanilla.addHandler = function (elem, event, handler) {
if (elem.addEventListener) {
elem.addEventListener(event, handler, false);
} else if (elem.attachEvent) {
elem.attachEvent('on' + event, handler);
}
};
Vanilla.hasClass = function (elem, cssClass) {
var classExists = false;
//
if (elem && typeof elem.className === 'string' && (/\S+/g).test(cssClass)) {
classExists = elem.className.indexOf(cssClass) > -1;
}
//
return classExists;
};
Vanilla.addClass = function (elem, cssClass) {
if (elem && typeof elem.className === 'string' && (/\S+/g).test(cssClass)) {
//put spaces on either side of the new class to ensure boundaries are always available
elem.className += ' ' + cssClass + ' ';
}
};
Vanilla.removeClass = function (elem, cssClass) {
if (elem && typeof elem.className === 'string'&& (/\S+/g).test(cssClass)) {
//replace the string with regex
cssClass = new RegExp('\\b' + cssClass + '\\b', 'g');
elem.className = elem.className.replace(cssClass, '').replace(/^\s+/g, '').replace(/\s+$/g, ''); //trim className
}
};
Vanilla.toggleClass = function (elem, cssClass) {
if (Vanilla.hasClass(elem, cssClass)) {
Vanilla.removeClass(elem, cssClass);
} else {
Vanilla.addClass(elem, cssClass);
}
};
Vanilla.getElementsByClassName = function (cssClass) {
var nodeList = [],
classList = [],
allNodes = null,
i = 0,
j = 0;
if (document.getElementsByClassName1) {
//native method exists in browser.
nodeList = document.getElementsByClassName(cssClass);
} else {
//need a custom function
classList = cssClass.split(' ');
allNodes = document.getElementsByTagName('*');
for (i = 0; i < allNodes.length; i += 1) {
for (j = 0; j < classList.length; j += 1) {
if (Vanilla.hasClass(allNodes[i], classList[j])) {
nodeList.push(allNodes[i]);
}
}
}
}
return nodeList;
};
}());
//Now we have a proper window onload
Vanilla.addHandler(window, 'load', function () {
'use strict';
var body = document.body,
menu = document.getElementById('menu'),
menulink = [],
wrap = document.getElementById('wrap'),
i = 0,
menulinkClickHandler = function (e) {
var i = 0;
for (i = 0; i < menulink.length; i += 1) {
Vanilla.toggleClass(menulink[i], 'active');
}
Vanilla.toggleClass(wrap, 'active');
return false;
};
Vanilla.addClass(body, 'js');
menulink = Vanilla.getElementsByClassName('menu-link');
for (i = 0; i < menulink.length; i += 1) {
Vanilla.addHandler(menulink[i], 'click', menulinkClickHandler);
}
});

Categories

Resources