Attach a char limit to each comment area jQuery - javascript

I am having some issues, and cannot solve this, since I cannot get my head around this. It's kinda a big issue. I want to dynamically attach a char limit and a submit comment button to each post, and each commentArea to be a form of its own. Any help is welcome, I want to make it dynamic, independent from each other.
Thanks!
$(".comment-box").keyup(function(){
var text_max = 140;
var length_reached = $(this).val().length;
var remaining = text_max - length_reached;
$('.counter').html(remaining);
if(remaining < 5 || remaining > text_max)
$(".btn").prop("disabled", true);
else
$(".btn").prop("disabled", false);
});
Here's my jsfiddle: http://jsfiddle.net/3sCfG/25/
EDIT: Trying to make something similar to Twitter's Reply section which is attached to each micropost on their Timeline, but not sure if IDs should be used, found IDs on Twitter's, but not fully clear. I am trying to make a similar comment box to that of Twitter's.

have a look here: http://jsfiddle.net/3sCfG/38/
CODE
$(".comment-box").keyup(function () {
var parent = $(this).parent();
var text_max = 140;
var length_reached = $(this).val().length;
var remaining = text_max - length_reached;
$(parent).find('.counter').html(remaining);
if (remaining < 5 || remaining >= text_max)
$(parent).find(".btn").prop("disabled", true);
else
$(parent).find(".btn").prop("disabled", false);
});
hope it helps
EDIT cleaned up code a little

Your problem is using classes (hence affecting multiple elements) without specifying which part of the DOM you're trying to update.
The simplest solution is to add a "search context" to the selectors in your handler.
I've used $(selector, parent) as a shorthand for $(parent).find(selector):
$(".comment-box").keyup(function() {
var parent = this.parentNode; // new
var text_max = 140;
var length_reached = this.value.length;
var remaining = text_max - length_reached;
$('.counter', parent).html(remaining);
$('.btn', parent).prop('disabled', (remaining < 5 || remaining >= text_max));
});
I've also refactored the .prop call, since:
if (condition) {
.prop('disabled', true);
} else {
.prop('disabled', false);
}
is exactly equivalent to:
.prop('disabled', condition);
and I changed the > text_max to >= text_max, since I presume the intent was to disable the "submit" button if there's no input.
See http://jsfiddle.net/alnitak/ATW9u/

Maybe add a data- attribute to text area and use that to set the max length?
<textarea class="comment-box" type="text" data-limit="10" placeholder="Write a comment"><textarea>
along with that, instead of referring to the counter with its class, navigate to it and reduce the no. of characters from it. (Like this)
$(this).next(".tools").find("span").html(remaining);
Gives the textareas the inpedendance you wanted to give them. Heres your updated fiddle : http://jsfiddle.net/3sCfG/28/

Related

Wrap a row of blocks in the middle instead of end (CSS/JS/jQ)

How can a row of inline-blocks be wrapped by a shrinking parent resulting in equal (or almost equal) rows?
So instead of wrapping like this:
wrap like this:
And if there's an uneven number of blocks, like this:
You can use CSS Grid grid-template-columns and #media (if you want to wrap by screen-width) or in JS with docment.getElementById('bottomblocks').style.gridTemplateColumns variable to achieve this. (If I understand correctly)
I wrote here an example with JS:
https://jsfiddle.net/Lhbqdt2z/
You can learn about it where I started with it: Coding Tech Talk
Or just from W3Schools
Moz://a has a good examples here
He is something fun I just wrote... Assuming you want an "enhanced wrap" behavior that wraps by the half of its childs, instead of the normal floating.
It's more an "essay" than a strong best practice answer. ;)
$(window).on("load resize",function(){
$(".container div").css({"clear":"initial"});
var wrapped = false;
var wrappedAt = 0;
var wrappedNtimes =0;
var pos = $(".container div").first().offset();
var n = $(".container div").length;
$(".container div").each(function(index){
if(!wrapped){
if( ($(this).offset().top != pos.top)){
console.log("Wrapped at "+index+" out of "+n);
wrapped = true;
wrappedAt = index;
wrappedNtimes++;
}
pos=$(this).offset();
}
});
if(wrapped){
// Force enhanced wrapping... .oO(lol)
console.log("--"+wrappedAt+"--");
var half = Math.ceil(n/(wrappedNtimes+1));
$(".container div").each(function(){
if( $(this).index() != 0 && ($(this).index())%half == 0){
$(this).css({"clear":"left"}); // zero-based.
}
});
}
});
CodePen demo
Here's a solution that inserts <br> elements at the ends of each row. This code can be placed into a function to run whenever you need to wrap the blocks.
// Make sure that the last row of blocks doesn't have 2 less blocks than all
// the previous rows. Assume that all blocks are equal size.
var blocks = sharing.find('.btn');
//what's the parent width
var parentWidth = blocks.parent().width();
//how many blocks can fit in such a width
var maxNumOfBlocksInOneRow = Math.floor(parentWidth / blocks.outerWidth(true));
//repeatable code
var calcNumOfBlocksInLastRow = function(){
var lastRowFull = blocks.length % maxNumOfBlocksInOneRow ? false : true;
if (lastRowFull) {
return maxNumOfBlocksInOneRow;
} else {
return blocks.length % maxNumOfBlocksInOneRow;
}
}
//do we have more blocks than row's maximum?
if (blocks.length > maxNumOfBlocksInOneRow) {
//how many blocks would the last row have
var numOfBlocksInLastRow = calcNumOfBlocksInLastRow();
//if the last row is missing more than 1 block, try with 1 less block in each row
while (numOfBlocksInLastRow < maxNumOfBlocksInOneRow - 1) {
maxNumOfBlocksInOneRow--;
numOfBlocksInLastRow = calcNumOfBlocksInLastRow();
}
//insert <br> at the end of each row
jQuery('<br>').insertAfter(blocks.filter(':nth-child(' + maxNumOfBlocksInOneRow + 'n)'));
}

How would I separate multiple elements added from javascript into my HTML?

I am trying to reproduce the following image in HTML / Javascript:
This is how far I have got:
This is my code in javascript:
function createLink(text, parentElement) {
var a = document.createElement('a');
var linkText = document.createTextNode(text);
a.appendChild(linkText);
temp1 = text.replace("/","-");
temp2 = res1.replace("/","-");
a.href = "http://www.drakedesign.co.uk/mdmarketing/uploads/" + temp2 + ".csv";
parentElement.appendChild(a);
}
var txtFile8 = new XMLHttpRequest();
txtFile8.open("GET", "http://www.drakedesign.co.uk/mdmarketing/uploads/date.txt", true);
txtFile8.onreadystatechange = function() {
if (txtFile8.readyState === 4) { // Makes sure the document is ready to parse.
if( (txtFile8.status == 200) || (txtFile8.status == 0) ) { // Makes sure it's found the file.
allText8 = txtFile8.responseText;
arrayOfLines8 = allText8.match(/[^\r\n]+/g);
for (i = 0; i < arrayOfLines8.length - 1; i++) {
createLink(arrayOfLines8[i], document.getElementById("previousResultsList"));
}
}
}
};
txtFile8.send(null);
This code snippet does the following:
reads an online textfile containing dates.
separates each date into an element in an array.
runs through a for loop making each date into a link in the div previousResultsList
I am writing to ask how I could possibly separate the elements added to the div:"previousResultsList"
The first problem is:
1) Separating the elements out simply one after another in a list form.
2) How would I separate the dates into chunks for any dates in that month and attach the image on the side.
I'm guessing it has something to do with CSS and position: aboslute based on the screenshot. Can't do much more unless you post some HTML and CSS.
I have a working example here https://jsfiddle.net/tkcohpqv/20/
Add this in your function and it will stack and separate the a as long as the parentElement width is less than the width of 2 elements on the same line.
var a = document.createElement('a');
$(a).css('position', '');
$(a).css('display', 'block');
$(a).css('float', 'left');
I solved this issue by editing the position in the CSS to relative and edited my code by adding:
var br = document.createElement('br');
parentElement.appendChild(br);
to the end of my createLink() function.

How to limit typing number in text input

I have an text input for pagination page changing. I need to limit typing of page numbers to some number f.e. 15 (max pages number). So i'm trying with this code below but always when number is higher than 15 value is changing to 15 and actual typing number.
actual.on('keypress', function() {
console.log('test');
var t = $(this);
if (t.val() < 1) t.val('1');
if (t.val() > 15) t.val('15');
});
Fiddle: http://jsfiddle.net/v6fhobr7/
Can anybody help?
Try changing it from 'keypress' to 'keyup' ... there's a slight flicker, but it works.
Use a number field.
<input type="number" min="1" max="15" step="1">
#rfornal's solution works okay, but it's hard to type single digit value unless you're really fast:
http://jsfiddle.net/v6fhobr7/7/
So it's better to set a slight timeout before changing the value:
var actual = $('.actual');
var tm;
actual.on('keyup', function () {
var t = $(this);
if (tm) clearTimeout(tm);
tm = setTimeout(function() {
if (t.val() < 1) t.val('1');
if (t.val() > 15) t.val('15');
}, 250);
});
JSFiddle demo: http://jsfiddle.net/v6fhobr7/10/
In jQuery 2.x, you can use actual.on('input'), which does what you want without the flicker.
Note that this will prevent the user from clearing out the input entirely; if you want to allow this then you might want to handle the case where t.val() == '' explicitly.
actual.on('input', function(e) {
var t = $(this);
if (t.val() == '') return;
if (t.val() < 1) t.val('1');
if (t.val() > 15) t.val('15');
});
http://jsfiddle.net/v6fhobr7/12/
Edit:
Note that this solution doesn't restrict input to only numeric characters (you can still type letters and symbols). If you want to prevent that, use this solution in addition to my answer above.
Or, if you don't care about IE 9 or mobile browsers, Mathletics's answer is the best.

How to re-order and animate text in jquery?

Firstly, I've made a CODEPEN or jsfiddles
Background:
Ok I have a span tag within a few header tags h1,h2,h3. Inside that spantag is the word
experience which is spelled backwards like so:
<h3>for <span class="hover-spell">ecneirepxe</span>.</h3>
Question
I'm unsure on the best way to approch this but I would like on hover:
reorder to spell experience correctly
if possible animate them overlapping another while re-ordering
I have no idea how to do this but I keep thinking regex, with arrays but this feels overly complicated and I really don't know anything about regex and proper array sorting. Any information to lead me in the right direction would be most appreciated. Or an edit to the codepen or jsfiddles would be so excellent.
One possible solution is to use css to accomplish this. This solution doesn't animate the transition, it just changes the order of the letters. Add this to your css:
.hover-spell:hover{
direction: rtl;
unicode-bidi: bidi-override;
}
Edit: Thanks to Marcel Gwerder for pointing out that it's not possible to animate the direction property
I found this answer, in another post (it goes through a given string of text and wraps each character in a span then assigns transiton styles to each), that may help with a jquery solution.
I've just tried to set up something animated with jquery, it's a bit tricky to get a fancy looking animation. But that one doesn't look too bad (DEMO).
var expElem = $(".hover-spell");
var exp = expElem.text();
var run = false;
expElem.empty();
for(var i = 0; i <= exp.length; i++) {
expElem.append('<span>'+exp.charAt(i)+'</span>');
}
expElem.mouseover(function() {
if(run === true) return false;
run = true;
var stepDuration = 300;
var counter = 0;
(function anim(){
if(counter == exp.length -1) return false; //Remove -1 to get last "e" animated
counter++;
var nth = exp.length;
var elem = $('span:nth-child('+nth+')', expElem);
elem.slideUp(stepDuration, function() {
(function() {
if(counter == 1) return elem.prependTo(expElem);
else return elem.insertAfter($('span:nth-child('+(counter-1)+')', expElem));
})().slideDown(stepDuration, anim);
});
})();
});
To get it working with hover(including mouseleave) is a bit more complicated. You could also try something with storing the position and then slide them over each other but again a bit more complicated.
<span id = "spell">olleh</span> //hello in reverse
<script type="text/javascript">
var newText;
var text = null;
text = document.getElementById("spell").innerHTML;
for (var i = text.length - 1; i >= 0; i--) {
if (i == text.length - 1) {
newText = text.substr(i, 1);
}
else {
newText = newText + text.substr(i, 1);
}
}
alert(newText);
</script>
write this script in body tag...

Disable holding the up and down buttons on a jQueryUI spinner

I'm using jQuery 1.7.1 and jQueryUI 1.9.1.
I have a spinner, and every time it changes, a text field will be created or removed to match the number on the spinner. Holding the button will cause the number to change very rapidly, causing a ton of fields to be created or removed.
Not a huge problem since it's client-side, but I just don't like it. So I want to disable the rapid spinning when the user holds the spinner buttons.
I came up with a solution using a function for incremental, which looks like this:
var incrementalFunction = function(numOfSpins) {
if (numOfSpins == 1) {
return 1;
}
return 0;
};
This worked great at first, but caused another issue. Next to each newly created text box, I made a 'remove' button that would remove the element and decrement the spinner. But when I call the stepDown method, for some reason, this calls my incremental function, with an increasing numOfSpins every time it was called. So it would only decrement once.
Anyone have a more straightforward solution to preventing the user from holding the increment/decrement buttons (or the up/down arrows on the keyboard)?
If you upgrade to jQuery UI 1.10, the problem will go away. See https://github.com/jquery/jquery-ui/commit/0d53fbfd0b7651652601b3b8577225ab753aab44 which causes stepUp() and stepdDown() to behave as you'd expect.
If you use the stop event, instead of targeting each increment, you can detect when a selection has been made. Then, you can compare that number to how many are currently there, and determine what to do - remove or add more. Try this:
var targetArea = $("#target_area");
targetArea.on("click", ".remover", function () {
$(this).closest("div").remove();
$("#input1").spinner("stepDown");
});
$("#input1").spinner({
stop: function (event, ui) {
var $this = $(this);
var num = $this.val();
var newTargets = targetArea.find("div");
var difference = num - newTargets.length;
if (difference < 0) {
newTargets.slice(difference).remove();
} else if (difference > 0) {
for (var i = 0; i < difference; i++) {
var newTarget = $("<div><input type='text' /><span class='remover' title='Remove'>×</span></div>");
targetArea.append(newTarget);
}
}
}
});
DEMO: http://jsfiddle.net/PJpUC/1/

Categories