This question already has answers here:
How to Create Grid/Tile View? [duplicate]
(8 answers)
Closed 6 years ago.
I've been sending this emails:
I'm about to release an application for web application security which requires the use of a grid like Masonry. I've tried all, and every single angular module, directives, and different approaches, including CSS based techniques, pure Vanilla JS, and your solution is, one of the best options available online. I found, however a main issue, that affects not only your approach, but every single Angular module or addon.
Issue #1:
Your solution, as any other solution, is based on an array of information that is already handled by angular. In your example case, it would be source="photos". Now, the problem comes when there's 2 different groups of elements. Let's assume, that I have a group of elements that where previously defined in the DOM. In other words:
<div angular-grid>
<p class="angular-grid-elem">This content is already here from the beginning, in the DOM, directly in the HTML, and I want to apply a Masonry like style on it.</p>
<div class="angular-grid-elem" style="height:500px">Same happens with this content.</div>
<!-- and here comes more content, which is loaded from an array of information -->
<div class="angular-grid-elem" ng-repeat="data in data_array">
<p>{{data.header}}</p>
<p>{{data.details}}</p>
</div>
</div>
Now, as you can see in the example, the content inside the main div, , should be all, affected by the masonry layout. Of course, this is pseudo code and I'm aware that the sintaxis of your approach is different. However what I'm trying to represent here, is that your module, would be way better, if you would be able to apply the masonry like grid, including elements which are already present in the DOM/HTML in first place, with elements that are coming from an array.
Issue #2:
There's a second issue I found in multiple angular modules and approaches. What happens if I have 2, 3 or let's say even 16 divs which all of them, present the same masonry like behaviour? I have to admit, I didn't try it with your module, as I couldn't solve the initial problem, that requires the proper handling of the combination of elements that are (1) pre-defined in the HTML, and (2) coming from and ng-repeat function.
A possible approach:
In order to solve the second problem and the first one, at the same time, I have thought that the best approach might be to make use of element classes and elements ids to handle the situation? Why? Because it can easily applied into elements that are already there in the DOM in first place, as well, to elements that are joining or leaving dynamically by the use of a ng-repeat or any other of the angular functions.
Here's an example of what I'm saying:
<div class="angular-grid-dad-one" ng-grid="{'dad': 'angular-grid-dad-one', 'childs': 'angular-grid-elem'}" >
<p class="angular-grid-elem">This content is already here from the beginning, in the DOM, directly in the HTML, and I want to apply a Masonry like style on it.</p>
<div class="angular-grid-elem" style="height:500px">Same happens with this content.</div>
<!-- and here comes more content, which is loaded from an array of information -->
<div class="angular-grid-elem" ng-repeat="data in data_array">
<p>{{data.header}}</p>
<p>{{data.details}}</p>
</div>
</div>
In this case, the main div defines itself as id="angular-grid-dad-one",
And also tells the Angular module, that the element angular-grid-dad-one is a container div of a masonry like structure,
And that it's childs are marked as angular-grid-elem.
As we could see on this line.
ng-grid="{'dad': 'angular-grid-dad-one', 'childs': 'angular-grid-elem'}"
This way, it allow us to make use of the Angular module in multiple instances. For example.
<div class="seccion_01" ng-grid="{'dad': 'seccion_01', 'childs': 'seccion_01_child'}" ng-show="seccion == '1'">
<p class="seccion_01_child">This content is already here from the beginning, in the DOM, directly in the HTML, and I want to apply a Masonry like style on it.</p>
<div class="seccion_01_child" style="height:500px">Same happens with this content.</div>
<!-- and here comes more content, which is loaded from an array of information -->
<div class="seccion_01_child" ng-repeat="data in data_array">
<p>{{data.header}}</p>
<p>{{data.details}}</p>
</div>
</div>
<div class="another_container" ng-grid="{'dad': 'another_container', 'childs': 'child_of_container'}" ng-show="seccion == '2'">
<p class="child_of_container">This content is already here from the beginning, in the DOM, directly in the HTML, and I want to apply a Masonry like style on it.</p>
<div class="child_of_container" style="height:500px">Same happens with this content.</div>
<!-- and here comes more content, which is loaded from an array of information -->
<div class="child_of_container" ng-repeat="data in data_array">
<p>{{data.header}}</p>
<p>{{data.details}}</p>
</div>
</div>
<div class="redundant_example" ng-grid="{'dad': 'redundant_example', 'childs': 'childs_of_redundancy'}" ng-show="seccion == '3'">
<p class="childs_of_redundancy">This content is already here from the beginning, in the DOM, directly in the HTML, and I want to apply a Masonry like style on it.</p>
<div class="childs_of_redundancy" style="height:500px">Same happens with this content.</div>
<!-- and here comes more content, which is loaded from an array of information -->
<div class="childs_of_redundancy" ng-repeat="data in data_array">
<p>{{data.header}}</p>
<p>{{data.details}}</p>
</div>
</div>
I have used a Json styled instruction in the ng-grid value in order to explain my point, but it doesn't really have to be Json. It even could be 2 different paramenters:
<div class="dad" ng-grid-dad="dad" ng-grid-childs="childs" ng-show="seccion == '3'">
<p class="childs">This content is already here from the beginning, in the DOM, directly in the HTML, and I want to apply a Masonry like style on it.</p>
<div class="childs" style="height:500px">Same happens with this content.</div>
<!-- and here comes more content, which is loaded from an array of information -->
<div class="childs" ng-repeat="data in data_array">
<p>{{data.header}}</p>
<p>{{data.details}}</p>
</div>
</div>
As well, regarding the infinite scroll that you have created, you would be able to load more elements, triggering the infinite scroll, and loading only elements from one specific array, of course.
Please let me know if I can help further, I would like to integrate your module into my application.
And let's hope that by the next implementation of HTML and CSS we have this situation fully under control by the next generation of browsers, I'm aware of the work it takes to make this grids in Javascript.
Actually, I am gonna go out on a limb and say that flex-wrap: wrap will fix the issue.
.holder {
flex-wrap: wrap
-moz-columns: 2 auto;
box-sizing: border-box;
display: flex;
padding: 0 40px;
width: 100%;
}
I'm using the Froala editor v2 and I'm running into a very frustrating and intermittent problem. I'm embedding a custom HTML widget (a rich preview when the user enters a URL on its own line). But when I retrieve the final HTML to be saved to our database, it seems Froala decides to "clean up" my HTML before giving it to me. When I inspect the editor instance while I'm editing the content, all the markup is in good shape. But when I call $('.froala-editor').froalaEditor('html.get') to retrieve the HTML, the HTML for the URL preview widget is completely mangled.
My suspicion is that, since the entire preview is wrapped in an <a> tag to make the whole thing linked (and I don't have any nested <a> tags in it because that's bad HTML), Froala is taking the other structural elements like the divs, h# tags, p tags, etc and placing copies of the wrapping <a> tag inside all of them (as you'll see in the code samples) because it doesn't think you're allowed to have an <a> wrapping all that stuff. But that's just a guess.
And to top it all off, sometimes Froala will give me the HTML intact and other times it won't.
I don't think it makes any difference, but I'm using React to generate the widget and then injecting the resulting HTML into the editor. I've removed all the data-reactid attributes to reduce the clutter.
Original injected HTML (the outermost <p> tags are there because Froala seems to like to wrap everything in semantic block level tags):
<p>
<a href="http://www.google.com" target="_blank" class="embedly-preview" title="http://www.google.com" data-source-url="http://www.google.com">
<span class="ui media content-item-wrapper content-summary post-body">
<span class="media-left content-summary-image post-image">
<img src="https://res.cloudinary.com/peerlyst/image/fetch/http%3A%2F%2Fwww.google.com%2Fimages%2Fbranding%2Fgooglelogo%2F1x%2Fgooglelogo_white_background_color_272x92dp.png">
</span>
<span class="media-body content-summary-body">
<h2 class="content-summary-title content-title post-title">Google</h2>
<p class="content-summary-content post-content">Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for.</p>
<p class="content-summary-link">http://www.google.com</p>
</span>
</span>
</a>
</p>
What Froala gives me:
<p>
<a class="embedly-preview" data-source-url="http://www.google.com" href="http://www.google.com" target="_blank" title="http://www.google.com">
<span class="ui media content-item-wrapper content-summary post-body">
<span class="media-left content-summary-image post-image">
<img src="https://res.cloudinary.com/peerlyst/image/fetch/http%3A%2F%2Fwww.google.com…randing%2Fgooglelogo%2F1x%2Fgooglelogo_white_background_color_272x92dp.png">
</span>
<span class="media-body content-summary-body"></span>
</span>
</a>
</p>
<h2 class="content-summary-title content-title post-title">
<a class="embedly-preview" data-source-url="http://www.google.com" href="http://www.google.com" target="_blank" title="http://www.google.com">Google</a>
</h2>
<p class="content-summary-content post-content">
<a class="embedly-preview" data-source-url="http://www.google.com" href="http://www.google.com" target="_blank" title="http://www.google.com">Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for.</a>
</p>
<p class="content-summary-link">
<a class="embedly-preview" data-source-url="http://www.google.com" href="http://www.google.com" target="_blank" title="http://www.google.com">http://www.google.com</a>
</p>
The problem is not the editor, but the HTML structure you have. You have used a H2 tag inside a P tag which browsers do not allow (see https://stackoverflow.com/a/8696078/1806855 for more details) You could check that in a very basic jsFiddle: https://jsfiddle.net/0jLzm2b0/.
Instead it should work just fine if you'd use a DIV tag instead: https://jsfiddle.net/0jLzm2b0/1/. You can see the output is no longer changed.
After digging into the Froala code using a breakpoint to isolate the point at which the HTML gets mangled, turns out it's actually jQuery that's mangling my HTML. Effectively, given the original HTML from above in the variable html:
$(html).html() !== html
What's even more interesting is that (taking the relevant snippet from Froala's code where it wraps the fetched HTML in a div before processing):
$('<div>' + html + '</div>').html() !== $(html).html() !== html
(Clearly, wrapping html in a <div> will make the HTML not equal to the others, but even the HTML inside the <div> that is output is mangled from the original)
So the jQuery constructor is the thing being "helpful" by retooling my HTML for me.
I'm trying to create a simple tool to ease the addition of tags in blog posts (not sure if I can mention the website, therefore i won't do it now).
I've inspected the code and I've noticed that when a tag is added, a new span is created between the divs post-form--tag-editor and tag-input-wrapper
<div class="post-form--tag-editor" data-subview="tagEditor">
-> TAG CODE here !! <span class=""> ::before This is a tag </span> <- TAG CODE here!!!
<span class=""> ::before This is another tag </span>
<div class="tag-input-wrapper" data-js-taginputfieldwrapper="">
<div data-name="tagInput" data-subview="tagInputField">
<div data-js="editor-wrapper" class="editor-wrapper" style="position: relative;">
Right now, my tool is injecting the necessary HTML to create dynamic spans and add new tags. I can see my "injected" tags in the webpage but when I submit the post the "injected" tags do not appear in the live post.
Since I'm able to see the "injected tags" shouldn't I be able to see them too when my post is submitted and live ? Am I using the wrong approach to achieve what I want?
Thank you in advance !
So this is actually a very tricky concept to portray so here is my attempt.
I am utilizing an HTML form template in LANDesk Service Desk - tool is irrelevant but important to note that there is back-end code that I cannot touch that is generating HTML.
So basically, the tool is pulling data from a back-end database containing a list of objects. It then inputs this data into an HTML form template that I have created using variables as placeholders for the objects. The HTML is then built on the fly with however many objects are in the database. Thus, I have no way of accessing the head - (which means native JS, and inline CSS).
My template looks like this...
<div class="my-template">
<a class="my-template my-link">My Link</a>
</div>
<script>
var myLinks = document.getElementsByClassName('my-link');
for (var i = 0 ; i < myLinks.length ; i++) {
myLinks[i].style.display = "none";
}
</script>
When I view the source on the loaded page it looks something like this...
<body>
<!--misc. page stuff-->
<!--First Item-->
<div class="auto-create">
<div class="my-template">
<a class="my-template my-link">My-Link</a>
</div>
</div>
<!--Second Item-->
<div class="auto-create">
<div class="my-template">
<a class="my-template my-link">My-Link</a>
</div>
</div>
</body>
All of the elements are formatted the way I want them to be...besides the last element on each page. I have determined that this is because each time the tool is running the object through the template, it is running the script. The issue is, there is a stupid default button that they place at the bottom of each object that is broken. (This is why I have the script changing the style to display: none..should have mentioned this earlier). Basically I want to delay the execution of the script until not only the object has been run through the template...but the entire page has loaded...but I can't seem to get the last button to go away.
I know that this is a lot of poorly written words trying to form an explanation, but I really think this is impossible...but I am convinced there has to be a way. (Also, the company isn't providing us with any help in finding a workaround, so I had to basically MacGyver this one
I am using this: http://angular-ui.github.io/ui-utils/ and to be more specific this:https://github.com/angular-ui/ui-utils/blob/master/modules/scroll/README.md
however it does not seem to work. Here is an example:
<div ng-scroll-viewport style="height:240px;" class="chat-messages">
<div class="chat-message" ng-scroll="chat in chats">
<div ng-class="$index % 2 == 0? 'sender pull-right' : 'sender pull-left'">
<div class="icon">
<img src="{{chat.img}}" class="img-circle" alt="">
</div>
<div class="time">
{{chat.time}}
</div>
</div>
<div ng-class="$index % 2 == 0? 'chat-message-body on-left' : 'chat-message-body'">
<span class="arrow"></span>
<div class="sender">{{chat.name}}</div>
<div class="text">
{{chat.msg}}
</div>
</div>
</div>
</div>
But All I get in HTML is this :
<div class="chat">
<div class="chat-messages" style="height:240px;" ng-scroll-viewport="">
<!--
ngScroll: chat in chats
-->
</div>
If I replace ng-scroll with ng-repeat, it works perfectly. But chats need scroll bars, so... How can I get one? :)
The documentation of ngScroll directive had also tricked me into simply replacing ng-repeat by ng-scroll. Unfortunately, it turned out not as simple as that, see also the small, working example at http://plnkr.co/edit/fWhe4vBL6pevcuLutGC4 .
Note that
"datasource" (or whatever object you want to iterate over for the contents of the scroll list) must implement a method "get(index,count,success)" that calls success(results), see hXXps://github.com/angular-ui/ui-utils/blob/master/modules/scroll/README.md#data-source
The array must have exactly count elements. Otherwise, no scroll window/bar will ever show, which can be very irritating!
Although UI.Utils says it has no external dependencies, ui.scroll has actually a dependency on either ui.scroll.jqlite, or jQuery. So make sure to list both ui.scroll and ui.scroll.jqlite in your module definition which contains the controller with datasource object (and load their .js files, or load ui-utils.js which contains both), see https://github.com/angular-ui/ui-utils/blob/master/modules/scroll/README.md#dependencies
Be careful when your server is sending some Content Security Policies (CSP). Maybe turn them off while trying to get ng-scroll to work first, then re-apply CSP and tune the policies accordingly for ui.scroll to work.
One way of getting a scroll is to use CSS, set overflow-y to scroll and you will get scroll bar.
If you need to scroll to the bottom, play with anchorScroll
http://docs.angularjs.org/api/ng.$anchorScroll.