Finding which element has specific text on a list - javascript

I'm doing a menu with fast acess links. I have a button on a different div that when clicked checks if the text is already there, and if it is it does nothing and if it isn't it adds to the bottom position. After that, using jquery ui the user can reorder the list.
The thing is, I want to make it so that when the user clicks and the text is already on the link, I wanted to hightlight for a brief moment the place where the link is already.
The problem I'm facing is how to get in a variable the id from the anchor that has the same text the button would input. I know I can run 10 "ifs" looking if the text is there in each variable, and if it is the animation goes off. But I was looking for a simpler solution, if there is one.
var route = "http://link";
$('.add').click(function() {
if(($('#ref1').text() == "Text") || ($('#ref2').text() == "Text") || ($('#ref3').text() == "Text") || ($('#ref4').text() == "Text") || ($('#ref5').text() == "Text") || ($('#ref6').text() == "Text") || ($('#ref7').text() == "Text") || ($('#ref8').text() == "Text") || ($('#ref9').text() == "Text") || ($('#ref10').text() == "Text")){
}
else{
$('#ref10').attr("href", route)
$('#ref10').text("text")
}
});
EDIT: Adding HTML as asked:
<h4 class="card-tittle"><i class="material-icons" id="acessicon">bookmark</i>Fast acess</h4>
<hr>
<div class="list-group list-group-flush" id="sortable">
Rules
Forms
Placeholder
Placeholder
Placeholder
Placeholder
Placeholder
Placeholder
Placeholder
Placeholder
</div>
<script>
$( ".acesstop" ).click(function() {
var themes ="procgeral";
sessionStorage.setItem("themes", themes);
});
$( function() {
$( "#sortable" ).sortable({
update: function(event, ui) {
$('.link1').each(function(i) {
$(this).attr('id', 'ref' + (i + 1)); // update id
});
}
});
$( "#sortable" ).disableSelection();
} );
</script>
I thought $(this) would work, but it doesn't unfortunatly.
Thanks in advance!

I have used jQuery .each() method to iterate through all links, compare with passed text and add them to an array.
Here is what I have done to clear out your 10 if statements:
function findElems(text) {
let found = [];
let index = 0;
// Iterate
$('a').each((i, elem) => {
if(elem.textContent == text){
found[index] = elem;
index++;
}
});
console.log(found);
}
a {
width: 50px;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
AAA
BBB
CCC
BBB
EEE
FFF
GGG
HHH
<br>
<button onclick="findElems('BBB');">Find Elements</button>
OP's Solution:
var text = "TextIWantToFind";
var found;
//Iterate
$('a').each((i, elem) => {
if (elem.textContent == text) {
found = elem;
}
});
// Using ES6 Template Literals
$(`#${found.id}`).effect("highlight");
/*
// Original approach
$('#' + found.id).effect("highlight");
*/

Related

How to manipulate list element on Enter key press

I want to allow the editing of an ordered list using contenteditable.
When the user changes or adds in a new element in the list I want to be able to manipulate the text (e.g. wrap in span tag, replace text etc).
I've created a listener for the Enter key and can get the last list element value.
I've tried to change this and replace with the new value. However this populates the new list element created on the enter press.
<div>
<ol contenteditable=true class="editor">
<li><br></li>
</ol>
</div>
$('.editor' ).on('keydown .editable', function(e){
if ( e.keyCode === 13 ) {
var insertText = "<span>"+e.target.lastElementChild.innerText+"</span>";
e.target.lastElementChild.innerHTML = insertText;
return true
}
});
What is the best way to implement this functionality for new entries anywhere in the list not just the end? Open to Jquery solutions
example jsfiddle
You could use a MutationObserver to detect when a child is added to your list, and then update the previousSibling to wrap it in a <span>:
function subscriber(mutations) {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
const prev = node.previousSibling;
if (prev) {
prev.innerHTML = `<span>${prev.innerHTML.replace(/<br>$/, '')}</span>`;
}
});
});
}
const observer = new MutationObserver(subscriber);
observer.observe(document.querySelector('ol[contenteditable]'), { childList: true });
.editor span::after {
content: '😀';
}
<ol contenteditable class="editor">
<li>First li</li>
</ol>
You could bind your logic to the last li, and perform your logic from the events it emits.
$('.editor .last-item')
.on('click', function(e){
// clear out the html so the user can just type
e.target.innerHTML = '';
})
.on('keydown', function(e){
if (e.keyCode === 13) {
// ignore the enter key so it doesn't insert a new like
e.preventDefault();
// create the new li before the last one
$('<li>'+ e.target.innerHTML.trim() +'</li>').insertBefore(e.target);
// clear out the html so the user can keep entering items
e.target.innerHTML = '';
}
})
.on('blur', function(e){
// if the user leaves the field, change it back to the instructional text
e.target.innerHTML = 'Click to enter New List Item';
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<ol class="editor">
<li class="last-item" contenteditable=true>Click to enter New List Item</li>
</ol>
</div>
Instead of taking action when an edit happens, you could set an interval that will modify the html of the li elements as desired.
setInterval(function(){
$('.editor' ).find('li').each(function(){
if ($(this).html().indexOf('span')==-1){
$(this).html('<span>' + $(this).html() + '</span>');
}
});
}, 200);
hello you might wanna check this let me give you a heads up. instead of using the
lastchild.innerHTML
replace it with
nextSibling.innerHTML
like this
$('.editor' ).on('keydown .editable', function(e){
if ( e.keyCode === 13 ) {
var insertText = "<span>"+e.target.lastElementChild.innerText+"</span>";
e.target.nextSibling.innerHTML = insertText;
return true
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<ol contenteditable=true class="editor">
<li><br></li>
</ol>
</div>
$('.editor' ).on('keydown .editable', function(e){
if ( e.keyCode === 13 ) {
var insertText = "<span>"+e.target.lastElementChild.innerText+"</span>";
e.target.nextSibling.innerHTML = insertText;
return true
}
});

Input is not detecting that it is empty if removing text with "ctrl + a + backspace"

I am doing some easy div filtering with jQuery and input field. It is working, however it is not detecting that it is empty if I remove input using " Ctrl + a + backspace ", in other words if I select all text and remove it. What causes this?
It is not reordering divs back to default if using the keyboard commands but is going back to normal if you backspace every character.
This is how I do it:
$('#brandSearch').keyup(function() {
var valThis = $(this).val().toLowerCase();
if (valThis.length == 0) {
$('.card').show();
} else {
$('.card').each(function() {
var text = $(this).text().toLowerCase();
(text.indexOf(valThis) >= 0) ? $(this).parent().show(): $(this).parent().hide();
});
};
});
Your if block that handles the empty string is not showing the same elements that the else block hides. The else block calls .parent() but the if block does not.
So the else case shows or hides the parent of each .card element, but the if case shows the .card elements themselves—without unhiding their parents. See my comments added to the code (I also reformatted the conditional expression in the else for clarity):
$('#brandSearch').keyup(function() {
var valThis = $(this).val().toLowerCase();
if (valThis.length == 0) {
// Show all of the .card elements
$('.card').show();
} else {
$('.card').each(function() {
var text = $(this).text().toLowerCase();
// Show or hide the *parent* of this .card element
text.indexOf(valThis) >= 0 ?
$(this).parent().show() :
$(this).parent().hide();
});
};
});
Since it sounds like the non-empty-string case is working correctly, it should just be a matter of adding .parent() in the if block so it matches the others:
$('#brandSearch').keyup(function() {
var valThis = $(this).val().toLowerCase();
if (valThis.length == 0) {
// Show the parent of each .card element
$('.card').parent().show();
} else {
// Show or hide the parent of each .card element
$('.card').each(function() {
var text = $(this).text().toLowerCase();
text.indexOf(valThis) >= 0 ?
$(this).parent().show() :
$(this).parent().hide();
});
};
});
This is the kind of situation where familiarity with your browser's debugging tools would pay off big time. The .show() or .hide() methods manipulate the DOM, and by using the DOM inspector you could easily see which elements are being hidden and shown.
In fact, as a learning exercise I recommend un-fixing the bug temporarily by going back to your original code, and then open the DOM inspector and see how it reveals the problem. While you're there, also try out the JavaScript debugger and other tools.
If you use Chrome, here's an introduction to the Chrome Developer Tools. Other browsers have similar tools and documentation for them.
It seems to be working just fine:
$('#brandSearch').keyup(function() {
var valThis = $(this).val().toLowerCase();
if (valThis.length == 0) {
$('.card').show();
console.log("input is empty");
} else {
console.log("input is not empty");
$('.card').each(function() {
var text = $(this).text().toLowerCase();
(text.indexOf(valThis) >= 0) ? $(this).parent().show(): $(this).parent().hide();
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="brandSearch">

break string into pieces and wrap each piece in html with js

I'm using a content editable div to try and make tags. When the user presses return, I need to be able to select the previous text (but not the previous tags) and turn it into a new tag. A tag will be wrapped in , so an example would be:
<em>tag1></em><em>tag2</em>tag3--- // about to press enter for tag3
This is what I'm thinking so far:
$('#tags').keydown(function(e) {
if (e.keyCode == 13 || e.which == 13) {
paste('---'); // this adds a separator when the user presses enter
var content = $(this).html();
var newTag = // the text between the last </em> and ---
newtag.wrapInEm(somehow);
event.preventDefault();
return false;
}
});
Maybe you should separate the current tags from the new tag creation.
HTML
<div id='tags'>
<span id='tag-list'></span>
<span id='tag-new' contenteditable></span>
</div>
JS
(function($){
var tags = ['tag1', 'tag2'];
$('#tag-new').on("keydown", function(e) {
e.preventDefault();
if (e.keyCode == 13 || e.which == 13) {
// if (!saveToDB) return;
tags.push($(this).text());
_renderTags();
return false;
}
});
$('#tag-list').on("click", "em", function(e){
// if (!deleteFromDB) return;
var idx = tags.indexOf($(this).html());
tags.splice(idx,1);
_renderTags();
});
function _renderTags(){
$('#tag-list').html("<em>" + tags.join("</em><em>") + "</em>");
}
$(document).ready(function(){
// loadTagsFromDB
_renderTags();
});
})(jQuery);
It's hard for me to understand your question--there are a handful of typos and your html sample doesn't make any sense.
Nevertheless:
How about using the [.wrap(]http://api.jquery.com/wrap/) jquery function?
$('#tags'.keydown(function(e) {
if (e.keyCode == 13 || e.which == 13) {
$([selector for previous text]).text().wrap(<em></em>);
}
});

function to remove empty <p> removes <p>'s with content

ive made a function that should remove a p-element if it doesnt have any content or has a br inside itself, when leaving after contenteditable. The problem is that it removes an li that HAS content aswell when .blur() !?
Im going nuts because im sure it worked 10min ago.........
here's the function:
$('p').live('blur', function() {
localStorage.setItem('todo', listan.innerHTML);
color();
if ($(this).html() == "" || "<br>")
{
console.log($(this).html());
$(this).parent().remove();
localStorage.setItem('todo', listan.innerHTML);
}
});
the list ("listan") looks like this:
<ul ID="listan">
<li><p contenteditable="true" class="thing">something</p><input type="button" value="ta bort" class="delete"></li>
</ul>
Remove .parent() from the code, since the parent element of "blurring" p is li. Also check your if statement.
$('p').live('blur', function() {
localStorage.setItem('todo', listan.innerHTML);
color();
var html = $(this).html();
if (html == "" || html == "<br>") {
console.log($(this).html());
$(this).remove();
localStorage.setItem('todo', listan.innerHTML);
}
});​
if( $(this).html() == "" || "<br>")
What this line is saying is "if the html is empty, or if <br> is something".
So it's always true, so no matter what the content is it gets removed.
Try this:
if( $(this).html().replace(/\s|<br ?\/?>/) == "")
This will strip out spaces (most importantly leading and trailing) and line breaks and see if the result is empty.
var html = $(this).html();
if (html == "" || html == "<br>") {....do stuff....}
Why not use CSS?
p:empty {
display: none
}

Showing a div element dependent on if it has content

With jQuery I am trying to determine whether or not <div> has content in it or, if it does then I want do nothing, but if doesn't then I want to add display:none to it or .hide(). Below is what I have come up with,
if ($('#left-content:contains("")').length <= 0) {
$("#left-content").css({'display':'none'});
}
This does not work at all, if the div has not content then it just shows up anyway, can any offer any advice?
Just use the :empty filter in your selectors.
$('#left-content:empty').hide();
if( $( "#left-content" ).html().length == 0 ) {
$( "#left-content" ).hide();
}
try to remove first whitespaces:
// first remove whitespaces
// html objects content version:
var content = $.trim($("#left-content).html()).length;
if(content == 0) {
$("#left-content).hide();
}
// html RAW content version:
var content = $.trim($("#left-content).html()); // <-- same but without length
if(content == "") { // <-- this == ""
$("#left-content).hide();
}

Categories

Resources