i made a JavaScript function to increment and decrement a number in the like button, here is the function
var val = 0;
var negative = false;
$('.i-t').click(function(){
val = val + ((negative) ? -1 : 1);
negative = (negative) ? false : true;
$("#myval").text(val);
});
This function works great on the first click but clicking the second time it doesn't remove the value, is something wrong with the function? here is the button
<button id="myvals" class="myvals">
<i class="myvals" id="i-t"></i>
<span class="myvals" id="voteScore">123</span></button>
i want to change the 123 to 124 if liked and 122 if disliked and it doesn't works, i'm sorry i had to prepare the question better from the beginning
From your comments and update, what you want to do is to increase/decrease the vote count based on whether you have already clicked or not.
In that case, instead of using a variable, you can store the state using a class to support multiple vote button if you need like
$('button.vote').click(function () {
var $btn = $(this).toggleClass('voted');
$(this).find("span.score").text(function (i, val) {
return +val + ($btn.hasClass('voted') ? 1 : -1);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button class="myvals vote"> <i class="myvals" id="i-t">here</i><span class="myvals score">123</span></button>
You need two buttons, one for up and one for down, or you could use one button and a checkbox for up or down, but I think two buttons is simpler.
When reading values from DOM elements, they're generally strings so if numbers are required, particularly for addition, don't forget to convert the value to a number before doing arithmetic.
So the buttons and code can be something like:
function vote(n) {
// Get the element to update
var el = document.getElementById('votes');
// Convert the text content to Number, then add value
el.textContent = Number(el.textContent) + n;
}
Votes: <span id="votes">123</span>
<button onclick="vote(1)">up vote</button>
<button onclick="vote(-1)">down vote</button>
Of course this is just a demo, adapt it however you wish.
Try this:
var val = 0;
var negative = false;
$('.i-t').click(function() {
val = parseInt($("#voteScore").val()) + ((negative) ? -1 : 1);
negative = (negative) ? false : true;
$("#myval").text(val);
});
Related
I am using jquery filter to search for names in a big list of names. It works just fine with good speed when I type in the input field. But when I press backspace button to clear the search text there is a delay of more then 4s when there are about 2 or 3 characters left.
I have made a demo to explain my problem
<input type="text" class="search">
<div class="list"></div>
<script>
// Get the list div
let $list = $('.list');
// Form a list of numbers from 1 to 8000
let listHtml = ''
for (let i = 0; i < 8000; i++) {
listHtml += `<div class="list_item"><div class="list_item_value c${i}">${i}</div></div>`;
}
$list.html(listHtml);
// Get all the list items
$listItem = $list.find('.list_item');
$('.search').on('keyup', function(e) {
// Get the search text
let text = $(this).val();
$listItem.filter(function() {
$(this).toggle($(this).find(`.list_item_value`).text().includes(text));
});
});
</script>
I have simplified my problem with this demo by replacing the text search by number search.
One way to fix this problem would be by canceling the ongoing jquery filter process when a backspace is pressed. But I don't know how to do that. Please someone help me fix it.
Consider the following example.
$(function() {
function makeItems(n, t) {
for (var i = 1; i < n; i++) {
$(t).append("<div class='list_item'><div class='list_item_value " + i + "'>" + i + "</div>");
}
}
var $list = $('.list');
makeItems(8000, $list);
$('.search').keyup(function(e) {
var text = $(this).val().toLowerCase();
$(".filtered").removeClass("filtered");
var search = (text.length > 0);
if (search) {
$(".list_item", $list).filter(function(index) {
return $(this).text().indexOf(text) === -1;
}).addClass("filtered");
}
});
});
.filtered {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="search">
<div class="list"></div>
Not too much different from your code. Some reduction of code. When the Search is done, there is a condition to ensure it's not done on an empty value. Also we reset the view each time. Show, Hide, and Toggle have easing and callbacks, so they can be slower at times. Add/Remove class is very quick.
https://ryanpeden.com/javascript-indexof-vs-includes-performance/
So while includes will be a tiny, tiny amount slower because it has to check if you passed it a regex, in reality this will make no difference to how fast your code runs. You should use indexOf if you care about where the substring is in the original string. If you don’t care, just call includes because it makes the intent of your code more clear.
In the end, it's your call if you want to use includes or indexOf for your comparison.
I would like 5 left do -1 e.g. become 4 left.
HTML
<span class="small">5 left</span>
jQuery
// Store the 5 left in "numberStock" variable
var numberStock = parseInt($(".small:first").text());
// Subtract with "numberStock -1"
var minusStock = numberStock - 1;
// Here comes the issue, how do I add the new content?
$(".small:first").attr(minusStock "left");
Question
How do I add the new numberStock number 4 and text left?
A solution in plain Javascript
Array.prototype.forEach.call(document.getElementsByClassName('small'), function (a) {
a.innerHTML = a.innerHTML.replace(/\d+/, function (v) {
return v - 1;
});
});
<span class="small">5 left</span>
You can use replace:
// Store the 5 left in "numberStock" variable
var numberStock = parseInt($(".small:first").text());
// Subtract with "numberStock -1"
var minusStock = numberStock - 1;
console.log(minusStock);
// Here comes the issue, how do I add the new content?
var original = $(".small:first").text();
var toAdd = original.replace(original[0], minusStock);
$(".small:first").text(toAdd);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="small">5 left</span>
Use String#replace method with a callback function.
// use text method with callback where second
// argumnet is old text
$(".small:first").text(function(i, txt) {
// replace text with decremented value
return txt.replace(/\d+/, function(m) {
return m - 1;
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="small">5 left</span>
UPDATE : With pure JavaSript do something like this.
// since you just want the first element use
// querySelector otherwise you need to use
// querySelectorAll and then need to iterate
// over them
var ele = document.querySelector(".small");
// update text content of span element
ele.textContent = ele.textContent.replace(/\d+/, function(m) {
return m - 1;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="small">5 left</span>
i am not sure if i understood your question, but if i did here is a way to do it , which is pretty close to what you were trying to achieve
var numberStock = parseInt($('.small').text())
var minusStock = numberStock - 1;
$('.small').text(minusStock + ' left');
here is a fiddle in case you want to test around with it
https://jsfiddle.net/09wcjp7b/
Assume that I have two buttons with the values 'abc' and 'efg' respectively, and an inputbox.
This is what I want to achieve :
When I click the button with the value 'abc' a single time, the value 'a' gets appended to the inputbox. If I press it two times immediately the value suddenly changes to 'b' instead of 'a', and when I do it three times it changes to 'c' instead of 'b'.
I should be able to type double 'a''s (or any of 'a', 'b', 'c') by waiting some time between button clicks on button 'abc'. For instance : I first click button 'abc', then 'a' gets into the inputbox, I wait for a short time and clicks one more time to get another 'a'.
I want the same functionality with all the buttons ('abc' and 'efg').
I have linked sample expected output image.
View this jsfiddle Code
<div ng-controller="MyCtrl">
<input type="text" ng-model="btnTxt[btnarr]">
<button ng-modle="btnarr" ng-Click="change()">abc</button>
</div>
Expected output:
Can anyone help me with this ?
I have tried one without using built-in timer functions, and checking it manually.
Solution at Pastebin : pastebin.com/vHF517FN
See if it's good enough for you. Btw, I didn't really refactor much, will do it if you are satisfied with this (I'm also new to js -_-).
EDIT
Refactored anyway.
Refactored Solution at Pastebin : pastebin.com/EnHz2EHK
EDIT 2
Added it to JSFiddle. However, I had to add everything to HTML part to make it work there, moving script to script part isn't working for me (wonder why).
Solution at JSFiddle
<script>
var prevClick = '!';
var prevClickTime;
var clicks = 0;
function buttonClick(letters) {
var input = document.getElementById("put");
var backLetterIndex = (clicks == 0) ? letters.length-1 : clicks - 1;
if(letters[backLetterIndex] == prevClick) {
var now = (new Date()).getTime();
if(now - prevClickTime < 500) {
var val = input.value;
input.value = val.slice(0, val.length - 1);
}
else
clicks = 0;
}
else
clicks = 0;
prevClickTime = (new Date()).getTime();
prevClick = letters[clicks];
clicks = (clicks + 1) % letters.length;
input.value = input.value + prevClick;
}
</script>
<input id="put" type="text"></input>
<button onClick="buttonClick('abc');">abc</button>
<button onClick="buttonClick('defg');">defg</button>
I get it, you want to do phone keyboard.
I am not sure what exactly is your question so here I wrote complete example
http://jsfiddle.net/daybda4h/5/
Bacically, I wrote click event listener with timer if click comes within 200ms after another click I count up.
clicks++;
if(timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
timer = null;
updateInput(clicks, evt.target);
clicks = 0;
}, timeout);
Then, when no more clicks are comming, I take the final number of clicks, take data attribute of a button that says what letters does it control, and take the letter number according to num of clicks.
to add value to input, you simply take input value and add the same value + some custom string.
function updateInput(cl, btn) {
var input = document.getElementById("test");
var letters = btn.getAttribute("data-letters").split("");
input.value = input.value + letters[cl-1];
}
Hope this resolves your problem :)
My jquery function allows me to click on the UP arrow and it swaps rows in a table. I have ranking numbers in each of the rows. I can only get the clicked number to change. I want both numbers to swap. I know the value abovecnt isn't getting set correctlty. I just can't figure out how to get it. Right now it is just undefined.
http://jsfiddle.net/Thread7/2rmowem4/15/
$('.change-rank').click(function() {
var cnt = $(this).attr('cnt');
var direction = $(this).attr('data-direction'),
$original = $(this).closest("tr"),
$target = direction === "up" ? $original.prev() : $original.next();
if ( $target.length && direction === "up" ) {
$original.insertBefore($target);
abovecnt = $original.find('.ranky input[type="text"]').val();
$('#rank_' + cnt).val(cnt-1);
$('#rank_' + abovecnt).val(cnt);
alert('abovecnt=' + abovecnt + '|cnt=' + cnt);
}
else if( $target.length ) {
$original.insertAfter($target);
}
});
I will want the down arrow to change the value also but atm I just want the up arrow to work.
According to your HTML:
<input type='text' id='rank_1' value='4' class='ranky'>
You have a problem with this line:
abovecnt = $original.find('.ranky input[type="text"]').val();
Which should be:
abovecnt = $original.find('input[type="text"].ranky').val();
// As "id" attribute have to be unique, even better using this:
abovecnt = $('#rank_1').val();
Why is that?
Using .ranky input[type="text"] (note the space between ranky and input) means, that you're looking for an input type="text" which is inside an element with ranky class (which is not).
Using input[type="text"].ranky you refer to input field with ranky class - as should be.
Althought the rest of your code works correctly, you should NOT use the same id attribute for more than one element. id-selector have to be unique. I would also suggest you to not use custom attributes like cnt. There's a data attribute to store arbitrary data associated with the matched elements. Eg:
<a href='#' class='change-rank' data-direction='down' data-cnt=4>
And then access it using jQuery's data() method:
var cnt = $(this).data('cnt');
Hey guys,
I have this great scripts someone on stack overflow helped me out with, except the one major function I need is missing.
This is a game where the user picks a number (by entering that number in a text field) then hits a play button. After they hit the play button a series of numbers will appear, they then have to click on the number that matches their number.
The query script I'm using counts how many times they hit the number and how many times they missed the number. Take a look at the script in action here. link text
now what I need it to do, is send the score (hits and misses ) to a database after 3 misses, so I can keep high score. Any ideas? Here's the script.
var hitCount = 0,
missCount = 0;
function IsNumeric(n) {
return !isNaN(n);
}
$("#getit").click(function() {
var li = [],
intervals = 0,
n = parseInt($('#MyNumber').val());
if (IsNumeric(n)) {
setInterval(function() {
li[intervals++ % li.length].text(Math.random() > .1 ? Math.floor(Math.random() * (10 + n) + (n / 2)) : n).attr('class', '');
}, <?php echo $time ?>);
}
$('#randomnumber').empty();
for (var i = 0; i < 5; i++) {
li.push($('<li />').click(function() {
var $this = $(this);
if (!$this.hasClass('clicked')) {
if (parseInt($this.text(), 10) === n) {
$this.addClass('correct');
$('#hitcount').text(++hitCount);
} else {
$this.addClass('wrong');
$('#misscount').text(++missCount);
}
}
$this.addClass('clicked');
}).appendTo('#randomnumber'));
}
return false;
});
I've updated your problem here.
After updating the status Check for the missCount if it is greater than or equal to 3 then stop the play(clear the interval and unbind the event), then save the value using an ajax request.
I've changed the event handling to use event delegation instead of direct click event on the <li> elements. Event delegation is better in cases where there are lot of elements to which we have to bind a particular event.
I updated your fiddle with the solution. Check http://jsfiddle.net/DHPQT/2/.
I marked all the new stuff with a comment in the form of
//new ....
The main thing to do is checking after
$('#misscount').text(++missCount);
if missCount is 3 and if yes stop the game and send something