Related
my element structure looks something like this (simplified):
#Element Holder
#Element Data
#Element Holder
#Element Data
#Element Holder.
#Element Data
#Element Holder
#Element Data
Think of it as something of a file structure, where a File/Folder is equal to #Element Holder and #Element Data is each files/folders style content (icons etc.)
Im trying to move an array of type #ElementData to the Dropzone element, so far Ive tried versions of this:
for(i = 0; i < ElementDataArray.length; i++){
Dropzone.appendChild(ElementDataArray[i].parentNode)
}
but this only works for the first element of the array (other elements stay unchanged).
Im guessing there is something going on in the DOM that Im not aware of, but currently Im just a bit lost
UPDATE
As requested by Barmar here is the stack snippet, Im sorry for this code dump, but the simplified version worked as expected, however I have no clue what went wrong here, the part that gives me headaches is located in the drop event listener
How to reproduce the issue:
run the snippet, CTRL select two or more items of the same type (2+ files or 2+ folders) and drag them into a random folder or the parent directory (gray zone below all the files and folders)
Current Result:
only one item is moved, the other items stay unchanged (moved items higlighted with red)
Expected Result: All the selected items get transferred
var file_manager = document.getElementById('file-manager')
var dragged;
var dropzone = undefined
var items = []
var dataSet = [{
"_id": "60f5b94f7e7e030d80888dd4",
"name": "EEEEE",
"path": [],
"dateCreated": "2021-07-19T17:41:35.290Z",
"isFile": true
},
{
"_id": "60f5e8ac429e454e341534fb",
"name": "pog",
"path": [],
"dateCreated": "2021-07-19T21:03:40.888Z",
"isFile": false
},
{
"_id": "60f5f7aad1b95b51840e98ca",
"name": "poem",
"path": [{
"name": "pog",
"_id": "60f5e8ac429e454e341534fb"
}],
"dateCreated": "2021-07-19T22:07:38.044Z",
"isFile": true
},
{
"_id": "60f8ae19a44c7048306fdd8b",
"name": "New folder",
"path": [],
"dateCreated": "2021-07-21T23:30:33.580Z",
"isFile": false
},
{
"_id": "60f8ae1ba44c7048306fdd8d",
"name": "new",
"path": [{
"name": "New folder",
"_id": "60f8ae19a44c7048306fdd8b"
}],
"dateCreated": "2021-07-21T23:30:35.846Z",
"isFile": false
},
{
"_id": "60f8b4708a065c4f3c068689",
"name": "New file",
"path": [{
"name": "New folder",
"_id": "60f8b4718a065c4f3c06868a"
},
{
"name": "new",
"_id": "60f8ae1ba44c7048306fdd8d"
},
{
"name": "New folder",
"_id": "60f8ae19a44c7048306fdd8b"
}
],
"dateCreated": "2021-07-21T23:57:36.198Z",
"isFile": true
},
{
"_id": "60f8b4718a065c4f3c06868a",
"name": "New folder",
"path": [{
"name": "new",
"_id": "60f8ae1ba44c7048306fdd8d"
},
{
"name": "New folder",
"_id": "60f8ae19a44c7048306fdd8b"
}
],
"dateCreated": "2021-07-21T23:57:37.204Z",
"isFile": false
},
{
"_id": "60f9b4117a7946585c8487ba",
"name": "New file",
"path": [{
"name": "New folder",
"_id": "60f8b4718a065c4f3c06868a"
},
{
"name": "new",
"_id": "60f8ae1ba44c7048306fdd8d"
},
{
"name": "New folder",
"_id": "60f8ae19a44c7048306fdd8b"
}
],
"dateCreated": "2021-07-22T18:08:17.771Z",
"isFile": true
},
{
"_id": "60fa3abc8612930538c4ecb4",
"name": "New folder",
"path": [{
"name": "pog",
"_id": "60f5e8ac429e454e341534fb"
}],
"dateCreated": "2021-07-23T03:42:52.671Z",
"isFile": false
},
{
"_id": "60fa3ac68612930538c4ecb5",
"name": "no",
"path": [],
"dateCreated": "2021-07-23T03:43:02.320Z",
"isFile": false
},
{
"_id": "6100be61171bce035120d603",
"name": "mobile test",
"path": [{
"name": "no",
"_id": "60fa3ac68612930538c4ecb5"
}],
"dateCreated": "2021-07-28T02:18:09.181Z",
"isFile": true
},
{
"_id": "6100be6f171bce035120d604",
"name": "mobile test 2",
"path": [{
"name": "pog",
"_id": "60f5e8ac429e454e341534fb"
}],
"dateCreated": "2021-07-28T02:18:23.676Z",
"isFile": true
},
{
"_id": "6104088123b899c7bd4ff752",
"name": "New folder",
"path": [],
"dateCreated": "2021-07-30T14:11:13.560Z",
"isFile": false
},
]
loadFileManager()
function loadFileManager() {
file_manager.innerHTML = ''
items = []
loop(undefined, 1)
function loop(parentid, depth) {
var tmp = []
dataSet.forEach(item => {
if (item.path.length > 0) { //sub directory
if (parentid) {
if (item.path[0]._id == parentid) {
tmp.push({
item: item,
depth: depth
})
}
}
} else { //main directory
if (parentid == undefined) {
tmp.push({
item: item,
depth: depth
})
}
}
});
var folders = tmp.filter(i => i.item.isFile == false)
var files = tmp.filter(i => i.item.isFile == true)
folders.forEach(f => {
create(f.item, f.depth)
loop(f.item._id, f.depth + 1)
});
files.forEach(f => {
create(f.item, f.depth)
//loop(f.item.id, f.depth + 1)
});
}
}
function create(item, depth) {
var holder = document.createElement('div')
var name = document.createElement('span')
var data = document.createElement('div')
data.style.textIndent = (20 *depth) + 'px'
if (item.isFile) {
data.innerHTML = data.innerHTML + `
<svg class="file-icon-svg" width="13" height="15" viewBox="0 0 77 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M73.5 34.5192V89C73.5 93.1421 70.1421 96.5 66 96.5H11C6.85786 96.5 3.5 93.1421 3.5 89V11C3.5 6.85787 6.85787 3.5 11 3.5H42.751C44.7551 3.5 46.6759 4.30212 48.0848 5.72742L71.3338 29.2466C72.7217 30.6505 73.5 32.5451 73.5 34.5192Z" stroke="#CCCCCC" stroke-width="7"/>
<path d="M42.875 2V36H75.25" stroke="#CCCCCC" stroke-width="7"/>
</svg>
`
} else {
data.innerHTML = data.innerHTML + `
<svg class="arrow-icon-svg" width="10" height="5" viewBox="0 0 56 29" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M55.0248 6.02109L28 28.5L24 23.4976L51 1L55.0248 6.02109Z" fill="#CCCCCC"/>
<path d="M5 1L31.5786 23.6976L28 28.5L0.910334 5.79628L5 1Z" fill="#CCCCCC"/>
</svg>
<svg class="folder-icon-svg" width="15" height="20" viewBox="0 0 98 80" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M94 21.3256V71.9437C94 74.1839 92.189 76 89.9551 76H8.04494C5.81098 76 4 74.1839 4 71.9437V8.05634C4 5.81608 5.81098 4 8.04494 4H39.5183C40.5315 4 41.5079 4.38133 42.2541 5.06854L52.6028 14.5979C54.4686 16.316 56.9094 17.2693 59.4423 17.2693H89.9551C92.189 17.2693 94 19.0853 94 21.3256Z" stroke="#CCCCCC" stroke-width="7"/>
</svg>
`
}
name.innerHTML = item.name
holder.classList.add('file-manager-item', 'noselect', (item.isFile) ? 'file' : 'folder')
holder.id = item._id
data.title = item._id
data.classList.add('file-manager-item-hover')
data.draggable = true
data.onclick = function (e) {
removeClass(file_manager, 'selected-file-manager-item')
data.classList.add('selected-file-manager-item')
var nodeDepth = 0
if(e.ctrlKey){
if(data.classList.contains('ctrl-selected-file-manager-item')){
data.classList.remove('ctrl-selected-file-manager-item')
removeClass(file_manager, 'ctrl-selected-file-manager-item-removed')
data.classList.add('ctrl-selected-file-manager-item-removed')
}
else{
removeClass(file_manager, 'ctrl-selected-file-manager-item-removed')
data.classList.add('ctrl-selected-file-manager-item')
}
}
else{
getDepth(holder)
function getDepth(child) {
if (child != null) {
nodeDepth++
getDepth(child.parentNode)
}
}
nodeDepth = nodeDepth - 6
removeClass(file_manager, 'ctrl-selected-file-manager-item-removed')
removeClass(file_manager, 'ctrl-selected-file-manager-item')
data.classList.add('ctrl-selected-file-manager-item')
if(item.isFile == false) { //folder
var arrow = data.getElementsByClassName('arrow-icon-svg')[0]
var arrowStyle = getComputedStyle(arrow).transform
if (arrowStyle == 'none' || arrow.style.transform == 'rotate(0deg)') { //close folder
arrow.style.transform = 'rotate(-90deg)'
if (holder.children.length > 0) {
for (i = 1; i < holder.children.length; i++) {
holder.children[i].style.display = 'none'
}
}
} else { //open folder
arrow.style.transform = 'rotate(0deg)'
if (holder.children.length > 1) {
for (i = 1; i < holder.children.length; i++) {
holder.children[i].style.display = 'block'
}
}
}
}
}
}
data.ondblclick = function () {
console.log(item.name + ' [' + item._id + ']')
}
data.appendChild(name)
holder.appendChild(data)
if (item.path.length == 0) {
file_manager.appendChild(holder)
} else {
document.getElementById(item.path[0]._id).appendChild(holder)
holder.style.display = 'none'
}
}
file_manager.onclick = function (e) {
if (e.target.id == 'file-manager') {
removeClass(file_manager, 'ctrl-selected-file-manager-item')
removeClass(file_manager, 'selected-file-manager-item')
removeClass(file_manager, 'ctrl-selected-file-manager-item-removed')
}
}
document.body.onclick = function (e) {
if (e.target.nodeName == 'BODY') {
removeClass(file_manager, 'ctrl-selected-file-manager-item')
removeClass(file_manager, 'selected-file-manager-item')
removeClass(file_manager, 'ctrl-selected-file-manager-item-removed')
}
}
function windowItemClick(e) {
for (i = 0; i < windowItems.length; i++) {
windowItems[i].classList.remove('window-header-item-selected')
}
if (e.target.classList.contains('window-header-item-close-button')) {
e.target.parentNode.classList.add('window-header-item-selected')
} else {
e.target.classList.add('window-header-item-selected')
}
}
/* events fired on the draggable target */
document.addEventListener("drag", function (event) {
removeClass(file_manager, 'selected-file-manager-item')
}, false);
document.addEventListener("dragstart", function (event) {
var many = file_manager.getElementsByClassName('ctrl-selected-file-manager-item')
if(many.length > 0){
var includes = false
for(i = 0; i < many.length; i++){
if(many[i] == event.target){
includes = true
break
}
}
if(includes){//CTRL
for (i = 0; i < items.length; i++) {
items[i].children[0].classList.remove('selected-file-manager-item')
}
dragged = many
createCoverup(dragged.length)
}
else{//CTRL -> DRAG
removeClass(file_manager, 'ctrl-selected-file-manager-item')
for (i = 0; i < items.length; i++) {
items[i].children[0].classList.remove('selected-file-manager-item')
}
event.target.classList.add('selected-file-manager-item')
dragged = []
dragged.push(event.target)
createCoverup(dragged[0].children[dragged[0].children.length - 1].innerText)
}
}
else{//DRAG
for (i = 0; i < items.length; i++) {
items[i].children[0].classList.remove('selected-file-manager-item')
}
event.target.classList.add('selected-file-manager-item')
dragged = []
dragged.push(event.target)
createCoverup(dragged[0].children[dragged[0].children.length - 1].innerText)
}
function createCoverup(text){
var coverup = document.createElement('span')
coverup.innerText = text
coverup.classList.add('coverup')
coverup.style.position = "absolute";
coverup.style.top = "0px";
coverup.style.right = "-300px";
document.body.appendChild(coverup);
event.dataTransfer.setDragImage(coverup, -10, -10);
}
}, false);
document.addEventListener("dragend", function (event) {
// reset the transparency
event.target.style.opacity = "";
}, false);
/* events fired on the drop targets */
document.addEventListener("dragover", function (event) {
// prevent default to allow drop
event.preventDefault();
}, false);
document.addEventListener("dragenter", function (e) {
dropzone = undefined
var found = document.elementsFromPoint(e.clientX, e.clientY)
removeClass(document, 'hovered-folder')
removeClass(document, 'hovered-main')
if (found.length > 3) {
for (i = 0; i < found.length; i++) {
if (found[i].classList.contains('folder')) {
var highlight = true
for (x = 0; x < dragged.length; x++) {
if (dragged[x].parentNode.parentNode == found[i] || dragged[x].parentNode == found[i] || dragged[x].parentNode.contains(found[i])) {
highlight = false
break
}
}
if (highlight) {
found[i].classList.add('hovered-folder')
dropzone = found[i]
}
return
}
}
} else if (found[0].id == 'file-manager') {
for (x = 0; x < dragged.length; x++) {
if (dragged[x].parentNode.parentNode.id != 'file-manager') {
found[0].classList.add('hovered-main')
dropzone = found[0]
return
}
}
}
}, false);
document.addEventListener("drop", function (event) {
event.preventDefault();
file_manager.classList.remove('hovered-main')
removeClass(file_manager, 'hovered-folder')
if (dropzone) {
var depth = 0
var path = []
getDepth(dropzone)
function getDepth(child){
if(child != null){
if(child.id){
if(child.id != 'file-manager'){
var v = dataSet.find(data => data._id == child.id)
path.push({"name":v.name, "_id":v._id})
}
}
depth++
getDepth(child.parentNode)
}
}
depth = depth - 4
for(i = 0; i < dragged.length; i++){
var currentDragged = dragged[i].parentNode
if(currentDragged.classList.contains('folder')){
dropzone.insertBefore(currentDragged, dropzone.children[1]);
}
else{
dropzone.appendChild(currentDragged)
}
loop(currentDragged, depth + 1)
function loop(element, currentDepth){
var tmp = []
element.children[0].style.textIndent = (20 * (currentDepth)) + 'px'
element.children[0].style.color = 'red'
for(x = 1; x < element.children.length; x++){
tmp.push(element.children[x])
}
tmp.forEach(t => {
loop(t, currentDepth + 1)
});
}
}
var arrow = dropzone.getElementsByClassName('arrow-icon-svg')[0]
arrow.style.transform = 'rotate(0deg)'
for (x = 1; x < dropzone.children.length; x++) {
dropzone.children[x].style.display = 'block'
}
dropzone = undefined
}
}, false);
function removeClass(element, classname) {
let x = element.getElementsByClassName(classname);
[...x].forEach(x => x.classList.remove(classname));
}
body {
background-color: black;
margin: 0;
overflow-x: hidden;
}
:root {
color-scheme: dark;
}
.noselect {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.hovered-folder .file-manager-item-hover{
background-color: #08574F !important;
}
.hovered-main{
background-color: #08574F !important;
}
/*#region file manager*/
#file-manager{
width: 300px;
max-height: calc(100vh - 520px);
overflow-y: auto;
overflow-x: hidden;
scrollbar-color: #202020 #101010;
scrollbar-width: thin;
padding-bottom: 200px;
background-color: #101010;
}
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #101010;
}
::-webkit-scrollbar-thumb {
background: #202020;
}
::-webkit-scrollbar-thumb:hover {
background: #353535;
}
#file-manager:hover .file-manager-line{
opacity: 1;
}
.file-manager-item{
background-color: #101010;
width: 100%;
font-smooth: always;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 14px;
color: #dfdfdf;
cursor: pointer;
-webkit-tap-highlight-color: transparent;/*disable blue tap highlight*/
}
.selected-file-manager-item{
background-color: #202020;
-webkit-box-shadow: inset 0px 0px 0px 1px #009688;
box-shadow: inset 0px 0px 0px 1px #009688;
}
.file-manager-item-hover{
width: 100%;
height: 20px;
}
.file-manager-item-hover:hover{
background-color: #404040;
}
.file-manager-line{
width: 1px;
height: 20px;
background-color: #333333;
opacity: 0;
transition: .15s;
float: left;
margin-left: 12px;
}
.selected-file-manager-line{
background-color: #585858 !important;
}
.file-icon-svg {
margin-bottom: -2.5px;
}
.file-icon-svg path {
stroke: #dfdfdf;
}
.folder-icon-svg {
margin-bottom: -4px;
margin-left: -1px;
}
.folder-icon-svg path {
stroke: #dfdfdf;
}
.arrow-icon-svg{
transform: rotate(-90deg);
margin-bottom: 3px !important;
margin-left: -12px;
}
.coverup {
width: auto;
height: auto;
z-index: 2;
background-color: #202020 !important;
-webkit-box-shadow: inset 0px 0px 0px 1px #009688;
box-shadow: inset 0px 0px 0px 1px #009688;
color: #dfdfdf;
font-smooth: always;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 14px;
padding-left: 4px;
padding-right: 4px;
}
/*#endregion*/
.ctrl-selected-file-manager-item, .ctrl-selected-file-manager-item:hover{
background-color: #202020;
}
.ctrl-selected-file-manager-item-removed, .ctrl-selected-file-manager-item-removed:hover{
background-color: #070707;
}
.test{
background-color: red !important;
}
<!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">
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="/window.css">
<title>Document</title>
</head>
<body>
<div id="file-manager"></div>
<div id="coverup"></div>
<script src="/script.js"></script>
</body>
</html>
I was trying to add two legends containers for the same graph(sunburst drill-down). one on the left side and another on the right side of the graph.
After lots of research, I found the solution but it was for piechart not for sunburst drill down. I want the same solution for sunburst drill down.
Below is the Image of the solution which I found.
enter image description here
code for above image:
Js, CSS, HTML
/**
* ---------------------------------------
* This demo was created using amCharts 4.
*
* For more information visit:
* https://www.amcharts.com/
*
* Documentation is available at:
* https://www.amcharts.com/docs/v4/
* ---------------------------------------
*/
am4core.useTheme(am4themes_animated);
// Create chart instance
var chart = am4core.create("chartdiv", am4charts.PieChart);
// Add data
chart.data =
[{
"country": "Lithuania",
"litres": 501.9
}, {
"country": "Czechia",
"litres": 301.9
}, {
"country": "Ireland",
"litres": 201.1
}, {
"country": "Germany",
"litres": 165.8
}, {
"country": "Australia",
"litres": 139.9
}, {
"country": "Austria",
"litres": 128.3
}, {
"country": "UK",
"litres": 99
}, {
"country": "Belgium",
"litres": 60
}, {
"country": "The Netherlands",
"litres": 50
}];
// Add and configure Series
var pieSeries = chart.series.push(new am4charts.PieSeries());
pieSeries.dataFields.value = "litres";
pieSeries.dataFields.category = "country";
pieSeries.labels.template.disabled = true;
radius = am4core.percent(95);
chart.legend = new am4charts.Legend();
chart.legend.position = "left";
chart.legend.scrollable = true;
// Create custom legend
chart.events.on("ready", function(event) {
// populate our custom legend when chart renders
chart.customLegend = document.getElementById('legend');
pieSeries.dataItems.each(function(row, i) {
var color = chart.colors.getIndex(i);
var percent = Math.round(row.values.value.percent * 100) / 100;
var value = row.value;
legend.innerHTML += '<div class="legend-item" id="legend-item-' + i + '" onclick="toggleSlice(' + i + ');" onmouseover="hoverSlice(' + i + ');" onmouseout="blurSlice(' + i + ');" style="color: ' + color + ';"><div class="legend-marker" style="background: ' + color + '"></div>' + row.category + '<div class="legend-value">' + value + ' | ' + percent + '%</div></div>';
});
});
function toggleSlice(item) {
var slice = pieSeries.dataItems.getIndex(item);
if (slice.visible) {
slice.hide();
}
else {
slice.show();
}
}
function hoverSlice(item) {
var slice = pieSeries.slices.getIndex(item);
slice.isHover = true;
}
function blurSlice(item) {
var slice = pieSeries.slices.getIndex(item);
slice.isHover = false;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
#chartdiv {
width: 530px;
height: 450px;
font-size: 11px;
border: 1px solid #eee;
float: left;
}
#legend {
width: 200px;
height: 450px;
border: 1px solid #eee;
margin-left: 10px;
float: left;
}
#legend .legend-item {
margin: 10px;
font-size: 15px;
font-weight: bold;
cursor: pointer;
}
#legend .legend-item .legend-value {
font-size: 12px;
font-weight: normal;
margin-left: 22px;
}
#legend .legend-item .legend-marker {
display: inline-block;
width: 12px;
height: 12px;
border: 1px solid #ccc;
margin-right: 10px;
}
#legend .legend-item.disabled .legend-marker {
opacity: 0.5;
background: #ddd;
}
<script src="https://cdn.amcharts.com/lib/4/core.js"></script>
<script src="https://cdn.amcharts.com/lib/4/charts.js"></script>
<script src="https://cdn.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>
<div id="legend"></div>
I tried to solve my problem with the above solution but it didn't work.
Below are the details for my changes :
enter image description here
/**
* ---------------------------------------
* This demo was created using amCharts 4.
*
* For more information visit:
* https://www.amcharts.com/
*
* Documentation is available at:
* https://www.amcharts.com/docs/v4/
* ---------------------------------------
*/
// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
// create chart
var chart = am4core.create("chartdiv", am4plugins_sunburst.Sunburst);
chart.padding(0, 0, 0, 0);
chart.radius = am4core.percent(98);
data1 = [{
name: "First",
children: [
{ name: "A1", value: 100 },
{ name: "A2", value: 60 }
]
},
{
name: "Second",
children: [
{ name: "B1", value: 135 },
{ name: "B2", value: 98 }
]
},
{
name: "Third",
children: [
{
name: "C1",
children: [
{ name: "EE1", value: 130 },
{ name: "EE2", value: 87 },
{ name: "EE3", value: 55 }
]
},
{ name: "C2", value: 148 },
{
name: "C3", children: [
{ name: "CC1", value: 53 },
{ name: "CC2", value: 30 }
]
},
{ name: "C4", value: 26 }
]
},
{
name: "Fourth",
children: [
{ name: "D1", value: 415 },
{ name: "D2", value: 148 },
{ name: "D3", value: 89 }
]
},
{
name: "Fifth",
children: [
{
name: "E1",
children: [
{ name: "EE1", value: 33 },
{ name: "EE2", value: 40 },
{ name: "EE3", value: 89 }
]
},
{
name: "E2",
value: 148
}
]
}];
let dt1 = [];
for(var i=0;i<data1.length;i++){
dt1[i] = {"name":data1[i].name,"fill":"#72A6B2"};
}
chart.data = data1;
chart.colors.step = 2;
chart.fontSize = 11;
chart.innerRadius = am4core.percent(20);
// define data fields
chart.dataFields.value = "value";
chart.dataFields.name = "name";
chart.dataFields.children = "children";
var level0SeriesTemplate = new am4plugins_sunburst.SunburstSeries();
chart.seriesTemplates.setKey("0", level0SeriesTemplate)
// this makes labels to be hidden if they don't fit
level0SeriesTemplate.labels.template.truncate = true;
level0SeriesTemplate.labels.template.hideOversized = true;
level0SeriesTemplate.showOnInit = false;
level0SeriesTemplate.usePercentHack = false;
level0SeriesTemplate.radius = am4core.percent(100);
level0SeriesTemplate.innerRadius = am4core.percent(0);
let selectedState = level0SeriesTemplate.states.create("selected");
selectedState.properties.opacity = 0.7;
level0SeriesTemplate.defaultState.properties.radius = am4core.percent(100);
var currentlySelected;
level0SeriesTemplate.slices.template.events.on("over", function(event) {
if(event.target.dataItem.sunburstDataItem.children){
event.target.cursorOverStyle = am4core.MouseCursorStyle.pointer;
}
})
level0SeriesTemplate.slices.template.events.on("hit", function(event) {
zoomOutButton.show();
var hitSlice = event.target;
if (hitSlice.dataItem.sunburstDataItem.children) {
var series = event.target.dataItem.component;
if (!series.dummyData) {
series.tooltip.disabled = true;
hitSlice.dataItem.label.radius = (hitSlice.radius - hitSlice.pixelInnerRadius) - 7;
hitSlice.dataItem.label.bent = true;
hitSlice.dataItem.label.rotation = -180;
currentlySelected = hitSlice;
series.dummyData = true;
series.setState("selected");
hitSlice.dataItem.sunburstDataItem.series.show();
series.slices.each(function(slice) {
if (slice != event.target) {
slice.dataItem.hide();
}
})
}
else {
drillUp(hitSlice);
}
}
})
level0SeriesTemplate.labels.template.adapter.add("rotation", function(rotation, target) {
target.maxWidth = target.dataItem.slice.radius - target.dataItem.slice.innerRadius - 10;
target.maxHeight = Math.abs(target.dataItem.slice.arc * (target.dataItem.slice.innerRadius + target.dataItem.slice.radius) / 2 * am4core.math.RADIANS);
return rotation;
})
var level1SeriesTemplate = level0SeriesTemplate.clone();
level1SeriesTemplate.hidden = true;
level1SeriesTemplate.innerRadius = am4core.percent(10);
chart.seriesTemplates.setKey("1", level1SeriesTemplate)
level1SeriesTemplate.fillOpacity = 0.75;
var level2SeriesTemplate = level0SeriesTemplate.clone();
level2SeriesTemplate.hidden = true;
level2SeriesTemplate.innerRadius = am4core.percent(20);
chart.seriesTemplates.setKey("2", level2SeriesTemplate)
level0SeriesTemplate.hiddenInLegend = false;
level1SeriesTemplate.hiddenInLegend = true;
level2SeriesTemplate.hiddenInLegend = true;
var zoomOutButton = chart.seriesContainer.createChild(am4core.ZoomOutButton);
zoomOutButton.visible = false;
zoomOutButton.horizontalCenter = "middle";
zoomOutButton.verticalCenter = "middle";
zoomOutButton.events.on("hit", function() {
drillUp(currentlySelected)
})
function drillUp(slice) {
collapse(slice);
var series = slice.dataItem.component;
series.tooltip.disabled = false;
series.dummyData = false;
series.setState("default");
series.slices.each(function(slice) {
if (slice != event.target) {
slice.dataItem.show();
}
})
if (series.parentDataItem.seriesDataItem) {
currentlySelected = series.parentDataItem.seriesDataItem.slice;
}
else {
zoomOutButton.hide();
}
}
function collapse(slice) {
slice.dataItem.label.bent = false;
slice.dataItem.label.radius = 10;
if (slice.dataItem.sunburstDataItem.children) {
slice.dataItem.sunburstDataItem.children.each(function(child) {
child.seriesDataItem.component.setState("hidden");
collapse(child.seriesDataItem.slice);
})
}
}
/* var legend = new am4charts.Legend();
legend.position = "right";
legend.scrollable = true;
legend.parent = chart.chartContainer;
legend.background.fill = am4core.color("#000");
legend.background.fillOpacity = 0.05;
legend.width = 120;
legend.align = "right";
legend.data = dt1; */
/*
[{
"name": "2016",
"fill":"#72A6B2"
}, {
"name": "2017",
"fill": "#667E93"
}, {
"name": "2018",
"fill": "#488BB2"
}];*/
chart.legend = new am4charts.Legend();
//chart.legend.parent = chart.chartContainer;
//chart.legend.itemContainers.template.togglable = true;
chart.legend.position = "left";
chart.legend.scrollable = true;
// Create custom legend
chart.events.on("ready", function(event) {
// populate our custom legend when chart renders
chart.customLegend = document.getElementById('legend');
/* level0SeriesTemplate.slices.dataItems.each(function(row, i) { */
level0SeriesTemplate.dataItems.each(function(row, i) {
var color = chart.colors.getIndex(i);
var percent = Math.round(row.values.value.percent * 100) / 100;
var value = row.value;
legend.innerHTML += '<div class="legend-item" id="legend-item-' + i + '" onclick="toggleSlice(' + i + ');" onmouseover="hoverSlice(' + i + ');" onmouseout="blurSlice(' + i + ');" style="color: ' + color + ';"><div class="legend-marker" style="background: ' + color + '"></div>' + row.name + '<div class="legend-value">' + value + ' | ' + percent + '%</div></div>';
});
});
function toggleSlice(item) {
var slice = level0SeriesTemplate.dataItems.getIndex(item);
if (slice.visible) {
slice.hide();
}
else {
slice.show();
}
}
function hoverSlice(item) {
var slice = level0SeriesTemplate.slices.getIndex(item);
slice.isHover = true;
}
function blurSlice(item) {
var slice = level0SeriesTemplate.slices.getIndex(item);
slice.isHover = false;
}
/* var legendContainer = am4core.create("legend", am4core.Container);
legendContainer.width = am4core.percent(100);
legendContainer.height = am4core.percent(100);
legend = new am4charts.Legend();
legend.parent = legendContainer;
legend.position = "middle";
legend.valign = "middle";
legend.data = dt1;
legend.scrollable = true;
let Label1 = legendContainer.createChild(am4core.Label);
//Label1.height = 50;
Label1.fontWeight = "600";
Label1.align = "left";
Label1.paddingTop = 6;
Label1.paddingBottom = 6;
Label1.text = "Non-Reco Analytics"; */
/*
chart.legend.data = [{
"name": "2016",
"fill":"#72A6B2"
}, {
"name": "2017",
"fill": "#667E93"
}, {
"name": "2018",
"fill": "#488BB2"
}]; */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
#chartdiv {
width: 530px;
height: 450px;
font-size: 11px;
border: 1px solid #eee;
float: left;
}
#legend {
width: 200px;
height: 450px;
border: 1px solid #eee;
margin-left: 10px;
float: left;
}
#legend .legend-item {
margin: 10px;
font-size: 15px;
font-weight: bold;
cursor: pointer;
}
#legend .legend-item .legend-value {
font-size: 12px;
font-weight: normal;
margin-left: 22px;
}
#legend .legend-item .legend-marker {
display: inline-block;
width: 12px;
height: 12px;
border: 1px solid #ccc;
margin-right: 10px;
}
#legend .legend-item.disabled .legend-marker {
opacity: 0.5;
background: #ddd;
}
<script src="https://cdn.amcharts.com/lib/4/core.js"></script>
<script src="https://cdn.amcharts.com/lib/4/charts.js"></script>
<script src="https://cdn.amcharts.com/lib/4/plugins/sunburst.js"></script>
<script src="https://cdn.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>
<div id="legend"></div>
objective: I want legends for the 1st layer of the sunburst on the right side and the 2nd layer on the left side of the chart.
I hope you get enough understanding of my problem.
I am new to programming I am working on dynamic organization hierarchy chart using GetOrgChart. I want to remove hard code values in java script function and pass my mysql query result data in to javascript function i have get data from database through query and converted it in to json format to display in javascript function.
Here is my code :
<?php
require ('db.php');
$selectSql = "SELECT
emp.id, emp.employee_parent_id, emp.emp_name,
emp.email,hd.desg_name
FROM
hr_employees emp
LEFT JOIN
hr_employees_designations empd ON emp.id = empd.id
LEFT JOIN
hr_designations hd ON empd.id = hd.id";
$result = mysqli_query($conn, $selectSql);
$arrAssociate = [];
while ($value = mysqli_fetch_assoc($result))
{
$json_array = json_encode($value);
echo $json_array;
//echo '<pre>', print_r($value, 1) , '</pre>';
}
?>
<!DOCTYPE html>
<html>
<head>
<title>OrgChart | Create Your Own Theme 3</title>
<style type="text/css">
html, body {
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
overflow: hidden;
}
#people {
width: 100%;
height: 100%;
}
.get-org-chart rect.get-box {
fill: #ffffff;
stroke: #D9D9D9;
}
.get-org-chart .get-text.get-text-0 {
fill: #262626;
}
.get-org-chart .get-text.get-text-1 {
fill: #262626;
}
.get-org-chart .get-text.get-text-2 {
fill: #788687;
}
.get-green.get-org-chart {
background-color: #f2f2f2;
}
.more-info {
fill: #18879B;
}
.btn path {
fill: #F8F8F8;
stroke: #D9D9D9;
}
.btn {
cursor: pointer;
}
.btn circle {
fill: #555555;
}
.btn line {
stroke-width: 3px;
stroke: #ffffff;
}
</style>
</head>
<body>
<div id="people"></div>
<script type="text/javascript">
getOrgChart.themes.myTheme =
{
size: [330, 260],
toolbarHeight: 46,
textPoints: [
{ x: 20, y: 45, width: 300 },
{ x: 120, y: 100, width: 200 },
{ x: 120, y: 125, width: 200 }
],
// textPointsNoImage: [] NOT IMPLEMENTED,
box: '<rect x="0" y="0" height="260" width="330" rx="10" ry="10"
class="get-box"></rect>'
+ '
<g transform="matrix(0.25,0,0,0.25,123,142)"><path
d="M48.014,42.889l-9.553-
4.776C37.56,37.662,37,36.756,37,35.748v-3.381c0.229-0.28,0.47-
0.599,0.719-0.951 c1.239-1.75,2.232-3.698,2.954-
5.799C42.084,24.97,43,23.575,43,22v-4c0-0.963-0.36-1.896-1-
2.625v-5.319 c0.056-0.55,0.276-3.824-2.092-
6.525C37.854,1.188,34.521,0,30,0s-7.854,1.188-
9.908,3.53C17.724,6.231,17.944,9.506,18,10.056 v5.319c-
0.64,0.729-1,1.662-
};
var orgChart = new getOrgChart(document.getElementById("people"), {
theme: "myTheme",
enableEdit: false,
enableDetailsView: false,
primaryFields: ["Title", "Name", "Email", "Image"],
color: "green",
updatedEvent: function () {
init();
},
dataSource: [
// Want Dynamic data here instead of this hard code values
{ id : 1,
parentId : null,
Name : "Jasper Lepardo",
Title : "CEO",
Email : "jasper#example.com",
Image :
"http://www.getorgchart.com/GetOrgChart/getorgchart-
demos/images/f-11.jpg"
},
{ id : 2,
parentId : 1,
Name : "John Smith",
Title : "Front-endDeveloper",
Email : "john#example.com",
Image :
"http://www.getorgchart.com/GetOrgChart/getorgchart
demos/images/f-12.jpg"
},
{ id : 3,
parentId : 1,
Name : "Avaa Field",
Title : "Project Manager",
Email : "ava#example.com",
Image :
"http://www.getorgchart.com/GetOrgChart/getorgchart-demos/images/f-
14.jpg"
},
{ id : 4,
parentId : 1,
Name : "Ava Field",
Title : "Project Manager",
Email : "ava#example.com",
Image :
"http://www.getorgchart.com/GetOrgChart/getorgchart-demos/images/f-
14.jpg" }]
});
function getNodeByClickedBtn(el) {
while (el.parentNode) {
el = el.parentNode;
if (el.getAttribute("data-node-id"))
return el;
}
return null;
}
var init = function () {
var btns = document.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function () {
var nodeElement = getNodeByClickedBtn(this);
var action = this.getAttribute("data-action");
var id = nodeElement.getAttribute("data-node-id");
var node = orgChart.nodes[id];
switch (action) {
case "add":
orgChart.insertNode(id);
break;
case "edit":
orgChart.showEditView(id);
break;
case "preview":
orgChart.showDetailsView(id);
break;
}
});
}
}
init();
</script>
</body>
</html>
Look at this.
Using Laravel (Blade):
let json = JSON.parse('#json($your_array_here)');
No Framework (your case):
let json = JSON.parse('<?=json_encode($your_array_here)?>');
When you have an Array in PHP and need to use it in JS, you have two ways to implement:
Ajax (fetch, axios, xhr2);
Hard coding like you did.
But pay attention to you browser Console (Chrome, Firefox), you will be warned if your JSON is malformatted.
Take a look at JSON.parse and JSON.stringify, it is important to understand this functions too.
And don't forget the ' in the beginning and at the end of the declaration, like I did in the example below.
Hope it helps you.
Have a nice day.
I've been continuing my work on a drag and drop page that will parse and display the json data.
I was able to parse the .json file and showed it in console but at the end there is an error showing up (Please refer on the screenshot below). Did I miss anything from my code? Thank you in advance!
JSFiddle : https://jsfiddle.net/vy19a7sf/2/
(function() {
var dropzone = document.getElementById("dropzone");
dropzone.ondrop = function(event) {
event.preventDefault();
this.className = "dropzone";
console.log(event.dataTransfer.files[0]);
var fileInput = document.getElementById("dropzone");
var fileDisplayArea = document.getElementById("displayarea");
var file = event.dataTransfer.files[0]
var textType = "";
if (file.type.match(textType)) {
var reader = new FileReader();
reader.onload = function(read) {
// fileDisplayArea.innerText = reader.result;
var json = reader.result;
for(var num = 0; num < json.length; num++) {
obj = JSON.parse(json);
// console.log(obj["value"][num]);
console.log(obj["value"][num]["changesetId"]);
console.log(obj["value"][num]["author"]["displayName"]);
console.log(obj["value"][num]["createdDate"]);
console.log(obj["value"][num]["comment"]);
}
}
reader.readAsText(file);
}
else {
// fileDisplayArea.innerText = "File not supported!";
console.log("File not supported!")
}
}
dropzone.ondragover = function() {
this.className = "dropzone dragover";
return false;
};
dropzone.ondragleave = function() {
this.className = "dropzone";
return false;
};
}())
.dropzone {
display: flex;
line-height: 300px;
justify-content: center;
border: 2px dashed #ccc;
color: #ccc;
}
.dropzone.dragover {
border-color: #000;
color: #000;
}
.displayarea {
height: 200px;
width: 100%;
color: #000;
padding: 20px;
background-color: #e7e7e7;
overflow-x: auto;
}
<!DOCTYPE html>
<html lang="en">
<head>
<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://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css" />
<link rel="stylesheet" href="/css/styles.css" />
<link rel="stylesheet" href="/changesets/css/styles.css" />
<title>Code Metrics Tool</title>
</head>
<body>
<header>
<div>
Code Metrics Tool
</div>
</header>
<main>
<h2>Changesets</h2>
<div class="dropzone" id="dropzone">Drop .json files here to convert</div>
</main>
<footer>
</footer>
<script src="/changesets/js/dragdrop.js"></script>
</body>
</html>
SCREENSHOT Console log was successfully printed, but at the end there is an error showing up
JSON File
{
"count": 2,
"value": [
{
"changesetId": 1456,
"url": "https://.../changesets/1456",
"author": {
"displayName": "--",
"url": "https://.../0e79980d-2df8-47b2-9aa3-4a7a118f1c90",
"id": "0e79980d-2df8-47b2-9aa3-4a7a118f1c90",
"uniqueName": "--",
"imageUrl": "https://.../identityImage?id=0e79980d-2df8-47b2-9aa3-4a7a118f1c90"
},
"checkedInBy": {
"displayName": "--",
"url": "https://.../0e79980d-2df8-47b2-9aa3-4a7a118f1c90",
"id": "0e79980d-2df8-47b2-9aa3-4a7a118f1c90",
"uniqueName": "--",
"imageUrl": "https://.../identityImage?id=0e79980d-2df8-47b2-9aa3-4a7a118f1c90"
},
"createdDate": "2018-02-28T11:20:36.52Z",
"comment": "fixed problems",
"commentTruncated": true
},
{
"changesetId": 1451,
"url": "https://.../changesets/1451",
"author": {
"displayName": "--",
"url": "https://.../f62e6531-cb28-6ebb-bb5c-1663549c6165",
"id": "f62e6531-cb28-6ebb-bb5c-1663549c6165",
"uniqueName": "--",
"imageUrl": "https://.../identityImage?id=f62e6531-cb28-6ebb-bb5c-1663549c6165"
},
"checkedInBy": {
"displayName": "--",
"url": "https://.../f62e6531-cb28-6ebb-bb5c-1663549c6165",
"id": "f62e6531-cb28-6ebb-bb5c-1663549c6165",
"uniqueName": "--",
"imageUrl": "https:///identityImage?id=f62e6531-cb28-6ebb-bb5c-1663549c6165"
},
"createdDate": "2018-02-26T11:47:42.233Z",
"comment": "Added an item",
"commentTruncated": true
}
]
}
As Patrick Evans commented, json.length is not the length of the array in "value".
You also don't want to use obj = JSON.parse(json) inside that loop, you only need to parse it once.
To solve this issue you described, you need to get the actual ids inside the "value" array.
let valueArray = obj.value;
valueArray.forEach(function(vel){
console.log(vel.changesetId);
console.log(vel.author);
//etc..
});
Down below, there's two pieces of codes. For infinite scroll & search system. Everything works, but the problem with the search system is that, if I search something, then it messes up positioning of the cards or boxes. They should be on one line, if you search them, but those a bit up etc.. I also have added an picture about that. 2nd problem is that, I have an Infinite scroll on my site, but I think I would have to change the search system to search from JSON Data, so it would work correctly? By that I mean, You type something into search, click enter then it searches matches from the JSON and then shows them in that container. I hope I was clear enough about my problem and I hope someone can help me out to solve it :). Thanks to everyone! :)
Here's some CSS as well:
main.css - http://pastebin.com/Tgds0kuJ
zmd-hierarchical-display - http://pastebin.com/Fn5JBpaQ
Materialize - http://pastebin.com/ZxSGZtc8
Here's picture of normal piece: http://prntscr.com/b3yrwa
Here's picture if I search them: http://prntscr.com/b3yrub
Here's the infinite scroll & cards
var perPage = 50;
function paginate(items, page) {
var start = perPage * page;
return items.slice(start, start + perPage);
}
var condition = '';
function renderItems(pageItems) {
pageItems.forEach(function(item, index, arr) {
var message = 'BitSkins Price: $' + Math.round(item.bprice) + '';
if (item.price !== null) {
if (item.bprice === '') {
message = 'Item never sold on BitSkins!';
}
if (item.name != 'Operation Phoenix Case Key' && item.name != 'CS:GO Case Key' && item.name != 'Winter Offensive Case Key' && item.name != 'Revolver Case Key' && item.name != 'Operation Vanguard Case Key' && item.name != 'Operation Wildfire Case Key' && item.name != 'Shadow Case Key' && item.name != 'Operation Breakout Case Key' && item.name != 'Chroma Case Key' && item.name != 'Huntsman Case Key' && item.name != 'Falchion Case Key' && item.name != 'Chroma 2 Case Key') {
$("#inventory").html($("#inventory").html() + "<li class='col 2 zoomIn animated' style='padding:8px;font-weight:bold;font-size:13.5px'><div class='card item-card waves-effect waves-light' style='margin:0%;min-height:295px;width:245.438px;border-radius: 0px;height: 295px;box-shadow: inset 0px 0px 25px 2px #232323;border: 1px solid black' id='" + item.id + "'><div class='iteam' style='text-decoration: underline;text-align: left;font-size: 14.5px;color: #E8E8E8;font-family: Roboto;position: relative;right: -3px;'>" + item.name + "</div><div class='condition' style='text-align: left;color: #E8E8E8;font-family: Roboto;position: relative;left: 3px;'>" + item.condition + "</div><div class='center-align' style='position: relative;padding:0%;top: -33px;'><img title=\"" + item.originalname + "\" draggable='false' src='https://steamcommunity-a.akamaihd.net/economy/image/" + item.iconurl + "/235fx235f'></div><div class='secondarea' style='position: relative;top: -129px;background: rgba(0, 0, 0,0.15);display: block;height: 163px;'><div class='buyer-price center-align' style='font-size:22.5px;font-family: Arial Black;color:#E8E8E8'>$" + Math.round(item.price) + "<div class='bitskinscomp' style='font-weight: normal;font-size:12px;font-family: Roboto;font: bold;'>" + message + "</div></div><a class='btn waves-effect waves-light' style='position:relative;left:-5px;top:50px' href='" + item.inspect + "' target='_blank'>Inspect</a><a class='btn waves-effect waves-light' style='position:relative;right:-5px;top:50px' id='purchaseButton'>Cart</a></div></li>");
}
}
});
}
var win = $(window);
var page = 0;
renderItems(paginate(items, page));
win.scroll(function() {
if ($(document).height() - win.height() == win.scrollTop()) {
page++;
renderItems(paginate(items, page));
}
});
JavaScript search system
$('#SearchItemsFromList').keyup(function() {
var valThis = $(this).val().toLowerCase();
if (valThis === "") {
$('#inventory > li > div').show();
} else {
$('#inventory > li > div').each(function() {
var text = $(this).text().toLowerCase();
(text.indexOf(valThis) >= 0) ? $(this).show(): $(this).hide();
});
}
});
Overview
First off, I have no visibility to the
...messes up positioning of the cards or boxes...
since I do not know what your CSS consists of so I simply made some guesses on that. I suspect it may be due to the actual rendering of your items somehow. To assist in this I removed all the CSS from the injected markup as injecting those "style" attributes is not best practice and frankly difficult to debug as you seem to have experienced. I made an attempt but you will need to adjust the CSS I have provided as it simply does not have all yours in it.
To assist with this, I simply did a "replace" with the current page rather than append each time and then face the challenge of end of scroll/start and deal with the search disruption of that.
I removed the injection of duplicate id on the button and instead used a class injection instead. This will resolve the issue of the invalid HTML which would cause unexpected results at some point that would be very difficult to debug.
The more difficult issue is the dynamic nature of your items array when searching the on-page object list. This I have addressed by creation of a "view candidate list called currentSearch which I have taken the liberty of adding to a name called myApp.data as myApp.data.currentSearch.
Speaking of the namespace, I did that to avoid multiple global objects. I also did that with my custom functions as a best practice.
Here is my sample markup that I used:
<div id="search">
<input id="SearchItemsFromList" type="text" />
</div>
<ul id="inventory">
</ul>
CSS
Here is the CSS which in great part was extracted from the style properties. I took the liberty of naming them poorly as first-style-thing class, second-style-thing etc. which simply coordinate to the injected sequence of elements. This has the additional benefit of reducing the injection string size as well.
.li-style-thing {
padding: 8px;
font-weight: bold;
font-size: 13.5px;
}
.first-style-thing {
margin: 0%;
min-height: 295px;
width: 245.438px;
border-radius: 0px;
height: 295px;
box-shadow: inset 0px 0px 25px 2px #232323;
border: 1px solid black;
}
.second-style-thing {
text-decoration: underline;
text-align: left;
font-size: 14.5px;
color: #E8E8E8;
font-family: Roboto;
position: relative;
right: -3px;
}
.third-style-thing {
text-align: left;
color: #E8E8E8;
font-family: Roboto;
position: relative;
left: 3px;
}
.fourth-style-thing {
position: relative;
padding: 0%;
top: -33px;
}
.fifth-style-thing {
position: relative;
top: -129px;
background: rgba(0, 0, 0, 0.15);
display: block;
height: 163px;
}
.sixth-style-thing {
font-size: 22.5px;
font-family: Arial Black;
color: #E8E8E8;
}
.seventh-style-thing {
font-weight: normal;
font-size: 12px;
font-family: Roboto;
font: bold;
}
.eighth-style-thing {
position: relative;
left: -5px;
top: 50px;
}
.ninth-style-thing {
position: relative;
right: -5px;
top: 50px;
}
.btn {
position: relative;
display: block;
height: 1.5em;
width: 5em;
color: cyan;
background-color: blue;
font-weight: bold;
text-align: center;
padding-top: 0.5em;
margin: 1em;
text-decoration: none;
text-transform: uppercase;
}
#inventory {
display: block;
position: relative;
top: 1em;
left: 0em;
border: solid lime 1px;
}
#inventory li {
background-color: #888888;
}
#inventory li {
display: inline-block;
float: left;
}
.purchaseButton {
right: -8em;
top: 0;
}
#search {
height: 4em;
width: 100%;
background-color: #00aaaa;
padding: 1em;
}
Code:
About the code, note the items object which I simply made from reverse engineering your injection code and likely needs adjusted to your exact object properties.
Note the debounce function which addresses an issue where you might fire the scroll/mouse wheel events too often. I added a "throttle" which you might use instead, borrowed from here: https://remysharp.com/2010/07/21/throttling-function-calls Speaking of, I added the "wheel" event to the "scroll" event so that if you are at the top/bottom of the scroll the mouse wheel can also fire the scroll when no scroll actually occurs. I did not address other possible challenges such as the down/up arrow when the scroll is at the top/bottom; I will leave that up to you to address based upon your needs.
Note that upon a "search" event when typing, I reset the currentSearch list.
I left some console.log in place which you can remove - but allows you to see the page and some event fire logging.
Here is a sample so you can try this all out https://jsfiddle.net/MarkSchultheiss/hgfhh2y7/3/
var myApp = myApp || {};
myApp.data = {
currentSearch: [],
pageStart: 0,
pageEnd: 0,ma
perPage: 3,
page: 0,
lastScroll: 0,
scrollDelay: 250,
outputContainer: $('#inventory'),
excludes: ['Operation Phoenix Case Key', 'CS:GO Case Key', 'Winter Offensive Case Key', 'Revolver Case Key', 'Operation Vanguard Case Key', 'Operation Wildfire Case Key', 'Shadow Case Key', 'Operation Breakout Case Key', 'Chroma Case Key', 'Huntsman Case Key', 'Falchion Case Key', 'Chroma 2 Case Key']
};
myApp.func = {
contains: function(myArray, searchTerm, property) {
var found = [];
var len = myArray.length;
for (var i = 0; i < len; i++) {
if (myArray[i][property].toLowerCase().indexOf(searchTerm.toLowerCase()) > -1) found.push(myArray[i]);
}
return found;
},
paginate: function(items) {
myApp.data.pageStart = myApp.data.perPage * myApp.data.page;
myApp.data.pageEnd = myApp.data.pageStart + myApp.data.perPage;
if (myApp.data.pageEnd > items.length) {
myApp.data.pageEnd = items.length;
myApp.data.pageStart = myApp.data.pageEnd - myApp.data.perPage >= 0 ? myApp.data.pageEnd - myApp.data.perPage : 0;
}
console.log("Page:" + myApp.data.page + " Start:" + myApp.data.pageStart + " End:" + myApp.data.pageEnd + " max:" + items.length);
return items;
},
debounce: function(fn, delay) {
var timer = null;
return function() {
var context = this,
args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
};
},
throttle: function(fn, threshhold, scope) {
threshhold || (threshhold = 250);
var last,
deferTimer;
return function() {
var context = scope || this;
var now = +new Date,
args = arguments;
if (last && now < last + threshhold) {
// hold on to it
clearTimeout(deferTimer);
deferTimer = setTimeout(function() {
last = now;
fn.apply(context, args);
}, threshhold);
} else {
last = now;
fn.apply(context, args);
}
}
},
renderItems: function(pageItems) {
// $("#inventory").html("");
console.log('renderStart Items:' + pageItems.length);
console.log(myApp.data.pageStart + ":" + myApp.data.pageEnd);
var renderList = pageItems.filter(function(itemValue) {
return !!(myApp.data.excludes.indexOf(itemValue) == -1)
}).slice(myApp.data.pageStart, myApp.data.pageEnd);
console.log(renderList);
var newContent = "";
renderList.forEach(function(item, index, arr) {
var message = 'BitSkins Price: $' + Math.round((item.bprice * 1));
if (item && item.price !== null) {
if (item.bprice === '') {
message = 'Item never sold on BitSkins!';
}
if (myApp.data.excludes.indexOf(item.name) == -1) {
newContent += "<li class='col 2 zoomIn animated'><div class='card item-card waves-effect waves-light first-style-thing' id='" + item.id + "'><div class='iteam second-style-thing' >" + item.name + "</div><div class='condition third-style-thing'>" + item.condition + "</div><div class='center-align fourth-style-thing' ><img title='" + item.originalname + "' draggable='false' src='https://steamcommunity-a.akamaihd.net/economy/image/" + item.iconurl + "/235fx235f'></div><div class='secondarea fifth-style-thing'><div class='buyer-price center-align sixth-style-thing'>$" + Math.round(item.price) + "<div class='bitskinscomp seventh-style-thing'>" + message + "</div></div><a class='btn waves-effect waves-light eighth-style-thing' href='" + item.inspect + "' target='_blank'>Inspect</a><a class='btn waves-effect waves-light purchaseButton'>Cart</a></div></li>";
}
}
myApp.data.outputContainer.html(newContent);
});
}
};
var items = [{
id: "123",
name: "freddy Beer",
condition: "worn",
originalname: "beer stein",
price: 10.22,
bprice: "34.33",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
inspect: "http://example.com/myinspect/4"
}, {
id: "123",
name: "freddy Beer",
condition: "worn",
originalname: "beer stein",
price: 10.22,
bprice: "34.33",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
inspect: "http://example.com/myinspect/4"
}, {
id: "123",
name: "freddy Beer",
condition: "worn",
originalname: "beer stein",
price: 10.22,
bprice: "34.33",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
inspect: "http://example.com/myinspect/4"
}, {
id: "123",
name: "freddy Beer",
condition: "worn",
originalname: "beer stein",
price: 10.22,
bprice: "34.33",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
inspect: "http://example.com/myinspect/4"
}, {
id: "123",
name: "Operation Phoenix Case Key",
condition: "worn",
originalname: "Operation Phoenix Case Key",
price: 10.22,
bprice: "34.33",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
inspect: "http://example.com/myinspect/4"
}, {
id: "234",
name: "Johnson Wax",
condition: "waxy",
originalname: "Ear wax",
price: 2244.22,
bprice: "",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
inspect: "http://example.com/myinspect/4"
}, {
id: "45245",
name: "Door Knob | Green",
condition: "green tint",
originalname: "Green door knob",
price: 35.68,
bprice: "",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXU5A1PIYQNqhpOSV-fRPasw8rsQEl9Jg9SpIW1KgRrg6GGJWRBtI-ykYTak6WhN76JlWgFsJN1j72SotWiigbi-0BqYjuncdDDdRh-Pw9UqwY-SA",
inspect: "http://example.com/myinspect/4"
}, {
id: "45245red",
name: "Door Knob | Red",
condition: "red tint",
originalname: "Red door knob",
price: 35.68,
bprice: "",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXU5A1PIYQNqhpOSV-fRPasw8rsQEl9Jg9SpIW1KgRrg6GGJWRBtI-ykYTak6WhN76JlWgFsJN1j72SotWiigbi-0BqYjuncdDDdRh-Pw9UqwY-SA",
inspect: "http://example.com/myinspect/4"
}, {
id: "45245red",
name: "Door Knob | Red",
condition: "red tint",
originalname: "Red door knob",
price: 35.68,
bprice: "",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXU5A1PIYQNqhpOSV-fRPasw8rsQEl9Jg9SpIW1KgRrg6GGJWRBtI-ykYTak6WhN76JlWgFsJN1j72SotWiigbi-0BqYjuncdDDdRh-Pw9UqwY-SA",
inspect: "http://example.com/myinspect/4"
}, {
id: "45245blue",
name: "Door Knob | Blue",
condition: "blue tint",
originalname: "Blue door knob",
price: 35.68,
bprice: "",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXU5A1PIYQNqhpOSV-fRPasw8rsQEl9Jg9SpIW1KgRrg6GGJWRBtI-ykYTak6WhN76JlWgFsJN1j72SotWiigbi-0BqYjuncdDDdRh-Pw9UqwY-SA",
inspect: "http://example.com/myinspect/4"
}, {
id: "45245Brown",
name: "Door Knob | Brown",
condition: "brown tint",
originalname: "Brown door knob",
price: 35.68,
bprice: "34.23",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXU5A1PIYQNqhpOSV-fRPasw8rsQEl9Jg9SpIW1KgRrg6GGJWRBtI-ykYTak6WhN76JlWgFsJN1j72SotWiigbi-0BqYjuncdDDdRh-Pw9UqwY-SA",
inspect: "http://example.com/myinspect/4"
}, {
id: "45245Malt",
name: "Beer malt | Brown",
condition: "brown tint",
originalname: "Brown Beer Malt ",
price: 35.68,
bprice: "34.23",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
inspect: "http://example.com/myinspect/4"
}, {
id: "4Beef",
name: "Beefeaters Mug | Brown",
condition: "new tint",
originalname: "Brown Beefeaters mug",
price: 35.68,
bprice: "34.23",
iconurl: "-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRc7cF4n-T--Y3nj1H6-hBrMW_3LIOWdlU_MlGDqwO6wrvq15C6vp-bnHY36SAm4XbYl0SwhgYMMLJqUag1Og",
inspect: "http://example.com/myinspect/4"
}];
myApp.data.outputContainer.on('customRenderEvent', function() {
myApp.func.renderItems(myApp.func.paginate(myApp.data.currentSearch));
});
$('#SearchItemsFromList').on('keyup', function() {
var valThis = $(this).val();
if (valThis === "") {
// item-card
// items hold the things to pageinate
// currentSearch holds the filtered items
myApp.data.currentSearch = items;
} else {
// "name" is the matching property in the object
myApp.data.currentSearch = myApp.func.contains(items, valThis, "name");
}
myApp.data.outputContainer.trigger('customRenderEvent');
console.log("keyup len:" + myApp.data.currentSearch.length);
}).trigger('keyup'); // trigger for initial display
$(window).on('scroll wheel', myApp.func.debounce(function(event) {
// set the page on scroll up/down
if ($(this).scrollTop() == 0) {
myApp.data.page > 0 ? myApp.data.page-- : myApp.data.page = 0;
} else {
myApp.data.page++;
}
myApp.func.renderItems(myApp.func.paginate(myApp.data.currentSearch));
}, myApp.data.scrollDelay));
Final note on the code, you have a quite long, difficult to maintain conditional which I replaced by added an array with the exclusions and then the code uses it with a filter: .filter(function(itemValue) {
return !!(myApp.data.excludes.indexOf(itemValue) == -1)
})