Count number of occurrence of value in data items - javascript

I am trying to count the number of times each value occurs for 'classtext' which is in data.items
However, by adding a function below to do that for each new inputted classtext on button click, I get 0 returned, even if I previously input several 'test' in the classtext field. I am very new in vuejs so obviously I am doing something wrong.
The code looks like this:
<!DOCTYPE html>
<html>
<script src="https://vuejs.org/js/vue.js"></script>
<style>
/* Vue List Item transition */
.list-item-enter-active,
.list-item-leave-active {
transition: opacity 0.3s, -webkit-transform 0.3s;
transition: opacity 0.3s, transform 0.3s;
transition: opacity 0.3s, transform 0.3s, -webkit-transform 0.3s;
-webkit-transform-origin: left center;
transform-origin: left center;
}
.list-item-enter,
.list-item-leave-to {
opacity: 0;
-webkit-transform: scale(0.5);
transform: scale(0.5);
}
/* //////////////////////////////////////// */
/* Basic Styles */
html {
background: #eee;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.list {
background: #FFF;
margin: auto;
padding: 1em 1em 1em;
box-shadow: 0 5px 30px rgba(0, 0, 0, 0.2);
}
.list :last-child {
margin-bottom: 0;
}
.list__ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.list__input {
display: flex;
margin-bottom: 0.5em;
}
.list__item {
display: block;
margin-bottom: 0.25em;
}
</style>
</head>
<body>
<div id="example-1" class="list">
<div class="list__input" #keydown.enter="add">
<button v-on:click="count">+</button>
<input v-model="newBeneficiary" placeholder="Add beneficiary" />
<input v-model="newClass" placeholder="Add new task topic" />
<input v-model="newItem" placeholder="Add new task text" />
</div>
<transition-group name="list-item" tag="ul" class="list__ul">
<li class="list__item" v-for="item in items" :key="item">
Timestamp: {{ item.timestamp }} <br />
Beneficiary: {{ item.beneficiarytext }} <br />
Topic: {{ item.classtext }} <br />
Task: {{ item.message }}
</li>
</transition-group>
</div>
</body>
<script>
/**
* Return a timestamp with the format "m/d/yy h:MM:ss TT"
* #type {Date}
*/
function timeStamp() {
var now = new Date();
var date = [ now.getMonth() + 1, now.getDate(), now.getFullYear() ];
var time = [ now.getHours(), now.getMinutes(), now.getSeconds() ];
var suffix = ( time[0] < 12 ) ? "AM" : "PM";
time[0] = ( time[0] < 12 ) ? time[0] : time[0] - 12;
time[0] = time[0] || 12;
for ( var i = 1; i < 3; i++ ) {
if ( time[i] < 10 ) {
time[i] = "0" + time[i];
}
}
return date.join("/") + " " + time.join(":") + " " + suffix;
}
var app = new Vue({
el: '#example-1',
data: {
items: [
/*{ timestamp:'testdate', beneficiarytext: 'TestBeneficiary', classtext: 'TestTopic', message: 'TestMessage' }*/
]
},
methods: {
/* MIGHT BE USED LATER TO DELETE TASKS
remove: function(item){
this.items.splice( this.items.indexOf(item), 1 );
},
*/
add: function(){
this.items.unshift({ timestamp: timeStamp(), beneficiarytext: this.newBeneficiary, classtext: this.newClass, message: this.newItem });
this.newItem = '';
console.log(this.items);
},
count: function() {
var counting = this.items.reduce(function (n, class1) {
return n + (class1.classtext == this.newClass);
}, 0)}
}
})
</script>
</body>
</html>

You didn't bind this to the reducer function. Use
this.items.reduce((n, class1) => { ... })
or
this.items.reduce(function (n, class1) { ... }.bind(this))
See How does the “this” keyword work?.
The compute the counts for each classtext in the array:
this.items.reduce((map, item) => {
map.set(item.classtext, (map.get(item.classtext) || 0) + 1)
return map
}, new Map())
// Returns Map of (classtext, count) pairs:
// {
// apple => 2,
// banana => 6,
// }

Related

Weekly Calendar

I want to create a weekly calendar which display the current week and has two buttons nextweek and previousweek. Im able to move to the nextweek, but Im struggling with previousweek button. Need some suggestions for the same. I have used HTML, CSS and Javascript. Im struggling with the logic of previousweek button.
const date = new Date();
function renderCalendar(lastdayofweek)
{
var lastofweek = lastdayofweek;
date.setDate(1);
const monthDays = document.querySelector(".days");
var lastDay = new Date( date.getFullYear(), date.getMonth() + 1, 0).getDate();
const prevLastDay = new Date( date.getFullYear(), date.getMonth(), 0 ).getDate();
const firstDayIndex = date.getDay();
const lastDayIndex = new Date( date.getFullYear(), date.getMonth() + 1, 0 ).getDay();
const nextDays = 7 - lastDayIndex - 1;
const months =
[ 'January', 'February', 'March', 'April', 'May', 'June'
, 'July', 'August', 'September', 'October', 'November', 'December'
];
document.querySelector(".date h1").innerHTML = months[date.getMonth()];
document.querySelector(".date p").innerHTML = new Date().toDateString();
let days = ''
, count = 0
;
if (lastofweek+7 >= lastDay)
{
for (let x = firstDayIndex; x > 0; x--)
{
days += `<div class="prev-date">${prevLastDay - x + 1}</div>`;
count = count+1;
lastofweek = prevLastDay - x + 1;
lastDay = lastofweek;
}
}
const nxtDay = 7 - count - 1;
if (lastofweek == undefined)
{
for (let i = 1; i <= nxtDay+1; i++)
{
if (i === new Date().getDate() && date.getMonth() === new Date().getMonth())
{
days += `<div class="today">${i}</div>`;
}
else
{
days += `<div>${i}</div>`;
lastDayOfWeek = i;
}
count = count+1;
monthDays.innerHTML = days;
}
}
else
{
if (lastofweek+1 > lastDay)
{
lastofweek = 0;
}
var forCount = 0;
for (let i = lastofweek+1; i <= lastofweek+7; i++)
{
if(lastDay >= i && forCount <= nxtDay)
{
if (i === new Date().getDate() && date.getMonth() === new Date().getMonth())
{
days += `<div class="today">${i}</div>`;
}
else
{
days += `<div>${i}</div>`;
lastDayOfWeek = i;
}
count = count+1;
forCount = forCount + 1;
monthDays.innerHTML = days;
}
}
}
if (count < 7)
{
for (let j = 1; j <= nextDays; j++)
{
days += `<div class="next-date">${j}</div>`;
monthDays.innerHTML = days;
}
}
}
document.querySelector(".prev").addEventListener("click", () =>
{
date.setMonth(date.getMonth());
renderCalendar();
});
const lastDay = new Date( date.getFullYear(), date.getMonth() + 1, 0 ).getDate();
document.querySelector(".next").addEventListener("click", () =>
{
if(lastDayOfWeek+7 > lastDay)
{
date.setMonth(date.getMonth()+1);
renderCalendar(lastDayOfWeek);
}
else
{
date.setMonth(date.getMonth());
renderCalendar(lastDayOfWeek);
}
});
renderCalendar();
* {
margin : 0;
padding : 0;
box-sizing : border-box;
font-family : "Quicksand", sans-serif;
}
html {
font-size : 62.5%;
}
.container {
width : 100%;
height : 100vh;
background-color : #12121f;
color : #eee;
display : flex;
justify-content : center;
align-items : center;
}
.calendar {
width : 45rem;
height : 52rem;
background-color : #222227;
box-shadow : 0 0.5rem 3rem #00000066;
}
.month {
width : 100%;
height : 12rem;
background-color : #167e56;
display : flex;
justify-content : space-between;
align-items : center;
padding : 0 2rem;
text-align : center;
text-shadow : 0 0.3rem 0.5rem #00000080;
}
.month i {
font-size : 2.5rem;
cursor : pointer;
}
.month h1 {
font-size : 3rem;
font-weight : 400;
text-transform : uppercase;
letter-spacing : 0.2rem;
margin-bottom : 1rem;
}
.month p {
font-size : 1.6rem;
}
.weekdays {
width : 100%;
height : 5rem;
padding : 0 0.4rem;
display : flex;
align-items : center;
}
.weekdays div {
font-size : 1.5rem;
font-weight : 400;
letter-spacing : 0.1rem;
width : calc(44.2rem / 7);
display : flex;
justify-content : center;
align-items : center;
text-shadow : 0 0.3rem 0.5rem #00000080;
}
.days {
width : 100%;
display : flex;
flex-wrap : wrap;
padding : 0.2rem;
}
.days div {
font-size : 1.4rem;
margin : 0.3rem;
width : calc(40.2rem / 7);
height : 5rem;
display : flex;
justify-content : center;
align-items : center;
text-shadow : 0 0.3rem 0.5rem #00000080;
transition : background-color 0.2s;
}
.days div:hover:not(.today) {
background-color : #262626;
border : 0.2rem solid #777;
cursor : pointer;
}
.today {
background-color : #167e56;
}
/* --- --- ---
.prev-date,
.next-date {
opacity : 0.5;
}
--- --- --- */
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css" >
<link href="https://fonts.googleapis.com/css2?family=Quicksand:wght#300;400;500;600;700&display=swap" rel="stylesheet" >
<input type="hidden" name="dates" class="dates" value="<?= $dates ?>" >
<div class="container">
<div class="calendar">
<div class="month">
<i class="fas fa-angle-left prev"></i>
<div class="date">
<h1></h1>
<p></p>
</div>
<i class="fas fa-angle-right next"></i>
</div>
<div class="weekdays">
<div>Sun</div>
<div>Mon</div>
<div>Tue</div>
<div>Wed</div>
<div>Thu</div>
<div>Fri</div>
<div>Sat</div>
</div>
<div class="days"></div>
</div>
</div>

jQuery response() function doesn't return any results because of the variable scope

The problem I encountered is I can't get any results from the jQuery UI Autocomplete form because of the variable scope. Let me show you.
// TAKE A CLOSE LOOK AT THIS METHOD
select: function(e, ui) {
$('#instant-search').text(ui.item.label);
$("#search").autocomplete("option", "source",
function(request, response) {
getAutocompleteResults(function(d) {
// DOESN'T WORK response(d);
});
// WORKS BUT IT SHOULD BE A DYNAMIC ARRAY FROM THE "D" OBJECT
// response(["anarchism", "anarchist black cross", "black rose (symbolism)", "communist symbolism", "political symbolism"]);
});
$("#search").autocomplete("search", ui.item.label);
In order to return results I have to use a function response([...]); outside the getAutocompleteResults(function(d) { ... }); function.
However, the source should be dynamic and not like the static array. In other words:
The function response(d); should return an object, which contains a few properties (title, value, extract). I have to access them by using response(d);, however, this function doesn't work inside getAutocompleteResults(function(d) { ... }); function. How can I achieve this?
There is a small snippet of code, however, the main problem is the select method. You can find this in the middle of the whole code block. I commented it out.
$(function() {
$("html").removeClass("no-js");
var autocompleteResults = [{
title: [],
extract: [],
pageId: []
}];
var capitalizeFirstLetter = function(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
};
var changeText2 = function(e) {
var request = $("input").val() + String.fromCharCode(e.which);
$("#instant-search").text(request);
var getAutocompleteResults = function(callback) {
$.ajax({
url: "https://en.wikipedia.org/w/api.php?format=json&action=query&generator=search&gsrlimit=6&prop=extracts&origin=*&pilimit=max&exintro&explaintext&exsentences=1&gsrsearch=" +
$("#instant-search").text(),
beforeSend: function() {
$(".loading").show();
},
success: function(d) {
$(".loading").hide();
autocompleteResults[0].title = [];
autocompleteResults[0].extract = [];
autocompleteResults[0].pageId = [];
if (d.hasOwnProperty("query")) {
if (d.query.hasOwnProperty("pages")) {
$.each(d.query.pages, function(i) {
autocompleteResults[0].title.push(d.query.pages[i].title);
autocompleteResults[0].extract.push(d.query.pages[i].extract);
autocompleteResults[0].pageId.push(d.query.pages[i].pageid);
});
}
}
if (!autocompleteResults[0].length) {
$(".ui-autocomplete").hide();
}
autocompleteResults[0].title.sort(function(a, b) {
var nameA = a.toUpperCase();
var nameB = b.toUpperCase();
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
return 0;
});
autocompleteResults[0].title = autocompleteResults[0].title.map(
function(i) {
return i.toLowerCase();
}
);
callback(autocompleteResults[0]);
},
datatype: "json",
cache: false
});
};
$("#search").autocomplete({
source: function(request, response) {
getAutocompleteResults(function(d) {
var results = [],
filteredAutocompleteResults = [];
filteredAutocompleteResults = d.title.filter(function(i) {
return (
i !=
$("#instant-search")
.text()
.toLowerCase()
);
});
for (var i = 0; i < d.title.length; i++) {
results[i] = {
label: filteredAutocompleteResults[i],
extract: d.extract[i],
pageId: d.pageId[i]
};
}
if (results.length == 5) {
response(results);
} else {
response(results.slice(0, 5));
}
});
},
response: function() {
if ($("#instant-search").text()) {
$("table").css("display", "table");
$(".wikisearch-container").css("margin-top", 100);
}
},
close: function() {
if (!$(".ui-autocomplete").is(":visible")) {
$(".ui-autocomplete").show();
}
},
appendTo: ".input",
focus: function(e) {
e.preventDefault();
},
delay: 0,
// TAKE A CLOSE LOOK AT THIS METHOD
select: function(e, ui) {
$('#instant-search').text(ui.item.label);
$("#search").autocomplete("option", "source",
function(request, response) {
getAutocompleteResults(function(d) {
// DOESN'T WORK response(d);
});
// WORKS BUT IT SHOULD BE A DYNAMIC ARRAY FROM THE "D" OBJECT
// response(["anarchism", "anarchist black cross", "black rose (symbolism)", "communist symbolism", "political symbolism"]);
});
$("#search").autocomplete("search", ui.item.label);
// EVERYTHING SHOULD BE FINE BELOW THIS LINE
if ($(".search-results").css("opacity") != 1) {
$(".search-results h4").text(capitalizeFirstLetter(ui.item.label));
$(".search-results p").text(ui.item.extract);
$(".search-results a").prop(
"href",
"https://en.wikipedia.org/?curid=" + ui.item.pageId
);
$(".search-results").css("opacity", 1);
} else if (
$(".search-results h4")
.text()
.toLowerCase() != ui.item.label
) {
$(".search-results").css("opacity", 0);
setTimeout(function() {
$(".search-results h4").text(capitalizeFirstLetter(ui.item.label));
$(".search-results p").text(ui.item.extract);
$(".search-results a").prop(
"href",
"https://en.wikipedia.org/?curid=" + ui.item.pageId
);
$(".search-results").css("opacity", 1);
}, 500);
}
},
create: function() {
$(this).data("ui-autocomplete")._renderItem = function(ul, item) {
return $("<li>")
.append(
'<div class="ui-menu-item-wrapper"><div class="autocomplete-first-field"><i class="fa fa-search" aria-hidden="true"></i></div><div class="autocomplete-second-field three-dots">' +
item.label +
"</div></div>"
)
.appendTo(ul);
};
}
});
};
var changeText1 = function(e) {
if (
/[-a-z0-90áãâäàéêëèíîïìóõôöòúûüùçñ!##$%^&*()_+|~=`{}\[\]:";'<>?,.\s\/]+/gi.test(
String.fromCharCode(e.which)
)
) {
$("input").on("keypress", changeText2);
}
// DONT TOUCH THIS AREA, IT HAS NOTHING TO DO WITH THE PROBLEM
var getInputSelection = function(input) {
var start = 0,
end = 0;
input.focus();
if (
typeof input.selectionStart == "number" &&
typeof input.selectionEnd == "number"
) {
start = input.selectionStart;
end = input.selectionEnd;
} else if (document.selection && document.selection.createRange) {
var range = document.selection.createRange();
if (range) {
var inputRange = input.createTextRange();
var workingRange = inputRange.duplicate();
var bookmark = range.getBookmark();
inputRange.moveToBookmark(bookmark);
workingRange.setEndPoint("EndToEnd", inputRange);
end = workingRange.text.length;
workingRange.setEndPoint("EndToStart", inputRange);
start = workingRange.text.length;
}
}
return {
start: start,
end: end,
length: end - start
};
};
switch (e.key) {
case "Backspace":
case "Delete":
e = e || window.event;
var keyCode = e.keyCode;
var deleteKey = keyCode == 46;
var sel, deletedText, val;
val = this.value;
sel = getInputSelection(this);
if (sel.length) {
// 0 kai paprastai trini po viena o 1 ar daugiau kai select su pele trini
$("#instant-search").text(
val.substr(0, sel.start) + val.substr(sel.end)
);
} else {
$("#instant-search").text(
val.substr(0, deleteKey ? sel.start : sel.start - 1) +
val.substr(deleteKey ? sel.end + 1 : sel.end)
);
}
break;
case "Enter":
if ($("#instant-search").text()) {
console.log("Redirecting...");
}
break;
}
if (!$("#instant-search").text()) {
$("table, .ui-autocomplete").hide();
$(".wikisearch-container").css("margin-top", "");
}
if (
$(".ui-menu-item-wrapper").hasClass("ui-state-active") &&
(e.key == "ArrowRight" || e.key == "ArrowLeft")
) {
$(".ui-autocomplete").autocomplete(""); // Error metas console ir taip neturėtų būti bet nežinau kaip padaryti kad pasirinkus elementą su <-- ar --> nepadarytų tik vieno rezultato todėl paliekam laikinai ;)
}
};
$("input").on("keydown", changeText1);
$("input").on("input", function(e) {
$("#instant-search").text($("#search").val());
});
});
html,
body {
height: 100%;
width: 100%;
}
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background-image: url("http://www.part.lt/img/96816a00ec1fb87adc4ca8a04365b2b5719.jpg");
background-size: cover;
background-position: 100%;
}
.v-container {
display: table;
height: 100%;
width: 100%;
}
.v-content {
display: table-cell;
vertical-align: middle;
}
.text-center {
text-align: center;
}
.input {
overflow: hidden;
white-space: nowrap;
}
.input input#search {
width: calc(100% - 30px);
height: 50px;
border: none;
font-size: 10pt;
float: left;
color: #4f5b66;
padding: 0 15px;
outline: none;
}
.ui-autocomplete {
list-style: none;
background-color: #fff;
-webkit-user-select: none;
user-select: none;
padding: 0;
margin: 0;
width: 100% !important;
top: auto !important;
display: table;
table-layout: fixed;
}
.ui-helper-hidden-accessible {
display: none;
}
.autocomplete-first-field {
width: 15%;
display: inline-block;
}
.autocomplete-second-field {
width: 85%;
display: inline-block;
text-align: left;
vertical-align: middle;
}
.three-dots {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
table {
width: 100%;
border-spacing: 0;
border-collapse: collapse;
display: none;
table-layout: fixed;
}
table tr {
background-color: #fff;
-webkit-user-select: none;
user-select: none;
}
tr:first-child {
background-color: #ffc800;
color: #fff;
}
table td,
.ui-menu-item-wrapper {
padding: 10px 0;
}
td:nth-child(2) {
width: 85%;
text-align: left;
}
.ui-menu-item,
table {
cursor: pointer;
}
:focus {
outline: 0;
}
a {
text-decoration: none;
color: #fff;
position: relative;
}
a:before {
content: "";
position: absolute;
width: 100%;
height: 0.0625rem;
bottom: 0;
left: 0;
background-color: #fff;
visibility: hidden;
-webkit-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: all 0.3s ease-in-out 0s;
transition: all 0.3s ease-in-out 0s;
}
a:hover:before {
visibility: visible;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
.search-results {
background: #fff;
margin-top: 50px;
border-left: 5px solid #0ebeff;
opacity: 0;
-webkit-transition: opacity 1s;
transition: opacity 1s;
}
.search-results h4,
.search-results p {
margin: 0;
padding: 10px;
text-align: left;
}
.search-results a {
color: #0ebeff;
display: inline-block;
margin: 1rem 0;
}
.search-results a:before {
background-color: #0ebeff;
}
.wikisearch-container {
width: 65%;
margin: 0 auto;
}
/* Loading animation */
#keyframes lds-eclipse {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#-webkit-keyframes lds-eclipse {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.loading {
position: relative;
top: 9.5px;
right: 15px;
pointer-events: none;
display: none;
}
.lds-eclipse {
-webkit-animation: lds-eclipse 1s linear infinite;
animation: lds-eclipse 1s linear infinite;
width: 2rem;
height: 2rem;
border-radius: 50%;
margin-left: auto;
box-shadow: 0.08rem 0 0 #0ebeff;
}
#media (max-width: 71.875em) {
.wikisearch-container {
width: 75%;
}
}
#media (max-width: 50em) {
.wikisearch-container {
width: 85%;
}
}
#media (max-width: 17.96875em) {
.wikisearch-container {
width: 100%;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<html class="no-js">
<div class="v-container">
<div class="v-content text-center">
<div class="wikisearch-container">
<div class="input">
<input type="text" id="search" placeholder="Search...">
<div class="loading">
<div class="lds-eclipse"></div>
</div>
<button class="icon"><i class="fa fa-search"></i></button>
<table>
<tr>
<td class="fa fa-search">
<td id="instant-search" class="three-dots"></td>
</tr>
</table>
</div>
<div class="search-results">
<h4></h4>
<p></p>
<a target="_blank">Click here for more</a>
</div>
</div>
</div>
</div>
EDIT 1
After some changes, the results are shown, however, before the ajax call. How can I use response() only after the ajax was successfully completed (tried using success callback, didn't work :()?
Full project code: https://codepen.io/Kestis500/pen/zRONyw?editors=0010.
Here you can see step by step how it looks like:
How it looks like when you just reloaded the page:
Let's try entering "a":
We've got some results. Ok, let's try to click on the "anarchist symbolism" element:
Results should look like "anarchist symbolism" search. However, it returns the result of the "a" search. What if we pressed "fraktur" element?
Now it shows our previous search "anarchist symbolism" results. However, it should return elements of the "fraktur" search.
EDIT 2
I've fixed many things and removed some really non sense things from my code. However, the situation with the ajax call is still the same.
https://codepen.io/Kestis500/pen/pazppP?editors=0110
Any ideas?
EDIT 3
Fixed ajax lag (now the ajax request will be sent only after the previous ajax call).
https://codepen.io/Kestis500/pen/JpPLON?editors=0110
I had to first fix a few things in your Ajax call. We then collect the results and build an array that should be returned to response(). This will populate the AutoComplete.
First we will examine the HTML. There was some closing tags missing.
HTML
<div class="v-container">
<div class="v-content text-center">
<div class="wikisearch-container">
<div class="input ui-front">
<input type="text" id="search" placeholder="Search...">
<div class="loading">
<div class="lds-eclipse"></div>
</div>
<button class="icon">
<i class="fa fa-search"></i>
</button>
<table>
<tr>
<td class="fa fa-search"></td>
<td id="instant-search" class="three-dots"></td>
</tr>
</table>
</div>
<div class="search-results">
<h4></h4>
<p></p>
<a target="_blank">Click here for more</a>
</div>
</div>
</div>
</div>
You can see the table and it's cells all have the proper closing tags now.
I didn't make any changes to your CSS or Style.
JavaScript
$(function() {
var capitalizeFirstLetter = function(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
};
$("#search").autocomplete({
source: function(request, response) {
var results = [];
$.ajax({
url: "https://en.wikipedia.org/w/api.php",
data: {
format: "json",
action: "query",
generator: "search",
gsrlimit: 6,
prop: "extracts|pageimages",
origin: "*",
pilimit: "max",
exintro: false,
explaintext: false,
exsentences: 1,
gsrsearch: request.term
},
beforeSend: function() {
$(".loading").show();
},
success: function(d) {
$(".loading").hide();
if (d.query.pages) {
$.each(d.query.pages, function(k, v) {
console.log(k, v.title, v.extract, v.pageid);
results.push({
label: v.title,
value: "https://en.wikipedia.org/?curid=" + v.pageid,
title: v.title,
extract: v.extract,
pageId: v.pageid
});
});
response(results);
}
},
datatype: "json",
cache: false
});
response(results);
},
close: function() {
if (!$(".ui-autocomplete").is(":visible")) {
$(".ui-autocomplete").show();
}
},
focus: function(e) {
e.preventDefault();
return false;
},
delay: 0,
select: function(e, ui) {
if ($(".search-results").css("opacity") != 1) {
$(".search-results h4").text(capitalizeFirstLetter(ui.item.label));
$(".search-results p").text(ui.item.extract);
$(".search-results a").prop(
"href",
ui.item.value
);
$(".search-results").css("opacity", 1);
} else if (
$(".search-results h4")
.text()
.toLowerCase() != ui.item.label
) {
$(".search-results").css("opacity", 0);
setTimeout(function() {
$(".search-results h4").text(capitalizeFirstLetter(ui.item.label));
$(".search-results p").text(ui.item.extract);
$(".search-results a").prop(
"href",
ui.item.value
);
$(".search-results").css("opacity", 1);
}, 500);
}
return false;
}
}).autocomplete("instance")._renderItem = function(ul, item) {
var $item = $("<li>");
var $wrap = $("<div>").appendTo($item);
var $field1 = $("<div>", {
class: "autocomplete-first-field"
}).appendTo($wrap);
$("<i>", {
class: "fa fa-search",
"aria-hidden": true
}).appendTo($field1);
$("<div>", {
class: "autocomplete-second-field three-dots"
}).html(item.label).appendTo($wrap);
return $item.appendTo(ul);
};
});
There was a lot of things to fix and improve.
Let's start with the Ajax. You're making a call to a MediaWiki API and expecting some results. When the call would come back, it would generate warnings about pilimit. Digging into the API docs, this is a parameter specific to the pageimages properties call. To fix this, the prop value had to be extracts|pageimages. Now I get a clean set of results.
You can see I broke out the data so that I could more easily make changes and see what parameters I was sending to the API. Nothing wrong with your method, I just find this a lot easier to work with.
This is all happening inside .autocomplete() when we are populating the source. When we use function as a source, it has to follow a few guidelines:
we pass a request and response in
results must be in an array
the array can contain objects, as long as they contain at least { label, value }
our results array must be passed to response function.
A brief example:
$(selector).autocomplete({
source: function(req, resp){
var q = req.term;
// The Request is an object that contains 1 index: term
// request.term will contain the content of our search
var results = [];
// An array to store the results
$.getJSON("myapi.php", {query: q}, function(data){
$.each(data, function(key, val){
// iterate over the result data and populate our result array
results.push({
label: data.name,
value: data.url
});
resp(results);
});
});
}
});
You can sort or filter the results all you like; as long as you pass them to response in the end.
With your focus and select callbacks, you want to return false. This is discussed more here: http://jqueryui.com/autocomplete/#custom-data
We also see a good example of rendering the menu item. I switched over to making jQuery objects versus raw HTML. You do what works best for you.
Working Example: https://jsfiddle.net/Twisty/vr6gv2aw/4/
Hope this helps.

Add/remove box in html using angularJS

I want to create/use an add-remove box like this in HTML using angularJS where you have a list of some objects on the left and you select the objects to put them on under the headings listed on the right. Any idea what do we call such tables/lists and can I create/find them?
I don't know what is the accurate title to call it :)
but I tried to implement a sample of 'add/remove box' to achieve the concept you want with AngularJS!
the main part consists of three sections:
left section which is going to be added
middle section which contains the buttons
right section which is going to be removed
The code below applies the above section which aforesaid:
<div class="box leftBox">
<div>
<div id="{{left.name}}" ng-click="clicked($event, 0)" data-ng-repeat="left in lefts">{{left.name}}</div>
</div>
</div>
<div class="box button_holder">
<button ng-click="add()" class="button button-blue">ADD ></button>
<button ng-click="remove()" class="button button-red">< REMOVE</button>
<button ng-click="addAll()" class="button button-blue button-dark">ADD ALL >></button>
<button ng-click="removeAll()" class="button button-red button-dark"><< REMOVE ALL</button>
<button ng-click="deleteChoice()" class="button delete">X</button>
</div>
<div class="box rightBox">
<div>
<div ng-click="clicked($event, 1)" data-ng-repeat="right in rights">{{right.name}}</div>
</div>
</div>
by using angularjs directives including data-ng-repeat you can control the procedure of adding or removing
here is the implemented overview.
here is the completed code on the "codepen".
you can also check my github.
try to run the snippet in a fullscreen window!
/**
* Created by ALIREZA on 8/30/2017.
*/
var app = angular.module('Add_Remove_Box', []);
app.controller('Ctrl', function($scope) {
var i;
var isRepeated = false;
var actionLicense = true;
var prevElement = null;
var currentElement = null;
var positionSide = null;
$scope.choices = ["left", "right"];
$scope.lefts = [{
id: 'left1'
}, {
id: 'left2'
}, {
id: 'left3'
}, {
id: 'left4'
}];
for (i = 0; i < $scope.lefts.length; i++) {
$scope.lefts[i].name = "left" + (i + 1).toString();
}
$scope.rights = [{
id: 'right1'
}, {
id: 'right2'
}];
for (i = 0; i < $scope.rights.length; i++) {
$scope.rights[i].name = "right" + (i + 1).toString();
}
$scope.insert = function($event) {
var side = $scope.selectedSide;
if (side == null || side == "left") {
var leftItemNo = $scope.lefts.length + 1;
$scope.lefts.push({
'id': 'left' + leftItemNo
});
$scope.lefts[leftItemNo - 1].name = $scope.choice.name;
} else {
var rightItemNo = $scope.rights.length + 1;
$scope.rights.push({
'id': 'right' + rightItemNo
});
$scope.rights[rightItemNo - 1].name = $scope.choice.name;
}
};
$scope.deleteChoice = function() {
if (positionSide === 0) {
var ItemNo = -1;
$scope.lefts.forEach(function(i, j) {
if (i.name === currentElement.textContent) {
ItemNo = j;
return;
}
});
$scope.lefts.splice(ItemNo, 1);
}
};
$scope.add = function() {
if (actionLicense && positionSide === 0) {
actionLicense = false;
var leftItemNo = -1;
$scope.lefts.forEach(function(i, j) {
if (i.name === currentElement.textContent) {
leftItemNo = j;
return;
}
});
$scope.lefts.splice(leftItemNo, 1);
var rightItemNo = $scope.rights.length + 1;
$scope.rights.push({
'id': 'right' + rightItemNo
});
$scope.rights[rightItemNo - 1].name = currentElement.textContent;
}
};
$scope.remove = function() {
if (actionLicense && positionSide === 1) {
actionLicense = false;
var rightItemNo = -1;
$scope.rights.forEach(function(i, j) {
if (i.name === currentElement.textContent) {
rightItemNo = j;
return;
}
});
$scope.rights.splice(rightItemNo, 1);
var leftItemNo = $scope.lefts.length + 1;
$scope.lefts.push({
'id': 'left' + leftItemNo
});
$scope.lefts[leftItemNo - 1].name = currentElement.textContent;
}
};
$scope.addAll = function() {
$scope.lefts.forEach(function(i) {
var rightItemNo = $scope.rights.length + 1;
$scope.rights.push({
'id': 'right' + rightItemNo
});
$scope.rights[rightItemNo - 1].name = i.name;
});
$scope.lefts.splice(0, $scope.lefts.length);
};
$scope.removeAll = function() {
$scope.rights.forEach(function(i) {
var leftItemNo = $scope.lefts.length + 1;
$scope.lefts.push({
'id': 'left' + leftItemNo
});
$scope.lefts[leftItemNo - 1].name = i.name;
});
$scope.rights.splice(0, $scope.rights.length);
};
$scope.clicked = function($event, pos) {
actionLicense = true;
positionSide = pos;
currentElement = $event.currentTarget;
var deleteButton = document.getElementsByClassName("delete")[0];
if (pos === 1) {
if (deleteButton.className.indexOf("button-deactive") === -1) {
deleteButton.className += " button-deactive";
}
} else {
deleteButton.className = deleteButton.className.replace(" button-deactive", "");
}
if (prevElement === null) {
prevElement = currentElement;
} else {
if (prevElement === currentElement) {
isRepeated = !isRepeated;
} else {
if (isRepeated) {
isRepeated = false;
}
}
}
if (prevElement.className.indexOf("active") !== -1) {
prevElement.className = prevElement.className.replace(" active", "");
}
if (!isRepeated && currentElement.className.indexOf("active") === -1) {
currentElement.className += " active";
}
prevElement = currentElement;
};
});
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
.container {
display: inline-block;
width: 100%;
padding: 10px;
height: 100vh;
border: #E64A19 inset .7vh;
background: #616161;
/* fallback for old browsers */
background: -webkit-linear-gradient(to left, #9bc5c3, #616161);
/* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to left, #9bc5c3, #616161);
/* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
.addItems {
height: 10vh;
margin-bottom: 5vh;
}
.box {
float: left;
display: inline-block;
margin: 0;
padding: 10px;
height: 80vh;
border: #cfcfcf outset 2px;
color: #eee;
font-size: medium;
}
.box>div {
border: #FFF59D ridge 2px;
border-bottom: none;
border-radius: 5px;
}
.box>div>div {
padding: 7px;
border-bottom: #FFF59D ridge 2px;
}
.box>div>div:hover {
background-color: rgba(100, 150, 220, .5);
transition: background-color .4s ease;
}
.box>button {
display: inline-block;
width: 70%;
margin: 5% 15%;
}
.button {
padding: 10px 24px;
border-radius: 3px;
border: none;
box-shadow: 2px 5px 10px rgba(22, 22, 22, .1);
}
.button:hover {
transition: all 60ms ease;
opacity: .95;
box-shadow: #444 0 3px 3px 0;
}
.button-blue {
color: #FFFFFF;
background: #416dea;
}
.button-red {
color: #FFFFFF;
background: #F32C52;
}
.button-dark {
filter: brightness(85%) contrast(110%);
}
.leftBox {
width: 40%;
}
.button_holder {
width: 20%;
}
.rightBox {
width: 40%;
}
input[type="text"],
select {
padding: 5px;
}
.active {
transition: all .1s ease;
background-color: #888;
color: #000;
;
border: dotted 1px black;
box-shadow: 0 2px 2px 0 rgba(97, 97, 97, .5);
margin-bottom: 1px;
}
.button-deactive {
opacity: .5;
box-shadow: none;
}
.button-deactive:hover {
opacity: .5;
box-shadow: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AddRemoveBox</title>
<link rel="stylesheet" href="index.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<!--include angularJs-->
<script src="index.js"></script>
</head>
<body>
<div class="container" ng-app="Add_Remove_Box" ng-controller="Ctrl">
<fieldset class="addItems">
<legend>Insert Items</legend>
<select ng-model="selectedSide">
<option ng-repeat="choice in choices">{{choice}}</option>
</select>
<input type="text" ng-model="choice.name" name="" placeholder="Enter The Item Name">
<button class="button insert" value="insert" ng-click="insert($event)">Insert</button>
</fieldset>
<div class="box leftBox">
<div>
<div id="{{left.name}}" ng-click="clicked($event, 0)" data-ng-repeat="left in lefts">{{left.name}}</div>
</div>
</div>
<div class="box button_holder">
<button ng-click="add()" class="button button-blue">ADD ></button>
<button ng-click="remove()" class="button button-red">< REMOVE</button>
<button ng-click="addAll()" class="button button-blue button-dark">ADD ALL >></button>
<button ng-click="removeAll()" class="button button-red button-dark"><< REMOVE ALL</button>
<button ng-click="deleteChoice()" class="button delete">X</button>
</div>
<div class="box rightBox">
<div>
<div ng-click="clicked($event, 1)" data-ng-repeat="right in rights">{{right.name}}</div>
</div>
</div>
</div>
</body>
</html>

Vue Way of Adding Detail content Row Dynamically

I have a Vue Calendar that I'm working on. When a day is clicked, I would like to open a full-width box under the week of the selected day that displays details of the day (Think Google Images layout) I know how to pass data in Vue, but how do I add this details (component, view?) under the row of the current week? (See my CodePen
<div class="calendar">
<div class="header z-depth-2">
<a #click="lastMonth" class="waves-effect waves-light btn"><i class="material-icons left">chevron_left</i>Last Month</a>
<p>{{month}} {{year}}</p>
<a #click="nextMonth" class="waves-effect waves-light btn"><i class="material-icons right">chevron_right</i>Next Month</a>
</div>
<ul class="dates month">
<li class="dow" v-for="dow in days">{{dow}}</li>
<li v-for="blank in firstDayOfMonth" class="day"></li>
<li v-for="date in daysInMonth" #click="openday(date)"
class="day" :class="{'today': date == initialDate && month == initialMonth && year == initialYear}">
<span>{{date}}</span>
</li>
</ul>
</div>
JS
new Vue({
el: '.calendar',
data: {
today: moment(),
dateContext: moment(),
days: ['S', 'M', 'T', 'W', 'T', 'F', 'S']
},
methods:{
nextMonth: function () {
var t = this;
t.dateContext = moment(t.dateContext).add(1, 'month');
},
lastMonth: function () {
var t = this;
t.dateContext = moment(t.dateContext).subtract(1, 'month');
}
},
computed: {
year: function () {
var t = this;
return t.dateContext.format('YYYY');
},
month: function () {
var t = this;
return t.dateContext.format('MMMM');
},
daysInMonth: function () {
var t = this;
return t.dateContext.daysInMonth();
},
currentDate: function () {
var t = this;
return t.dateContext.get('date');
},
firstDayOfMonth: function () {
var t = this;
var firstDay = moment(t.dateContext).subtract((t.currentDate - 1), 'days');
return firstDay.weekday();
},
//Previous Code Above
initialDate: function () {
var t = this;
return t.today.get('date');
},
initialMonth: function () {
var t = this;
return t.today.format('MMMM');
},
initialYear: function () {
var t = this;
return t.today.format('YYYY');
}
}
})
Because you have no concept of a row (you just auto-wrap), you can't really insert a box that takes up a row. What I've done here is insert a div that is positioned absolutely, so that I can make it full width, but it overlays the rows below, rather than shifting them out of the way.
If you rework it to have weeks, you could insert a detail box between weeks.
The basic working, though, is that you set a data item for the currently selected date when you click on a date, and you clear that item to dismiss the detail box (a click in the detail box does it, here). The HTML is controlled by a v-if.
new Vue({
el: '.calendar',
data: {
today: moment(),
dateContext: moment(),
days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
selectedDate: null
},
methods: {
nextMonth: function() {
var t = this;
t.dateContext = moment(t.dateContext).add(1, 'month');
},
lastMonth: function() {
var t = this;
t.dateContext = moment(t.dateContext).subtract(1, 'month');
},
openday(date) {
this.selectedDate = date;
},
dismiss() {
this.selectedDate = null;
}
},
computed: {
year: function() {
var t = this;
return t.dateContext.format('YYYY');
},
month: function() {
var t = this;
return t.dateContext.format('MMMM');
},
daysInMonth: function() {
var t = this;
return t.dateContext.daysInMonth();
},
currentDate: function() {
var t = this;
return t.dateContext.get('date');
},
firstDayOfMonth: function() {
var t = this;
var firstDay = moment(t.dateContext).subtract((t.currentDate - 1), 'days');
return firstDay.weekday();
},
//Previous Code Above
initialDate: function() {
var t = this;
return t.today.get('date');
},
initialMonth: function() {
var t = this;
return t.today.format('MMMM');
},
initialYear: function() {
var t = this;
return t.today.format('YYYY');
}
}
})
*,
*:before,
*:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body {
font-size: 1.5em;
font-weight: 100;
color: rgba(255, 255, 255, 1);
background: #222222;
}
.calendar {
transform: translate3d(0, 0, 0);
width: 100vw;
}
.header {
display: flex;
padding: 0 1em;
justify-content: space-between;
align-items: center;
width: 100%;
background-color: #333;
}
.fade-enter {
/*overflow: hidden;*/
opacity: 0;
}
.fade-enter-active {
animation: fadeIn 1s ease-out;
opacity: 1;
}
.month.in.next {
animation: moveFromTopFadeMonth .4s ease-out;
opacity: 1;
}
.month.out.next {
animation: moveToTopFadeMonth .4s ease-in;
opacity: 1;
}
.month.in.prev {
animation: moveFromBottomFadeMonth .4s ease-out;
opacity: 1;
}
.month.out.prev {
animation: moveToBottomFadeMonth .4s ease-in;
opacity: 1;
}
.dates {
display: flex;
flex-wrap: wrap;
}
.day {
width: 14%;
padding: 1em;
text-align: center;
cursor: pointer;
}
.dow {
width: 14%;
text-align: center;
padding: 1em;
color: teal;
font-weight: bold;
}
.detail-panel {
width: 100vw;
background-color: darkred;
color: white;
height: 10rem;
position: absolute;
left: 0;
}
.today {
color: teal;
font-weight: bold;
}
.day-name {
font-size: 1em;
text-transform: uppercase;
margin-bottom: 5px;
color: rgba(255, 255, 255, .5);
letter-spacing: .7px;
}
.day-number {
font-size: 24px;
letter-spacing: 1.5px;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/materialize/0.98.2/css/materialize.min.css" rel="stylesheet" />
<div class="calendar">
<div class="header z-depth-2">
<a #click="lastMonth" class="waves-effect waves-light btn"><i class="material-icons left">chevron_left</i>Last Month</a>
<p>{{month}} {{year}}</p>
<a #click="nextMonth" class="waves-effect waves-light btn"><i class="material-icons right">chevron_right</i>Next Month</a>
</div>
<ul class="dates month">
<li class="dow" v-for="dow in days">{{dow}}</li>
<li v-for="blank in firstDayOfMonth" class="day"></li>
<li v-for="date in daysInMonth" class="day" :class="{'today': date == initialDate && month == initialMonth && year == initialYear}">
<span #click="openday(date)">{{date}}</span>
<div class="detail-panel" v-if="selectedDate === date" #click="dismiss">Hi there I see you selected {{date}}</div>
</li>
</ul>
</div>

Switch between stylesheets css

Ok I am new in this site and even new in html ,css and javascript.
Like the title says I need help with switching between style sheets.
I did everything I need but there is one thing, switching between style sheets works in internet explorer perfectly, but not in chrome.
What is happening in chrome? I can switch in chrome too and everything works perfectly but not the whole background color changes , only the viewed section become black , then you need to scroll down to change the color of the rest of the page.
It will be nice to get some help.
This is the code.
function darkTheme() {
var theme = document.getElementById('lightTheme');
theme.href = "styleSheetDarkTheme.css";
}
function lightTheme() {
var theme = document.getElementById('lightTheme');
theme.href = "styleSheetLightTheme.css";
}
#option_list {
height: 40px;
width: 500px;
margin: auto;
}
#option1 {
position: relative;
display: inline-block;
height: 40px;
width: 100px;
margin-left: 0.7291666666666666em;
margin-right: 0.7291666666666666em;
background-clip: content-box;
text-align: center;
cursor: pointer;
font: bold 19px serif;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-ms-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
}
.themes {
display: block;
padding: 20px;
transition: 0.2s;
}
#option1:hover {
background-color: rgb(84, 84, 84);
color: white;
}
#dropDownMenu {
position: fixed;
padding-left: 0px;
background-color: rgb(84, 84, 84);
width: 190px;
margin-top: 17px;
display: none;
color: #fff;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
#option1:hover #dropDownMenu {
display: block;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}
.themes:hover {
background-color: rgba(3, 3, 3, 0.51);
}
<head>
<link id="lightTheme" rel="stylesheet" type="text/css" href="styleSheetLightTheme.css">
</head>
<body>
<div id="option_list">
<div id="option1">
Theme
<ul id="dropDownMenu">
<li onclick="darkTheme()" class="themes">Dark the</li>
<li onclick="lightTheme()" class="themes">Light theme</li>
</ul>
</div>
</div>
</body>
Mistake in your lightTheme:
function lightTheme() {
var theme = document.getElementById('lightTheme');
theme.href = "styleSheetLightTheme.css";
}
In the lighttheme funtion, change the variable theme
function lightTheme() {
var theme = document.getElementById('lightTheme');
theme.href = "styleSheetLightTheme.css";
}
The lighttheme function isn't doing anything.
function lightTheme() {
var theme = document.getElementById('lightTheme');
theme.href = "styleSheetLightTheme.css";
}
function darkTheme() {
var theme = document.getElementById('darkTheme');
theme.href = "styleSheetDarkTheme.css";
}
This one with set cookie valid for 1 day, so it will checks for the style-setting cookie, and if present, switches the style sheets accordingly. Otherwise, it use default style.
<head>
<link rel="stylesheet" type="text/css" title="light" href="styleLightTheme.css">
<link rel="alternate stylesheet" type="text/css" title="dark" href="styleDarkTheme.css">
</head>
<body onload="set_style_from_cookie()">
<div id="option_list">
<div id="option1">
Theme
<ul id="dropDownMenu">
<li onclick="switch_style('dark'); return false;" class="themes" id="dark">Dark Theme</li>
<li onclick="switch_style('light'); return false;" class="themes" id="light">Light Theme</li>
</ul>
</div>
</div>
</body>
Script:
var style_cookie_name = "style" ;
var style_cookie_duration = 30 ;
function switch_style ( css_title )
{
var i, link_tag ;
for (i = 0, link_tag = document.getElementsByTagName("link") ;
i < link_tag.length ; i++ ) {
if ((link_tag[i].rel.indexOf( "stylesheet" ) != -1) &&
link_tag[i].title) {
link_tag[i].disabled = true ;
if (link_tag[i].title == css_title) {
link_tag[i].disabled = false ;
}
}
set_cookie( style_cookie_name, css_title,
style_cookie_duration );
}
}
function set_style_from_cookie()
{
var css_title = get_cookie( style_cookie_name );
if (css_title.length) {
switch_style( css_title );
}
}
function set_cookie ( cookie_name, cookie_value,
lifespan_in_days, valid_domain )
{
var domain_string = valid_domain ?
("; domain=" + valid_domain) : '' ;
document.cookie = cookie_name +
"=" + encodeURIComponent( cookie_value ) +
"; max-age=" + 60 * 60 *
24 * lifespan_in_days +
"; path=/" + domain_string ;
}
function get_cookie ( cookie_name )
{
//
var cookie_string = document.cookie ;
if (cookie_string.length != 0) {
var cookie_value = cookie_string.match (
'(^|;)[\s]*' +
cookie_name +
'=([^;]*)' );
return decodeURIComponent ( cookie_value[2] ) ;
}
return '' ;
}

Categories

Resources