On my jsf page at some point I send a message to the growl component.
<p:growl id="growlLong" for="growlLong" showDetail="true" life="10000" sticky="false"/>
Once the 10sec is over, or dismissed by clicking the X, the issue that occurs is the element below the growl is not selectable. By inspecting the components on the page, looks like the actual div stayed there and blocks the content below it.
<?xml version="1.0" encoding="UTF-8"?>
<div class="ui-growl-item">
<div class="ui-growl-icon-close ui-icon ui-icon-closethick" style="display: none;" />
<span class="ui-growl-image ui-growl-image-info" />
<div class="ui-growl-message">
<span class="ui-growl-title">Success!</span>
<p>Configuration successfully saved.</p>
</div>
<div style="clear: both;" />
</div>
So, the question is - how do I make this to go away and keep the content below still usable?
Here is the screenshot of the issue, as seen with "inspect element", blue boxes are existing links, red box is the dismissed growl. Inside the blue box, we can't click the part that is covered by the red box.
This topic might be older but I just recently stumbled upon it:
The reason that the showcase is working but my version was not was that I gave the .ui-growl CSS class a height AND a width. In the showcase, the size of the container is only defined by its content and thus 0 if there are no items to display.
I moved my height definition to .ui-growl-item (which is more appropriate anyhow) and now it's working like a charm.
While the it would be desirable to be able to tell growl to not leave behind the <div id="growlLong_container"> structure in the DOM, the simple solution is to just select it and remove it using your favorite method to manipulate the DOM.
The ID appears to be the ID you passed to growl: id="growlLong" + "_container". With a DOM ID it is a simple matter of selecting it and removing it.
Yes, it would be nice to be able to get growl to not leave it in there. However, there is a point of diminishing returns vs. the amount of effort you spend trying to find a solution. It appears to be well past the point where you should just use a hack and remove it. Make a note about it, move on. Leave a comment in the code that this is why you are making the DOM manipulation. A possibility rather than removing teh <div> is to adjust the z-index such that it is below that of the UI elements. Another possibility is to add display:none; to the style. Obviously, code it such that if the <div> is not there nothing goes wrong. Verify that the next use of growl still performs correctly.
Ask on the Growl discussion group. Submit it as a bug with growl. If a way surfaces to make growl not leave something like this in the DOM revisit the code and apply it.
As to removing it, if you have JavaScript available it is as simple as:
document.getElementById("growlLong_container").remove();
To be more specific we really need more information about your code and the environment in which you are running.
A "solution" that should remove the <div>:
Hopefully you will receive an answer which allows the elements to be hidden/removed by growl. However, there does not appear to be one at present.
The following script should wait around checking every 250ms to see if the <div id="growlLong_container"> has been entered into the DOM. Once the <div> has been entered into the DOM, the script will wait 10s. If the <div> exists after the 10s it will be removed. The script is a hack. But it should work.
You will need to place it such that it makes it onto the page, either enclosed in tags (as are here), or in a file without the first line:<script class="code" type="text/javascript"> and the last line: </script> removed. If you use a separate file you will need to have it included in a similar manner as you do jquery.js, foundation.js, foundation.topbar.js and foundation.tooltip.js.
<script class="code" type="text/javascript">
(function () {
"use strict";
const maxGrowlTime = 10000; //In milliseconds
const checkFrequency = 250; //In milliseconds
var intervalTimer=0;
var foundGrowl=false;
function dismissGrowl() {
var growlId;
growlId = document.getElementById("growlLong_container");
if(growlId) {
growlId.parentNode.removeChild(growlId);
}
foundGrowl=false;
setGrowlCheckInterval();
}
function checkForGrowl() {
var growlId;
if(foundGrowl) {
return;
}
growlId = document.getElementById("growlLong_container");
if(growlId) {
foundGrowl=true;
clearInterval(intervalTimer);
setTimeout(dismissGrowl, maxGrowlTime );
}
}
function setGrowlCheckInterval() {
intervalTimer = setInterval(checkForGrowl, checkFrequency );
}
setGrowlCheckInterval();
})();
</script>
My hope is that you find an answer that does not require a hack such as this. However, this should solve your problem, at least to an extent. With the script, the prevention of using those controls will last for at least the entire 10s up to 10.25s even if the user dismisses the growl early. With the two screenshots mentioned in the comments it would probably be possible to change the script such that it detects if the user dismisses the grow and then remove the <div> immediately. This would make it more responsive to user input.
This solution assumes that the <div id="growlLong_container"> does not exist in the DOM prior to your issuing the <p:growl id="growlLong" and that it is not needed afterwards. This is very likely because the ID of the dive appears to be composed of the ID you pass the growl.
Mainly, this issue looks like a bug or incompatibility issue between components.
Related
I'm looking to create a reusable, modularized component in Umbraco 9. I've never worked with any Umbraco before. The example I'll use is a text widget/component that has an image on the left and text on the right, with the ability to set whether you want to swap this to be image right, text left.
I come from the Sitecore world where creating a component like this would mean creating a definition with the fields in the back office, creating an MVC controller and an action, and pointing that back office definition at the controller/action combo. Then, anywhere I've deemed a component hot spot, I can click an "add component" and it'd display the available components I've created (Text + Image Block, in our example).
Our team has been researching how to do something like this in Umbraco. We've been using element types. I've got it working where I can create a list of element types, but we couldn't figure out how to add a controller/action/view to this process to really control what gets displayed.
We've looked into the Grid Type Editor. That requires some Angular work that wasn't exactly playing nice, for some reason it was seeing our image fields as null even though they had an image.
We also tried messing with the Block List editor, and are currently investigating macros.
We've been spinning our wheels and I'm hoping to get some assistance on how to do something like this in Umbraco. Perhaps I'm searching/using the wrong terminology?
Most of our components are super simple, and rather than create a reusable component, we can just use the grid editor. In our example above, we could create a 50/50 grid row and put an image in the left column and the text in the right. This would work, but we'd like to have a little more of a reusable package. Furthermore, a few of the components will require some controller functionality to be able to hit an API and massage some data before passing it to the presentation layer.
We will keep investigating, but ultimately I'm hoping someone can clear up if we're going down the wrong path, or just missing some crucial point here.
Sure! Two ways come to mind for me. One would be make a simple doctype like the screenshot below and let layout decide how to stack them
This sample uses bootstrap which of course you don't have to use, and in my case I have them in a nested content element so I basically just loop through them and alternate putting flex-row-reverse on the row.
#{
var i = 0
foreach(var contentBlock in Model.ContentBlocks)
{
<div class="d-flex flex-wrap align-items-center #(i %2 != 0 ? "flex-row-reverse" : null)">
<div class="block-left col-sm-7">
<h5>#contentBlock.SectionHeading</h5>
#Html.Raw(contentBlock.SectionDescription.ToString())
</div>
#if(contentBlock.HasValue("sectionImage") && contentBlock.SectionImage != null)
{
<div class="block1-right col-sm-5 ml-auto">
<figure class="hover">
<img id="#contentBlock.SectionImage.Name.Trim().Replace(" ", "-")" src="#contentBlock.SectionImage.Url">
</figure>
</div>
}
</div>
i++;
}
}
The other way (as you asked for) is to give the content editor the choice with a toggle, add a toggle to the doctype
and instead of this line
<div class="d-flex flex-wrap align-items-center #(i %2 != 0 ? "flex-row-reverse" : null)">
you could use this line
<div class="d-flex flex-wrap align-items-center #(contentBlock.SectionAlignment == true ? "flex-row-reverse":null)">
Or even something like this where you just assign your own class and write the CSS separately
<div class="d-flex flex-wrap align-items-center #(contentBlock.SectionAlignment == true ? "block-right":"block-left")">
Hope that helps get you going in the right direction. I'm sure you'll have to adapt this for your situation and this code is not tested.
Happy to help if you have any issues.
I have a situation with the Sortable I can't seem to replicate in Plunker.
From what I can tell, Sortable slows down a lot because of something in change detection. Slow to the point of unusable. Visually, you can see the first animation, but then it very slowly refreshes as it slowly finishes change detection.
Here's a plunker that mimics what I have in my code.
http://plnkr.co/edit/veH2Y6CkFZ1Dc5jwcPWZ?p=preview
<kendo-sortable [data]="columns"
zone="abcdefg"
[animation]="true"
[activeIndex]="activeIndex"
itemClass="item"
emptyItemClass="emptyItem"
activeItemClass="activeItem item">
<ng-template let-column="item">
<div class="container" (click)="itemClick(column)">
<span class="col-name">
{{column.title || column.field}}
</span>
<span class="col-width">{{column.width}}</span>
</div>
</ng-template>
</kendo-sortable>
Basically the dialog is wrapped in a reusable component where I feed strings, templates or components into.
The "columns" array coming into the Input of SortableThingComponent is a copy of the array (all new'd Column objects) from a kendo grid.
Since I can't replicate the slow-down, I'm not sure what's going on. Does anyone see anything or have any tidbits about Sortable?
Edit
Here's an updated plunker that includes a grid. I noticed that if I didn't have data in the grid, the Sortable was faster. Workable, but still a little bit slow. The grid is virtual scrolling, page size 100.
http://plnkr.co/edit/hw8HaKpyZ0lRlVwF2tYp?p=preview
Edit 2
Updated the last plunker with data. Now I'm repro'ing the issue.
What can be done about this?
Here's a fix for now; detach the change detector for the grid component while the dialog with the sortable is open: http://plnkr.co/edit/yy1Z4rWC53vS3xCnxrWT?p=preview
constructor(private changeDetectorRef: ChangeDetectorRef) { }
this.changeDetectorRef.detach(); // when dialog opens
this.changeDetectorRef.reattach(); // when dialog closes
In the plunker, I had to add a this.changeDetectorRef.detectChanges() because of the way I'm opening the dialog.
For now, this is an OK workaround. I might play with the change detection strategy to get it all a little more efficient
We have implemented a layout where the main content resides in dynamic sidebars. We defined following layoutTemplate:
<template name="layout">
{{> content}}
{{> leftbar}}
{{> rightbar}}
<nav class="navigation">
{{#if currentUser}}
{{> navigation_logged_in}}
{{else}}
{{> navigation_logged_out}}
{{/if}}
</nav>
</template>
We include e.g. the rightbar template in the layout template.
<template name="rightbar">
<aside class="rightbar">
<button id="closeRightBar" class="close-cross"></button>
{{yield 'rightbar'}}
</aside>
</template>
The rightbar template includes the rightbar yield where we yield the specific content into.
We have implemented following RouteController:
UserShowRouter = RouteController.extend({
before: function() {
var username = this.params.username;
if(App.subs.user) {
App.subs.user.stop();
}
App.subs.user = Meteor.subscribe('user', username);
},
waitOn: function () {
return Meteor.subscribe('user');
},
data: function() {
return Meteor.users.findOne({'profile.username': this.params.username});
},
action: function() {
this.render('profile', {to: 'rightbar'});
}
});
What we wanted to achieve is that for example the profile template is yielded into the rightbar yield and get's updated and re-rendered as the data changes.
The problem is now that the sidebars are dynamically animated, shown and hidden. Now every time the profile template gets re-rendered also the layout template gets re-rendered. Why is that? We thought one of the purposes of yield regions is that the whole site doesn`t need to be re-renderd. Now when the layout gets re-rendered the whole css of the animations are set back to the original values.
We now have tried several different approaches, but none of them seems to be a good and clean solution. Is there a way to keep the layout template from being re-rendered and just keep the yield region and template up-dated? Any suggestions or alternatives would be highly appreciated.
As I understand it, the behavior in which re-rendering of your templates "bubbles up" and causes re-rendering of their parent templates is not particular to iron-router or the way your code is implemented, but is inherent in Spark. Iron-router's {{yield}} pattern does not alter this behavior, as far as I can tell from its documentation.
The good news is that Spark is set to be replaced imminently with a newer, more fine-grained rendering engine, currently codenamed "Spacebars," which should alleviate the concern.
Here is a preview of the new rendering system:
https://github.com/meteor/meteor/wiki/New-Template-Engine-Preview
This talk from a week ago is also excellent at describing the benefits coming through the new rendering engine (while fairly long, an overview is given in the first 5 minutes):
https://www.youtube.com/watch?v=aPf0LMQHIqk
As for your options today, you can:
a) Use the {{#constant}} and {{#isolate}} parameters to try to limit re-rendering.
b) Work from a development branch as described in the link above:
You can play with the current work-in-progress version of the code using the template-engine-preview-4 release tag (run your app with meteor --release template-engine-preview-4), or by checking out the shark branch (it's an internal codename).
c) Best of all if the timeframe of your project allows is to allow the re-rendering to continue until Meteor 1.0 hits and "Spacebars" resides on the main branch - it sounds like this is 1-3 months away.
I think that the reason your layout template gets rerendered is because the data hook you implemented uses a reactive data source. If the current user object changes, the router probably decides to rerender the whole page because there is no simple way to decide which parts exactly depend on your reactive data.
If I'm right, a simple solution to your problem is to create a user helper that will fetch the necessary data only where they're actually needed, e.g.
Template.profile.user = function () {
return Meteor.users.findOne({/*...*/});
}
Then you can use it in your profile template along with the with helper (sic!), i.e.
{{#with user}}
...
{{/with}}
to prevent multiple calls to the Template.profile.user function.
Also, if I were you, I would use the data hook only for data which is required by templates in my layout.
I am having some problems getting CodeMirror to indent the code at the beginning of a new line.
I have a text area, and when I hit save, the code that is saved to the DB is something like:
<meta charset=\"utf-8\">\r\n\t\t\t<title></title>\r\n\r\n<div class=\"wra ... etc
But when I read that out and do in the code behind in asp.net, ViewCode.Text = dbModel.ViewCode ... i.e. try to assign that string to the textarea which will then be 'converted' into the code mirror editor with relevant js on the page, the indent at the start of new lines is lost. If I indent half way along a line however, those render.
Also, if there is a new line return and then a blank row and then more text, the blank row gets lost when read back out to the text area.
Note: the textarea is runat server to fill the value from the database. I have tried with divs and literals but can't get it working.
So how can I save something like:
<div>
<b>
test
</b>
</div>
and not get it back like
<div>
<b>
test
</b>
</div>
I presume I have to encode it on save but I swear I have tried all encoding methods and now work! lol
Any pointers would be appreciated.
Cheers
Robin
Update/Solution
I have come back to put this in, in case some one stumbles across this post.
Basically I could not still not get the following to play nicely on the particular page in question. I.e.
Code behind
ViewCode.Value = dbModel.ViewCode
where
dbModel.ViewCode
// --> is comes from db as e.g.:
// <meta charset=\"utf-8\">\r\n\t\t\t<title></title>\r\n\r\n<div class=\"wra ... etc
JS (at end of page)
<script>
var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("ViewCode"), {
lineNumbers: true
});
</script>
What I did get working however, is if you put the same JS code on the page, however, do NOT fill the text area from the code behind. Then I just make a simple ajax call to a page method to get the data (on page load).
$.ajax({
url: '/WidgetMaint.aspx/GetFileHTML',
type: 'Get',
contentType: 'application/json',
data: { tempid: id },
success: function(result) {
myCodeMirror.setValue(result.d);
}
});
The save and everything else works perfectly because the textarea is still run at server, so can still get its value 'on save', as code mirror takes care of this.
I am fairly sure that there is something else in the pipeline which is stuffing around with the text and 'formatting' it different before code mirror can get to it in time in the first attempt I was doing. However, with the ajax call the problem goes away because the browser/framework/whatever does not have any opportunity to access the string the DB returns. It is feed straight to the instance of code mirror which deals with it.
So in case you are having a similar problem, might be easier to change approach....
Cheers
Robin
Note: accepted answer by Eliran as it gave me this idea, and upvoted Marjin, because that comment proved it code mirror can handle indents...
I would advice you to drop that textarea and keep a live instance of CodeMirror on the page. That way you can assign the response directly to that instance using the CodeMirror API.
Take a look at doc.setValue(content: string) in particular, that should get you on the right track.
I created a script to publish the following html page using Html Service:
<html>
<div id="fixeddiv"></div>
<script>
var div=document.getElementById("fixeddiv");
div.style.position="fixed";
alert(div.style.position);
</script>
</html>
The alert window shows an empty string.
Isn't possible to set a fixed position for a div element?
I just ran into the same thing and the answer appears to be NO. Apparently they're worried fixed divs are a security exposure.
Next thing they'll be wanting to remove the keys from our keyboards too ;-)
I used this to get a 'fixed' effect for a global navbar at the top. It might be of use to you or others.
$(document).ready(function() {
$( window ).scroll(function() {
$( '.fixed' ).css('top', $( this ).scrollTop());
});
});
Note: in GAS the $( window ).scroll() wasn't working for me so I instead created a div block the size of the view port with a scroll bar overflow and used that instead.
I've found another 'solution' for this:
I created 2 divs, fixedHeader and content
<div id="fixedHeader"></div>
<div id="content"></div>
The css code, where we set #fixedHeader to be always on top and for #content we set a padding-top matching the height of #fixedHeader so the elements won't get under #fixedHeader:
#fixedHeader {position:absolute; top:0;}
#content {padding-top:50px; overflow:auto;}
And finally javascript to make #contet match the height of the viewport when document loads:
$(function(){ $("#content").css('height',window.innerHeight); }
Hope it helps
It appears that position:fixed is not allowed due to security concerns: http://code.google.com/p/google-apps-script-issues/issues/detail?id=1840