I have implemented a proof of concept to illustrate what I try to achiev https://codesandbox.io/s/html-react-parser-forked-wcxv8?file=/src/index.js
I render an article content, which is fetched from the API but I used an example.html file for simplicity. I need to parse it using html-react-parser because we need to do some transformations before rendering it, but I omitted that part as it's not relevant for the scope of this issue.
Once we have it parsed and rendered, I've added an effect to insert an advertisement banner with a distance of twice the viewport height. As you can see, 4 or 5 banners will be inserted, depending on your viewport height, but that's not the amount of banners that should be inserted as the article continues and the conditions to still apply. Hence, we should see more banners.
What am I doing wrong? Thanks!
It looks like the parsed HTML returns an object of length 112, where the odd numbered indices are string types. By filtering out the elements that are strings and inserting at index + viewPortDistance, you get the correct insertion positions.
I have added console statements to ensure that the ads are actually inserted after the correct nodes.
https://codesandbox.io/s/html-react-parser-forked-0476i
The issue is not the amount of ads, but their position. Your array of articles has 116 elements, but the ref.current.children only 56.
In order to force the number of children to match the article nodes, you can wrap each item in the article array in the span of its own. That way, the articles and the children count will be the same and allow for equal distribution of ads. You can see that in here:
https://codesandbox.io/s/html-react-parser-forked-gvvmd?file=/src/index.js
Related
I'm trying to implement a utility to accurately clamp multi-line text to a given maximum number of lines. The approach I'm taking is to binary search the text of the element to find the maximum number of words where if the element contains only those words and an ellipsis, its height is not greater than what I determine is the height for N lines.
Since this is basically a trial-and-error method, I'll need to change an element that's actually rendered and check its size. I'd like it to be some other element than the actual one the user sees, because it'd be weird to have its contents blink around for a bit as the page loads. But since the clamp location will very much depend on the precise styling of the original element, I think what I'll need is to make an exact duplicate of it that's not visible to the user but still has the browser lay it out.
How do I accomplish this using JavaScript or jQuery?
I've considered creating an element at say x=-1000000, y=-1000000, and set its style properties to the uhh... computed style of the original element? I don't think that would actually work because the computed style already considers the current content of the element. What I need is some way to get all the style declarations that apply to the given element; or maybe make the new element an absolutely positioned sibling of the original, but since that's outside the regular block flow, I'm not sure its sizing would work the same.
Or is there some general way to make 'invisible' temporary changes to the style of an element that still let me access what the rendering engine makes of them?
I have a number of elements that I need to add to a page using javascript with data pulled from the server with their position information. I want to arrange them so that there is no overlap. For example, element 5 would be moved to where the thin green box is, so that it doesn't overlap element 3.
I have successfully created a function which decides whether two boxes overlap. For example, if I ran overlaps($('#element5')[0],$('#element3')[0]) it would return true.
However, with this function I would have to loop through each element and compare it with every other element. So for 50 elements I would need to do run the overlays function 1275 times which would take a long time to load.
I decided I would best creating an rtree to organise the elements first so that I could easily work out which 2 elements I would need to run the overlay function with, significantly reducing the number of runs of the overlay function. However, I am extremely confused on how this would work. How would I organise them so that I would only have to run the function with a small number? Wouldn't 2 of the rtree's bounding boxes overlap and make this technique redundant? What would be the best way to do this?
In an R-tree, rectangular pages can indeed overlap.
When searching for overlaps, you would have to explore both groups then.
But the number of overlapping pages in the r-tree shouldn't be too big (unless the tree was built very badly), so this will still yield a good speedup. Assuming you have 50 elements in 5 pages of 10 elements each, you will first have to test the 5 top level pages, then maybe test the 10 elements in 0-2 of these pages, so maybe just 15 overlap tests instead of 50.
The exact numbers will of course vary a lot.
For a HTML solution, however, I would consider a grid based approximation instead.
Divide your surface in 10x10 cells. Each cell contains references of the rectangles that overlap with this grid cell.
When testing for overlap, you look at the grid cells the query rectangle touches, collect all referenced existing rectangles, and then overlap test only those. If you store two lists in each cell - "overlaps partially" and "overlaps completely", you can even skip many of the overlap tests: if any grid cell touched by one is overlapped completely by the other, they will overlap somewhere.
Yet another approach would be to sort the rectangles by X axis, to quickly narrow down the number of rectangles that can actually overlap with a binary search. This also should drastically reduce the number of intersection calls.
Oh, and last but not least: 1275 overlap tests should not take a lot of time anyway. This is by any means a tiny data set that you are talking about. R-trees and similar approaches are meant for data sets with millions of items.
This is currently just conseptual, but it bothers my brain.
If I have a list of items - in my mind it's a HTML/JS implementation, but that's just because I'm a visual thinker ;)
I want to use drag and drop to sort this list, with the aim of storing the new order when I'm done. Is there a way to do this without numbering the items, and then updating the number of the dropped item + every single item that follows it? Isn't that very inefficient?
As far as performance goes, changing the numbering of the elements is nothing next to actually rendering the transition (while you're dragging an element), so no, it's not inefficient.
You can use a doubly linked list in order to minmize the amount of operations needed to change the order of the collection.
I would recommend using a JavaScript framework to do the job.
KnockoutJS should fit your needs (from the website):
Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model. Any time you have sections of UI that update dynamically (e.g., changing depending on the user’s actions or when an external data source changes), KO can help you implement it more simply and maintainably.
If you left gaps in the numbers, you could probably do it efficiently -- for instance, let the first element be 10, the second be 20, the third 30, etc. Then when you drag something in front of the second one and after the first, call it 15 (or something).
Rather than incrementing numbers every time, you'd only have to do it if you ran out of space. At the end, you could just order the objects by lowest number.
Not including any code here, because this is a conceptual question.
You have to have a number for every element in the list anyway, since they have to have a Total Ordering among themselves to be represented as a list.
If you don't expect the number of elements in the list to be large, a Bubble Sort should work very well for you.
I have a piece of HTML which I am displaying inside a UIWebView using Webkit stylesheet attributes. I use Webkit to display the HTML in columns in order to simulate a book.
Only one column is visible at a time (one column represents one page). Now, I am trying to find the range of the visible HTML so that I can insert a span element right before the first visible word.
I managed to get the HTML element which contains the first visible word by using the JavaScript function, document.elementAtPoint(I might have the function name wrong), and changed its CSS class. but that just isn't accurate enough for me. I need it to be accurate up to the first visible word.
The idea is the create a column break at the first visible word when the fontsize is increased or decreased. I can using JavaScript to figure out in which column the element is, and programmatically scroll the user to that column, but first I need to get the element in there.
Can anyone help me?
The CSSOM View Module specification adds caretPositionFromPoint(x, y) to the Document interface, which returns a caret position for the specified x and y co-ordinates. WebKit supports caretRangeFromPoint, a close analogue from an earlier specification, which returns a Range.
It is possible that the word has been hyphenated and thus spans two columns, so rather than wrapping the first word in a span you may wish to consider the more naive approach of inserting the span directly at the cursor point. Here's an example:
var caretPos = document.caretRangeFromPoint(x, y);
if (caretPos)
caretPos.insertNode(document.createElement('span'));
Demo (WebKit only—click to insert spans): http://jsfiddle.net/Jordan/Aw9aV/
One final consideration: it is possible that WebKit will eventually stop supporting caretRangeFromPoint in lieu of caretPositionFromPoint; if so, you will need to adapt your code. Also note that the latter returns a CaretPosition which may not implement the insertNode method. The spec is still at WD, so be mindful that it is still in flux.
Ok, nog entirely sure what you are currently doing, but at the very least I should be able to give some useful tips, as I have some experience building page browsing systems in javascript.
First of all, in CSS3 you can define columns https://developer.mozilla.org/en/CSS3_Columns , which will automatically split up the content into different columns within a single element (where a single column has the full width of the uiwebview) and next add browsing controls which move the entire element containing the element (using css3 3d translations for smooth hardware accelerated motion and you know the width of the columns so you don't need to worry about what the first word on the page is). In which case you don't need to worry about splitting up the column breaks yourself. (Though, as I said, I am not sure to what extend you are already doing this).
Alternatively you may decide to wrap all your content in small inline-blocks (as older column implementations did) or even up to the point of single inline elements, each containing a single word. (Though this doesn't seem necessary anymore)
Lastly, work is being done on http://www.w3.org/TR/css3-regions/ which will make this even easier in the future, but for now it's only available in chrome and ie10
On the other hand, you might already be doing this or I might be missing the point, in which case I would need to see some code before I can give you a more specific answer. (I can think of various javascript tricks to work with letters within a text, but none seem necessary in your case)
Suppose I have a large list of objects (thousands or tens of thousands), each of which is tagged with a handful of tags.
There are dozens or hundreds of possible tags and their usage follows a typical power law:
some tags are used extremely often but most are rare.
All but the most frequent couple dozen tags could typically be ignored, in fact.
Now the problem is how to visualize the relationship between these tags.
A tag cloud is a nice visualization of just their frequencies but it ignores which tags occur with which other tags.
Suppose tag :bar only occurs on objects also tagged :foo.
That should be visually apparent.
Similarly for three tags that tend to occur together.
You could make each tag a bubble and let them partially overlap with each other.
Technically that's a Venn diagram but treating it that way might be unwieldy.
For example, Google charts can create Venn diagrams, but only for 3 or fewer sets (tags):
http://code.google.com/apis/chart/docs/gallery/venn_charts.html
The reason they limit it to 3 sets is that any more and it looks horrendous.
See "extentions to higher numbers of sets" on the Wikipedia page: http://en.wikipedia.org/wiki/Venn_diagrams
But that's only if every possible intersection is non-empty.
If no more than 3 tags ever co-occur (maybe after throwing out the rare tags) then a collection of Venn diagrams could work (with the sizes of the bubbles representing tag frequency).
Or perhaps a graph (as in vertices and edges) with visually thicker or thinner edges to represent frequency of co-occurrence.
Do you have any ideas, or pointers to tools or libraries?
Ideally I'd do this with javascript but I'm open to things like R and Mathematica or really anything else.
I'm happy to share some actual data (you'll laugh if I tell you what it represents) if anyone is curious.
Addendum: The application I originally had in mind was TagTime but it occurs to me that this also maps well to the problem of visualizing one's delicious bookmarks.
If i understand your question correctly, an image matrix should work nicely here. The implementation i have in mind would be an n x m matrix in which the tagged items are rows, and each tags type is a separate column. Every cell in the matrix would consist entirely of "1's" and "0's", i.e., a particular item either has a given tag or it doesn't.
In the matrix below (which i rotated 90 degrees so it would fit better in this window--so columns actually represent tagged items, and each row shows the presence or absence of a given tag across all items), i simulated the scenario in which there are 8 tags and 200 tagged items. , a "0" is blue and a "1" is light yellow.
All values in this matrix were randomly selected (each tagged item is eight draws from a box consisting of two tokens, one blue and one yellow (no tag and tag, respectively). So not surprisingly there's no visual evidence of a pattern here, but if there is one in your data, this technique, which is dead simple to implement, can help you find it.
I used R to generate and plot the simulated data, using only base graphics (no external packages or libraries):
# create the matrix
A = matrix(data=r1, nrow=1, ncol=8)
# populate it with random data
for (i in seq(0, 200, 1)){r1 = sample(0:1, 8, replace=TRUE); A = rbind(A, r1)}
# now plot it
image(z=A, ann=F, axes=F, col=topo.colors(12))
I would create something like this if you are targeting the web. Edges connecting the nodes could be thicker or darker in color, or perhaps a stronger force connecting them so they are close in distance. I would also add the tag name inside the circle.
Some libraries that would be very good for this include:
Protovis (Javascript)
Flare (Adobe Flash)
Some other fun javascript libraries worth looking into are:
Processing for Javascript
Raphael
Although this is an old thread, I just came across it today.
You may also want to consider using a Self-Organizing Map.
Here is an example of a self-organizing map for world poverty. It used 39 of what you call your "tags" to arrange what you call your "objects".
http://www.cis.hut.fi/research/som-research/povertymap.gif
Note sure it would work as I did not test that, but here is how I would start:
You can create a matrix as doug suggests in his answer, but instead of having documents as rows and tags as columns, you take a square matrix where tags are rows and columns. Value of the cell T1;T2 will be the number of documents tagged with both T1 and T2 (note that by doing that you'll get a symetric matrix because [T1;T2] will have the same value as [T2;T1]).
Once you have done that, each row (or column) is a vector locating the tag in a space with T dimensions. Tags near each others in this space often occur together. To visualize co-occurrence you can then use a method to reduce your space dimensionality or any clustering method. For example you can use a kohonen self organizing map to project your T-dimensions space to a 2D space, you'll then get a 2D matrix where each cell represents an abstract vector in the tag space (meaning the vector won't necessary exists in your data set). This vector reflect a topological constraint of your source space, and can be seen as a "model" vector reflecting a significant co-occurence of some tags. Moreover, cells near each others on this map will represent vectors close to each other in the source space, thus allowing you to map the tag space on a 2D matrix.
Final visualization of the matrix can be done in many ways but I cannot give you advice on that without first seeing the results of the previous processing.