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>
Related
I want to ask about this, I search in a lot of thread about this topic since it is a common topic but, It seems I don't quite understand where is the fail part in my code. At first, my code works fine without any problem, but when I add a data from API suddenly I got this ClassList of undefined even thought I already check it using if.
this is my code before Adding Any Data from API: https://codesandbox.io/s/goofy-sara-2fy30
and this is my code after I add API Data:
Template:
<!-- start tab content -->
<div class="tab-pane fade in active show" id="tab_sec1">
<div class="merchandise-item-wrapper">
<table class="merchandise-table">
<tr id="customWrapper">
<td
class="item-store"
v-for="(merchandise, index) in merchandises"
:key="index"
>
<div>
<div
class="portfolio-img bg-white position-relative text-center overflow-hidden"
>
<img
class="merchandise-img"
:src="
merchandise.Thumbnail
? merchandise.Thumbnail
: 'https://via.placeholder.com/300x300'
"
/>
</div>
<div style="padding-top: 3vh;">
<div class="portfolio-hover-main text-center">
<div class="portfolio-hover-box align-middle">
<div
class="portfolio-hover-content position-relative"
>
<div class="row text-left">
<div class="col-10 col-md-11 col-lg-4">
<p class="merchandise-category">
Mechandise Code
</p>
</div>
<div class="col-2 col-md-1 col-lg-1">
<p class="merchandise-category">:</p>
</div>
<div class="col-12 col-md-12 col-lg-7">
<p class="merchandise-code">
{{ merchandise.Name }} ({{
merchandise.ProductCode
}})
</p>
</div>
</div>
<div class="row text-left">
<div class="col-10 col-md-11 col-lg-4">
<p class="merchandise-category">
Description
</p>
</div>
<div class="col-2 col-md-1 col-lg-1">
<p class="merchandise-category">:</p>
</div>
<div class="col-12 col-md-12 col-lg-7">
<p
class="merchandise-text number-of-lines-5"
>
{{ merchandise.Description }}
</p>
</div>
</div>
<div class="row text-left">
<div class="col-10 col-md-11 col-lg-4">
<p class="merchandise-category">Price</p>
</div>
<div class="col-2 col-md-1 col-lg-1">
<p class="merchandise-category">:</p>
</div>
<div class="col-12 col-md-12 col-lg-7">
<p class="merchandise-price">
{{ formattedPrice(merchandise.Price) }}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</td>
</tr>
</table>
</div>
</div>
<!-- end tab content -->
this is my method:
data() {
return {
loading: true,
statusRelease: false,
totalItems: 9,
currentPosition: 0,
maxPosition: 0,
multiplier: 0,
imgScaller: 0,
originalLength: 0,
prevStatus: true,
nextStatus: true,
intervalStatus: true,
merchandises: []
};
},
methods: {
toNextSection() {
let next = document.getElementById("merchandise");
next.scrollIntoView({ behavior: "smooth" });
},
formattedPrice(price) {
return formatCurrency(price);
},
itemSlider() {
let autoScroller = document.getElementById("customWrapper");
let item = autoScroller.getElementsByTagName("td");
this.maxPosition = -1 * autoScroller.offsetWidth;
if (this.intervalStatus) {
if (this.multiplier === this.originalLength * 2) {
item[this.imgScaller].classList.remove("active");
this.multiplier = 0;
this.imgScaller = 0;
for (let i; i < this.originalLength; i++) {
autoScroller.removeChild(autoScroller.children[i]);
}
item[this.imgScaller + 1].classList.add("active");
}
if (item[this.imgScaller].classList != undefined) {
this.currentPosition =
-1 * item[this.imgScaller].offsetWidth * this.multiplier;
autoScroller.style.transform = `translateX(${this.currentPosition}px)`;
autoScroller.style.transition = `0.5s`;
}
if (this.imgScaller - 1 !== -1 && this.imgScaller !== 0) {
let firstSlide = item[this.imgScaller - 1];
let cloneFirst = firstSlide.cloneNode(true);
autoScroller.appendChild(cloneFirst);
}
if (this.imgScaller) {
item[this.imgScaller + 1].classList.add("active");
}
if (this.imgScaller - 1 !== -1) {
item[this.imgScaller].classList.remove("active");
item[this.imgScaller - 1].classList.remove("active");
}
this.multiplier++;
this.imgScaller++;
setTimeout(this.itemSlider, 3000);
} else {
for (let i = 0; i < item.length; i++) {
if (item[i].classList) {
item[i].classList.remove("active");
}
}
}
},
removeCells() {
let autoScroller = document.getElementById("customWrapper");
let item = autoScroller.getElementsByTagName("td");
this.originalLength = item.length;
for (let i = 0; i < this.originalLength; i++) {
if (item[i]) {
autoScroller.removeChild(item[i]);
}
}
},
getMerchandise() {
getMerchandise({
Limit: 16,
Page: 1,
OrderBy: "Name",
OrderType: "ASC",
PublishStatus: true
})
.then(({ data: { data, errors } }) => {
if (errors && errors[0]) {
throw Error(
errors[0].message ? errors[0].message : "Unknown Error"
);
}
this.merchandises = data.item;
this.originalLength = this.merchandises.length;
if (this.originalLength != 0) {
this.itemSlider();
}
this.loading = false;
})
.catch(e => {
console.log("getMerchandise => getMerchandiseFunction : ", e);
this.loading = false;
});
}
},
mounted() {
this.getMerchandise();
}
If it looks so long, You can only focus in this part:
methods: {
itemSlider() {
let autoScroller = document.getElementById("customWrapper");
let item = autoScroller.getElementsByTagName("td");
this.maxPosition = -1 * autoScroller.offsetWidth;
if (this.intervalStatus) {
if (this.multiplier === this.originalLength * 2) {
item[this.imgScaller].classList.remove("active");
this.multiplier = 0;
this.imgScaller = 0;
for (let i; i < this.originalLength; i++) {
autoScroller.removeChild(autoScroller.children[i]);
}
item[this.imgScaller + 1].classList.add("active");
}
if (item[this.imgScaller].classList != undefined) {
this.currentPosition =
-1 * item[this.imgScaller].offsetWidth * this.multiplier;
autoScroller.style.transform = `translateX(${this.currentPosition}px)`;
autoScroller.style.transition = `0.5s`;
}
if (this.imgScaller - 1 !== -1 && this.imgScaller !== 0) {
let firstSlide = item[this.imgScaller - 1];
let cloneFirst = firstSlide.cloneNode(true);
autoScroller.appendChild(cloneFirst);
}
if (this.imgScaller) {
item[this.imgScaller + 1].classList.add("active");
}
if (this.imgScaller - 1 !== -1) {
item[this.imgScaller].classList.remove("active");
item[this.imgScaller - 1].classList.remove("active");
}
this.multiplier++;
this.imgScaller++;
setTimeout(this.itemSlider, 3000);
} else {
for (let i = 0; i < item.length; i++) {
if (item[i].classList) {
item[i].classList.remove("active");
}
}
}
},
removeCells() {
let autoScroller = document.getElementById("customWrapper");
let item = autoScroller.getElementsByTagName("td");
this.originalLength = item.length;
for (let i = 0; i < this.originalLength; i++) {
if (item[i]) {
autoScroller.removeChild(item[i]);
}
}
},
getMerchandise() {
getMerchandise({
Limit: 16,
Page: 1,
OrderBy: "Name",
OrderType: "ASC",
PublishStatus: true
})
.then(({ data: { data, errors } }) => {
if (errors && errors[0]) {
throw Error(
errors[0].message ? errors[0].message : "Unknown Error"
);
}
this.merchandises = data.item;
this.originalLength = this.merchandises.length;
if (this.originalLength != 0) {
this.itemSlider();
}
this.loading = false;
})
.catch(e => {
console.log("getMerchandise => getMerchandiseFunction : ", e);
this.loading = false;
});
}
},
mounted() {
this.getMerchandise();
}
can someone help me to solve this? I'm confused as how can I solved this, since this problem appear after I add data from API. The data it self, I can successfully get it, and it looks like this:
this is error that I got:
Can Someone Help me to solve this?
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.
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>
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>
I am trying to put form content in a JSON dynamically.
It worked before, but after I added a extra layer (arrays in arrays) there seem to be something that I am doing wrong:
aJSON = {};
aJSON['properties'] = [];
aJSON['options'] = [];
aJSON['arrays'] = [];
$('input').each(function () {
if($(this).attr('name') != undefined) {
if($(this).attr('name').indexOf('[]') > -1) {
if(aJSON['arrays'][$(this).attr('name')] == undefined) {
aJSON['arrays'][$(this).attr('name')] = [];
}
if($(this).is(':checked')) {
aJSON['arrays'][$(this).attr('name')][$(this).attr('value')] = 1;
} else {
aJSON['arrays'][$(this).attr('name')][$(this).attr('value')] = 0;
}
} else {
aJSON['properties'][$(this).attr('name')] = $(this).val();
}
}
});
$('select').each(function () {
if($(this).attr('name') != undefined) {
aJSON['properties'][$(this).attr('name')] = $(this).val();
}
});
var array = getUrlVars();
aJSON['options']['type'] = array['type'];
aJSON['options']['id'] = array['id'];
aJSON['options']['view'] = pageSpecificVariables['view'];
The top 4 lines are just a tryout, I also tried:
aJSON = {'properties':[], 'options':[], 'arrays':[]}
But the only result I am getting is an object with empty arrays of properties, options and arrays.
Before I put all the values directly in aJSON and that worked perfectly.
But for categorizing, I need the 3 categories to exist.
Any idea why my values aren't written to the aJSON?
EDIT
Added JSfiddle here: http://jsfiddle.net/abayob/pob32fs1/
I assume you are trying to serialise a form.
Use jQuery's serializeArray function instead
var myform = $("#myform");
var data = JSON.stringify( myform.serializeArray() );
Update
Because you're trying to use arrays like object-maps
Solution: http://jsfiddle.net/pob32fs1/8/
var oJSON = {
properties: {},
options: {},
arrays: {}
};
$('input[name]').each(function(){
var $el = $(this),
value = $el.attr("value"),
name = $el.attr('name');
if(name.indexOf('[]') >= 0)
{
oJSON.arrays[name] = oJSON.arrays[name] || {};
oJSON.arrays[name][value] = $el.is(':checked') ? 1 : 0;
} else {
oJSON.properties[name] = $el.val();
}
});
$('select[name]').each(function(){
var $el = $(this);
oJSON.properties[$el.attr('name')] = $el.val();
});
oJSON.options['type'] = 'user';
oJSON.options['id'] = 1;
oJSON.options['view'] = 'user-settings';
console.log(oJSON);
Assuming that the name and value attributes of your various inputs are strings, and not just numbers, you should be using nested objects, not nested arrays. You're trying to use associative arrays, which are not available in JavaScript.
var oJSON = {};
$('._save, .btn-success').click(function() {
oJSON = {
properties: {},
options: {},
arrays: {}
};
$('input').each(function() {
if ($(this).attr('name') != undefined) {
if ($(this).attr('name').indexOf('[]') > -1) {
if (oJSON['arrays'][$(this).attr('name')] == undefined) {
oJSON['arrays'][$(this).attr('name')] = {};
}
if ($(this).is(':checked')) {
oJSON['arrays'][$(this).attr('name')][$(this).attr('value')] = 1;
} else {
oJSON['arrays'][$(this).attr('name')][$(this).attr('value')] = 0;
}
} else {
oJSON['properties'][$(this).attr('name')] = $(this).val();
}
}
});
$('select').each(function() {
if ($(this).attr('name') != undefined) {
oJSON['properties'][$(this).attr('name')] = $(this).val();
}
});
oJSON['options']['type'] = 'user';
oJSON['options']['id'] = 1;
oJSON['options']['view'] = 'user-settings';
console.log(oJSON);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="tab-content">
<div id="tab-general" class="tab-pane active">
<h4>Gebruikersnaam</h4>
<input type="text" value="John Doe" name="username" class="form-control" required="" placeholder="J. Average">
<h4>E-mailadres</h4>
<input type="email" value="info#info.info" name="mailaddress" class="form-control" required="" placeholder="E-mail#adres.nl">
<div class="row">
<div class="col-md-6">
<input type="password" name="password" minlength="10" class="form-control" placeholder="Nieuw wachtwoord">
</div>
<div class="col-md-6">
<input type="password" name="password_retype" minlength="10" class="form-control" placeholder="Herhaal wachtwoord">
</div>
</div>
<input type="password" name="password_old" class="form-control margin-y-10" placeholder="Huidig Wachtwoord">
</div>
<div id="tab-sites" class="tab-pane">
<h4>Websites</h4>
<div id="site_container">
<div class="checkbox block">
<input name="sites[]" checked="" type="checkbox" value="0">
<label>A</label>
</div>
<div class="checkbox block">
<input name="sites[]" checked="" type="checkbox" value="1">
<label>B</label>
</div>
<div class="checkbox block">
<input name="sites[]" checked="" type="checkbox" value="2">
<label>C</label>
</div>
</div>
</div>
</div>
<div class="panel-footer">
<button type="button" class="btn btn-warning _cancel">Annuleren</button>
<button type="button" class="btn btn-success _save">Opslaan</button>
</div>