I have a json file that loads sales data for salespeople based on the current year and the previous year.
I created a table in which I show the total sales for each year for each salesperson and, in the last row, I need to load the total for all salespeople added up. As shown in the image below:
I am using dc.dataTable to create my table.
Can you tell me if there is any way in DC.js to create a row in my table to put the total sales?
Here is my code, thank you in advance.
var vendedorTable = dc.dataTable("#Vendedores");
var url = 'http://www.json-generator.com/api/json/get/cgsUhkPSjS?indent=2';
d3.json(url).then(function(data) {
data.forEach(function(d) {
var myCrossfilter = crossfilter(data);
var all = myCrossfilter.groupAll();
dc.dataCount(".dc-data-count")
.dimension(myCrossfilter)
.group(all);
vendedorDim = myCrossfilter.dimension(function(d) {
return d.vendnm;
});
var vendedorGroup = vendedorDim.group().reduce(reduceAdd, reduceRemove, reduceInitial);
function reduceAdd(p, v) {
p.totalAno += +v.Vendas_Ano;
p.totalHomologo += +v.Vendas_Ant;
return p;
}
function reduceRemove(p, v) {
p.totalAno -= v.Vendas_Ano;
p.totalHomologo -= v.Vendas_Ant;
return p;
}
function reduceInitial() {
return {
totalAno: 0,
totalHomologo: 0,
};
}
// formatter = d3.format(".3s");
// formatter2 = d3.format(".0%");
//Fake Dimension
rank = function(p) {
return ""
};
function checkRows(d) {
if (d.value.totalAno <= 0 || isNaN(d.value.totalAno) || d.value.totalHomologo <= 0 || isNaN(d.value.totalHomologo)) {
return 0;
}
return d;
}
//vendedorTable
vendedorTable.width(500)
.height(480)
.dimension(vendedorGroup)
.group(rank)
.columns([function(d) {
d = checkRows(d);
while (d != 0) {
return d.key;
}
},
function(d) {
d = checkRows(d);
while (d != 0) {
return Number(Math.round(d.value.totalAno * 100) / 100).toLocaleString("es-ES", {
minimumFractionDigits: 2
}) + '€';
}
},
function(d) {
d = checkRows(d);
while (d != 0) {
return Number(Math.round(d.value.totalHomologo * 100) / 100).toLocaleString("es-ES", {
minimumFractionDigits: 2
}) + '€';
}
}
])
.sortBy(function(d) {
return d.value.totalAno
})
.order(d3.descending)
vendedorTable.on('pretransition', function(table) {
table.selectAll('td.dc-table-column')
.on('click', function(d) {
let filters = table.filters().slice();
if (filters.indexOf(d.key) === -1)
filters.push(d.key);
else
filters = filters.filter(k => k != d.key);
if (filters.length === 0)
vendedorDim.filter(null);
else
vendedorDim.filterFunction(function(d) {
return filters.indexOf(d) !== -1;
})
table.replaceFilter([filters]);
dc.redrawAll();
});
let filters = table.filters();
table.selectAll('tr.dc-table-row')
.classed('sel-rows', d => filters.indexOf(d.key) !== -1);
});
dc.renderAll();
});
$('#reset').on('click', function() {
vendedorTable.filter(null);
vendedorDim.filter(null)
dc.redrawAll();
});
$('#resetTable').on('click', function() {
vendedorTable.filter(null);
vendedorDim.filter(null)
dc.redrawAll();
});
});
<head>
<style>
.dc-table-group {
visibility: collapse;
}
tr.dc-table-row.sel-rows {
background-color: lightblue;
}
</style>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.8/dc.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script>
<script src="https://d3js.org/d3.v5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.js"></script>
<title>Vendedores</title>
</head>
<body>
<div class="container-fluid">
<div class="row content">
<div class="col-md-8" style="padding-left: 20px;">
<div class="row marginClass">
<h4 class="pull-left" id="Introduction"><small>Dados fictícios da empresa | Exemplo de Pesquisa
Detalhada |
</small></h4>
<h6 class="dc-data-count" style="float: left;margin-left:5px;">
<span>
<span class="filter-count"></span> selected out of
<span class="total-count"></span> records |
<a id="reset"> Reset All </a>
</span>
</h6>
</div>
<div class="col-md-6">
<br>
<a id="resetTable"> Reset</a>
<table class="table" id="Vendedores">
<thead>
<tr>
<th>Sales</th>
<th>Current Year</th>
<th>Last Year</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div>
</body>
dc.js is the frontend for crossfilter, which is an in-memory database for JavaScript that is tuned for these kinds of dashboards.
You always want to add data on the database side. So the right place to look is in the crossfilter API, and here it is: crossfilter.add()
I might have just left a comment, but since you were nice enough to include running code, let's try it out!
First, let's reserve one of the vendors out of the dataset:
rows = data0.filter(d => d.vendnm === 'JOÃO LUIS');
var data = data0.filter(d => d.vendnm !== 'JOÃO LUIS');
Then, when the Add Row button is clicked, let's add that data and redraw all the associated charts:
$('#addRow').on('click', function() {
myCrossfilter.add(rows);
dc.redrawAll();
});
Notice that if you click Add Row multiple times, the sales for that vendor will double, then triple, because we are displaying an aggregated group, so that vendor gets more and more sales added in.
That's all there is to it!
var vendedorTable = dc.dataTable("#Vendedores");
// lift crossfilter and row so they are visible to addRow handler
var myCrossfilter, rows;
var url = 'http://www.json-generator.com/api/json/get/cgsUhkPSjS?indent=2';
d3.json(url).then(function(data0) {
// save Joao for later
rows = data0.filter(d => d.vendnm === 'JOÃO LUIS');
var data = data0.filter(d => d.vendnm !== 'JOÃO LUIS');
data.forEach(function(d) {
myCrossfilter = crossfilter(data);
var all = myCrossfilter.groupAll();
dc.dataCount(".dc-data-count")
.dimension(myCrossfilter)
.group(all);
vendedorDim = myCrossfilter.dimension(function(d) {
return d.vendnm;
});
var vendedorGroup = vendedorDim.group().reduce(reduceAdd, reduceRemove, reduceInitial);
function reduceAdd(p, v) {
p.totalAno += +v.Vendas_Ano;
p.totalHomologo += +v.Vendas_Ant;
return p;
}
function reduceRemove(p, v) {
p.totalAno -= v.Vendas_Ano;
p.totalHomologo -= v.Vendas_Ant;
return p;
}
function reduceInitial() {
return {
totalAno: 0,
totalHomologo: 0,
};
}
// formatter = d3.format(".3s");
// formatter2 = d3.format(".0%");
//Fake Dimension
rank = function(p) {
return ""
};
function checkRows(d) {
if (d.value.totalAno <= 0 || isNaN(d.value.totalAno) || d.value.totalHomologo <= 0 || isNaN(d.value.totalHomologo)) {
return 0;
}
return d;
}
//vendedorTable
vendedorTable.width(500)
.height(480)
.dimension(vendedorGroup)
.group(rank)
.columns([function(d) {
d = checkRows(d);
while (d != 0) {
return d.key;
}
},
function(d) {
d = checkRows(d);
while (d != 0) {
return Number(Math.round(d.value.totalAno * 100) / 100).toLocaleString("es-ES", {
minimumFractionDigits: 2
}) + '€';
}
},
function(d) {
d = checkRows(d);
while (d != 0) {
return Number(Math.round(d.value.totalHomologo * 100) / 100).toLocaleString("es-ES", {
minimumFractionDigits: 2
}) + '€';
}
}
])
.sortBy(function(d) {
return d.value.totalAno
})
.order(d3.descending)
vendedorTable.on('pretransition', function(table) {
table.selectAll('td.dc-table-column')
.on('click', function(d) {
let filters = table.filters().slice();
if (filters.indexOf(d.key) === -1)
filters.push(d.key);
else
filters = filters.filter(k => k != d.key);
if (filters.length === 0)
vendedorDim.filter(null);
else
vendedorDim.filterFunction(function(d) {
return filters.indexOf(d) !== -1;
})
table.replaceFilter([filters]);
dc.redrawAll();
});
let filters = table.filters();
table.selectAll('tr.dc-table-row')
.classed('sel-rows', d => filters.indexOf(d.key) !== -1);
});
dc.renderAll();
});
$('#reset').on('click', function() {
vendedorTable.filter(null);
vendedorDim.filter(null)
dc.redrawAll();
});
$('#resetTable').on('click', function() {
vendedorTable.filter(null);
vendedorDim.filter(null)
dc.redrawAll();
});
$('#addRow').on('click', function() {
myCrossfilter.add(rows);
dc.redrawAll();
});
});
<head>
<style>
.dc-table-group {
visibility: collapse;
}
tr.dc-table-row.sel-rows {
background-color: lightblue;
}
</style>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/2.1.8/dc.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script>
<script src="https://d3js.org/d3.v5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.12/crossfilter.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.1.8/dc.js"></script>
<title>Vendedores</title>
</head>
<body>
<div class="container-fluid">
<div class="row content">
<div class="col-md-8" style="padding-left: 20px;">
<div class="row marginClass">
<h4 class="pull-left" id="Introduction"><small>Dados fictícios da empresa | Exemplo de Pesquisa
Detalhada |
</small></h4>
<h6 class="dc-data-count" style="float: left;margin-left:5px;">
<span>
<span class="filter-count"></span> selected out of
<span class="total-count"></span> records |
<a id="reset"> Reset All </a>
</span>
</h6>
</div>
<div>
<a id="addRow"> Add Row </a>
</div>
<div class="col-md-6">
<br>
<a id="resetTable"> Reset</a>
<table class="table" id="Vendedores">
<thead>
<tr>
<th>Sales</th>
<th>Current Year</th>
<th>Last Year</th>
</tr>
</thead>
</table>
</div>
</div>
</div>
</div>
</body>
Related
I am having some difficulty filtering through a list of tasks in To Do List project.
I use an object to store the core properties of each task created like the id, content, completed, and date.
The filter should occurs after the user selects an option in a drop down menu.
I use an Event Listener to catch the id of the option selected, but I don't know what to do with that Id. For example, when the user selects the option 'completed' the app should only display the completed task, or the tasks that have a property of 'completed:true'.
I also want to filter the list in a fancy way such as make tasks fade out when filtering.
URL: https://alonzocarlos95.github.io/WDD-330/
//html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--ClockPicker libraries-->
<link rel="stylesheet" href="https://weareoutman.github.io/clockpicker/dist/jquery-clockpicker.min.css"></link>
<!-- <script src="http://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Moment JS library CDN -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.25.1/moment.min.js"></script> -->
<!--Material Icons and Fonts-->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght#0,200;1,100&display=swap" rel="stylesheet">
<!--Small view-->
<link rel="stylesheet" href="css/small.css" media="screen">
<title>Document</title>
</head>
<body>
<header>
<nav>
<ul>
<li><span class="material-icons">done</span></li>
<li class="drop-down" ><div class="dropdown"><button class="dropbtn" onclick="showModal()">All Lists<span class="material-icons" style="vertical-align: middle;">arrow_drop_down</span></button><div id="myDropdown" class="dropdown-content"><span id="select1">All Lists</span><span id="select2">Active</span><span id="select3">Completed</span></div></div></li>
<li><span class="label_list">BYU-Idaho To do List</span></li>
<li><span class="material-icons">search</span></li>
<li><img src="images/b2-removebg-preview.png" alt="logo"></li>
</ul>
</nav>
</header>
<main>
<div class="notes">
<img id="no_tasks" src="images/palms-300x220.png" alt="No tasks">
</div>
<div class="main_list" id="main_list">
<ul id="parentList">
</ul>
</div>
<div class="new_task_container" id="container_schedule">
<div class="new_task" id="new_todo">
<label>What is to be done?</label>
<div class="new_input">
<input type="text" name="todo" id="todo" placeholder="Enter task here">
<span class="material-icons">keyboard_voice</span>
</div>
<label>Due Date</label>
<input type="date" id="date" name="date" placeholder="Date not set">
</div>
<div class="new_task_group2">
<div class="new_time" id="new_time_container">
<input type="text" name="time" id="time" placeholder="Time not set(all day)">
<span class="material-icons">schedule</span>
<!-- <input type="checkbox" style="display: none;"> -->
</div>
</div>
</div>
</main>
<div class="add_task">
<button id="add" class="bounce">+</button>
</div>
<script src="https://weareoutman.github.io/clockpicker/dist/jquery-clockpicker.min.js"></script>
<script src="js/todo.js"></script>
</body>
</html>
//Javacript
let toDoList = [];
let options = {weekday:'long', year:'numeric', month:'long', day:'numeric'};
let indicador = 0;
let list_container = document.getElementById('main_list');
document.getElementById('container_schedule').style.display = 'none';
const chosenDate = document.getElementById("date");
const time = document.getElementById('new_time_container');
let ulTasks = document.getElementById('parentList');
time.style.display = 'none';
document.getElementById('add').addEventListener('click', () => {
document.getElementById('container_schedule').style.display = 'block';
document.getElementById('add').innerHTML = '<span class="material-icons">done</span>';
let inputNewTask = document.getElementById("todo");
let valInputNewTask = inputNewTask.value;
let valInputNewTask2 = inputNewTask.value;
let dateSet = document.getElementById('date').value;
if(indicador === 0){
indicador = 1;
list_container.style.display = "none";
}else {
if(!isBlank(valInputNewTask)){ //Valida si el valor del input no es null o undefined o whitespace
indicador = 0;
inputNewTask.value = "";
inputNewTask.focus();
let newDateSet = valDate(dateSet);
taskCreated();
manageTask(valInputNewTask2,newDateSet);
}
else {
alert("Enter task at first.");
}
}
} );
document.getElementById('date').addEventListener('change',() => {
// alert("New date");
time.style.display = 'flex';
});
function taskCreated(){
document.getElementById('container_schedule').style.display = 'none';
// debugger;
if(document.getElementsByClassName('notes').length >= 1){
document.getElementsByClassName('notes')[0].remove();
}
document.getElementById('add').textContent = '+';
}
/*Clock picker functionality*/
$("input[name=time]").clockpicker({
placement: 'bottom',
align: 'left',
autoclose: true,
default: 'now',
donetext: "Select",
init: function() {
console.log("colorpicker initiated");
},
beforeShow: function() {
console.log("before show");
},
afterShow: function() {
console.log("after show");
},
beforeHide: function() {
console.log("before hide");
},
afterHide: function() {
console.log("after hide");
},
beforeHourSelect: function() {
console.log("before hour selected");
},
afterHourSelect: function() {
console.log("after hour selected");
},
beforeDone: function() {
console.log("before done");
},
afterDone: function() {
console.log("after done");
}
});
function isBlank(str) {
//debugger;
return (!str || /^\s*$/.test(str));
}
function valDate(dateToDo){
// debugger;
if(dateToDo === null || dateToDo === ''){
dateToDo = "No date";
return dateToDo;
}
else {
dateToDo = new Date(dateToDo);
dateToDo.setDate(dateToDo.getDate()+1);
// testDate = new Date(Date.UTC(dateToDo));
dateToDo = dateToDo.toLocaleString('en-US',options);
return dateToDo;
}
}
function manageTask(getTask,dateSet){
const todo = {
id: Date.now(),
content: getTask,
completed: false,
date: dateSet
}
toDoList.push(todo);
addToLocalStorage(toDoList);
// storeData(todo);
}
function addToLocalStorage(toDoList){
// debugger;
localStorage.setItem('toDoList',JSON.stringify(toDoList));
renderTodos(toDoList);
}
function renderTodos(toDoList){
// debugger;
ulTasks.innerHTML = '';
toDoList.forEach(function(valInputNewTask2,index){
console.log(index);
const checked = toDoList.completed ? 'checked': null;
let currentTasks = document.createElement('li');
currentTasks.id = valInputNewTask2.id;
currentTasks.setAttribute('style','display:flex;background-color:#519872;width:100%;border-radius:7px;margin:0 0 10px 0;padding:6px 4px 6px 4px;min-height:3em;box-shadow: rgba(14, 30, 37, 0.12) 0px 2px 4px 0px, rgba(14, 30, 37, 0.32) 0px 2px 16px 0px;');
currentTasks.innerHTML = '<input id='+index+' type = "checkbox" class="checkInactive"><div style="display:flex;flex-direction:column;flex-grow:2;"><span style="margin-left:2em;">'+valInputNewTask2.content+'</span><span style="margin-left:2em;color:#17301C;">'+valInputNewTask2.date+'</span></div><div class="clear"><span class="material-icons">clear</span></div>';
if(valInputNewTask2.completed === true){
currentTasks.classList.add('checkActive');
currentTasks.firstChild.checked = true;
}
document.getElementById('parentList').appendChild(currentTasks);
});
list_container.style.display = "block";
}
function getFromLocalStorage(){
const getReference = localStorage.getItem('toDoList');
if(getReference){
document.querySelector('.notes').style.display = 'none';
toDoList = JSON.parse(getReference);
renderTodos(toDoList);
}
}
function showModal(){
document.getElementById('myDropdown').classList.toggle('show');
}
getFromLocalStorage();
function toggle(id){
toDoList.forEach(function(item){
if(item.id == id){
item.completed = !item.completed;
}
});
addToLocalStorage(toDoList);
}
function deleteToDo(id){
debugger
// alert(id);
toDoList = toDoList.filter(function(getTask){
return getTask.id != id;
});
addToLocalStorage(toDoList);
}
debugger;
ulTasks.addEventListener('click',function(event){
debugger;
if(event.target.type === 'checkbox'){
toggle(event.target.parentElement.getAttribute('id'));
}
if(event.target.parentElement.classList.contains('clear')){
debugger;
deleteToDo(event.target.parentElement.parentElement.getAttribute('id'));
}
});
//Close the dropdown if the user clicks outside it
window.onclick = function(e) {
if (!e.target.matches('.dropbtn')) {
var myDropdown = document.getElementById("myDropdown");
if (myDropdown.classList.contains('show')) {
myDropdown.classList.remove('show');
}
}
}
//Drop down Events
document.getElementById("myDropdown").addEventListener('click',function(event){
debugger;
if(event.target.localName === 'span'){
alert(event.target.id);
}
});
I don't know about the animations but at least for the filtering:
Ideally you should be using the select html element to create a dropdown menu and use the value attribute of the option elements to perform actions when an option is selected. Read more here: https://www.w3schools.com/tags/tag_select.asp
In your case, we can use the text inside the span tag, instead of the id to see which option was selected and render the todos based on the selected option.
We can then use the JS ES6 array function .filter(item => condition), which loops over the items in the array and returns a new array with all the items that match the provided condition.
document.getElementById('myDropdown').addEventListener('click', function(event) {
if (e.target.localName === 'span'){
let selectedOption = e.target.innerText;
if(selectedOption === 'All Tasks')
renderToDos(toDoList); // render everything
else if(selectedOption === 'Active'){
let activeToDos = toDoList.filter(todo => todo.completed === false);
renderToDos(activeToDos); // only render the todos which have not been completed
}
else if(selectedOption === 'Completed'){
let completedToDos = toDoList.filter(todo => todo.completed === true);
renderToDos(completedToDos); // only render the todos which have not been completed
}
}
});
I'm probably being very stupid here...
I have two JavaScript functions that are practically identical except each one refers to a different element.
The idea is to show and hide a toast/notification when the document loads.
For one element (errorexplanationcontainer), it works... For the other (alert), it doesn't...
CODE FOR errorexplanationcontainer (WORKS)
<div id="errorexplanationcontainer" class=""></div>
<script type="text/javascript">
window.onload = function() {
var z = document.getElementById("errorexplanationcontainer")
z.className = "show";
setTimeout(function(){ z.className = z.className.replace("show", ""); }, 3000);
}
</script>
^^ This is copied and pasted from the inspect window within Google Chrome. As you can see, the script ran successfully. We know this because class="" is absent in the source document and has been added by the script (after showing class="show" for 3 seconds).
CODE FOR alert (DOESN'T WORK)
<p id="alert">Invalid Email or password.</p>
<script type="text/javascript">
window.onload = function() {
var y = document.getElementById("alert")
y.className = "show";
setTimeout(function(){ y.className = y.className.replace("show", ""); }, 3000);
}
</script>
^^ No class="" here! The script has not worked...
FULL HTML DOC
<html class="mdl-js"><head>
<title>Dennis' Coffee Hut | CuppaDesk</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="/assets/favicon-16x16-347e46971826b54de74f354ae410242483f471bb3051a5f948d83af70770dadc.png" sizes="16x16">
<link rel="icon" type="image/png" href="/assets/favicon-32x32-ac516884b2aa2ea870ddfbd0ae383c0dd66ec1a640181174ac7adaba8e7ccd7d.png" sizes="32x32">
<link rel="apple-touch-icon" type="image/x-icon" href="/assets/apple-touch-icon-af3f73bee131a689a15fede0d2d6f7cf9698786524670279ac74cd128ec5dc40.png" sizes="180x180">
<link rel="mask-icon" type="image/x-icon" href="/assets/safari-pinned-tab-4f97411db829aebf4a4796a8f216e788ba4eeddf4d062a0a1efe473ee10fce3b.svg" color="#99cc33">
<link rel="icon" type="image/png" href="/assets/android-chrome-192x192-cb0ced957daf2743c293b898f5e595fcf07fc0842b9d0aeef37c08b8c5f74d42.png" sizes="192x192">
<link rel="manifest" href="/manifest.json">
<meta name="apple-mobile-web-app-title" content="CuppaDesk">
<meta name="application-name" content="CuppaDesk">
<meta name="msapplication-TileColor" content="#99cc33">
<meta name="msapplication-TileImage" content="/assets/mstile-144x144-5de954b6d137b31283af01b9a7645c90440392de2b44ec88949fdba65cca75e7.png">
<meta name="theme-color" content="#99cc33">
<meta name="csrf-param" content="authenticity_token">
<meta name="csrf-token" content="wphb5Z8aebicMl6E2CiCJiNPnQowqP2TVUrXOWclCukQwiX/xrbLf3jBE4YRyyswVMEaPEszTO/7xxl1/iClsw==">
<link rel="stylesheet" media="all" href="/assets/main.self-b06bcba5344c9fc9a5c6491a38f0780f4594d723339bc0543a25138d83fe3de3.css?body=1" data-turbolinks-track="reload">
<link rel="stylesheet" media="all" href="/assets/places.self-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css?body=1" data-turbolinks-track="reload">
<link rel="stylesheet" media="all" href="/assets/scaffolds.self-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css?body=1" data-turbolinks-track="reload">
<link rel="stylesheet" media="all" href="/assets/application.self-f0d704deea029cf000697e2c0181ec173a1b474645466ed843eb5ee7bb215794.css?body=1" data-turbolinks-track="reload">
<script src="/assets/rails-ujs.self-56055fe2ac3f3902deb9d12c17b2d725d432162b48fc443946daf7dfbc96d88a.js?body=1" data-turbolinks-track="reload"></script>
<script src="/assets/turbolinks.self-1d1fddf91adc38ac2045c51f0a3e05ca97d07d24d15a4dcbf705009106489e69.js?body=1" data-turbolinks-track="reload"></script>
<script src="/assets/action_cable.self-be3674a79bb9d13d41d259b2c17fad23aef20946dab3603b9d02374ea795005f.js?body=1" data-turbolinks-track="reload"></script>
<script src="/assets/cable.self-8484513823f404ed0c0f039f75243bfdede7af7919dda65f2e66391252443ce9.js?body=1" data-turbolinks-track="reload"></script>
<script src="/assets/places.self-877aef30ae1b040ab8a3aba4e3e309a11d7f2612f44dde450b5c157aa5f95c05.js?body=1" data-turbolinks-track="reload"></script>
<script src="/assets/application.self-eba3cb53a585a0960ade5a8cb94253892706bb20e3f12097a13463b1f12a4528.js?body=1" data-turbolinks-track="reload"></script>
<!-- BEGIN MATERIAL DESIGN LITE -->
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<!-- <link rel="stylesheet" href="/material.min.css"> -->
<script defer="" src="https://code.getmdl.io/1.3.0/material.min.js"></script>
<!-- END MATERIAL DESIGN LITE -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<p id="alert">Invalid Email or password.</p>
<script type="text/javascript">
window.onload = function() {
var y = document.getElementById("alert")
y.className = "show";
setTimeout(function(){ y.className = y.className.replace("show", ""); }, 3000);
}
</script>
<div id="login-container">
<div id="cuppadesk-logo-large"></div>
<div id="card-white">
<h1>Log in</h1>
<div class="dropdown-dots">
<button onclick="dotsDropdown()" class="dropbtn-dots"></button>
<div id="dotsDropdown" class="dropdown-content">
<a href="/users/sign_up">
<div class="dropdown-content-item">Sign up</div>
</a>
<a href="/users/password/new">
<div class="dropdown-content-item">Forgot password</div>
</a>
<a href="/users/confirmation/new">
<div class="dropdown-content-item">Didn't recieve email confirmation</div>
</a>
<a href="/users/unlock/new">
<div class="dropdown-content-item">Didn't receive unlock instructions</div>
</a>
<a href="/users/auth/facebook">
<div class="dropdown-content-item">Log in with
Facebook
</div>
</a>
</div>
</div>
<script>
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function dotsDropdown() {
document.getElementById("dotsDropdown").classList.toggle("show-dots");
}
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropbtn-dots')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show-dots')) {
openDropdown.classList.remove('show-dots');
}
}
}
}
</script>
<form class="new_user" id="new_user" action="/users/sign_in" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="authenticity_token" value="wphb5Z8aebicMl6E2CiCJiNPnQowqP2TVUrXOWclCukQwiX/xrbLf3jBE4YRyyswVMEaPEszTO/7xxl1/iClsw==">
<div id="errorexplanationcontainer" class=""></div>
<script type="text/javascript">
window.onload = function() {
var z = document.getElementById("errorexplanationcontainer")
z.className = "show";
setTimeout(function(){ z.className = z.className.replace("show", ""); }, 3000);
}
</script>
<div class="field-white">
<input autofocus="autofocus" placeholder="Email" type="email" value="" name="user[email]" id="user_email">
</div>
<div class="field-white">
<input autocomplete="off" placeholder="Password" type="password" name="user[password]" id="user_password">
</div>
<div class="checkbox">
<input name="user[remember_me]" type="hidden" value="0"><input class="css-checkbox" type="checkbox" value="1" name="user[remember_me]" id="user_remember_me">
<label class="css-label clr" for="user_remember_me">Remember me</label>
</div>
<script>
// generic tools to help with the custom checkbox
function UTIL() { }
UTIL.prototype.bind_onclick = function(o, f) { // chain object onclick event to preserve prior statements (like jquery bind)
var prev = o.onclick;
if (typeof o.onclick != 'function') o.onclick = f;
else o.onclick = function() { if (prev) { prev(); } f(); };
};
UTIL.prototype.bind_onload = function(f) { // chain window onload event to preserve prior statements (like jquery bind)
var prev = window.onload;
if (typeof window.onload != 'function') window.onload = f;
else window.onload = function() { if (prev) { prev(); } f(); };
};
// generic css class style match functions similar to jquery
UTIL.prototype.trim = function(h) {
return h.replace(/^\s+|\s+$/g,'');
};
UTIL.prototype.sregex = function(n) {
return new RegExp('(?:^|\\s+)' + n + '(?:\\s+|$)');
};
UTIL.prototype.hasClass = function(o, n) {
var r = this.sregex(n);
return r.test(o.className);
};
UTIL.prototype.addClass = function(o, n) {
if (!this.hasClass(o, n))
o.className = this.trim(o.className + ' ' + n);
};
UTIL.prototype.removeClass = function(o, n) {
var r = this.sregex(n);
o.className = o.className.replace(r, '');
o.className = this.trim(o.className);
};
var U = new UTIL();
function getElementsByClassSpecial(node, classname) {
var a = [];
var re = new RegExp('(^| )'+classname+'( |$)');
var els = node.getElementsByTagName("*");
for(var i=0,j=els.length; i<j; i++)
if(re.test(els[i].className))a.push(els[i]);
return a;
}
// specific to customized checkbox
function chk_labels(obj, init) {
var objs = document.getElementsByTagName('LABEL');
for (var i = 0; i < objs.length; i++) {
if (objs[i].htmlFor == obj.id) {
if (!init) { // cycle through each label belonging to checkbox
if (!U.hasClass(objs[i], 'chk')) { // adjust class of label to checked style, set checked
if (obj.type.toLowerCase() == 'radio') {
var radGroup = objs[i].className;
var res = radGroup.split(" ");
var newRes = res[0] + " " + res[1];
var relLabels = getElementsByClassSpecial(document.body,newRes);
for (var r = 0; r < relLabels.length; r++) {
U.removeClass(relLabels[r], 'chk');
U.addClass(relLabels[r], 'clr');
}
U.removeClass(objs[i], 'clr');
U.addClass(objs[i], 'chk');
obj.checked = true;
}
else {
U.removeClass(objs[i], 'clr');
U.addClass(objs[i], 'chk');
obj.checked = true;
}
} else { // adjust class of label to unchecked style, clear checked
U.removeClass(objs[i], 'chk');
U.addClass(objs[i], 'clr');
obj.checked = false;
}
return true;
} else { // initialize on page load
if (obj.checked) { // adjust class of label to checked style
U.removeClass(objs[i], 'clr');
U.addClass(objs[i], 'chk');
} else { // adjust class of label to unchecked style
U.removeClass(objs[i], 'chk');
U.addClass(objs[i], 'clr')
}
}
}
}
}
function chk_events(init) {
var objs = document.getElementsByTagName('INPUT');
if (typeof init == 'undefined') init = false;
else init = init ? true : false;
for(var i = 0; i < objs.length; i++) {
if (objs[i].type.toLowerCase() == 'checkbox' || objs[i].type.toLowerCase() == 'radio' ) {
if (!init) {
U.bind_onclick(objs[i], function() {
chk_labels(this, init); // bind checkbox click event handler
});
}
else chk_labels(objs[i], init); // initialize state of checkbox onload
}
}
}
U.bind_onload(function() { // bind window onload event
chk_events(false); // bind click event handler to all checkboxes
chk_events(true); // initialize
});
</script>
<div class="green-submit">
<input type="submit" name="commit" value="Log in" data-disable-with="Log in">
</div>
</form>
</div>
</div>
</body></html>
Again, I'm probably missing something obvious here... I'm completely new to developing and JavaScript is something I particularly struggle with. I've read through many resources but in my mind, the code still looks correct...
Obviously, I'm wrong... So any help will be greatly appreciated!
Use window.addEventListener instead of overwriting window.onload.
For errorexplanationcontainer,
<div id="errorexplanationcontainer" class=""></div>
<script type="text/javascript">
window.addEventListener("load", function() {
var z = document.getElementById("errorexplanationcontainer");
z.className = "show";
setTimeout(function() {
z.className = z.className.replace("show", "");
}, 3000);
}, false);
</script>
For alert,
<p id="alert">Invalid Email or password.</p>
<script type="text/javascript">
window.addEventListener("load", function() {
var y = document.getElementById("alert")
y.className = "show";
setTimeout(function() {
y.className = y.className.replace("show", "");
}, 3000);
}, false);
</script>
I'm using ng-route to show a page called "london.htm" (in the same directory of my principal page) into this principal page, such this example:
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>
<body ng-app="myApp">
<p>Main</p>
City 1
City 2
<p>Click on the links to read about London and Paris.</p>
<div ng-view></div>
<script>
var app = angular.module("myApp", ["ngRoute"]);
app.config(function($routeProvider) {
$routeProvider
.when("/", {
templateUrl : "main.htm"
})
.when("/london", {
templateUrl : "london.htm"
})
.when("/paris", {
templateUrl : "paris.htm"
});
});
</script>
</body>
</html>
This is my principal page, when I call <div ng-view></div> to show "london.htm" page:
<!DOCTYPE html>
<!-- saved from url=(0069)https://hackerstribe.com/guide/IT-bootstrap-3.1.1/examples/dashboard/ -->
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="shortcut icon" href="images/puzzle.png" />
<link rel="stylesheet" href="bootstrap/css/bootstrap.css" />
<link rel="stylesheet" href="styles/angular-bootstrap-datepicker.css" />
<link rel="stylesheet" href="styles/mainBoot.css">
<link rel="stylesheet" href="styles/scrollbar.css">
<link rel="stylesheet" href="styles/noscroll_numberfield.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<!-- <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.js"></script> -->
<script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-route.min.js"></script>
<script src="scripts/deployeePanel.js"></script>
<script src="scripts/rest-services.js"></script>
<script src="scripts/jquery.js"></script>
<script src="bootstrap-3.3.7-dist/js/bootstrap.js"></script>
<!-- <script src="scripts/emailchecker.js"></script> -->
<script src="scripts/angular-bootstrap-datepicker.js" charset="utf-8"></script>
<!-- <script src="scripts/number-directive.js"></script> -->
<script type="application/javascript"></script>
<title>Pannello dipendenti</title>
<!-- Bootstrap core CSS -->
<link href="./styles/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="./styles/dashboard.css" rel="stylesheet">
<!-- Just for debugging purposes. Don't actually copy this line! -->
<!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]-->
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<style id="holderjs-style" type="text/css"></style></head>
<body ng-app="StaffManagement" ng-controller="StaffController" background="images/sfondoblu3.png">
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand">FDDispenser</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li>Pannello Dipendenti</li>
<li>Settings</li>
<li>Profile</li>
<li>Help</li>
</ul>
<form class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="Search...">
</form>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
<li class="active">Aggiungi/Modifica Dipendente</li>
<li>Reports</li>
<li>Analytics</li>
<li>Export</li>
</ul>
<ul class="nav nav-sidebar">
<li>Nav item</li>
<li>Nav item again</li>
<li>One more nav</li>
<li>Another nav item</li>
<li>More navigation</li>
</ul>
<ul class="nav nav-sidebar">
<li>Nav item again</li>
<li>One more nav</li>
<li>Another nav item</li>
</ul>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<div ng-view></div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<!-- <script src="./Dashboard Template for Bootstrap_files/jquery.min.js.download"></script> -->
<script src="./scripts/bootstrap.min.js.download"></script>
<script src="./scripts/docs.min.js.download"></script>
</body></html>
This is my js page when I make call ng-route:
var app = angular.module("StaffManagement", ['ng-bootstrap-datepicker','ngRoute']);
//Controller Part
app.controller("StaffController", function($scope, $filter, $http, restService) {
$scope.staffs = [];
$scope.staffLast = [];
$scope.staffForm = {
idstaff : -1,
staffType: {
idstaffType: 2,
type: "Dipendente"
},
name: "",
surname: "",
birthDate: "",
phone: "",
gender: true,
working: true,
staffLogin: {
idstaffLogin: -1,
email: "",
// pass: "",
}
};
$scope.staffLoginForm = {
idstaffLogin: -1,
email: "",
// pass: ""
};
$scope.selectg = [
{name:'uomo', type: true},
{name:'donna', type: false}
];
$scope.dateold = {
getdateold: ""
};
$scope.datepickerOptions = {
format: 'yyyy/mm/dd',
language: 'it',
startDate: "01/01/1900",
endDate: new Date(),
autoclose: true,
weekStart: 1
};
/*
$scope.emailcheck = function () {
$scope.answer = EmailChecker.emailc($scope.staffForm.staffLogin.email);
}
*/
//////////////////per il number controller
$scope.wks = {number: 1, name: 'testing'};
/////////////////////////////////////////
console.log($scope.staffForm.gender);
//Now load the data from server
_refreshStaffData();
//HTTP POST/PUT methods for add/edit country
// with the help of id, we are going to find out whether it is put or post operation
$scope.submitStaff = function() {
console.log($scope.staffForm);
if($scope.staffForm.name == "" || $scope.staffForm.surname == "" || $scope.staffForm.staffLogin.email == "" || $scope.staffForm.birthDate == "" || $scope.staffForm.phone == "" || $scope.staffForm.gender == null || $scope.staffForm.idstaff == null)
_showSBNoField();
else if(!_emailCheck($scope.staffForm.staffLogin.email))
_showSBInvalid();
/* else if(!angular._isDate($scope.staffForm.birthDate))
console.log("no date"); */
else{
if ($scope.staffForm.idstaff == -1) {
console.log("StaffLogin");
console.log($scope.staffForm.staffLogin);
console.log($scope.staffForm);
//Id is absent in form data, it is create new country operation
$scope.staffForm.birthDate = $filter('date')(new Date($scope.staffForm.birthDate), "yyyy-MM-dd");
console.log( $scope.staffForm.birthDate);
restService.insertstaff($scope.staffForm, _giveLast, _error);
/* $http({
method : 'POST',
url : 'http://localhost:8080/FoodDrinkDispener/rest/staff',
data : angular.toJson($scope.staffForm),
headers : {
'Content-Type' : 'application/json'
}
}).then( _giveLast, _error ); */
// console.log("StaffLogin");
} else {
//Id is present in form data, it is edit country operation
//var dateformat = new String($scope.staffForm.birthDate);
// $scope.getdateold.getdateold = $scope.staffForm.birthDate;
$scope.staffForm.birthDate = $filter('date')(new Date($scope.staffForm.birthDate), "yyyy-MM-dd");
console.log( $scope.staffForm.birthDate);
// $scope.staffForm.phone = $scope.staffForm.phone.toString();
// console.log( $scope.staffForm.phone);
// console.log( new Date($scope.staffForm.birthDate));
restService.updatestaff($scope.staffForm, _putStaffLogin, _error);
/* $http({
method : 'PUT',
url : 'http://localhost:8080/FoodDrinkDispener/rest/staff',
data : angular.toJson($scope.staffForm),
headers : {
'Content-Type' : 'application/json'
}
}).then( _putStaffLogin, _error ); */
}
console.log("HTTP: ");
console.log($http);
console.log($scope.staffForm.gender);
console.log($scope.staffForm.idstaff);
}
};
//HTTP DELETE- delete country by Id
/* $scope.deleteStaff = function(staff) {
$http({
method : 'DELETE',
url : 'http://localhost:8080/FoodDrinkDispener/rest/staff/' + staff.idstaff
}).then(_success, _error);
}; */
$scope.deleteStaff = function(staff) {
$scope.staffForm.name = staff.name;
$scope.staffForm.idstaff = staff.idstaff;
$scope.staffForm.surname = staff.surname;
$scope.staffForm.birthDate = staff.birthDate;
$scope.staffForm.phone = staff.phone;
// $scope.staffForm.gender = staff.gender;
$scope.selectg.type = staff.gender;
//$scope.staffForm.staffLogin.idstaffLogin = staff.staffLogin.idstaff;
$scope.staffForm.staffLogin.email = staff.staffLogin.email;
$scope.staffForm.staffLogin.staff = "";
$scope.staffForm.working = false;
// $scope.staffForm.pass = "prova";
console.log(staff.staffLogin.email);
restService.deletestaff($scope.staffForm, _success, _error);
}
// In case of edit, populate form fields and assign form.id with country id
$scope.editStaff = function(staff) {
console.log(staff.phone);
$scope.staffForm.name = staff.name;
$scope.staffForm.idstaff = staff.idstaff;
$scope.staffForm.surname = staff.surname;
// String a = staff.birthDate;
console.log(staff.birthDate);
// $scope.staffForm.birthDate = $filter('date')(staff.birthDate, "mm/dd/yyyy");
$scope.staffForm.birthDate = staff.birthDate;
console.log($scope.staffForm.birthDate);
$scope.staffForm.phone = parseInt(staff.phone, 10); // parseInt with radix;
$scope.staffForm.gender = staff.gender;
$scope.selectg.type = staff.gender;
//$scope.staffForm.staffLogin.idstaffLogin = staff.staffLogin.idstaff;
$scope.staffForm.staffLogin.email = staff.staffLogin.email;
$scope.staffForm.staffLogin.staff = "";
// $scope.staffForm.pass = "prova";
console.log(staff.staffLogin.email);
};
function _refreshStaffData() {
restService.allstaffworking(_getstaff, _timeout, _error);
}
function _getstaff(response){
if (response.data == ""){
console.log("Accesso non autorizzato")
}
$scope.staffs = response.data;
}
function _success(response) {
// console.log(staff.name);
console.log("successo");
_refreshStaffData();
_clearFormData();
_showSB();
console.log("cleared");
}
function _timeout() {
// console.log(staff.name);
console.log("timeout token");
_showSBtimeout();
}
function _error(response) {
console.log("qualcosa è andata male");
console.log(response.statusText);
}
//Clear the form
function _clearFormData() {
$scope.staffForm.idstaff = -1;
$scope.staffForm.name = "";
$scope.staffForm.surname = "";
$scope.staffForm.birthDate = "";
$scope.staffForm.phone = "";
$scope.staffForm.gender = true;
$scope.staffForm.staffLogin.idstaffLogin = -1;
$scope.staffForm.staffLogin.email = "";
// $scope.staffForm.staffLogin.pass = "";
$scope.staffForm.staffType.idstaffType=2;
$scope.staffForm.working= true;
};
function _giveLast(){
console.log("yes");
console.log($scope.staffForm);
// $scope.staffLast = restService.laststaff;
restService.laststaff(_postStaffLogin);
// _postStaffLogin();
}
function _postStaffLogin(response){
$scope.staffLast = response.data;
console.log($scope.staffForm.staffLogin.email);
console.log($scope.staffLast.idstaff);
//console.log($scope.staffForm.staffLogin.idstafflogin);
//$scope.staffForm.staffLogin.staff = $scope.staffLast;
//$scope.staffLoginForm.staff = $scope.staffLast;
$scope.staffForm.staffLogin.email;
// $scope.staffLoginForm.pass = $scope.staffForm.staffLogin.pass;
console.log($scope.staffLoginForm.idstaffLogin);
console.log($scope.staffLoginForm.email);
// console.log($scope.staffLoginForm.pass);
restService.insertstafflogin($scope.staffLoginForm, _success, _error);
}
function _putStaffLogin(){
console.log("CIAOOOO");
$scope.staffLoginForm.idstaffLogin = $scope.staffForm.idstaff;
$scope.staffLoginForm.email = $scope.staffForm.staffLogin.email;
// $scope.staffLoginForm.pass = "ab";
console.log($scope.staffLoginForm.idstaffLogin);
console.log($scope.staffLoginForm.email);
// console.log($scope.staffLoginForm.pass);
restService.updatestafflogin($scope.staffLoginForm, _success, _error);
x.className = "show";
// After 3 seconds, remove the show class from DIV
setTimeout(function(){ x.className = x.className.replace("show", ""); }, 3000);
}
function _showSBNoField() {
// Get the snackbar DIV
var x = document.getElementById("snackbar_nofield")
// Add the "show" class to DIV
x.className = "show";
// After 3 seconds, remove the show class from DIV
setTimeout(function(){ x.className = x.className.replace("show", ""); }, 3000);
}
function _showSBInvalid() {
// Get the snackbar DIV
var x = document.getElementById("snackbar_invalid")
// Add the "show" class to DIV
x.className = "show";
// After 3 seconds, remove the show class from DIV
setTimeout(function(){ x.className = x.className.replace("show", ""); }, 3000);
}
function _showSBtimeout() {
// Get the snackbar DIV
var x = document.getElementById("snackbar_timeout")
// Add the "show" class to DIV
x.className = "show";
// After 3 seconds, remove the show class from DIV
setTimeout(function(){ x.className = x.className.replace("show", ""); }, 3000);
}
function _isDate(value) {
return toString.call(value) === '[object Date]';
}
function _emailCheck(emailStr) {
var emailPat = /^(.+)#(.+)$/;
var specialChars = "\\(\\)<>#,;:\\\\\\\"\\.\\[\\]";
var validChars = "[^\\s" + specialChars + "]";
var quotedUser = "(\"[^\"]*\")";
var ipDomainPat = /^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
var atom = validChars + "+";
var word = "(" + atom + "|" + quotedUser + ")";
var userPat = new RegExp("^" + word + "(\\." + word + ")*$");
var domainPat = new RegExp("^" + atom + "(\\." + atom + ")*$");
var matchArray = emailStr.match(emailPat);
if (matchArray == null) {
alert("L'email sembra essere sbagliata: (controlla # e .)");
return false;
}
var user = matchArray[1];
var domain = matchArray[2];
if (user.match(userPat) == null) {
alert("La parte dell'email prima di '#' non sembra essere valida!");
return false;
}
var IPArray = domain.match(ipDomainPat);
if (IPArray != null) {
for (var i = 1; i <= 4; i++) {
if (IPArray[i] > 255) {
alert("L'IP di destinazione non è valido!");
return false;
}
}
return true;
}
var domainArray = domain.match(domainPat);
if (domainArray == null) {
alert("La parte dell'email dopo '#' non sembra essere valida!");
return false;
}
var atomPat = new RegExp(atom, "g");
var domArr = domain.match(atomPat);
var len = domArr.length;
if (domArr[domArr.length - 1].length < 2 ||
domArr[domArr.length - 1].length > 6) {
alert("Il dominio di primo livello (es: .com e .it) non sembra essere valido!");
return false;
}
if (len < 2) {
var errStr = "L'indirizzo manca del dominio!";
alert(errStr);
return false;
}
return true;
}
});
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/editEmployee', {
templateUrl: 'london.htm',
});
}]);
Where I have added appconfig for ng-route:
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/editEmployee', {
templateUrl: 'london.htm',
});
}]);
And this is the page that I want to show when I called the url: file:///C:/Users/Giacomo%20B/Desktop/progetto%20mainetti/prove%20angular/fddWebapp/edit_employee.html#/editEmployee , called "london.htm", a simple page to try it:
<!-- saved from url=(0043)http://www.w3schools.com/angular/london.htm -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252"></head><body><h1>London</h1>
<h3>London is the capital city of England.</h3>
<p>It is the most populous city in the United Kingdom, with a metropolitan area of over 13 million inhabitants.</p>
<p>{{msg}}</p></body></html>
In this way, it should works..but It doesn't work!!!
There are these errors:
angular.js:10765 XMLHttpRequest cannot load file:///C:/Users/Giacomo%20B/Desktop/progetto%20mainetti/prove%20angular/fddWebapp/london.htm. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
angular.js:12520 Error: [$compile:tpload] Failed to load template: london.htm (HTTP status: -1 )
http://errors.angularjs.org/1.4.8/$compile/tpload?p0=london.htm&p1=-1&p2=
I have an array of items in form of service - as I know it's like proper way to keep data you use in different controllers.I watched tutorial and did the filtering by brands. But I have an obstacle with filtering of my Items by another parameters, such as price, length and frequency... So I have made sliders by another example but I have no idea how to tie up it with my array of Items. Please do me a favour, show how to tie up even one of my parameters, price for example.
http://angular.zxcvbn.ru
services.js:
myApp.service('ProductDataService', function() {
//sample data
var items = [
{ name:'Picachoo', id:1, price:25000, pict:'http://www.metrord.do/_internal/gxml!0/2qijkhn0ctpwx8acoz5fxkpvtmr4nbh$r05jcw5nnz5dt1u7odn7q01jm5k3ezo/screen-shot-2016-07-24-at-11-55-41-am.jpeg', len: 250, friq: 5000, brand: 'came' },
{ name:'Tortule', id:2, price:30000, pict:'https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcR2APj6_uBfhHRXLn1dZN58ZocpzMxGMFLZmuqHEU5SybKN4QAVfg', len: 250, friq: 300, brand: 'came' },
{ name:'Dragon', id:3, price:33500, pict:'https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSJotIxkjgXgm9m3m-0FuUxN6g9fGGXmP84VDRrPZoWa-x8Dqqd', len: 350, friq: 300, brand: 'came' },
{ name:'encrypted1', id:4, price:45000, pict:'http://gaidi.ru/wp-content/uploads/2016/07/kak-pravilno-lovit-pokemonov-v-pokemon-go.jpg', len: 400, friq: 3000, brand: 'came' },
{ name:'pravilno', id:5, price:48600, pict:'http://vignette3.wikia.nocookie.net/pokemon/images/2/2e/009Blastoise_Dream.png/revision/latest?cb=20140812050618', len: 550, friq: 2000, brand: 'came' },
{ name:'images', id:6, price:30000, pict:'https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcSqywi0lMtmf1sAR-20rg0HXETMueY3H71iJP35WsdsPHGVokK41g', len: 550, friq: 1000, brand: 'bft' },
{ name:'Foxy', id:7, price:38000, pict:'http://vgtimes.ru/uploads/posts/2016-07/1468938437_pk_vulpix.png', len: 350, friq: 10000, brand: 'bft' },
{ name:'Pteradactys', id:8, price:43000, pict:'https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRJBXypwhl8-z4IsAZokgQlqPx_vZymtENBdlPy1HhN34uODEZ5', len: 800, friq: 10000, brand: 'bft' },
{ name:'encrypted', id:9, price:35800, pict:'https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQZNKoA9LMtQHhgU4Toy7xXfzGEp6Rb4Kv6I16RgMjWO0Dnb36EFA', len: 1200, friq: 3000, brand: 'faac' },
{ name:'Jidjfj', id:10, price:14000, pict:'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRPBKrRLvhYm9y-LxwRM4Qc_psMjd_luij_04ChmmQjcrdxgmcG3w', len: 800, friq: 5000, brand: 'fors' }
];
brands = {came : true, bft : true, faac : true, fors : true} ;
this.getItems = function() {
return items;
};
this.getBrands = function() {
return brands;
};
this.maxPrice = function() {
var max;
var producto;
for(var i = 0; i < items.length-1; i++) {
for(var j = 0; j < items.length-i-1; j++){
if (producto[j] > producto[j+1]) {
max = producto[j];
producto[j] = producto[j+1];
producto[j+1] = b;
}
}
}
return max;
}
this.minPrice = function() {
var min;
var producto;
for(var i = 0; i < items.length-1; i++) {
for(var j = 0; j < items.length-i-1; j++){
if (producto[j] < producto[j+1]) {
min = producto[j];
producto[j] = producto[j+1];
producto[j+1] = b;
}
}
}
return min;
}
});
slider_price.js:
myApp.controller('priceCtrl', function($scope, ProductDataService) {
$scope.search = { price_min : '', price_max : '', amount_min : 14000, amount_max : 48600 };
});
/* Range Slider
Input with default values:
-min=0 // Min slider value
-max=100 // Max slider value
-step=1 // Steps
Output / Input model
-value-min // Default value #min
-value-max // Default value #max
example:
<slider-range min="0" max="100" step="5" value-min="scope.form.slider_value_min" value-max="scope.form.slider_value_max"></slider-range>
*/
myApp.directive('priceRange', ['$document',function($document) {
// Move slider handle and range line
var moveHandle = function(handle, elem, posX) {
$(elem).find('.handle.'+handle).css("left",posX +'%');
};
var moveRange = function(elem,posMin,posMax) {
$(elem).find('.range').css("left",posMin +'%');
$(elem).find('.range').css("width",posMax - posMin +'%');
};
return {
template: '<div class="slider horizontal">'+
'<div class="range"></div>'+
'<a class="handle min" ng-mousedown="mouseDownMin($event)"></a>'+
'<a class="handle max" ng-mousedown="mouseDownMax($event)"></a>'+
'</div>',
replace: true,
restrict: 'E',
scope:{
valueMin:"=",
valueMax:"="
},
link: function postLink(scope, element, attrs) {
// Initilization
var dragging = false;
var startPointXMin = 0;
var startPointXMax = 0;
var xPosMin = 0;
var xPosMax = 0;
var settings = {
"min" : (typeof(attrs.min) !== "undefined" ? parseInt(attrs.min,10) : 0),
"max" : (typeof(attrs.max) !== "undefined" ? parseInt(attrs.max,10) : 100),
"step" : (typeof(attrs.step) !== "undefined" ? parseInt(attrs.step,10) : 1)
};
if ( typeof(scope.valueMin) == "undefined" || scope.valueMin === '' )
scope.valueMin = settings.min;
if ( typeof(scope.valueMax) == "undefined" || scope.valueMax === '' )
scope.valueMax = settings.max;
// Track changes only from the outside of the directive
scope.$watch('valueMin', function() {
if (dragging) return;
xPosMin = ( scope.valueMin - settings.min ) / (settings.max - settings.min ) * 100;
if(xPosMin < 0) {
xPosMin = 0;
} else if(xPosMin > 100) {
xPosMin = 100;
}
moveHandle("min",element,xPosMin);
moveRange(element,xPosMin,xPosMax);
});
scope.$watch('valueMax', function() {
if (dragging) return;
xPosMax = ( scope.valueMax - settings.min ) / (settings.max - settings.min ) * 100;
if(xPosMax < 0) {
xPosMax = 0;
} else if(xPosMax > 100) {
xPosMax = 100;
}
moveHandle("max",element,xPosMax);
moveRange(element,xPosMin,xPosMax);
});
// Real action control is here
scope.mouseDownMin = function($event) {
dragging = true;
startPointXMin = $event.pageX;
// Bind to full document, to make move easiery (not to lose focus on y axis)
$document.on('mousemove', function($event) {
if(!dragging) return;
//Calculate handle position
var moveDelta = $event.pageX - startPointXMin;
xPosMin = xPosMin + ( (moveDelta / element.outerWidth()) * 100 );
if(xPosMin < 0) {
xPosMin = 0;
} else if(xPosMin > xPosMax) {
xPosMin = xPosMax;
} else {
// Prevent generating "lag" if moving outside window
startPointXMin = $event.pageX;
}
scope.valueMin = Math.round((((settings.max - settings.min ) * (xPosMin / 100))+settings.min)/settings.step ) * settings.step;
scope.$apply();
// Move the Handle
moveHandle("min", element,xPosMin);
moveRange(element,xPosMin,xPosMax);
});
$document.mouseup(function(){
dragging = false;
$document.unbind('mousemove');
$document.unbind('mousemove');
});
};
scope.mouseDownMax = function($event) {
dragging = true;
startPointXMax = $event.pageX;
// Bind to full document, to make move easiery (not to lose focus on y axis)
$document.on('mousemove', function($event) {
if(!dragging) return;
//Calculate handle position
var moveDelta = $event.pageX - startPointXMax;
xPosMax = xPosMax + ( (moveDelta / element.outerWidth()) * 100 );
if(xPosMax > 100) {
xPosMax = 100;
} else if(xPosMax < xPosMin) {
xPosMax = xPosMin;
} else {
// Prevent generating "lag" if moving outside window
startPointXMax = $event.pageX;
}
scope.valueMax = Math.round((((settings.max - settings.min ) * (xPosMax / 100))+settings.min)/settings.step ) * settings.step;
scope.$apply();
// Move the Handle
moveHandle("max", element,xPosMax);
moveRange(element,xPosMin,xPosMax);
});
$document.mouseup(function(){
dragging = false;
$document.unbind('mousemove');
$document.unbind('mousemove');
});
};
}
};
}]);
app.js:
var myApp = angular.module("filterApp", []);
myApp.controller('ExampleController', ['$scope', '$window', function($scope, $window) {
$scope.greeting = 'Hello, World!';
$scope.doGreeting = function(greeting) {
$window.alert(greeting);
};
}]);
myApp.controller('coolCtrl', function($scope) {
$scope.whoAmI = function(){
console.log("This is whoAmI function in the coolCtrl!");
};
});
myApp.controller('mainCtrl', function($scope, ProductDataService){
$scope.helloWorld = function(){
console.log("This is helloWorld function in the mailCtrl!");
};
$scope.items = ProductDataService.getItems();
$scope.brands = ProductDataService.getBrands();
$scope.refresh = function(){
location.reload();
};
$scope.showPopUpMsg = false;
$scope.openPopUp = function( text ) {
$scope.showPopUpMsg = true;
$scope.popUpMsgContent = text;
$scope.minimun = 123;
};
});
jilters.js:
myApp.filter('brandsfilter', function () {
return function(input, filter) {
var result = [];
angular.forEach(input, function (item) {
angular.forEach(filter, function (isfiltered, brand) {
if (isfiltered && brand === item.brand) {
result.push(item);
}
});
});
return result;
};
});
index.php:
<?php
require 'scripts/mail_script.php';
?>
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="apple-touch-icon" href="apple-touch-icon.png">
<!-- Place favicon.ico in the root directory -->
<link rel="stylesheet" href="styles/normalize.css">
<link rel="stylesheet" href="styles/main.css">
<link rel="stylesheet" href="styles/bootstrap.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <!-- for slider work -->
</head>
<body ng-app="filterApp" ng-controller='mainCtrl'>
<!--[if lt IE 8]>
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please upgrade your browser to improve your experience.</p>
<![endif]-->
<!-- Add your site or application content here -->
<div class="container">
<section class='top' >
<h1>Filter</h1>
<!-- //// http://embed.plnkr.co/woqn3i/ /// -->
<!-- ///////// -->
<div class="row" id='items'>
<div>
<div class="col-md-4" ><h2>params:</h2>
<div ng-controller="priceCtrl">
<p>Choose price:</p>
<p>min: <input type="number" ng-model="search.amount_min"/> $</p>
<p>max: <input type="number" ng-model="search.amount_max"/> $</p>
<slider-range min="14000" max="48600" step="100" value-min="search.amount_min" value-max="search.amount_max"></slider-range>
</div>
<hr>
<p>По названию:</p>
<p><input type="text" ng-model="price" /></p>
<p>Brand:</p>
<ul >
<li ng-repeat="(brand, value) in brands">
<input type="checkbox" ng-model="brands[brand]" /> {{brand}}
</li>
</ul>
<hr>
<!-- //// http://embed.plnkr.co/woqn3i/ /// -->
<div ng-controller="filterCtrl">
<p>length:</p>
<p>От: <input type="text" ng-model="search.price_min"/> meters</p>
<p>До: <input type="text" ng-model="search.price_max"/> meters</p>
<slider-range min="2.5" max="12" value-min="search.price_min" value-max="search.price_max"></slider-range>
<hr>
<p>friquincy:</p>
<p>Min: <input type="number" ng-model="search.amount_min"/> times</p>
<p>Max: <input type="number" ng-model="search.amount_max"/> times</p>
<slider-range min="300" max="10000" step="100" value-min="search.amount_min" value-max="search.amount_max"></slider-range>
</div>
<hr>
<!-- ///////// -->
<div class="actions"/>
<input type="button" value="Сбросить" ng-click='refresh()'>
</div>
</div>
<div class="col-md-8"><h2>______ kinds</h2>
<?php
if($success) echo '<h4 class="bg-success text-center">'.'Сообщение отправлено!' . '</h4>';
if($error_message) echo '<h4 class="bg-danger text-center">'.'Сообщение не отправлено:' . $error_message. '</h4>';
?>
<div class="row">
<!-- LOOP.-->
<div ng-repeat="item in items | filter:price | orderBy:price | brandsfilter:brands ">
<div class="col-md-4 col-sm-6 col-sx-12">
<div class="item-inner">
<div class="image-product">
<div class="caption">
<div class="box-view">
<div class="name">{{item.name}}</div>
</div>
</div>
<img src="{{item.pict}}" alt="{{item.name}}" title="{{item.name}}" class="img-responsive">
<p class="price"><span class="price">Price: {{item.price}} $.</span></p>
<p class="description">{{item.name}} - just another piece of information, first preporty is {{item.len}} m. <br>another is: {{item.friq}} per day. </p>
</div>
</div>
</div><!-- col -->
</div> <!-- ng-repeat -->
</div> <!-- row -->
</div>
</div> <!-- mainCtrl -->
</section>
</div>
<div class="panel-footer">
<script src="vendor/angular.js"></script>
<script src="scripts/app.js"></script>
<script src="scripts/services.js"></script>
<script src="scripts/filters.js"></script>
<script src="scripts/slider.js"></script>
<script src="scripts/slider_price.js"></script>
<script src="vendor/jquery.js"></script>
<script src="vendor/bootstrap.js"></script>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
</div>
</body>
</html>
AngularJS built-in filter which you already used supports multiple keywords filter see, you only need to implement comparator function to fulfill your needs.
First, change your filter in template to
<div ng-repeat="item in items | filter:myFilters:myComparator | orderBy:price">
then inside your filterCtrl you need to define myFilters and myComparator
$scope.myFilters = {price: 4000, brand: 'abc'};
$scope.myComparator = function(actual, expected) {
if (actual == parseInt(actual)) {
return actual > expected;
}
else {
return actual == expected;
}
}
Inside myComparator you can customise how you want to filter it (exact match, arithmetic comparison or partial match, just remember to return Boolean.
Just update $scope.myFilters whenever your filter keywords changed, the result will be updated in next digest cycle.
I'm having problem with javascript sort function. I have this function:
var compare = function(a, b) {
if(a.last_nom < b.last_nom) {
return -1;
}
if(a.last_nom > b.last_nom) {
return 1;
}
return 0;
}
And the I call it with:
var sortedData = fullData.sort(compare);
But I don't know how to pass dates correctly.
You can find jsbin example here
Thank you in advance
As requested, to make sense of my code here is full code:
<html lang="en-US">
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.0/css/materialize.min.css">
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.0/sweetalert.min.css" rel="stylesheet">
<link rel="icon" href="http://www.mzirafos.lt/favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="http://www.mzirafos.lt/favicon.ico" type="image/x-icon" />
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mėmelio Žirafos - Facebook feeds page</title>
<style>
html {
overflow-y: scroll;
}
header {
margin-bottom: 50px;
}
.progress {
top: 50%;
width: 50%;
margin: 0 auto;
}
.event-only .not-event {
display: none;
}
.post-by {
display: block;
margin-bottom: 25px;
}
.post-date {
display: block;
}
.card .card-content .card-title {
line-height: 26px;
margin-bottom: 15px;
display: inline-block;
}
img.responsive-img {
width: 100%;
}
</style>
</head>
<body>
<div class="progress">
<div class="indeterminate"></div>
</div>
<div class="hide" id="content">
<!--header-->
<header>
<nav class="top-nav">
<div class="container">
<div class="nav-wrapper">
<p>Mėmelio Žirafos Facebook feeds page</p>
</div>
</div>
</nav>
</header>
<!--end header-->
<div class="container">
<div class="row">
<!--checkbox to show all posts or events only-->
<div class="col s6">
<p>
<input type="checkbox" id="events-only" />
<label for="events-only">Show events only</label>
</p>
</div>
<!--end checkbox-->
</div>
<div class="row">
<h3 class="center-align" id="posts-acc-title">Facebook posts</h3>
<!--posts wrapper-->
<div class="col s12" id="fb-posts-wrap"></div>
<!--end posts wrapper-->
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.0/js/materialize.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sugar/1.4.1/sugar.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.0/sweetalert.min.js"></script>
<script src="https://cdn.rawgit.com/zenorocha/clipboard.js/master/dist/clipboard.min.js"></script>
<script>
(function() {
/*
* Our Globals
*/
var html = '';
var finalData = [];
var token = 'CAAQYWWjo5zkBAGlqs2AxxsWKcgWEI0VM3UA7555dhCQEOCTu9VW91tpfaNvrt4tS0w8DkxPJHvRENRrMeDT9QC1aSvHdZA7nhw9ZBqZAyUhMM6PTQoJggn7pJRHEO8xQJp8lsGZAqixVU8SvrMlhUUhwmzB11h9ISqd3MvmoD4aVZBPPD1geO';
var baseURL =
'https://graph.facebook.com/v2.4/{slug}/feed?fields=picture,created_time,message,link,type,description,caption,full_picture,id,admin_creator,from&limit=50&access_token={token}';
var slugs = [{
slug: 'sisaidgallery',
complete: false
}, {
slug: 'duzenos',
complete: false
}, {
slug: 'bbcnews',
complete: false
}, {
slug: 'Klaipeda.renginiai',
complete: false
}, {
slug: 'PORTbyBarBara',
complete: false
}, {
slug: 'Kastonas',
complete: false
}, {
slug: 'klaipedosdramosteatras',
complete: false
}, {
slug: '238899589464193',
complete: false
}];
/*
* allComplete
*/
var allComplete = function() {
for (var i = 0; i < slugs.length; i++) {
if (slugs[i].complete === false) {
return false;
}
}
return true;
};
/*
* makeURL
*/
var makeURL = function(url, token, slug) {
return url.replace('{token}', token).replace('{slug}', slug);
};
/*
* Date formatter
*/
var dateFormatter = function(date) {
var dateFormat = '{HH}:{mm}, {Weekday}, {d} {Month}, {yyyy}';
return Date.create(date).format(dateFormat);
}
/*
* Mark slug as complete
*/
var completeSlug = function(mySlug) {
for (var i in slugs) {
if (slugs[i].slug === mySlug) {
slugs[i].complete = true;
}
}
};
var copyTextID = 100;
/*
* template
*/
var template = '' +
'<div class="card blue-grey darken-1 hoverable {isEvent}">' +
'<div class="card-content white-text">' +
'<span class="post-date">Posted on: {fb-post-date}</span>' +
'<span class="post-by">Post by: {fb-post-from}</span>' +
'<div class="row">' +
'<div class="col s2">' +
'<img class="responsive-img" src="{fb-image}" alt=""/>' +
'</div>' +
'<div class="col s10" id="post-target-{fb-post-id}">' +
'<span class="card-title">{fb-post-title}</span>' +
'<p>{fb-post-text}</p>' +
'</div>' +
'</div>' +
'</div>' +
'<div class="card-action">' +
'<a target="_blank" href="{fb-post-link}">Open post</a>' +
'<a class="waves-effect waves-light btn white-text red darken-1 hoverable" data-clipboard-target="#post-target-{fb-post-id}"><i class="material-icons right">subject</i>Copy</a>' +
'</div>' +
'</div>';
/*
* checking title, text and images
*/
var replaceUndefined = function(str) {
return str === undefined ? '' : str;
};
var replaceImage = function(str) {
return str === undefined ? 'https://placehold.it/350x150' : str;
};
/*
* bindTemplate
*/
var bindTemplate = function(template, obj) {
return template
.replace('{isEvent}', obj.type === 'event' ? '' : 'not-event')
.replace('{fb-image}', replaceImage(obj.picture))
.replace('{fb-post-from}', obj.from.name)
.replace('{fb-post-title}', replaceUndefined(obj.description))
.replace('{fb-post-text}', replaceUndefined(obj.message))
.replace('{fb-post-link}', obj.link)
.replace('{fb-post-date}', dateFormatter(obj.created_time))
.replace(/{fb-post-id}/g, obj.id);
};
var makeAjax = function(fbUrl, next, slug) {
$.ajax({
url: fbUrl
}).done(function(data) {
next(data, slug);
});
};
/*
* renderTemplate
*/
var renderTemplate = function() {
$('#fb-posts-wrap').html(html);
};
/*
* makeAjaxCalls
*/
var makeAjaxCalls = function(slugs) {
slugs.forEach(function(slug) {
makeAjax(makeURL(baseURL, token, slug.slug), showAllPosts, slug.slug);
});
};
/*
* Flatten data
*/
var flattenData = function(data) {
var fullData = [];
var empty = [];
data.forEach(function(row) {
fullData.push(row.data);
});
return empty.concat.apply(empty, fullData);
};
var compare = function(a, b) {
if (a.last_nom < b.last_nom) {
return -1;
}
if (a.last_nom > b.last_nom) {
return 1;
}
return 0;
}
var showAllPosts = function(data, slug) {
// Let's first mark this slug as complete
completeSlug(slug);
// And store our data
finalData.push(data);
if (allComplete()) {
// merge all data
var fullData = flattenData(finalData);
// sort all data and
var sortedData = fullData.sort(compare);
// build the html
sortedData.forEach(function(obj) {
html += bindTemplate(template, obj);
});
// call the renderTemplateFunction
renderTemplate();
// finally hide the progress bar
$('.progress').fadeOut();
$('#content').removeClass('hide');
}
};
/*
* Listen to the change in the checkbox
*/
$('#events-only').change(function() {
if ($(this).is(':checked')) {
// hide the non events with css
$('#fb-posts-wrap').addClass('event-only');
} else {
// show the non events with css
$('#fb-posts-wrap').removeClass('event-only');
}
});
/*
* Kick off
*/
makeAjaxCalls(slugs);
})();
</script>
</body>
</html>
What is last_nom? There is no such function in JS Date specification
Try this:
function compare(a, b) {
if (a.getTime() > b.getTime())
return 1;
if (a.getTime() < b.getTime())
return -1;
return 0
}
var sortedDatesArray = unsortedDatesArray.sort(compare);