const people = [
{name: 'tax overview'},
{name: 'patel'}
];
String.prototype.capitalize = function() {
return this.charAt(0).toUpperCase() + this.slice(1);
}
const list = document.getElementById('list');
function setList(group) {
clearList();
for (const person of group){
const item = document.createElement('li')
item.classList.add('list-group-item');
const text = document.createTextNode(person.name.capitalize());
item.appendChild(text);
list.appendChild(item);
}
if (group.length === 0){
setNoResults();
}
}
function clearList(){
while (list.firstChild){
list.removeChild(list.firstChild);
}
}
function setNoResults(){
const item= document.createElement('li')
item.classList.add('list-group-item');
const text = document.createTextNode("No results found")
item.appendChild(text);
list.appendChild(item);
}
function getRelevancy(value, searchTerm) {
if (value === searchTerm) {
return 2;
}else if(value.startsWith(searchTerm)){
return 1;
}else if (value.includes(searchTerm)){
return 0;
}else{
return -1;
}
}
const searchInput = document.getElementById('search');
searchInput.addEventListener('input' , (event) => {
let value = event.target.value;
if (value && value.trim().length > 0){
value = value.trim().toLowerCase();
setList(people.filter(person => {
return person.name.includes(value);
}).sort((personA, personB) => {
return getRelevancy(personB.name, value) -getRelevancy(personA.name, value);
}));
}else{
clearList();
}
});
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">
<span class="fa fa-search"></span>
</span>
</div>
<input autofocus placeholder="Search Topics" class="form-control" type="text" autocomplete="off" name="search" id="search" />
<ul class="list-group" id="list"></ul>
</div>
</div>
I want the search results to take me to another link, like a file. For example I search Tax Overview, then it takes me to taxoverview.html. Another minor problem is that since my search bar is in the navbar, when it displays the results, it pushs my navbar all the way down, and its pretty annoying. Is there anyway to make the results go over the screen and content instead of pushing everything down? Thanks, and any suggestions will be greatly appreciated.
Related
I am creating a comment box and I managed to append whatever I type to a div I wanted, however I have added another input and trying to append that along with the comments, however when I do this the second time,it appends both the previous and current comment therefore the previous comment duplicates. I know I'm doing something wrong in my display_commnents function, however I'm not entirely sure what it could be, basically I just want whatever is entered on both title and comments to append on the comment-box with title on top and comment just below. Below is my code:
<div class="container">
<h1>Write New Post</h1>
<form>
<input id="title" type="text" placeholder="Title" value="">
<textarea id="" placeholder="Leave us a comment" value=""></textarea>
<input id="giphy" type="text">
<div class="btn">
<input id="submit" type="submit" value="comment">
<button id="clear">Cancel</button>
</div>
</form>
</div>
<div class="comments">
<h2>Comments</h2>
<div id="comment-box" value="submit">
</div>
</div>
And this is my JS code:
const title = document.querySelector('#title')
const field = document.querySelector('textarea');
const textBackUp = title.getAttribute('placeholder')
const backUp = field.getAttribute('placeholder')
const btn = document.querySelector('.btn');
const clear = document.getElementById('clear')
const submit = document.querySelector('#submit')
// const comments = document.querySelector('#comment-box')
const titleText = document.getElementById('title')
const comments = document.getElementById('comment-box')
let title_arr = [];
let comments_arr = [];
title.onfocus = function(){
this.setAttribute('placeholder', '')
}
title.onblur = function(){
this.setAttribute('placeholder', textBackUp)
}
field.onfocus = function(){
this.setAttribute('placeholder','')
this.style.borderColor = '#333'
btn.style.display = 'block'
} // when clicking on this, placeholder changes into ' ', border colour changes and buttons will appear.
field.onblur = function(){
this.setAttribute('placeholder',backUp)
} //click away, placeholder returns
const display_comments = () => {
let list = '<ul>'
title_arr.forEach(title => {
comments_arr.forEach(comment => {
list += `<li>${title} <br>${comment}`
})
})
list += '</ul>'
comments.innerHTML = list
}
clear.onclick = function(e){
e.preventDefault();
btn.style.display = 'none'
title.value = ''
field.value = ''
display_comments()
}
submit.onclick = function(e){
e.preventDefault();
const head = title.value;
const content = field.value;
if(head.length > 0){
title_arr.push(head)
display_comments();
title.value = '';
}
if(content.length > 0){
comments_arr.push(content)
display_comments();
field.value = '';
}
}
any help would be appreciated
The problem is that you have a double nested loop, producing a Cartesion product of the all the introduced titles and the comments.
To solve this, use only one array for collecting the input, so that title and comment are always kept together in one array entry. Such an entry can be an object with two properties, one for the title, and one for the comment.
Here is your code adapted, just for fixing that issue:
const title = document.querySelector('#title')
const field = document.querySelector('textarea');
const textBackUp = title.getAttribute('placeholder')
const backUp = field.getAttribute('placeholder')
const btn = document.querySelector('.btn');
const clear = document.getElementById('clear')
const submit = document.querySelector('#submit')
// const comments = document.querySelector('#comment-box')
const titleText = document.getElementById('title')
const comments = document.getElementById('comment-box')
let arr = []; // Only one array
title.onfocus = function(){
this.setAttribute('placeholder', '');
}
title.onblur = function(){
this.setAttribute('placeholder', textBackUp);
}
field.onfocus = function(){
this.setAttribute('placeholder','');
this.style.borderColor = '#333';
btn.style.display = 'block';
}
field.onblur = function(){
this.setAttribute('placeholder', backUp);
}
const display_comments = () => {
let list = '<ul>';
// Only one loop -- over objects with two properties
arr.forEach(({head, content}) => {
list += `<li><b>${head}</b><br>${content}`;
})
list += '</ul>';
comments.innerHTML = list;
}
clear.onclick = function(e){
e.preventDefault();
btn.style.display = 'none';
title.value = '';
field.value = '';
display_comments();
}
submit.onclick = function(e){
e.preventDefault();
const head = title.value;
const content = field.value;
// Only one if-block
if(head.length > 0 || content.length > 0){
arr.push({head, content}); // Only one push -- of an object
display_comments();
title.value = '';
field.value = '';
}
}
<div class="container">
<h1>Write New Post</h1>
<form>
<input id="title" type="text" placeholder="Title" value="">
<textarea id="" placeholder="Leave us a comment" value=""></textarea>
<div class="btn">
<input id="submit" type="submit" value="comment">
<button id="clear">Cancel</button>
</div>
</form>
</div>
<div class="comments">
<h2>Comments</h2>
<div id="comment-box" value="submit">
</div>
</div>
enter() {
this.selection = this.matches[this.current];
this.open = false;
},
change() {
if (this.open == false) {
this.open = true;
this.current = 0;
}
if(this.search == "") {
this.isSearchText = false;
} else {
this.isSearchText = true;
}
},
inputChanged(event) {
if (event.code == "ArrowUp" || event.code == "ArrowDown")
return;
this.filteredUsers = [];
if (event.code == "Enter")
return;
var filtered = this.users.filter((user) => {
return user.text.match(this.search)
});
this.isOpen = true
this.filteredUsers.push(...filtered)
// console.log(this.filteredUsers)
},
onArrow(event) {
if (this.filteredUsers.length > 0) {
this.arrowCounter = event.code == "ArrowDown" ? ++this.arrowCounter : --this.arrowCounter;
if (this.arrowCounter >= this.filteredUsers.length)
this.arrowCounter = (this.arrowCounter) % this.filteredUsers.length;
else if (this.arrowCounter < 0)
this.arrowCounter = this.filteredUsers.length + this.arrowCounter;
this.setResult(this.filteredUsers[this.arrowCounter].text);
}
},
<input class="form-control bg-light-blue" id="SearchText" type="text" v-model="search"
#keydown.enter = 'enter'
#input = 'change'
#keyup="inputChanged"
#keydown.down="onArrow"
#keydown.up="onArrow"
/>
Example:- In the Flipkart website in the searchbar if i type shoes, and then if i go back and again click and search bar previously visited searched items will be saved in the searchbar.
I am looking for the same functionality in vuejs
I went to the Flipkart site and inspected their search input. It is an input tag combined with unordered list. So I created this sample component.
EDIT: Added logic to show/hide search history. Added history max length.
InputWithList.vue
<template>
<div class="input-with-list">
<h4>Input with List</h4>
<div class="row">
<div class="col-md-6">
<div class="input-group">
<input type="text" class="form-control" v-model="searchValue" #keyup.enter="processSearch"
#click="onClick" #input="onInput">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" #click="processSearch">Search</button>
</div>
</div>
<div class="form-group">
<ul class="list-group" v-if="showSearchHistory">
<li class="list-group-item" v-for="(item, index) in searchHistory" :key="index"
#click="selectPreviousSearch(index)">{{ item }}</li>
</ul>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<button type="button" class="btn btn-secondary" #click="clearHistory">Clear history</button>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
searchValue: '',
searchHistory: [],
showSearchHistory: false,
searchHistoryMaxLength: 5
}
},
methods: {
processSearch() {
if ( this.searchHistory.indexOf(this.searchValue) === -1) {
this.searchHistory.push(this.searchValue);
if (this.searchHistory.length > this.searchHistoryMaxLength) {
// Remove the first (oldest) element
this.searchHistory.shift();
}
}
this.searchValue = '';
},
selectPreviousSearch(index) {
this.searchValue = this.searchHistory[index];
this.showSearchHistory = false;
},
clearHistory() {
this.searchHistory = [];
this.searchValue = '';
},
onClick() {
// Toggle show/hide
this.showSearchHistory = !this.showSearchHistory;
},
onInput() {
this.showSearchHistory = false;
}
}
}
</script>
<style scoped>
li:hover {
background-color:gainsboro;
}
</style>
I want to make a dynamic search input according to the class names in the I'd like to span tags. However, I am having trouble listing the class name I found.
My aim; Displaying the class names matching the value entered in the input into the screen. Would you help me with this topic?
jQuery.expr[':'].contains = function(a, i, m) {
return jQuery(a).text().toUpperCase()
.indexOf(m[3].toUpperCase()) >= 0;
};
$(document).ready(function() {
$("#searchinput").keyup(function() {
var inputvalue = $("#searchinput").val();
var spantags = $("#iconlist span");
if (inputvalue.length == 0) {
spantags.show();
} else {
if (spantags.hasClass(inputvalue)) {
$("#iconlist span").hide();
}
}
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="search" placeholder="Ara" id="searchinput" />
<div id="iconlist">
<span class="test1">Deneme-1</span>
<span class="test2">Deneme-2</span>
<span class="test3">Deneme-3</span>
<span class="test4">Deneme-4</span>
</div>
You could try and use something like this to display the span where the class matches the input.
spantags.filter(function() {
return $(this).attr("class").indexOf(inputvalue) > -1;
}).show();
Demo
jQuery.expr[':'].contains = function(a, i, m) {
return jQuery(a).text().toUpperCase()
.indexOf(m[3].toUpperCase()) >= 0;
};
$(document).ready(function() {
$("#searchinput").keyup(function() {
var inputvalue = $("#searchinput").val();
var spantags = $("#iconlist span");
spantags.hide();
spantags.filter(function() {
return $(this).attr("class").indexOf(inputvalue) > -1;
}).show();
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="search" placeholder="Ara" id="searchinput" />
<div id="iconlist">
<span class="test1">Deneme-1</span>
<span class="test2">Deneme-2</span>
<span class="test3">Deneme-3</span>
<span class="test4">Deneme-4</span>
</div>
In the case that you're looking for an exact match, eg "test1" then you cause use
spantags.filter(":not(." + inputValue + ")").hide()
which says to hide everything that does not have the class you entered
(in the case where you want to match any letter, eg "t", use .attr("class").indexOf as in the other answer.
Updated snippet:
$(document).ready(function() {
$("#searchinput").keyup(function() {
var inputValue = $("#searchinput").val();
var spantags = $("#iconlist span");
spantags.show();
if (inputValue !== "") {
spantags.filter(":not(." + inputValue + ")").hide()
}
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="search" placeholder="Ara" id="searchinput" />
<div id="iconlist">
<span class="test1">Deneme-1</span>
<span class="test2">Deneme-2</span>
<span class="test3">Deneme-3</span>
<span class="test4">Deneme-4</span>
</div>
Hey im really newbie of walking around in js, saw a nice code about to-do list and would like to save it in every refresh page (in local storage). Have tried savy.js plugin but it doesn't really work. Was thinking about making some json file but don't really know how it would work in jQuery. here is my code:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="list">
<input type="text" class="txtb" placeholder="Add a task">
<div class="notcomp">
<h3>Not Completed</h3>
</div>
<div class="comp">
<h3>Completed</h3>
</div>
</div>
<script type="text/javascript">
$(".txtb").on("keyup", function(e) {
if (e.keyCode == 13 && $(".txtb").val() != "") {
var task = $("<div class='task'></div>").text($(".txtb").val());
var del = $("<i class='fas fa-trash-alt'></i>").click(function() {
var p = $(this).parent();
p.fadeOut(function() {
p.remove();
})
});
var check = $("<i class='fas fa-check'></i>").click(function() {
var p = $(this).parent();
p.fadeOut(function() {
$(".comp").append(p);
p.fadeIn();
});
$(this).remove();
});
task.append(del, check);
$(".notcomp").append(task);
$(".txtb").val("");
}
});
</script>
Aprieciate for any help.
try this code or check the example at Task List
HTML
<div class="list">
<input type="text" class="txtb" placeholder="Add a task">
<div class="notcomp">
<h3>Not Completed</h3>
</div>
<div class="comp">
<h3>Completed</h3>
</div>
</div>
jQuery
$(document).ready(function() {
var data = localStorage.getItem("todo");
if (data != "" && data != null) {
data = JSON.parse(data);
for (const [key, value] of Object.entries(data)) {
insertTask(value);
}
} else {
data = [];
}
function insertTask(data) {
var task = $("<div class='task'></div>").text(data.value);
var del = $("<i class='fa fa-trash' ></i>").click(function() {
removeData(data.id);
$(this)
.parent(".task")
.fadeOut("slow", function() {
$(this).remove();
});
});
task.append(del);
$(".notcomp").append(task);
}
function removeData(id) {
console.log(id);
for (const [key, value] of Object.entries(data)) {
if (value.id === id) {
data.splice(key, 1);
localStorage.setItem("todo", JSON.stringify(data));
return false;
}
}
}
$(".txtb").on("keyup", function(e) {
if (e.keyCode == 13 && $(".txtb").val() != "") {
let val = $(".txtb").val();
var unix = Math.round(+new Date() / 1000);
var taskData = {
value: val,
id: unix
};
data.push(taskData);
insertTask(taskData);
localStorage.setItem("todo", JSON.stringify(data));
$(".txtb").val("");
}
});
});
I have a case in which I need to divide tags when the user put a comma separation, for the moment the user can only add tags one by one, what I want to do is allows user to enter more than one tag in the input separated by a comma:
This is what I have now :
this is what I want to do :
what I have so far :
<div class="form-group">
<label>Mes centres d'intérêt</label>
<div class="input-group" style="margin-bottom: 8px;">
<input id="tagInsert" type="text" name="newTag" ng-model="newTag" ng-model-options="{debounce: 100}" typeahead="tag for tag in getTags($viewValue)" class="form-control" typeahead-loading="loadingTags" ng-keydown="addInterestOnEvent($event)" ng-disabled="interestLimit" autocomplete="off">
<span class="input-group-btn"><span class="btn btn-primary" ng-click="addInterest()" analytics-on="click" ng-disabled="interestLimit" analytics-event="Ajout Interet" analytics-category="Profil">Ajouter</span></span>
</div>
<p class="form__field__error" ng-show="interestLimit">Vous avez atteint la limite de 10 centres d'intérêt.</p>
<ul class="tags">
<li class="tag" ng-repeat="name in user.interests track by $index">{{ name }} <i class="icon-close" ng-click="removeInterest($index)" analytics-on analytics-event="Supprimer Interet" analytics-category="Profil"></i></li>
</ul>
</div>
My controller :
$scope.getTags = function (name) {
return $http.get('/api/tags/' + name.replace('/', '')).then(function (result) {
var tags = result.data;
for (var i = tags.length; i--; ) {
var tagName = tags[i].name;
if ($scope.user.interests.indexOf(tagName) !== -1) tags.splice(i, 1);
else tags[i] = tagName;
}
return tags;
});
};
$scope.removeInterest = function (id) {
$scope.interestLimit = false;
$scope.user.interests.splice(id, 1);
}
$scope.addInterest = function () {
if ($scope.interestLimit) return;
var element = $document[0].getElementById('tagInsert'),
value = element.value;
if (value.length) {
element.value = '';
if ($scope.user.interests.indexOf(value) === -1) {
$scope.user.interests.push(value);
$scope.interestLimit = $scope.user.interests.length === 10;
}
}
};
$scope.addInterestOnEvent = function (event) {
if (event.which !== 13) return;
event.preventDefault();
$scope.addInterest();
};
$scope.remove = function () {
$scope.confirmModal = Modal.confirm.delete(function () {
User.remove(function () {
submit = true;
Auth.logout();
$location.path('/');
});
})('votre compte');
};
You should split value with comma and do for loop.
Change "addInterest" function like this:
$scope.addInterest = function () {
if ($scope.interestLimit) return;
var element = $document[0].getElementById('tagInsert'),
value = element.value.split(',');
if (value.length) {
element.value = '';
for (var i = 0; i < value.length; i++) {
if ($scope.interestLimit) break;
if ($scope.user.interests.indexOf(value[i]) === -1) {
$scope.user.interests.push(value[i]);
$scope.interestLimit = $scope.user.interests.length === 10;
}
}
}
};
As far as I understand , you want to split text into string array by comma
Try this code please
<input id='tags' type="text" />
<input type="button" value="Click" onclick="seperateText()" />
<script>
function seperateText(){
var text= document.getElementById("tags").value;
var tags = text.split(',');
console.log(text);
console.log(tags);
}
</script>