I'm trying to build an HTML component that will provide a pivottable-like view on my data, but with custom html elements inside the pivotarea rather than a sum or count; in the example below I'll just use a string of text, but I'd like it to be any HTML element (img, div, text etc.).
I'm finding it difficult to choose a direction, writing my own code to generate it (with jQuery) or using a library like Pivottable. I've tried the latter, but couldn't even find the proper direction w.r.t. customizing the aggregator function.
I could see myself re-using the html generated by js pivottable (with a simple count) and appending items afterwards in jQuery, but this seems like a rather hacky solution, along with a lack of customization options. Pros of this approach include the fact that at some point I'd like to include filtering/customization of the colums in the web-ui.
What am I looking for? Given a JSON array with multiple rows having attributes [Columngroup1, Columngroup2], and [Rowgroup 1, rowgroup2, rowgroup3], I'd like to layout it according as following (built in Tableau):
In the example above, [Businessline, Type, Product] are the Row-groups and [Active_or_roadmap, Roadmap Quarter] are the column groups. The granularity of the dataset is one level deeper, each 'Product' can consist of multiple subproducts, which should be placed either in the 'active' column (period header) or one of the roadmap quarter columns. This can be seen by subproducts 15.03 and 15.01 being grouped in the same 'row' visually.
What difficulties am I facing?
Do I use an HTML table for this, should I go with divs with classes indicating the rows/column, or a combination of both? Added complexity: at some point I'd like the non-header columns to be 'scrollable' horizontally (if too wide).
In a situation where I'd like to filter out some rows, should I regenerate the entire table or (mis)use visibility:hidden? In the latter case: how would I deal with a Product group being partially filtered (i.e. subproduct 15.01 should not be visible, subproduct 15.03 does need to be visible)
How would I 'embed' the object details in the DOM element? i.e., in the case of a hover/clickevent, how would I know which row in the JSON object corresponds to the name that was clicked?
Note that I'm not necessarily looking for an answer that fully does what I'm saying above, I'm primarily looking for a direction w.r.t. the code to go from the JSON to the above table in a structurally decent and flexible manner.
Any help is greatly appreciated, I have a codepen that contains some sample data and a rather poor attempt.
function load_data(callback){
$.getJSON('https://s3-us-west-2.amazonaws.com/s.cdpn.io/997352/data_portfolioroadmap.json', function(data){
callback(data)
});
}
I'm thinking something like this
{[
{productTitle:"Product 01.01",state:"Active","quarter":"2017Q1"},
{productTitle:"Product 01.02",state:"Roadmap","quarter":"none"}
]}
With this you should be able to loop over the array and place each element. I would use custom divs. First loop over the quarters and build those out. The loop over the state and filter grabbing the ones you need. Put the filtered results in a new var and sort it. The place each item in the proper column position as you are building out your rows. Then repeat with the next state.
Hope this make sense.
I think that managing that complex structure could force you to think of this table as a embeded components. Thinking of that maybe React (https://facebook.github.io/react/) could be appropriate solution for that.
Thinking about extending existing library is crucial for making this cost-effective, so please see https://react.rocks/example/orb (http://github.com/nnajm/orb) that maybe could be easier to extend using component matter of React that was used there.
Related
I've got a 3x3 grid layout using divs which upon clicking a button I need the divs to rearrange randomly. The following link illustrates an idea of what I need to create.
I don't need help with the HTML layout nor CSS design of the assignment per-se, but rather how to create the onclick function using native Javascript or jQuery in order for the "shuffle" and "sort" buttons to work. If possible, preferably Jquery, as I am more comfortable with its syntax.
I thank all in advance for help and support. Any useful links for me to do my own research is highly appreciated.
I am not looking for others to per say do my work for me, although solutions are highly appreciated, but perhaps guide me in a pseudo-code sort of way.
There are a number of different algorithms that you can use to "shuffle" a list of items. However, one of my favorite methods is the following because it is very concise.
General Shuffle Algorithm:
Find a list of items to rearrange.
Remove a random element from the items to rearrange
Insert the element into a new list
Repeat steps 1-3 until there are no more items left in the original list
Code Example
Here is a function that should do the trick:
$container = $("#container");
$divList = $("div");
$("#shuffle").on("click", function(){
//copy and remove all divs
$divCopy = $divList.clone(true);
$("div").remove();
while($divCopy.length > 0){
//chose random index of div array
var randomIndex = Math.floor(Math.random() * $divList.length);
$container.append($divCopy.splice(randomIndex, 1));
}
});
There is a full working version at https://jsfiddle.net/oruq1qou/
If you are interested in looking for other methods of solving this problem, I would recommend doing some reading on the different types of shuffle algorithms around.
I'm doing a school assignment to visualize in-depth search algorithm and i'd like to visualize the tree javascript creates. I've written the javascript to implement in-depth search but i'm in trouble visualizing the tree.Currently i've created an object for a node which has attributes:
function createNode(parent,name,suur,vaike){
var Node = new Object();
Node["name"]= name;
Node["children"] = [];
Node["parent"] = parent;
return Node;
}
In general it wouldn't be really difficult to draw a tree in HTML but i would like to get my head around it before i start writing any code for visualizing. The main issues i've stated is that the length of branches have to dynamically change - if new children are added to the tree then the tree will expand so different elements wouldn't collapse.
This is an image from Wikipedia and i'd love to get something like this as a result.
What my question is that i'd like to get some pointers how to dynamically expand the branch lengths so that different children wouldn't collapse.
For this particular task i used Treant.js. Really simple to use and drew nicely fitted tree. Had about 60 elements in the tree and no collision.
Here's a little snip from the result (it's scrollable, couldn't fit all on one page)
I would recommend using a VS Code for all extensions that rainbow color the HTML code structure and others, besides all unique CSS Selectors
I have dropped all #rainbow extensions I use. I hope that would help.
enter image description here
Warning: not duplicate with existing questions, read through
I know I can have an event listen on changes on an contenteditable element.
What I would like is to be able to know what the changes are.
For example:
inserted "This is a sentence." at position X.
deleted from position X to Y.
formatted from X to Y with <strong>
Is that possible? (other than by doing a diff I mean)
The reason for this is to make a WYSIWYG editor of other languages than HTML, for example Markdown.
So I'd like to apply the changes to the Markdown source (instead of having to go from HTML to Markdown).
You may be able to do something with MutationObservers (falling back to DOM Mutation events in older browsers, although IE <= 8 supports neither) but I suspect it will still be hard work to achieve what you want.
Here's a simple example using MutationObservers:
http://jsfiddle.net/timdown/4n2Gz/
Sorry, but there is no way to find out what the changes are without doing a diff between the original content and the modified one when changes occur.
Are you looking for this
var strong=document.createElement("strong");
var range=window.getSelection().toString().getRangeAt(0);
range.surroundContents(strong);
this was for third part
You just need to select what you want to surround using real User interaction.
If you wanna do it dynamically
var range=document.createRange();
range.setStart(parentNode[textNode],index to start[X])
range.setEnd(parentNode[textNode],index to end[Y])
range.surroundContents(strong);
For 2nd Part
range.deleteContents()
1st part can be done by using simple iteration
var textnode=// node of the Element you are working with
textnode.splitText(offset)
offset- position about which text node splitting takes place[here==X]
Two child Nodes have been created of the parent editable Element
Now use simple insertBefore() on parent editable Element Node.
hope you will find it useful
The API you're looking for does not exist, as DOM nodes do not store their previous states.
The data / events you're wishing to get back are not native implementations in any browser Ive come across, and I struggle to think of a datatype that would be able to generically handle all those cases. perhaps something like this:
function getChanges() {
/* do stuff here to analyse changes */
var change = {
changeType : 'contentAdded',
changeStart : 50, /* beginning character */
changeContent : 'This is a sentence'
}
return change;
}
Since you're trying to get custom events / data, you're probably going to need a custom module or micro-library. Either way, to look at the changes of something, you need somehow be aware of what has changed, which can only be done by comparing what it was to what it is now.
I was hoping someone could tell me how to bring an entire set of elements toFront in Raphael JS.
I am working with some dynamically generated sets of raphael elements, each of which is stored in an array making it easier to interact with and target individual sets. When a user interacts with the various sets I would like to be able to bring the full set to the front of the application.
I have tried using .toFront() as outlined here: http://raphaeljs.com/reference.html#Element.toFront
However this hasn't worked properly. Each set contains either a circle or a circle sector, a text element and either an additional circle or an additional sector.
Any ideas? At any one point a user may have up to 40/50 of these sets so bringing sets to front is going to be a necessity regardless.
i've had similar issues with the toFront() function ...
well i'd say there are two ways to do it ...
The first one (not quite recommended) apply a loop on all the elements of the set to bring them to front but still they'd be ordered according to the sequence in the set .... not good approach ...
set.forEach(el){
e.toFront();}
The second one is really sexy :) my fav :) beautifully explained by mister phrogz here
I recommend using the 'g' tag ... simple javascript . let all your sets be enclosed in a g tag
var mySet = document.createElementNS("http://www.w3.org/2000/svg", "g");
mySet.setAttribute('id','myset');
//should look something like this
//use jQuery append or javaScript appendChild to add your set elements to this group
<g id = 'myset'>
<rect>
<circle>
//etc etc
</g>
now
mySet.parentNode.appendChild(mySet); //the key line
this would simply take it to the bottom of the svg container, hence being drawn last and shown at the top according to the painters model also mentioned by mister phrogz in the link .... you could use javascript to manipulate your own z-index if required...
Here's what I'm trying to do. I have an extremely large list of items. Let's say it's around 130,000 items long. Each item is a string, something along the lines of 'almond antique azure green firebrick'.
Right now, I'm just putting each item as a single cell in a single row of a table. It would be nice to only display items starting with a, or starting with b, and so on. I'm having a few problems with the js I'm writing to do this, but the biggest one is speed - doing ANYTHING on a table consisting of this many items is really slow. Is there a better way to approach this problem?
If the answer is no, then it's fine - this is an extra credit assignment for a databases class, and this component is on reporting. This particular dataset came from a DB table with 6 million items, so there's nothing that can really be done to reduce the size.
EDIT: Here's some more information on the problem. I am creating this HTML page through a C# program. The program uses LINQ2SQL to query this massive database, gets the results, and outputs it into an HTML file. This isn't going to be a website, no data is going to be coming from a server; this is a static HTML page, viewable in a browser. I could have implemented this as a csv if I wanted, but I think it looks nicer as a churched-up HTML file.
The type of data that I'm loading is this: "For each region, find all products that were not sold in the first half of 1993". So, with about 200,000 products, each region typically only sold about 70k. This means that there are 130k unsold products, and we have to list all of them for each region. I do have a separate HTML file for each region, but I can't think of any way to reduce the data further than that.
Further Edit: Thanks for everybody's suggestions. The short answer to this question, I guess, is "no; this is going to be slow". As one commenter said, lists of 100k+ items don't belong in HTML documents. I was going above and beyond the scope of my homework anyway by even doing this much, so I'll just let it rest.
If you could render descriptive classes onto the <tr>s and/or <td>s server-side, then you could just change the class of the parent table, and the browser would take care of re-rendering the table following the appropriate CSS.
table.just_a td,
table.just_bipeds td {
display:none;
}
table.just_a td.a,
table.just_bidpeds td.biped {
display:inherit;
}
<table class="" id="theTable">
<tr>
<td class="a quadraped">Anteater</td>
</tr>
<tr>
<td class="z quadraped">Zebra</td>
</tr>
<tr>
<td class="h biped">Human</td>
</tr>
</table>
<input type="button" onclick="document.getElementById('thTable').className='just_a'" value="Just A" />
No matter what it's going to be slow, sorry. Unless you're running on your web browser on a Blade server or something ;-)
However, there is one trick that will legitimately speed up things: instead of setting the display property of the rows to "none", set their class to "nodisplay", and define a css rule:
.nodisplay { display:none }
Now you might think, what's the difference, but in fact (as PPK of quirksmode.org once proved with benchmarks) browsers are faster at switching classes with associated style changes than they are at making direct style changes to elements.
Can't say that it will make changing your insanely huge table fast, but it should make it faster.
The key to performance when inserting lots of data into the website is to reduce the number of refreshes of the page. This can be done by trying to add all the data at once by concatting all the html into a string and inserting only once.
For example:
var html = "<table>";
for (var i = 0; i < listOfData.length; i++)
{
html += "<tr><td>" + listOfData[i] + "</td></tr>";
}
html += "</table>";
// Insert it
$("body").html(html);
Hope that helps!
I hate homework that doesn't make any sense! The right answer is, this is the wrong way to do this. You shouldn't try to display 100K+ (or even 10K..) items on a single HTML page, ever. But if the question is "how best to do something the wrong way," then I would do the following to break it down to a manageable size for display, while still keeping everything in a single client page
1) Render the data not as HTML, but as a Javascript array sorted alphabetically
2) Create a simple menu in HTML/javascript that lets the user select just the first letter
3) Using JS again render the table using data from the array you constructed before. To avoid time-consuming selections from that array, you could keep a separate index of the first element for each letter of the alphabet.
A JS array with 100K items is still going to be perceptibly slow, I would imagine, but probably a lot slower than trying to render it all at once.
You could further use something to create paging if that was what you wanted, just using all the data from your array.
Stick to the csv, 130k list items do not belong in a html page.