Get :first and :last with jQuery - javascript

I had this problem:
I was trying to do the Twitter Effect, so when you click on it,
checks if it's either :first or :last, and if it isn't, create a
margin-top and margin-bottom just like in Twitter's Timeline. I
want to create this effect when clicking in any of "One phrase here".
The main problem was that my jQuery code doesn't detect :first and
:last. I already tried also with :first-child and it did the same.
Using this HTML code:
<div class="phrases-container">
<div class="phrases-title">Titulo</div>
<div class="phrases-list">
<div class="phrases-item zooming">First child</div>
<div class="phrases-item zooming">One phrase</div>
<div class="phrases-item zooming">One phrase</div>
<div class="phrases-item zooming">Last child</div>
</div>
<div class="phrases-load-more">
<a class="link loadMore">Get more phrases!</a>
</div>
</div>
Using this jQuery code, I could fix it. Thanks for your help! (:
$(".zooming").live('click', function(){
var $z = $('.zooming');
index = $z.index(this);
var bradiust = $(this).css("borderTopLeftRadius");
if (bradiust == '0px')
var thand = "show";
else
var thand = "hide";
if (thand == "show"){
if (index == 0 ){
alert("This is the first");
}else
if (index == ($z.length-1)){
alert("This is the last");
}else{
alert("This is just another");
}
}else{
if (index == 0 ){
alert("This is the first");
}else
if (index == ($z.length-1)){
alert("This is the last");
}else{
alert("This is just another");
}
}
});

I'm not quite sure what is wrong with :first, but how about this:
var $z = $('.zooming'),
index = $z.index(this);
if (index == 0 || index == ($z.length-1)) {
return false;
}

$(document).on('click', '.zooming', function(){
var L = $('.zooming').length-1;
var I = $(this).index();
if (I===0 || I==L) {
return false;
}else{
var bradiust = $(this).css("borderTopLeftRadius");
if (bradiust == '0px') {
var thand = "show";
}else{
var thand = "hide";
}
alert(thand);
}
});​

Don't be fooled by the :first jquery selector:
Description: Selects the first matched element.
The :first pseudo-class is equivalent to :eq(0)
You have to use the :first-child selector

What about combining:
if ($(this).is(':first') || $(this).is(':last'))
But notice:
http://api.jquery.com/is/
Starting with jQuery 1.7, selector strings with positional selectors
apply the selector against the document, and then determine whether
the first element of the current jQuery set matches any of the
resulting elements. So for the HTML shown above, an expression such as
$("li:first").is("li:last") returns false.

Related

How would I focus on a input with jQuery

I'm trying to focus on a input using jQuery. I can easily do this by using the id of the input tag, however this is set to the id from a database field, and is ordered in a different way. This makes this not work as well as i want when using to focus on. What I want to be able to do is use the HTML5 data attribute to focus onto so the following would work:
<input class="navigable" type="text" data-id="1" ID="123" data-number="1" maxsize="1"> I want to be able to focus on this using jQuery. Currently I have:
$('.navigable').keyup(function() {
var self = $(this);
var next = $('#txt'+(self.data('number')+1));
if(next.length > 0 && self.val().length == self.attr('size')) {
next.focus();
}
My HTML tag has to be like this:
<input type="text" class="navigable" id="txt1" data-number="1" maxsize="1">
Thanks in advance.
You have typo in your code. You forgot to close if condition }. And self.attr('size') will return undefined. Because you dont have any attribute named size in your input. So replace self.attr('size') with self.data('number').
Try this:
$('.navigable').keyup(function() {
var self = $(this);
var next = $('#txt'+(self.data('number')+1));
console.log(next);
if(next.length > 0 && self.val().length == self.data('number')) {
next.focus();
}
});
DEMO
Try
Attribute Equals Selector [name="value"]
$('input.navigable[data-number="1"]').focus();
$('.navigable').keyup(function () {
var self = $(this);
var next = $('input.navigable[data-number="' + (self.data('number')+1) + '"]');
if (next.length > 0 && self.val().length == self.data('number')) {
next.focus();
}
});
You could use autofocus attribute on your input element, which is plain HTML5.
$('input.navigable[data-number="' + num +'"]').prop('autofocus', true);

Filtering a list <li> with jquery

I want to filter a list (show/hide the lis) based on the contents of a span within the li. Currently I have something working, but it filters the list no matter where the match occurs. I need it to be seeded to the start, so only if the match occurs at the start of the span will it be shown, otherwise it will be hidden.
<li><img/><span>text</span></li>
<li><img/><span>other text</span></li>
<li><img/><span>other words</span></li>
so, if I filter on "text", currently the first 2 would be returned whereas I only want the first (as the word "text" is at the start of it).
This is what I currently have:
var value = $("#listcontainer ul#list input").val();
if(value == '') {
$('ul#list> li').show(); //show all, if nothing entered
} else {
$('ul#list > li:not(.plain):not(:contains(' + value + '))').hide();
$('ul#list > li:not(.plain):contains(' + value + ')').show();
} //.plain = li which contains the text input
Thanks
Try:
$('ul#list > li:not(.plain)').text(function(i, text) {
var show = text.slice(0, value.length) === value;//starts with value
$(this).toggle(show);//if starts with val show otherwise hide
});
This will check if the text of each li starts with the value and show it if it does, otherwise hide it.
Try
var value = $("#listcontainer ul#list input").val().toLowerCase();
if (value == '') {
$('ul#list> li').show(); //show all, if nothing entered
} else {
var $lis = $('ul#list > li:not(.plain)').filter(function () {
return $.trim($(this).text()).toLowerCase().indexOf(value) == 0;
});
$('ul#list > li:not(.plain)').not($lis).hide();
$lis.show();
} //.plain = li which contains the text input
Even if you got this to work, you would run into all sorts of problems trying to escape parentheses, etc.
Try the more readable
var value = $("#listcontainer ul#list input").val();
if(value == '') {
$('ul#list> li').show();
} else {
$('ul#list > li').each(function() {
if($(this).text() == value) {
$(this).show();
} else {
$(this).hide();
}
});
}
Also, know that filter is an option (though for your problem, I would go with the solution above).
Try this way :
var value = $("#listcontainer ul#list input").val();
if(value == '') {
$('ul#list> li').show(); //show all, if nothing entered
} else {
$('ul#list > li').each(function() { $(this).toggle(
$(this).find('span').text() == value); });
}

Modifying HTML elements using jquery

I am trying to use jquery to add and remove a class from <li> elements according to a variable's value ( i ).
Here is a jsfiddle of what I have done so far http://jsfiddle.net/LX8yM/
Clicking the "+" increments i by 1 ( I have checked this with chrome's javascript console ).
One should be able to click "+" and the class .active should be removed from and added to the <li> elements accordingly.
...I can get the first <li> element to accept the class, that's all...
No need for if statements:
$(document).ready(function (){
$('#add').click(function (){
$('.numbers .active').removeClass('active').next().addClass('active');
});
});
jsfiddle
Do note that I added an 'active' class to first list item. You could always do this via JS if you do not have control over the markup.
Your if..else.. is hanging in document.ready. Wrap the increment inside a function and call it respectively.
Like
$(document).ready(function (){
//variable
var i = 1;
//if statments
function incre(i){ // wrap into a function and process it
if(i == 1){
$('#one').addClass('active');
$('#two').removeClass('active');
$('#three').removeClass('active');
}else if(i == 2){
$('#one').removeClass('active');
$('#two').addClass('active');
$('#three').removeClass('active');
}else if(i == 3){
$('#one').removeClass('active');
$('#two').removeClass('active');
$('#three').addClass('active');
}
}
//change i
$('#add').click(function (){
incre(i++); // pass it as a parameter
});
});
Working JSFiddle
This would be easier:
$(document).ready(function(){
var i = 0; // set the first value
$('#something').click(function(){
i++; // every click this gets one higher.
// First remove class, wherever it is:
$('.classname').removeClass('classname');
// Now add where you need it
if( i==1){
$('#one').addClass('classname');
} else if( i==2){
$('#two').addClass('classname');
} else if( i==3){
$('#three').addClass('classname');
}
}):
});
See this code. Initially you have to add class to one.
$(document).ready(function (){
//variable
var i = 1;
$('#one').addClass('active');
//if statments
//change i
$('#add').click(function (){
i++;
if(i == 1){
$('#one').addClass('active');
$('#two').removeClass('active');
$('#three').removeClass('active');
}else if(i == 2){
$('#one').removeClass('active');
$('#two').addClass('active');
$('#three').removeClass('active');
}else if(i == 3){
$('#one').removeClass('active');
$('#two').removeClass('active');
$('#three').addClass('active');
}
});
});
It's being called only once, not in the click event function. This edit of your fiddle works: http://jsfiddle.net/LX8yM/2/
put it in the
'$('#add').click(function (){}'

How do I change a class that is above the element that contains a string?

I have two elements here:
<div class="class1">Number 1</div>
<div class="class1">EQRST923</div>
However, there are multiple classes on the page like that. How do I change it so if class1 contains EQRST923, Number 1's text gets changed to Working?
I would like to use jQuery, but generic JavaScript would also be acceptable.
Thanks!
$(".class1:contains('EQRST923')").prev().text('Working');
EDIT:
as pXl said, :contains its not exact. So i found solution
jsFiddle example
You can extend jQuery expression like this:
$.extend( $.expr[":"], {
containsExact: $.expr.createPseudo ?
$.expr.createPseudo(function(text) {
return function(elem) {
return $.trim(elem.innerHTML) === text;
};
}) :
// support: jQuery <1.8
function(elem, i, match) {
return $.trim(elem.innerHTML) === match[3];
}
});
And then simply use as previous one, but using :containsExact:
$(".class1:containsExact('EQRST923')").prev().text('Working');
My solution is edited code i founded on jQuery Selectors - Adding a :contains exact match.
$('.class1').each(function(){
if($.trim($(this).text()) === "EQRST923"){
$(this).prev('.class1').text('Working');
}
});
My solution:
$('.class1').each(function(){
if($(this).text() === "EQRST923" && $(this).prev().text() === "Number 1")
$(this).prev().text("Working");
})
DEMO
I have created a function that you can add to your file :
//#Author Karl-André Gagnon
if(!$.fn.filterText) $.fn.filterText = function(text, caseSensitive){
var returnedObj = $(),
caseSensitive = caseSensitive || false,
$this = $(this);
if(text instanceof Array){
for(var i = 0; i < text.length; i++){
if(typeof text[i] == 'string'){
returnedObj = returnedObj.add($this.filter(function(){
var search = caseSensitive ? text[i] : new RegExp(text[i], 'i')
return $(this).text().search(search) != -1;
}))
}else if(text[i] instanceof RegExp){
returnedObj = returnedObj.add($this.filter(function(){
return $(this).text().search(text[i]) != -1;
}))
}
}
}else if(typeof text == 'string'){
returnedObj = returnedObj.add($this.filter(function(){
var search = caseSensitive ? text : new RegExp(text, 'i')
return $(this).text().search(search) != -1;
}))
}else if(text instanceof RegExp){
returnedObj = returnedObj.add($this.filter(function(){
return $(this).text().search(text) != -1;
}))
}
return returnedObj;
}
The you can call it like that :
$('.class1').filterText('EQRST923').prev().text('Working');
This function do many more thing, but for your case, it is doing the same as :
$(".class1:contains('EQRST923')").prev().text('Working');
Edit: Saw this comment :
this will work even if text is EQRST923222222 -pXL
So change it for that :
$('.class1').filterText(/^EQRST923$/).prev().text('Working');
Fiddle : http://jsfiddle.net/ZNPP7/
If you think this is too much code (and just need the regex), you can reduce the method to that:
if(!$.fn.filterText) $.fn.filterText = function(text){
var returnedObj = $();
if(text instanceof RegExp){
returnedObj = returnedObj.add($this.filter(function(){
return $(this).text().search(text) != -1;
}))
}
return returnedObj;
}
Relying on nothing except the fact that they are next to each other is very fragile, and your code will break if someone decides to change the layout and moves them into separate table cells, for example.
Instead, either add a wrapping div:
<div class="class1group">
<div class="class1label">Number 1</div>
<div class="class1">EQRST923</div>
</div>
<script type="text/javascript">
$('.class1').each(function(){
if($.trim($(this).text()) === "EQRST923"){
$(this).parent('.class1group').find('.class1label').first().text('Working');
}
});
</script>
Or just use data-attributes (bonus: you get to use css selectors for speed :):
<div class="class1" data-label-for="EQRST923">Number 1</div>
<div class="class1">EQRST923</div>
<script type="text/javascript">
$('.class1[data-label-for="EQRST923"]').text('Working');
</script>

How to match children innerText with user input using jQuery

I have the following structure:
<div id="campaignTags">
<div class="tags">Tag 1</div>
<div class="tags">Tag 2</div>
<div class="tags">Tag 3</div>
</div>
And I'm trying to match user input against the innerText of each children of #campaignTags
This is my latest attempt to match the nodes with user input jQuery code:
var value = "Tag 1";
$('#campaignTags').children().each(function(){
var $this = $(this);
if(value == $(this).context.innerText){
return;
}
The variable value is for demonstration purposes only.
A little bit more of context:
Each div.tags is added dynamically to div#campaignTags but I want to avoid duplicate values. In other words, if a user attempts to insert "Tag 1" once again, the function will exit.
Any help pointing to the right direction will be greatly appreciated!
EDIT
Here's a fiddle that I just created:
http://jsfiddle.net/TBzKf/2/
The lines related to this question are 153 - 155
I tried all the solutions, but the tag is still inserted, I guess it is because the return statement is just returning the latest function and the wrapper function.
Is there any way to work around this?
How about this:
var $taggedChild = $('#campaignTags').children().filter(function() {
return $(this).text() === value;
});
Here's a little demo, illustrating this approach in action:
But perhaps I'd use here an alternative approach, storing the tags within JS itself, and updating this hash when necessary. Something like this:
var $container = $('#campaignTags'),
$template = $('<div class="tags">'),
tagsUsed = {};
$.each($container.children(), function(_, el) {
tagsUsed[el.innerText || el.textContent] = true;
});
$('#tag').keyup(function(e) {
if (e.which === 13) {
var tag = $.trim(this.value);
if (! tagsUsed[tag]) {
$template.clone().text(tag).appendTo($container);
tagsUsed[tag] = true;
}
}
});
I used $.trim here for preprocessing the value, to prevent adding such tags as 'Tag 3 ', ' Tag 3' etc. With direct comparison ( === ) they would pass.
Demo.
I'd suggest:
$('#addTag').keyup(function (e) {
if (e.which === 13) {
var v = this.value,
exists = $('#campaignTags').children().filter(function () {
return $(this).text() === v;
}).length;
if (!exists) {
$('<div />', {
'class': 'tags',
'text': v
}).appendTo('#campaignTags');
}
}
});
JS Fiddle demo.
This is based on a number of assumptions, obviously:
You want to add unique new tags,
You want the user to enter the new tag in an input, and add on pressing enter
References:
appendTo().
filter().
keyup().
var value = "Tag 1";
$('#campaignTags').find('div.tags').each(function(){
if(value == $(this).text()){
alert('Please type something else');
}
});
you can user either .innerHTML or .text()
if(value === this.innerHTML){ // Pure JS
return;
}
OR
if(value === $this.text()){ // jQuery
return;
}
Not sure if it was a typo, but you were missing a close } and ). Use the jquery .text() method instead of innerText perhaps?
var value = "Tag 1";
$('#campaignTags').find(".tags").each(function(){
var content = $(this).text();
if(value === content){
return;
}
})
Here you go try this: Demo http://jsfiddle.net/3haLP/
Since most of the post above comes out with something here is another take on the solution :)
Also from my old answer: jquery - get text for element without children text
Hope it fits the need ':)' and add that justext function in your main customised Jquery lib
Code
jQuery.fn.justtext = function () {
return $(this).clone()
.children()
.remove()
.end()
.text();
};
$(document).ready(function () {
var value = "Tag 1";
$('#campaignTags').children().each(function () {
var $this = $(this);
if (value == $(this).justtext()) {
alert('Yep yo, return');)
return;
}
});
//
});

Categories