Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • faproietti/XRF-App
  • chnet/XRF-App
2 results
Show changes
Showing
with 7613 additions and 1267 deletions
// Copyright 2017 Istituto Nazionale di Fisica Nucleare
//
// Licensed under the EUPL
import * as $ from "jquery";
import * as Utility from "./utility";
import { Image } from "./image";
import { Chart } from "./chart";
enum ReadDirection {
u,// lettura non definita
r,//lettura per righe
c//lettura per colonne
}
class Fs {
xMin: number = 0;
xMax: number = 0;
yMin: number = 0;
yMax: number = 0;
step: number = 0;
direction: ReadDirection = ReadDirection.u;
constructor() { };
generateTree(xmlDoc: Document) {
let tree: any = [];
let first = true;
let oldFolderParent: string = "";
let oldFolder: string = "";
//inizio leggendo tutti gli elementi da inserire nell'albero (caratterizzati
//dall'avere un url di riferimento)
let entry = $("D:href", xmlDoc);
//per ogni elemento controllo se si tratta di una cartella o di un documento
for (let i: number = 0; i < entry.length; i++) {
let path: string[] = entry[i].childNodes[0].nodeValue.split("");
//cartella, creo l'oggetto corrsipondente
if (path[path.length - 1] == "/") {
let folderName: string[] = entry[i].childNodes[0].nodeValue.split("/");
let Folder = { text: folderName[folderName.length - 2], nodes: [] };
//posiziono la radice del file system, ne memorizzo il path e il padre
if (first) {
tree.push(Folder);
first = false;
oldFolder = entry[i].childNodes[0].nodeValue;
oldFolderParent = oldFolder.slice(0, oldFolder.lastIndexOf(folderName[folderName.length - 2]));
//per ogni cartella determino la relazione con la cartella precedente
} else {
let newFolder: string = entry[i].childNodes[0].nodeValue;
let newFolderParent: string = newFolder.slice(0, newFolder.lastIndexOf(folderName[folderName.length - 2]));
//cartella sorella con quella memorizzata
if (newFolderParent == oldFolderParent) {
oldFolder = newFolder;
this.insertOBJinFS(Folder, tree, folderName, 0);
//cartella figlia di quella memorizzata
} else if (newFolderParent == oldFolder) {
oldFolder = newFolder;
oldFolderParent = newFolderParent;
this.insertOBJinFS(Folder, tree, folderName, 0);
//nessuno dei casi precedenti
} else {
//arretro nell'albero fino a trovare lo stesso padre. Per fare questo
//tolgo al padre memorizzato in precedenza prima "/" poi il nome dell'
//ultima cartella
while (newFolderParent != oldFolderParent) {
oldFolderParent = oldFolderParent.slice(0, oldFolderParent.length - 1);
oldFolderParent = oldFolderParent.slice(0, oldFolderParent.lastIndexOf("/") + 1);
}
oldFolder = newFolder;
this.insertOBJinFS(Folder, tree, folderName, 0);
}
}
//documento, creo l'oggetto corrispondente e lo inserisco nell'albero
} else {
let fileName: string[] = entry[i].childNodes[0].nodeValue.split("/");
let filePath: string = entry[i].childNodes[0].nodeValue;
let File = {
text: fileName[fileName.length - 1], icon: "glyphicon glyphicon-file", selectedIcon: "glyphicon glyphicon-file", url: filePath
};
this.insertOBJinFS(File, tree, fileName, 1);
}
}
return tree;
}
//funzione che posiziona l'oggetto passato in input nell'albero
private insertOBJinFS(objfs, tree, objfsName, type) {
//determino la profondità dell'oggetto (se è un file devo aggiungere 1 a causa di "/")
let depth: number = objfsName.length;
if (type) depth++;
//in base alla profondità determino a quale oggetto agganciare quello in input
let treePosition: any;
let l: number = tree.length - 1;
switch (depth) {
case 6:
treePosition = tree;
break;
case 7:
treePosition = tree[l].nodes;
break;
case 8:
treePosition = tree[l].nodes[tree[l].nodes.length - 1].nodes;
break;
case 9:
treePosition = tree[l].nodes[tree[l].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes.length - 1].nodes;
break;
case 10:
treePosition = tree[l].nodes[tree[l].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes.length - 1]
.nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes[tree[l].nodes[tree[l].nodes.length - 1].nodes.length - 1].nodes.length - 1].nodes;
break;
default:
break;
}
treePosition[treePosition.length - 1].nodes.push(objfs);
}
//funzione che dato l'url di un file, lo apre e lo legge passandone il contenuto
//alla funzione readData(). Questa funzione è invocata quando viene selezionato
//un file dall'albero
openFileFromServer(url) {
let fileName: string[] = url.split("/");
console.log("Try to open " + fileName[fileName.length - 1] + " ...");
let txtFile: any = new XMLHttpRequest();
txtFile.open("GET", url, true);
txtFile.onreadystatechange = function () {
if (txtFile.readyState === 4) {
if (txtFile.status === 200) {
this.readImage(txtFile.responseText);
}
}
};
txtFile.send(null);
}
// version working on an array of numbers, obtained from the array of string lines
private get_metadata_num(image: Image, lines: number[]): void {
//let image = G.Image.getInstance();
this.xMin = 0;
this.yMin = 0;
this.xMax = 0;
this.yMax = 0;
this.step = 0; //dimensione di un pixel in micorn
this.direction = ReadDirection.u; //direzione di lettura
//scorro l'array soffermandomi solo sulle righe "intestazione delle x". Devo
//determinare ascisse e cordinate minime e massime, il passo e la direzione di
//scansione
for (let i = 0; i < lines.length; i++) {
if (Utility.isAnXHeader(lines[i], image)) {
if (this.xMin == 0) {
//se sono alla prima intestazione salvo la x e la y
this.xMin = lines[i];
this.yMin = lines[i + 1];
i++;
} else {
//definisco passo e direzione di scansione dalla seconda intestazione
if (lines[i] == this.xMin) {
this.direction = ReadDirection.c;
this.step = Math.abs(this.yMin - lines[i + 1]); // the unary + converts to number
//se sto leggendo per colonne determino this.xMax leggendo dalla fine
for (let j: number = lines.length; j > i; j--) {
//se la riga è "intestazione x" memorizzo this.xMax e lo confronto con this.xMin
if (Utility.isAnXHeader(lines[j], image)) {
this.xMax = lines[j];
if (this.xMax < this.xMin) {
let t: number = this.xMax;
this.xMax = this.xMin;
this.xMin = t;
}
break;
}
}
} else {
this.direction = ReadDirection.r;
this.step = Math.abs(this.xMin - lines[i]); // the unary + converts to number
//se sto leggendo per righe determino this.yMax leggendo dalla fine
for (let j: number = lines.length; j > i; j--) {
//se la riga è "intestazione y" memorizzo this.yMax e lo confronto con this.yMin
if (Utility.isAnYHeader(lines[j], image)) {
this.yMax = lines[j];
if (this.yMax < this.yMin) {
let t: number = this.yMax;
this.yMax = this.yMin;
this.yMin = t;
}
break;
}
}
}
break;
}
}
}
//A seconda della direzione di lettura determino o this.yMin e this.yMax, o this.xMin e this.xMax
for (let i: number = 2; i < lines.length; i++) {
if (this.direction == ReadDirection.c) {
//se leggo per colonne devo deterinare this.yMin e this.yMax
//mi soffermo sulle righe "intestazione y"
if (Utility.isAnYHeader(lines[i], image)) {
if (this.yMin > lines[i]) {
this.yMin = lines[i];
}
if (this.yMax < lines[i]) {
this.yMax = lines[i];
}
}
//alla terza colonna posso uscire perché ho già tutte le informazioni
if (lines[i] == this.xMin + this.step * 2) {
break;
}
} else {
//se leggo per righe devo deterinare this.xMin e this.xMax
//mi soffermo sulle righe "intestazione x"
if (Utility.isAnXHeader(lines[i], image)) {
if (this.xMin > lines[i]) {
this.xMin = lines[i];
}
if (this.xMax < lines[i]) {
this.xMax = lines[i];
}
}
//alla terza colonna posso uscire perché ho già tutte le informazioni
if (lines[i] == this.yMin + 2000) {
break;
}
}
}
}
get_metadata(image: Image, lines: number[]): void {
try {
this.get_metadata_num(image, lines);
}
catch (e) {
throw new Error(e);
}
}
// La funzione readImage() prende in ingresso il file di input memorizzato nella
// stringa "fileString". La funzione riempie la matrice "DataMatrix" con i dati
// in modo che essi siano memorizzati in un formato più leggibile. Sono ricavate
// anche altre variabili necessarie per il resto del codice.
readImage(image: Image, chart: Chart, content: any): Image {
let lines = content.split("\n").map(Number);
this.get_metadata(image, lines);
// Risolvo gli shift
for (let i = 0; i < lines.length; i++) {
if (Utility.isAnXHeader(lines[i], image)) {
// this is an x-coordinate
if (this.direction == ReadDirection.c && (lines[i] / 1000) % 2 != 0) {
// increment the y-coordinate of odd columns
lines[i + 1] += this.step;
} else if (this.direction == ReadDirection.r && (lines[i + 1] / 1000) % 2 != 0) {
// increment the x-coordinate of even rows
lines[i] += this.step;
}
}
}
//Definisco le dimensioni della matrice DataMatrix e la inizializzo
let xDim: number;
let yDim: number;
if (this.direction == ReadDirection.c) {
xDim = (this.xMax - this.xMin) / this.step + 1;
yDim = (this.yMax - this.yMin) / this.step - 2;
} else {
xDim = (this.xMax - this.xMin) / this.step - 2;
yDim = (this.yMax - this.yMin) / this.step + 1;
}
image.width = xDim;
image.height = yDim;
image.DataMatrix = new Array(xDim);
for (let i: number = 0; i < xDim; i++) {
image.DataMatrix[i] = new Array(yDim);
for (let j: number = 0; j < yDim; j++) {
image.DataMatrix[i][j] = new Array(image.depth);
for (let k: number = 0; k < image.depth; k++) {
image.DataMatrix[i][j][k] = 0;
}
}
}
//riempio la matrice DataMatrix eliminando i bordi
let x: number, y: number;
let write: boolean;
for (let i = 0; i < lines.length; i++) {
//riga "intestazione x": memorizzo le x e le y del punto e avanzo al conteggio
if (Utility.isAnXHeader(lines[i], image)) {
x = lines[i] - this.xMin;
y = lines[i + 1] - this.yMin;
if (x != 0) {
x /= this.step;
}
if (y != 0) {
y /= this.step;
}
i++;
//non è un pixel del bordo e sto leggendo per colonne: i successivi valori
//sono da considerare
if (this.direction == ReadDirection.c && y != 0 && y != 1 && y != (this.yMax - this.yMin) / this.step &&
y != (this.yMax - this.yMin) / this.step + 1) {
write = true;
y -= 2; //aggiorno la y con i bordi tagliati
} else if (
this.direction == ReadDirection.r && x != 0 && x != 1 && x != (this.xMax - this.xMin) / this.step &&
x != (this.xMax - this.xMin) / this.step + 1) {
//non è un pixel del bordo e sto leggendo per righe: i successivi valori
//sono da considerare
write = true;
x -= 2; //aggiorno la x con i bordi tagliati
} else {
//pixel del bordo: i valori successivi sono da ignorare
write = false;
}
//conteggio da considerare (non del bordo)
} else if (lines[i] < image.headerSetValue && write == true) {
image.DataMatrix[xDim - x - 1][yDim - y - 1][lines[i]] += 1;
}
}
//console.log(image.DataMatrix);
image.nOfCounts = new Array(xDim);
for (let i: number = 0; i < xDim; i++) {
image.nOfCounts[i] = new Array(yDim);
for (let j: number = 0; j < yDim; j++) {
image.nOfCounts[i][j] = Utility.sumVect(image.DataMatrix[i][j], 0, image.DataMatrix[i][j].length);
}
}
//console.log(image.nOfCounts);
image.maxAbsolute = Utility.findMax(image.nOfCounts, { x: 0, y: 0 }, { x: xDim - 1, y: yDim - 1 });
Utility.setDataForCompleteChart(image, chart);
return image;
}
}
export { Fs }
\ No newline at end of file
import * as Utility from "./utility";
interface coordinates // used in multiple files
{
x: number;
y: number;
}
class Calibration //used in multiple files
{
a: number;
b: number;
}
class Image {
private readonly saturationSliderID: string = "SaturationSlider";
private readonly transparencySliderID: string = "TrasparencySlider";
private readonly selectionCanvasID: string = "selectionCanvas";
private readonly myCanvasID: string = "myCanvas";
private context: CanvasRenderingContext2D;
private saturationSlider: HTMLInputElement;
private transparencySlider: HTMLInputElement;
pixel1: coordinates;
pixel2: coordinates;
private xMinRange: number;
private xMaxRange: number;
private selectionCanvas: HTMLCanvasElement;
private myCanvas: HTMLCanvasElement;
private ctx;
private isDown = false;
DataMatrix: number[][][];
width: number;
height: number;
readonly calibration: Calibration = { a: 3.36275, b: 58.2353 };
readonly depth: number = 8000;
channelDepth: number = Utility.round3(((this.depth + 1) * this.calibration.a - this.calibration.b) / 1000); //profondità massima in canali
readonly maxCoordValueX = 60000000; // to check
readonly headerSetValue = 17000;
readonly xCoordHeaderFirstValue = 5; //instestazione X
readonly yCoordHeaderFirstValue = 6; //intestazione y
globalxMinRange: number = 0;
globalxMaxRange: number = this.channelDepth;
zPixel1: coordinates;
zPixel2: coordinates; //pixel2 dello zoom
newOrigin: coordinates = { x: 0, y: 0 }; //nuovo origine nel caso di zoomù
maxAbsolute: number; //massimo conteggio della matrice nOfCounts
pixelDim: number; //dimensione dei pixel responsive
nOfCounts: number[][]; //matrici con i dati
rePrint: boolean = false; //variabile per ricolorare con il max relativo
constructor() {
this.selectionCanvas = <HTMLCanvasElement>document.getElementById(this.selectionCanvasID);
this.ctx = this.selectionCanvas.getContext("2d");
this.myCanvas = <HTMLCanvasElement>document.getElementById(this.myCanvasID);
this.saturationSlider = <HTMLInputElement>document.getElementById(this.saturationSliderID);
this.transparencySlider = <HTMLInputElement>document.getElementById(this.transparencySliderID);
}
//Il metodo findPosition definisce la posizione del cursore del mouse
//relativa al canvas nel momento in cui avviene l'evento passato in input
setPosition(event: any, pixel: coordinates, canvasID: string) {
let scrollTOP: number = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;
let scrollLEFT: number = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft;
let allX: number = event.clientX + scrollLEFT;
let allY: number = event.clientY + scrollTOP;
let elParent: any = document.getElementById(canvasID);
let objX: number = 0,
objY: number = 0;
while (elParent) {
objX += elParent.offsetLeft;
objY += elParent.offsetTop;
elParent = elParent.offsetParent;
}
pixel.x = Math.floor((allX - objX - 1) / this.pixelDim) + this.newOrigin.x;
pixel.y = Math.floor((allY - objY - 1) / this.pixelDim) + this.newOrigin.y;
}
drawImg(pixel1: coordinates, pixel2: coordinates, xMinRange: number, xMaxRange: number, callback?: () => void) {
this.pixel1 = pixel1;
this.pixel2 = pixel2;
//alert("disegno in corso");
//numero di pixel per dimensione
let nPixelX: number = this.pixel2.x - this.pixel1.x + 1;
let nPixelY: number = this.pixel2.y - this.pixel1.y + 1;
//dimensione dei canvas
let mappaPannelDim: any = document.querySelector("#mappa-pannel").getBoundingClientRect();
let mappaWidth: number = mappaPannelDim.right - mappaPannelDim.left - 40;
let mappaHeigth: number = 400;
//dimensione reale dei pixel
let dimPixelx: number = Math.floor(mappaWidth / nPixelX);
let dimPixely: number = Math.floor(mappaHeigth / nPixelY);
this.pixelDim = dimPixelx < dimPixely ? dimPixelx : dimPixely;
//dimensioni esatte dei canvas
this.myCanvas.height = nPixelY * this.pixelDim;
this.myCanvas.width = nPixelX * this.pixelDim;
this.selectionCanvas.height = nPixelY * this.pixelDim;
this.selectionCanvas.width = nPixelX * this.pixelDim;
let ctx = this.myCanvas.getContext("2d"); //contesto del canvas
if (xMaxRange - xMinRange >= this.channelDepth) {
//range completo
let max: number = 0; //massimo relativo o assoluto
if (this.rePrint) {
max = Utility.findMax(this.nOfCounts, this.pixel1, this.pixel2);
} else {
max = this.maxAbsolute;
}
max *= parseInt(this.saturationSlider.value) / 100;
this.drawCanvas(this.nOfCounts, max);
} else {
//range parziale (solo alcuni canali)
let xMinRangeCh: number = Math.floor((xMinRange * 1000 + this.calibration.b) / this.calibration.a - 1); //16
let xMaxRangeCh: number = Math.floor((xMaxRange * 1000 + this.calibration.b) / this.calibration.a - 1); //16371
//calcolo il numero di conteggi solo dei canali selezionati
let nOfCountsRelative: number[][];
nOfCountsRelative = new Array(this.width);
for (let i: number = 0; i < this.width; i++) {
nOfCountsRelative[i] = new Array(this.height);
for (let j: number = 0; j < this.height; j++) {
nOfCountsRelative[i][j] = Utility.sumVect(this.DataMatrix[i][j], xMinRangeCh, xMaxRangeCh);
}
}
//calcolo il massimo
let max: number = 0;
if (this.rePrint) {
max = Utility.findMax(nOfCountsRelative, this.pixel1, this.pixel2);
} else {
max = Utility.findMax(nOfCountsRelative, { x: 0, y: 0 }, { x: this.width - 1, y: this.height - 1 });
}
max *= parseInt(this.saturationSlider.value) / 100;
if (max == 0)
alert("WARNING: max value is 0");
else
this.drawCanvas(nOfCountsRelative, max);
}
if (typeof (callback) != typeof (undefined))
callback();
}
private drawCanvas(noc, max) {
//controllo il valore della trasparenza
let setTrsp: number = 1 - parseInt(this.transparencySlider.value) / 100;
//scorro tutti i pixel: ne determino il colore e li disegno
let color: string = "";
for (let i: number = this.pixel1.x; i <= this.pixel2.x; i++) {
for (let j: number = this.pixel1.y; j <= this.pixel2.y; j++) {
let intensity: number = noc[i][j] / max;
if (intensity < 1 / 5)
//blu
color = "rgba(0, 0, " + Math.floor(intensity * 5 * 255) + "," + setTrsp + ")";
else if (1 / 5 <= intensity && intensity < 2 / 5)
//blu+verde
color = "rgba(0, " + Math.floor((intensity - 1 / 5) * 5 * 255) + ",255, " + setTrsp + ")";
else if (2 / 5 <= intensity && intensity < 3 / 5)
// verde-blu
color = "rgba(0, 255, " + (255 - Math.floor((intensity - 2 / 5) * 5 * 255)) + ", " + setTrsp + ")";
else if (3 / 5 <= intensity && intensity < 4 / 5)
//verde + rosso
color = "rgba(" + Math.floor((intensity - 3 / 5) * 5 * 255) + ",255,0," + setTrsp + ")";
//rosso -verde
else
color = "rgba(255," + (255 - Math.floor((intensity - 4 / 5) * 5 * 255)) + ", 0, " + setTrsp + ")";
this.ctx.fillStyle = color;
this.ctx.fillRect((i - this.pixel1.x) * this.pixelDim, (j - this.pixel1.y) * this.pixelDim, this.pixelDim, this.pixelDim);
}
}
//console.log(color);
this.rePrint = false; //annullo rePrint
this.ctx.fillStyle = "rgba(0, 110, 255, 0.25)";
this.isDown = false;
}
}
export { coordinates, Calibration, Image };
import { Image } from "./image";
import { Chart } from "./chart";
import { Fs } from "./fs";
import { CallbackManager } from "./callbacks"
import $ = require("jquery");
class ImportFile {
private image: Image;
private chart: Chart;
private fs: Fs;
private callbackManager: CallbackManager;
constructor(drawImage: Image, drawChart: Chart) {
this.image = drawImage;
this.chart = drawChart;
this.fs = new Fs();
this.callbackManager = new CallbackManager();
}
//funzione che definisce tutti gli elementi responsabili dell'apertura di un file.
//Sono definiti quindi l'albero e il bottone per l'importazione da locale
setImportFile() {
// genero e leggo il contenuto della directory "filesystem"
// comment out waiting to properly address the request
// let xmlDoc: Document;
// let xmlListingFile: any = new XMLHttpRequest();
// xmlListingFile.open("PROPFIND", "CHNET/", false);
// xmlListingFile.setRequestHeader("Depth", "infinity");
// xmlListingFile.onreadystatechange = function () {
// if (xmlListingFile.readyState === 4) {
// if (xmlListingFile.status === 207) {
// let parser = new DOMParser();
// xmlDoc = parser.parseFromString(xmlListingFile.responseText, "text/xml");
// }
// }
// }
// xmlListingFile.send(null);
//ora genero l'albero e definisco l'evento in caso di selezione di un nodo
// jQuery(document.getElementById('FileTreeview')).treeview({ data: this.fs.generateTree(xmlDoc) });
// $('#FileTreeview').on('nodeSelected', (e, node) => {
// if (node['url'] != undefined) {
// $("#load-spinner").css("display", "inline");
// this.fs.openFileFromServer(node['url']);
// }
// });
// import a local file
let fileInputButton: any = document.getElementById("myImport");
fileInputButton.onchange = () => {
this.callbackManager.showElement("load-spinner", true);
let file: File = fileInputButton.files[0];
let readerObject = new FileReader();
readerObject.onload = () => {
let content = readerObject.result;
let image = this.fs.readImage(this.image, this.chart, content);
this.callbackManager.showElement("load-spinner", false);
this.image.drawImg({ x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, 0, image.channelDepth,
() => { this.callbackManager.closeBootstrapModel("btnCloseModal"); });
this.chart.drawChart(image, { x: 0, y: 0 }, { x: image.width - 1, y: image.height - 1 }, 0, image.channelDepth);
};
readerObject.readAsText(file);
};
}
//funzione per la compressione della sidenav sx
compressingSidenav() {
let fsLabel = document.getElementById("collapse-symbol");
let isClosedfs = false;
let fsLabel_cross = () => {
if (isClosedfs == true) {
isClosedfs = false;
console.log("closed");
$(".w3-bar-block").css("width", "65px");
$(".text-sidenav").css("display", "none");
document.getElementById("collapse-symbol").title = "Open Sidebar";
document.getElementById("collapse-symbol").classList.replace("fa-angle-double-left", "fa-angle-double-right");
} else {
isClosedfs = true;
$(".w3-bar-block").css("width", "200px");
$(".text-sidenav").css("display", "inline");
document.getElementById("collapse-symbol").title = "Close Sidebar";
document.getElementById("collapse-symbol").classList.replace("fa-angle-double-right", "fa-angle-double-left");
}
};
fsLabel.addEventListener("mousedown", fsLabel_cross, false);
}
//funzione che definisce l'area su cui si può eseguire il drag&drop
makeDroppable(droppableArea) {
//creo l'elemento "input type file" non visibile e lo aggiungo a "droppableArea"
let input: any = document.createElement("input");
input.type = "file";
input.multiple = true;
input.style.display = "none";
droppableArea.appendChild(input);
//questo evento è chiamato quando i file sono trascinati ma non ancora lasciati
droppableArea.addEventListener("dragover", function (e) {
e.preventDefault(); //impediamo l'apertura del file
e.stopPropagation();
e.dataTransfer.dropEffect = "copy";
droppableArea.classList.add("dragover");
});
//l'evento è chiamato quando un file lascia la zona predefinita per il drag&drop
droppableArea.addEventListener("dragleave", function (e) {
e.preventDefault();
e.stopPropagation();
droppableArea.classList.remove("dragover");
});
//questo evento si innesca quando il drop è effettivamente avvenuto
droppableArea.addEventListener("drop", function (e) {
e.preventDefault();
e.stopPropagation();
droppableArea.classList.remove("dragover");
this.callback(e.dataTransfer.files, this.image, this.chart);
});
}
//funzione chiamata in caso di drag&drop responsabile dell'apertura del file droppato,
//della sua lettura e del passaggio del suo contenuto alla funzione readData()
private callback(files, drawImage: Image, drawChart: Chart, fs: Fs) {
this.callbackManager.showElement("load-spinner", true);
let file: File = files[files.length - 1];
console.log("Try to open " + file.name + " ...");
let readerObject = new FileReader();
readerObject.onload = () => {
let content = readerObject.result;
fs.readImage(drawImage, drawChart, content);
this.callbackManager.showElement("load-spinner", false);
};
readerObject.readAsText(file);
}
}
export { ImportFile };
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!--Compatibilità con Microsoft e Responsività-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XRF analysis viewer</title>
<!-- CSS -->
<link href="src/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" type="text/css" href="src/bootstrap-treeview/dist/bootstrap-treeview.min.css">
<link rel="stylesheet" type="text/css" href="src/bootstrap-select/dist/css/bootstrap-select.min.css">
</head>
<body>
<!-- NAVBAR -->
<div class="navbar navbar-fixed-top navbar-inverse" role="navigation" id="top-navbar">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">XRF Analysis Viewer</a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav navbar-right">
<li><a href="#"><span class="glyphicon glyphicon-user"></span> Sign Up</a></li>
<li><a href="#"><span class="glyphicon glyphicon-log-in"></span> Login</a></li>
</ul>
</div>
<!-- /.nav-collapse -->
</div>
<!-- /.container -->
</div>
<!-- /.navbar -->
<div id="wrapper">
<!-- FILE-SYSTEM -->
<button type="button" class="fs-label is-closed" id="fsbtn">
<span class="glyphicon glyphicon-chevron-right"></span>
</button>
<div id="mySidenavfs" class="sidenav">
<h3> Import File From Server </h3>
<div id="FileTreeview"></div>
<h3> Import File From Local Repository </h3>
<label class="btn-bs-file btn btn-primary">
<span class="glyphicon glyphicon-open"></span> Choose a file...
<input id="myImport" type="file" / >
</label>
</div>
<!-- ./file-system -->
<!-- SETTINGS -->
<button type="button" class="btn-settings" id="setbtn">
<span class="glyphicon glyphicon-cog"></span>
</button>
<div id="mySidenavSet" class="sidenav">
<!--<div class="panel panel-default" id="pannelSettings">-->
<p><button id="reset" class="btn btn-primary">Reset</button></p>
<p><div class="btn-group">
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
<span class="glyphicon glyphicon-download-alt"></span>
Export <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#" id="ExportImage">Map</a></li>
<li><a href="#" id="ExportGraph">Chart</a></li>
</ul>
</div></p>
<ul class="nav nav-pills nav-stacked">
<li> <!-- Settings -->
<a href="#setmap" data-toggle="collapse" class="DropMenu">
Settings <span class="glyphicon glyphicon-chevron-down"></span>
</a>
<div id="setmap" class="collapse"><p>
<p><button type="button" class="btn btn-primary" id="rePlot">Re-color</button></p>
<p><div class="btn-group">
<div class="btn-group">
<button type="button" class="btn dropdown-toggle btn-primary" data-toggle="dropdown">Scale <span class="caret"></span></button>
<ul class="dropdown-menu" role="menu">
<li><a href="#" id="setlinearButton">Linear</a></li>
<li><a href="#" id="setlogButton">Log</a></li>
</ul>
</div>
<div class="btn-group">
<button type="button" class="btn dropdown-toggle btn-primary" data-toggle="dropdown">x Label <span class="caret"></span></button>
<ul class="dropdown-menu" role="menu">
<li><a href="#" id="setEnergyButton">Energy</a></li>
<li><a href="#" id="setChannelsButton">Channels</a></li>
</ul>
</div>
</div></p>
<p>Saturation<input type="range" id="SaturationSlider" value="100"></p>
<p>Opacity<input type="range" id="TrasparencySlider" value="0"></p>
</p></div>
</li> <!-- ./Settings -->
<li>
<a href="#peackselect" data-toggle="collapse" class="DropMenu">
Peack selection <span class="glyphicon glyphicon-chevron-down"></span>
</a>
<div id="peackselect" class="collapse"><p>
<p><select class="form-control selectpicker" data-style="btn-primary" data-width="75%" data-live-search="true" id="elementSelect" onchange="setElement()">
<option value="0">- inspect element -</option>
<option value="1">Ca</option>
<option value="2">Pb</option>
<option value="3">Hg</option>
<option value="4">Fe</option>
<option value="5">Cu</option>
<option value="6">Zn</option>
<option value="7">Ti</option>
<option value="8">K</option>
<option value="9">Co</option>
</select></p>
<div class="form-group">
<label for="spinBoxMin">Peak selection (only calibrated)</label>
<input type="number" class="form-control" id="spinBoxMin" min="0" max="55" step="0.01">
<input type="number" class="form-control" id="spinBoxMax" min="0" max="55" step="0.01">
</div>
<button id="readSpinbox" class="btn btn-primary">Select range</button>
</p></div>
</li>
</ul>
<!--</div>-->
</div>
<!-- ./settings -->
<!-- COLLAPSABLE PAGE -->
<div class="container-fluid droppable" id="myContent" dropzone="copy f:text/plain">
<!-- TITOLO -->
<div class="page-header well text-center"><h1>XRF analysis viewer</h1></div>
<!-- PAGE CONTENT -->
<div class="row">
<!-- MAPPA -->
<div class="col-md-4">
<div class="well" id="mappa-pannel">
<h2>XRF Image</h2>
<canvas id="myCanvas" onmousedown="findPosDown(event);" onmouseup="findPosUp(event);">
Browser doesn't support canvas tag
</canvas>
</div>
</div>
<!-- ./mappa -->
<!-- SPETTRO -->
<div class="col-md-8">
<div class="well" id="chart-pannel">
<h2>XRF Spectrum</h2>
<p id="chart" class="p-chart"></p>
<img id="chartToImg" style="display:none;">
</div>
</div>
<!-- ./spettro -->
</div>
<!-- ./page-content -->
</div>
<!-- /.collapsable-page -->
</div>
<!-- ./wrapper -->
<footer>
<p>© CHNET 2017</p>
<img width="150" src="Digilab2.png" class="img-responsive center-block">
</footer>
<!--Librerie -->
<script type="text/javascript" src="src/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="src/js/bootstrap.min.js"></script>
<script type="text/javascript" src="src/bootstrap-treeview/public/js/bootstrap-treeview.js"></script>
<script type="text/javascript" src="src/bootstrap-select/dist/js/bootstrap-select.js"></script>
<script type="text/javascript" src="LoadFile.js"></script>
<script type="text/javascript" src="src/dygraph-combined-dev.js"></script>
<script type="text/javascript" src="src/dygraph-extra.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!--Compatibilita' con Microsoft e Responsivita'-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XRF analysis viewer</title>
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" type="text/css" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="node_modules/bootstrap-select/dist/css/bootstrap-select.min.css">
<link rel="stylesheet" type="text/css" href="src/font-awesome/dist/font-awesome.min.css">
<!-- Librerie -->
<script type="text/javascript" src="node_modules/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="node_modules/dygraphs/dist/dygraph.min.js"></script>
<script type="text/javascript" src="xrf.js"></script>
<!-- ./Librerie -->
</head>
<body>
<!-- Spinner -->
<div align="center">
<div id="load-spinner" style="display:none">
<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
<span class="sr-only">Loading...</span>
</div>
</div>
<!-- /.spinner -->
<!-- Navbar -->
<nav class="navbar navbar-fixed-top bg-primary">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="/presentation/XRF-App/">
<img id="logo-chnet" src="Logo-chnet.png" width="35" height="35" alt="" class="img-rounded">
<div id="testo-logo-chnet">XRF Analysis Viewer</div>
</a>
</div>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<?php
$pic=$_SERVER["OIDC_CLAIM_picture"];
if (filter_var($pic, FILTER_VALIDATE_URL))
{
echo "<img src=\"$pic\" class=\"img-circle\" width=\"25\">";
} else {
echo "<img src=\"./default-avatar.png\" class=\"img-circle\" width=\"25\">";
}
//echo " ".ucfirst($_SERVER["OIDC_CLAIM_name"]);
?>
<span class="glyphicon glyphicon-chevron-down"></span>
</a>
<ul class="dropdown-menu">
<li>
<?php
echo "<div class=\"usrname\">".ucfirst($_SERVER["OIDC_CLAIM_name"])."</div>";
echo "<i class=\"usrmail\">".ucfirst($_SERVER["OIDC_CLAIM_email"])."</i>";
?>
</li>
<li class="divider"></li>
<li class="usr-menu"><a href="https://chnet-iam.cloud.cnaf.infn.it/dashboard#/home">Profile</a></li>
<li class="usr-menu"><a href="/presentation/.redirect/?logout=http%3A%2F%2Fchnet.infn.it%2F">Sign out</a></li>
</ul>
</li>
</ul>
</div>
</nav>
<!-- ./navbar -->
<!-- Sidenav -->
<div class="w3-bar-block w3-border" id="sidenav">
<div class="w3-bar-item w3-button">
<a href="">
<i class="fa fa-home" data-toggle="tooltip" data-placement="right" title="Home"></i>
<span class="text-sidenav" style="display:none">Home</span>
</a>
</div>
<div class="w3-bar-item w3-button" data-toggle="modal" data-target="#myModal">
<i class="fa fa-folder-o" data-toggle="tooltip" data-placement="right" title="Open File"></i>
<span class="text-sidenav" style="display:none">Open file</span>
</div>
<div class="w3-bar-item w3-button" data-toggle="collapse" data-target=".collapse-settings">
<i class="fa fa-cog" data-toggle="tooltip" data-placement="right" title="Settings"></i>
<span class="text-sidenav" style="display:none">Settings</span>
</div>
<div class="w3-bar-item w3-button" id="reset">
<i class="fa fa-refresh" data-toggle="tooltip" data-placement="right" title="Reset"></i>
<span class="text-sidenav" style="display:none">Refresh</span>
</div>
<div class="w3-bar-item w3-button">
<a id="ExportLink" download="Canvas.png" href="#" class="w3-bar-item w3-button">
<div id="ExportImage">
<i class="fa fa-file-image-o" data-toggle="tooltip" data-placement="right" title="Export Map"></i>
<span class="text-sidenav" style="display:none">Export Map</span>
</div>
</a>
</div>
<div class="w3-bar-item w3-button">
<a href="#" id="ExportGraph" download="Spectrum.png" class="w3-bar-item w3-button">
<i class="fa fa-bar-chart" data-toggle="tooltip" data-placement="right" title="Export Chart"></i>
<span class="text-sidenav" style="display:none">Export Chart</span>
</a>
</div>
<div class="w3-bar-item w3-button collapse-sidebar-manually sidebar-label">
<i id="collapse-symbol" class="fa fa-angle-double-right" data-toggle="tooltip" data-placement="right" title="Open Sidebar"></i>
<span class="text-sidenav" style="display:none">Collapse sidebar</span>
</div>
</div>
<!-- ./sidenav -->
<!-- Modal -->
<div id="myModal" class="modal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content" id="importPanel">
<div class="modal-header">
<button id="btnCloseModal" type="button" class="close" data-dismiss="modal">&times;</button>
<h3 class="modal-title">Import File</h3>
</div>
<div class="modal-body">
<h4>Select file from server</h4>
<div id="FileTreeview"></div>
Import File From Local Repository
<label class="btn-bs-file btn btn-primary btn-sm">
<span class="glyphicon glyphicon-open"></span> Choose a file...
<input id="myImport" type="file" / >
</label>
</div>
</div>
</div>
</div>
<!-- ./modal -->
<!-- COLLAPSABLE PAGE -->
<div class="container-fluid droppable" id="myContent" dropzone="copy f:text/plain">
<!-- PAGE CONTENT -->
<div class="row">
<!-- MAPPA -->
<div class="col-sm-4">
<div class="well" id="mappa-pannel">
<h2>XRF Image</h2>
<!-- canvas -->
<div style="position: relative; height: 400px;">
<canvas id="selectionCanvas" height="400px" width="360px"></canvas>
<canvas id="myCanvas" height="400px" width="360px"></canvas>
</div>
<!-- ./canvas -->
<div class="collapse collapse-settings" align="center">
<div class="panel panel-default">
<div class="panel-body">
Saturation<input type="range" id="SaturationSlider" value="100">
</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
Opacity<input type="range" id="TrasparencySlider" value="0">
</div>
</div>
<button type="button" class="btn btn-primary btn-sm" id="rePlot">Re-color</button>
</div>
</div>
<!-- ./ pannello-mappa -->
</div>
<!-- ./mappa -->
<!-- SPETTRO -->
<div class="col-md-8">
<div class="well" id="chart-pannel">
<h2>XRF Spectrum</h2>
<!-- grafico -->
<p id="chart" class="p-chart"></p>
<img id="chartToImg" style="display:none;">
<!-- impostazioni -->
<p><div class="collapse collapse-settings" align="center">
<!-- Asse y -->
<div class="btn-group">
<button type="button" class="btn dropdown-toggle btn-primary btn-sm" data-toggle="dropdown">Scale <span class="caret"></span></button>
<ul class="dropdown-menu" role="menu">
<li><a href="#" id="setlinearButton">Linear</a></li>
<li><a href="#" id="setlogButton">Log</a></li>
</ul>
</div>
<!-- Asse x -->
<div class="btn-group">
<button type="button" class="btn dropdown-toggle btn-primary btn-sm" data-toggle="dropdown">x Label <span class="caret"></span></button>
<ul class="dropdown-menu" role="menu">
<li><a href="#" id="setEnergyButton">Energy</a></li>
<li><a href="#" id="setChannelsButton">Channels</a></li>
</ul>
</div>
<!-- Selezione picco -->
<div class="btn-group">
<div class="form-group" id="myform">
<label for="spinBoxMin"><h6>Peak selection (only calibrated)</h6></label>
<p><input type="number" class="form-control" id="spinBoxMin" min="0" max="55" step="0.01">
<input type="number" class="form-control" id="spinBoxMax" min="0" max="55" step="0.01"></p>
<div align="center">
<button id="readSpinbox" class="btn btn-primary btn-sm" style="margin-left: -25px;">Select range</button>
</div>
</div>
</div>
<!-- Selezione elemento -->
<select class="form-control selectpicker" data-style="btn-primary btn-sm" data-width="25%" data-live-search="true" id="elementSelect">
<option value="0">- inspect element -</option>
<option value="1">Ca</option>
<option value="2">Pb</option>
<option value="3">Hg</option>
<option value="4">Fe</option>
<option value="5">Cu</option>
<option value="6">Zn</option>
<option value="7">Ti</option>
<option value="8">K</option>
<option value="9">Co</option>
</select>
</div></p>
<!-- ./impostazioni -->
</div>
<!-- ./pannello-spettro -->
</div>
<!-- ./colonna-spettro -->
</div>
<!-- ./riga 1 -->
</div>
<!-- /.collapsable-page -->
</body>
</html>
This diff is collapsed.
{
"name": "chnet-xrf",
"version": "0.1.0",
"scripts": {
"test": "jest"
},
"dependencies": {
"assert": "latest",
"bootstrap": "v3.3.7",
"bootstrap-select": "^1.12.4",
"bootstrap-slider": "^10.0.0",
"bootstrap-tooltip": "^3.1.1",
"dygraphs": "^2.0.0",
"jquery": "^3.3.1"
},
"description": "Web application to analyse XRF images",
"license": "EUPL",
"repository": {
"type": "git",
"url": "https://baltig.infn.it/chnet/XRF-App.git"
},
"devDependencies": {
"@types/dygraphs": "^1.1.8",
"@types/jest": "^21.1.6",
"@types/jquery": "^3.3.4",
"@types/node": "^8.10.18",
"jest": "^21.2.1",
"ts-jest": "^21.2.2",
"ts-md5": "^1.2.2",
"ts-node": "^6.1.0",
"typescript": "^2.9.1"
},
"jest": {
"testEnvironment": "node",
"transform": {
"^.+\\.ts?$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"testRegex": "^.+\\.test\\.ts$",
"moduleFileExtensions": [
"ts",
"js"
]
}
}
<!DOCTYPE html>
<html>
<head>
<!--Compatibilità con Microsoft e Responsività-->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Fisrts Bootstrap Template</title>
<!-- CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet" media="screen">
<style>
body { padding-top: 70px; }
</style>
</head>
<body>
<!-- Barra di navigazione -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<!--Logo e pulsante per barra ridimensionata -->
<div class="navbar-header">
<!-- Bottone mostrato quando è tutto collapsed -->
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<!-- Questo è per i non vedenti -->
<span class="sr-only">Espandi barra di navigazione</span>
<!-- Questo aggiunge le barre orizzontali al menù compresso -->
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!--Questo è il logo con il riferimento alla pagina iniziale -->
<a class="navbar-brand" href="Es2.html">Logo</a>
</div>
<!--Elementi della barra: serve per l'impostazione dei link -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav navbar-right">
<li class="active"><a href="Es2.html">Link 1</a></li>
<li><a href="https://www.google.it">Link 2</a></li>
<li><a href="https://www.google.it">Link 3</a></li>
</ul>
<!-- Questo è semplive testo -->
<p class="navbar-text navbar-right">creato da Me</p>
</div>
</nav>
<!-- Riempimento della tabella -->
<div class="container">
<div class="row">
<div class="col-md-4"><h1>Colonna 1</h1>"Lorem ipsum dolor sit amet, ..."</div>
<div class="col-md-4"> <h1>Colonna 2</h1><img width="500" src="lunaPiccola.JPG" class="img-responsive"></div>
<div class="col-md-4"><h1>Colonna 3</h1>"Lorem ipsum dolor sit amet, ..."</div>
</div>
<div class="row">
<div class="col-md-4"><h1>Colonna 1</h1>"Lorem ipsum dolor sit amet, ..."</div>
<div class="col-md-8"> <h1>Colonna 2</h1>"Lorem ipsum dolor sit amet, …"</div>
</div>
<div class="row">
<div class="col-md-6 col-md-offset-3"><h1>Colonna 1</h1>"Lorem ipsum dolor sit amet, ..."</div>
</div>
</div>
<!-- jQuery e plugin JavaScript -->
<script src="src/jquery/dist/jquery.min.js"></script>
<script src="src/js/bootstrap.min.js"></script>
</body>
</html>
<!--INFORMAZIONI SULLA PAGINA-->
<!--Struttura a colonne.
La struttura inizia con il tag (riga 16):
<div class="container">
Una volta stabilita una riga la si divide in colonne.
La pagina è di 12 colonne. Se si vogliono fare 3 colonne occorre occupare
4 colonne per ciascuna di esse (righe 17-21):
<div class="col-md-4">...</div>
Se si vogliono fare colonne di dimensioni diverse occorre modificare il tag
(righe 22-25):
<div class="col-md-4">...</div> in <div class="col-md-N">...</div>
dove la somma degli N deve dare 12.
Se voglio lasciare colonne vuote (ossia un offset) occorre modificare sempre
lo stesso tag (righe 26-30):
<div class="col-md-6 col-md-offset-N">...<|div>
dove N è il numero di colonne di offset.
Se si inseriscono delle immagini è fondamentale inserire la classe (riga 19):
<img class="img-responsive">
così l'immagine si adatta alla casella della tabella.
Si possono annidare le tabelle all'interno di altre tabelle. Basta aggiungere
una <div class="row"> all'interno di una colonna.
e' possibile dichiarare una colonna poi un'altra e invertire il loro ordine
con delle classi ma questa cosa è abbastanza inutile.
Ci sono 4 classi per le colonne: col-xs-N, col-sm-N, col-md-N, col-lg-N.
Servono per capire la responsività nei dispositivi: md per i pc, sm per i
telefoni.Però la pagina si aggiorna da sola in base al dispositivo.
Si può inserire anche più di una classe per una colonna per modificare lo
spazio che quella colonna occupa in caso di cambio di dispositivo. Cosa non
troppo utile.
https://www.mrwebmaster.it/web-design/bootstrap-navbar_11413.html
-->
\ No newline at end of file
engines:
duplication:
enabled: true
config:
languages:
javascript:
mass_threshold: 50
eslint:
enabled: true
csslint:
enabled: true
ratings:
paths:
- "**.js"
- "**.css"
exclude_paths:
Guidelines
=============
* The application JavaScript source code is transpiled using [Babel](https://babeljs.io/)
* We support both [SASS](http://sass-lang.com/) and [LESS](http://lesscss.org/). If you modify one in your PR, please modify both and make sure they both work.
* Additionally, when you are ready to submit your PR, please rebase your commits against the latest master branch so they are easier to examine!
* Please make sure you're not committing your re-built `dist` files, either. We'll do that!
* Also, please note, your code will not be merged if it does not pass our CI test. Thanks for your contribution!
Issues
=============
**NOTE:** Before filing a new issue, please search through the open issues list and check to see if an existing issue already exists that describes your problem. If so, leave a comment within that issue with the checklist items described below.
Please make sure you include the following in your issue report where appropriate:
- [ ] JSFiddle (or an equivalent such as CodePen, Plunker, etc) with the an example demonstrating the bug
- [ ] Instructions to replicate the bug in the Fiddle
Pull Requests
=============
Please accompany all pull requests with the following (where appropriate):
- [ ] unit tests (we use [Jasmine 2.x.x](https://jasmine.github.io/2.2/introduction))
- [ ] JSFiddle (or an equivalent such as CodePen, Plunker, etc) or screenshot/GIF with new feature or bug-fix
- [ ] Link to original Github issue (if this is a bug-fix)
- [ ] documentation updates to README file
- [ ] examples within [/tpl/index.tpl](https://github.com/seiyria/bootstrap-slider/blob/master/tpl/index.tpl) (for new options being added)
- [ ] Passes CI-server checks (runs automated tests, JS source-code linting, etc..). To run these on your local machine, type `grunt test` in your Terminal within the bootstrap-slider repository directory
.idea/*
temp
node_modules
bower_components
.grunt/*
_SpecRunner.html
npm-debug.log
.DS_STORE
index.html
\ No newline at end of file
5.1.1
#########################
## Sass Lint File
#########################
# Linter Options
options:
# Don't merge default rules
merge-default-rules: false
# Raise an error if more than 50 warnings are generated
max-warnings: 50
# File Options
files:
include: 'src/sass/**/*.s+(a|c)ss'
# Rule Configuration
rules:
extends-before-mixins: 2
extends-before-declarations: 2
placeholder-in-extend: 2
mixins-before-declarations:
- 2
-
exclude:
- breakpoint
- mq
no-warn: 1
no-debug: 1
no-ids: 2
no-important: 2
hex-notation:
- 2
-
style: uppercase
indentation:
- 2
-
size: 2
property-sort-order:
- 1
-
order:
- display
- margin
ignore-custom-properties: true
\ No newline at end of file
language: node_js
node_js:
- "5.1.1"
before_install:
- npm install -g grunt-cli bower
- npm install
9.8.0 / 2017-04-24
==================
* **New Feature:** Ability to add a custom class to the ranges of a slider with the `rangeHightlights` option specified. [See the PR for further details.](https://github.com/seiyria/bootstrap-slider/pull/742). Thanks to [jccode](https://github.com/jccode).
Tooling Update / 2017-04-09
==================
* Updates [grunt](https://github.com/gruntjs/grunt) dependency from version `0.4.4` to `^0.4.5`.
9.7.3 / 2017-04-09
==================
* **Bug Fix** Resolves PhantomJS error that was occurring while running the unit test suite. [See here for further details](https://github.com/seiyria/bootstrap-slider/issues/696).
* **Tooling Update** Updates unit test suite to [Jasmine 2.x.x](https://jasmine.github.io/2.2/introduction) by updating the [grunt-contrib-jasmine](https://github.com/gruntjs/grunt-contrib-jasmine) dependency from version `0.5.2` to `1.0.3`.
9.7.2 / 2017-02-10
==================
* **Bug Fix** Resolves accesibility issue in range sliders. [See here for further details](https://github.com/seiyria/bootstrap-slider/issues/687). Thanks to [Jerry (jerrylow)](https://github.com/jerrylow).
Tooling Update / 2017-02-02
==================
* Adds in [CodeClimate](https://codeclimate.com/) integration. Thanks to [Scott Larkin](https://github.com/larkinscott).
Tooling Update / 2017-02-01
==================
* Examples Page: Fixes code snippet for Example 6. Thanks to [Sergey Mezentsev](https://github.com/TheBits).
9.7.1 / 2017-01-29
==================
* **Bug Fix** Resolves "'slider' of undefined" error. [See here for further details](https://github.com/seiyria/bootstrap-slider/issues/587). Thanks to [Guto Sanches](https://github.com/gutosanches).
Tooling Update / 2017-01-06
==================
* Examples Page: Adds syntax highlighting to code snippets on Examples page
* Examples Page: Adds anchor tags to each example. For example, navigating to http://seiyria.com/bootstrap-slider/#example-10 will now load the page at Example #10.
* Examples Page: Fixed code snippet in Example #14 based on feedback from [this comment](https://github.com/seiyria/bootstrap-slider/issues/645#issuecomment-270751793).
9.7.0 / 2017-01-05
==================
* **Performance Enhancement** Use passive event listeners for touch-enabled devices. [See here for further details](https://github.com/seiyria/bootstrap-slider/pull/680). Thanks to [Chris Hallberg](https://github.com/crhallberg).
Tooling Update / 2017-01-05
==================
* Add an explicit `grunt lint` command to run Lint check on all source files and execute it in the NPM `pretest` script.
9.6.2 / 2017-01-04
==================
* Updating current year references in license from 2016 -> 2017.
Tooling Update / 2017-01-04
==================
* Adds in linting for SASS and LESS files in order to catch common syntax errors at CI step versus compile time.
9.6.1 / 2017-01-04
==================
* **Bug Fix:** Resolve issue with SASS file compilation. [See here for further details](https://github.com/seiyria/bootstrap-slider/issues/683). Thanks to [Schepotin](https://github.com/Schepotin) for reporting.
9.6.0 / 2017-01-03
==================
* **New Feature:** Adds ability to set direction (using HTML5 `dir` attribute). [See here for further details](https://github.com/seiyria/bootstrap-slider/pull/679). Thanks to [Denis Chenu](https://github.com/Shnoulle).
9.5.4 / 2016-12-18
==================
* **Bug Fix:** Fixes issue where dragging slider handle outside of modal and releasing cursor would close the modal. [See original issue for further details](https://github.com/seiyria/bootstrap-slider/issues/339). Thanks to [ZeVS777](https://github.com/ZeVS777).
9.5.3 / 2016-12-01
==================
* **Bug Fix:** Fixes typo from previous update to SCSS rules. Thanks to [Julien Bachmann](https://github.com/julienbachmann).
9.5.2 / 2016-11-30
==================
* **Bug Fix:** Fixes SCSS rules. [See original issue for further details](https://github.com/seiyria/bootstrap-slider/issues/662). Thanks to [Julien Bachmann](https://github.com/julienbachmann).
9.5.1 / 2016-11-23
==================
* **Bug Fix:** Removes `'none'` classes after selection change. [See here for further details](https://github.com/seiyria/bootstrap-slider/pull/659). Thanks to [John Clarke](https://github.com/john-clarke).
9.5.0 / 2016-11-21
==================
* **New Feature:** Adds `aria-valuetext` attribute to each slider handle element, which is set to be the current formatted value of the slider (based on the `formatter` option). [See here for further details](https://github.com/seiyria/bootstrap-slider/pull/646). Thanks to [mediaformat](https://github.com/mediaformat).
9.4.1 / 2016-11-04
==================
* **Documentation Fix:** Fixing an inconsistency with the licensing information in our source files. [See here for further details](https://github.com/seiyria/bootstrap-slider/pull/652). Thanks to [Tom Yue](https://github.com/yuethomas) for identifying this issue.
9.4.0 / 2016-10-31
==================
* **New Feature:** Adds the ability to set the slider value using stringified numbers. [See here for further details](https://github.com/seiyria/bootstrap-slider/pull/642). Thanks to [Ryan Bruns](https://github.com/snurby7)
9.3.2 / 2016-10-30
==================
* **Bug Fix:** Fixes reported bug where a slider was unable to be destroyed and re-created if there were event listeners bound to it. [See here for further details](https://github.com/seiyria/bootstrap-slider/issues/640).
9.3.0 / 2016-10-20
==================
* **New Feature:** Adds the ability to enable/disable tooltips when hovering over ticks via the `ticks_tooltip` option. [See here for further details](https://github.com/seiyria/bootstrap-slider/pull/638). Thanks to [Ryan Bruns](https://github.com/snurby7)
9.2.2 / 2016-10-18
==================
* **Bug Fix:** Resolves issue where range highlights were not being applied properly for reversed sliders. [See here for further details](https://github.com/seiyria/bootstrap-slider/pull/637). Thanks to [Bernard Gorman](https://github.com/gormanb)
9.2.0 / 2016-09-26
==================
* **New Feature:** Adding the ability to target certain ranges of the slider track via CSS in order to highlight them. [See here for further details](https://github.com/seiyria/bootstrap-slider/pull/619). Thanks to [lipoczkit](https://github.com/lipoczkit)
9.1.3 / 2016-08-06
==================
* **Bug Fix:** Checks for `window` object before attempting to attach `console` polyfills. [Resolves this issue](https://github.com/seiyria/bootstrap-slider/issues/607)
9.1.2 / 2016-08-06
==================
* Accidental publish
9.1.1 / 2016-07-15
==================
* **Bug Fix:** Adds `.npmignore` file to repository. [Resolves this issue](https://github.com/seiyria/bootstrap-slider/issues/601)
9.1.0 / 2016-07-14
==================
* **New Feature:** Always binding to the `$.fn.bootstrapSlider` namespace and printing a console warning when the `$.fn.slider` namespace is already bound. Idea came from discussion [in this issue](https://github.com/seiyria/bootstrap-slider/issues/575)
9.0.0 / 2016-07-13
==================
* **New Feature:** Wraps all of the ticks within a single container element with the class `.slider-tick-container` as opposed to being within the `.slider-track` element. This enables individual ticks to be more easily targeted with CSS selectors such as `nth-of-type(n)`. Idea came from discussion [in this issue](https://github.com/seiyria/bootstrap-slider/issues/500)
8.0.0 / 2016-07-13
==================
* **Revert:** Reverting bug fix made in `7.0.4 - 7.0.5` because it breaks UMD module definition and r.js build tool [as reported in this issue](https://github.com/seiyria/bootstrap-slider/issues/589#issuecomment-232429818). Updated README to address how to stub out optional JQuery dependency for Webpack builds.
7.1.0 - 7.1.1 / 2016-05-26
==================
* **New Feature:** Allow LESS/SASS variables to be overridden, but fall back to defaults if needed. [See here for further details](https://github.com/seiyria/bootstrap-slider/pull/579). Thanks to [Jonathan Rehm
(jkrehm)](https://github.com/jkrehm)
7.0.4 - 7.0.5 / 2016-05-26
==================
* **Bug Fix:** Changes webpack AMD build error on define() for optional jQuery dependency to be a warning, which allows webpack builds to be completed. [See here for further details](https://github.com/seiyria/bootstrap-slider/issues/578). Thanks to [Tomi Saarinen (TomiS)](https://github.com/TomiS)
7.0.2 / 2016-04-05
==================
* **Bug Fix:** Fixes overlap issue with range slider. [See here for further details](https://github.com/seiyria/bootstrap-slider/issues/435). Thanks to [Jerry (jerrylow)](https://github.com/jerrylow)
7.0.0 / 2016-04-05
==================
* **Breaking Change:** Restructured and refactored SASS source files to eliminate compass dependency and be more organized. Thanks to [Jacob van Mourik
(jcbvm)](https://github.com/jcbvm)
6.1.7 / 2016-04-03
==================
* **Bug Fix:** Fixes issue where slider accidently scrolls when user taps on mobile device. Thanks to [Jerry (jerrylow)](https://github.com/jerrylow)
6.1.5 / 2016-03-12
==================
* **Bug Fix:** Call resize() before layout() within relayout() method, which enables intially hidden sliders to be revealed and behave appropriately. Thanks to [Peter (MaZderMind)](https://github.com/MaZderMind)
6.1.3 / 2016-03-07
==================
* **Bug Fix:** Fixed horizontal centering issue with labels. Thanks to [Josh Guffey](https://github.com/jguffey)
6.1.0 / 2016-02-28
==================
* **New Feature:** Auto-registering/intializing slider via `data-provide="slider"` attribute. Thanks to [MaZderMind](https://github.com/MaZderMind)
* Adding Github Templates for Issues, Pull Requests, and Contributions
6.0.16 / 2016-02-04
==================
* **Bug Fix:** Attempted Bug fix from 6.0.11 was refined to ensure so side effects.
6.0.15 / 2016-02-04
==================
* **Bug Fix:** _setText() defaults to `.textContent` vs `.innerHTML`. Thanks to [gio-js](https://github.com/gio-js)
6.0.13 / 2016-01-31
==================
* Reverted Bug fix from prior release
6.0.11 / 2016-01-31
==================
* **Bug fix:** Slider was not scrolling properly when nested inside of scrollable container. Thanks to [serbiant](https://github.com/serbiant)
6.0.9 / 2016-01-26
==================
* **Bug fix:** Race condition in `setValue()` where slider value was being set after `change` and `slide` events were being triggered. Thanks to [glaszig](https://github.com/glaszig)
6.0.7 / 2016-01-22
==================
* **Bug fix:** When `tooltip_position` option is set to `"bottom"` on a slider with multiple split handles, position both tooltips below the slider. Thanks to [Martin Hesslund](https://github.com/kesse)
6.0.5 / 2016-01-20
==================
* bower.json: changing "main" to reference /dist/bootstrap-slider.js
6.0.2 / 2015-12-31
==================
* package.json: changing "main" to point at proper file path
6.0.0 / 2015-12-30
==================
* Moving all source code to `/src` directory
* Transpiling JS with [Babel](https://babeljs.io/)
* Adding `Other Guidelines` section to CONTRIBUTING.MD
* Updating README with Grunt CLI tasks
* Update postpublish script to reference transpiled code
* Freezing dependency versions (this allows us to ensure the module and grunt tasks always have consistent/repeatable behavior)
* Adding an `.nvmrc` file for Node 5.x.x. This version of node comes with NPM 3.x.x, which creates a flat dependency tree for `node_modules`, which basically eliminates the need for bower as our client-side deps management solution
5.3.6 / 2015-12-27
==================
* Restoring bootstrap depedency to bower.json file (Fixes issue with `grunt prod` task)
5.3.4 / 2015-12-27
==================
* **Bug fix:** Ticks now reposition themselves during window resize - Thanks to [Zachary Siswick](https://github.com/zsiswick)
/*global module:false*/
module.exports = function(grunt) {
var packageJSON = grunt.file.readJSON('package.json');
var bumpFiles = ["package.json", "bower.json", "composer.json"];
var commitFiles = bumpFiles.concat(["./dist/*"]);
// Project configuration.
grunt.initConfig({
// Metadata
pkg: packageJSON,
// Task configuration.
header: {
dist: {
options: {
text: "/*! =======================================================\n VERSION <%= pkg.version %> \n========================================================= */"
},
files: {
'<%= pkg.gruntConfig.dist.js %>': '<%= pkg.gruntConfig.temp.js %>',
'<%= pkg.gruntConfig.dist.jsMin %>': '<%= pkg.gruntConfig.temp.jsMin %>',
'<%= pkg.gruntConfig.dist.css %>': '<%= pkg.gruntConfig.temp.css %>',
'<%= pkg.gruntConfig.dist.cssMin %>': '<%= pkg.gruntConfig.temp.cssMin %>'
}
}
},
uglify: {
options: {
preserveComments: 'some'
},
dist: {
src: '<%= pkg.gruntConfig.temp.js %>',
dest: '<%= pkg.gruntConfig.temp.jsMin %>'
}
},
babel: {
options: {
presets: ['es2015']
},
dist: {
src: '<%= pkg.gruntConfig.js.slider %>',
dest: '<%= pkg.gruntConfig.temp.js %>'
}
},
jshint: {
ignore_warning: {
options: {
'-W099': true
},
src: '<%= pkg.gruntConfig.js.slider %>'
},
options: {
esnext: true,
curly: true,
eqeqeq: true,
immed: true,
latedef: false,
newcap: true,
noarg: true,
sub: true,
undef: true,
unused: true,
boss: true,
eqnull: true,
browser: true,
globals: {
$ : true,
Modernizr : true,
console: true,
define: true,
module: true,
require: true
},
"-W099": true
},
gruntfile: {
src: 'Gruntfile.js'
},
js: {
src: '<%= pkg.gruntConfig.js.slider %>'
},
spec : {
src: '<%= pkg.gruntConfig.spec %>',
options : {
globals : {
document: true,
console: false,
Slider: false,
$: false,
jQuery: false,
_: false,
_V_: false,
afterEach: false,
beforeEach: false,
confirm: false,
context: false,
describe: false,
expect: false,
it: false,
jasmine: false,
JSHINT: false,
mostRecentAjaxRequest: false,
qq: false,
runs: false,
spyOn: false,
spyOnEvent: false,
waitsFor: false,
xdescribe: false
}
}
}
},
sasslint: {
options: {
configFile: './.sass-lint.yml',
},
target: ['./src/sass/**/*.scss']
},
lesslint: {
src: ['./src/less/bootstrap-slider.less']
},
jasmine : {
src : '<%= pkg.gruntConfig.temp.js %>',
options : {
specs : '<%= pkg.gruntConfig.spec %>',
vendor : ['<%= pkg.gruntConfig.js.jquery %>', '<%= pkg.gruntConfig.js.bindPolyfill %>'],
styles : ['<%= pkg.gruntConfig.css.bootstrap %>', '<%= pkg.gruntConfig.temp.css %>'],
template : '<%= pkg.gruntConfig.tpl.SpecRunner %>'
}
},
template : {
'generate-index-page' : {
options : {
data : {
js : {
highlightjs: '<%= pkg.gruntConfig.js.highlightjs %>',
modernizr : '<%= pkg.gruntConfig.js.modernizr %>',
jquery : '<%= pkg.gruntConfig.js.jquery %>',
slider : '<%= pkg.gruntConfig.temp.js %>'
},
css : {
highlightjs: '<%= pkg.gruntConfig.css.highlightjs %>',
bootstrap : '<%= pkg.gruntConfig.css.bootstrap %>',
slider : '<%= pkg.gruntConfig.temp.css %>'
}
}
},
files : {
'index.html' : ['<%= pkg.gruntConfig.tpl.index %>']
}
},
'generate-gh-pages' : {
options : {
data : {
js : {
highlightjs: '<%= pkg.gruntConfig.js.highlightjs %>',
modernizr : '<%= pkg.gruntConfig.js.modernizr %>',
jquery : '<%= pkg.gruntConfig.js.jquery %>',
slider : 'js/bootstrap-slider.js'
},
css : {
highlightjs: '<%= pkg.gruntConfig.css.highlightjs %>',
bootstrap : '<%= pkg.gruntConfig.css.bootstrap %>',
slider : 'css/bootstrap-slider.css'
}
}
},
files : {
'index.html' : ['<%= pkg.gruntConfig.tpl.index %>']
}
}
},
watch: {
options: {
livereload: true
},
js: {
files: '<%= pkg.gruntConfig.js.slider %>',
tasks: ['jshint:js', 'babel', 'jasmine']
},
gruntfile: {
files: '<%= jshint.gruntfile %>',
tasks: ['jshint:gruntfile']
},
spec: {
files: '<%= pkg.gruntConfig.spec %>',
tasks: ['jshint:spec', 'jasmine:src']
},
css: {
files: [
'<%= pkg.gruntConfig.less.slider %>',
'<%= pkg.gruntConfig.less.rules %>',
'<%= pkg.gruntConfig.less.variables %>'
],
tasks: ['less:development']
},
index: {
files: '<%= pkg.gruntConfig.tpl.index %>',
tasks: ['template:generate-index-page']
}
},
connect: {
server: {
options: {
port: "<%= pkg.gruntConfig.devPort %>"
}
}
},
open : {
development : {
path: 'http://localhost:<%= connect.server.options.port %>'
}
},
less: {
options: {
paths: ["bower_components/bootstrap/less"]
},
development: {
files: {
'<%= pkg.gruntConfig.temp.css %>': '<%= pkg.gruntConfig.less.slider %>'
}
},
production: {
files: {
'<%= pkg.gruntConfig.temp.css %>': '<%= pkg.gruntConfig.less.slider %>',
}
},
"production-min": {
options: {
yuicompress: true
},
files: {
'<%= pkg.gruntConfig.temp.cssMin %>': '<%= pkg.gruntConfig.less.slider %>'
}
}
},
clean: {
dist: ["dist"],
temp: ["temp"]
},
bump: {
options: {
files: bumpFiles,
updateConfigs: [],
commit: true,
commitMessage: 'Release v%VERSION%',
commitFiles: commitFiles,
createTag: true,
tagName: 'v%VERSION%',
tagMessage: 'Version %VERSION%',
push: false,
pushTo: 'origin'
}
}
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-jasmine');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-open');
grunt.loadNpmTasks('grunt-template');
grunt.loadNpmTasks('grunt-header');
grunt.loadNpmTasks('grunt-bump');
grunt.loadNpmTasks('grunt-babel');
grunt.loadNpmTasks('grunt-sass-lint');
grunt.loadNpmTasks('grunt-lesslint');
// Create custom tasks
grunt.registerTask('append-header', ['header', 'clean:temp']);
grunt.registerTask('lint', [
'jshint',
'lesslint',
'sasslint'
]);
grunt.registerTask('test', [
'babel',
'less:development',
'jasmine',
'clean:temp'
]);
grunt.registerTask('build', [
'less:development',
'test',
'template:generate-index-page'
]);
grunt.registerTask('build-gh-pages', [
'less:development',
'babel',
'template:generate-gh-pages'
]);
grunt.registerTask('dist', [
'clean:dist',
'less:production',
'less:production-min',
'babel',
'uglify',
'append-header'
]);
grunt.registerTask('development', [
'less:development',
'babel',
'template:generate-index-page',
'connect',
'open:development',
'watch'
]);
grunt.registerTask('production', ['dist']);
grunt.registerTask('dev', 'development');
grunt.registerTask('prod', 'production');
grunt.registerTask('default', ['build']);
}; // End of module
This diff is collapsed.
This diff is collapsed.