I would like to add a target (e.g. _blank) property for a basicLeafNode on the Widget Container from the extension library.
I do not see the property for this.
Instead I could use the onClick property and return an URL. But then I still would have no target defined.
I could add a postScript method
var target = url;
view.postScript("window.open('"+target+"','_blank')")
but this fires when the container is loaded.
Can I add a target property without using the onClick Property?
In case I use the onClick property what method should I use or how I prevent the postscript is executed when the container is loaded?
The basicLeafNode doesn't currently provide a target property. You have 2 courses of action:
implement your own custom node as Michael suggested (hard)
use a class on the link e.g. "newpageopen" and add an onPageReady script that selects all a elements with the calss newpageopen and add the target property to the resulted HTML.
Something like this:
require(["dojo/ready","dojo/query"], function(ready){
ready(function(){
dojo.query("a.newpageopen").attr("target", "_blank");
});
});
Hope that helps;
To make this list of solutions a bit longer here another on wich does not require dojo or jquery:
Instead of using your code as SSJS like:
var target = url;
view.postScript("window.open('"+target+"','_blank')")
You can use the Client Side Code and add SSJS code in #{javascript:}' wich i think is the shortest solution on this Problem. Here a hardcoded example:
<xe:basicLeafNode>
<xe:this.onClick><![CDATA[window.open('#{javascript: return "http://www.google.com";}','_blank');]]></xe:this.onClick>
</xe:basicLeafNode>
the above example will also work with viewScope variables or SSJS funktions:
<xe:basicLeafNode>
<xe:this.onClick><![CDATA[window.open('#{javascript: return viewScope.url;}','_blank');]]></xe:this.onClick>
</xe:basicLeafNode>
You can add the target attribute using JavaScript. It's kind of inconvenient way but would work.
You can use dojo.query to query the HTML output generated by basicLeafNode on the Widget Container. Once you get the node of <a> then you can add attribute using dojo.attr.
One problem you might face is that the ID generated by XPages contains the character :, which will not work so you would have to escape it.
function escapeColon(controlID) {
return controlID.replace(/:/g, "\\3A");
}
So your code would be something like:
dojo.addOnLoad(function() {
dojo.attr(dojo.query(escapeColon("#{id:ID_of_basicLeafNode}") + " > a")[0], "target", "_blank");
});
The code escapeColon("#{id:ID_of_basicLeafNode}") + " > a" would generate a CSS selector. Here I am assuming that basicLeafNode on the Widget Container would generate something like this <div id="_id1:basicLeafNode"><a href=".... So the CSS selector would search for a tag with that ID and inside it the <a> tag. You would have to modify this based on the output that is generated.
As I said its a bit inconvenient. Also I haven't tested this code.
Related
I have a TLDR switch on my blog.
This switch is a javascript that hides any element with the class="tldr" attribute attached to it, or unhides it.
I've created custom block_formats in TinyMCE for Paragraphs that will let me create a Paragraph with the TLDR class attached.
However, when I insert a codesample using that plugin it will generate a pre block that I can not format afterward.
I've already tried to create a custom PRE block with the TLDR class but TinyMCE won't let me apply this format to the code sample block that has been created.
Does anyone have another solution for my problem or can you see if I'm doing anything wrong?
Is there another way in TinyMCE to add attributes to elements that have been added to the code already?
I've tried the code viewer but that doesn't allow me to modify the generated HTML code.
You can use formats and style_formats to customize the styling options available to users and how they operate.
To add a custom pre block with class="tldr", you can add this config to TinyMCE:
style_formats: [
// Adds a pre format to style_formats that applies a 'tldr' class
{ title: 'TLDR', block: 'pre', classes: 'tldr' }
]
See this TinyMCE fiddle: http://fiddle.tinymce.com/Ikhaab
On its own, this will override the default style formats, but you can add them back in and position the new TLDR option within the Blocks submenu as shown here: http://fiddle.tinymce.com/Jkhaab
Resources:
https://www.tiny.cloud/docs/configure/editor-appearance/#style_formats
https://www.tiny.cloud/docs/configure/content-formatting/#formats
https://www.tiny.cloud/docs/demo/format-custom/
I'm creating the Angular app which lets user save his html code (maybe it has style and script tag to control the view) and there is a live preview next to it. User can save the code and other users can come to see the code and the preview. I also worry about the security because of script tag and I want the script to work only with the code that user provides (Not allow to control or get the data in the parent frame). So I need some suggesting of how to do it.
I have tried the preview with iFrame by giving the value through the 'srcdoc' property, but it looks like the security is bad.
You would not need to use an iframe in that situation, you can just render an HTML string inside of a div element using the innerHtml input like so:
<div [innerHTML]="htmlString"></div>
Where htmlString is a string containing the HTML code. You will have to sanitize the content of that variable with the DomSanitizer.
constructor(private domSanitizer: DomSanitizer){}
...
ngOnInit() {
this.htmlString = this.domSanitizer.bypassSecurityTrustHtml(yourHTMLString);
}
I am trying to change the p:growl position of primefaces through the .ui-growl class to use position: sticky. However, since the component is rendered at the end in body, the relative behavior of the position does not work as I would like.
Is there any way to use the sticky position for this component?
Or some way to get the component to render where it is declared?
PrimeFaces 5.1;
Mojarra 2.1;
Disclamer: I tried this with the PF 7.0 showcase, but I think the basics also work with the 5.1 version.
You effectively have 4 options. The latter three all need you to inspect the javascript source of the component (which is open, so you can ALWAYS inspect it before asking questions, the java source is irrelevant here) and for the first solution it helps to see how the component works, but inspecting with a browser developer tool is sufficient (that is how I did it).
Basic analysis with or without looking at the source
This is a variant on your "Or some way to get the component to render where it is declared?". Since on the client side, it is all plain html, css and javascript, you can manipulate with al tools available on the client-side.
You can see that the main part of the grow is html technically rendered where it is declared. Check the PrimeFaces showcase and you'll see
<span id="j_idt700:growl" class="ui-growl-pl" data-widget="widget_j_idt700_growl" data-summary="data-summary" data-detail="data-detail" data-severity="all,error" data-redisplay="true"></span>
right inside the form where it also is in the xhtml. The javascript of the component creates the client side dom things, amongst which is the container that you see right before the end of the body (from the showcase)
<div id="j_idt700:growl_container" class="ui-growl ui-widget" style="z-index: 1002;"></div>
This last piece is html is where the individual growls are added to when they need to be rendered and hence the part that makes the component in most normal cases behave correctly but needs to be done differently in your case.
Solution 1, pure client-side component agnostic solution
Effectively this is as simple as moving this piece of html in the dom, see How to move an element into another element?.
In the online showcase I put the following jquery code in the browser developer tool console
$("#j_idt700\\:growl_container").prependTo(".layout-content");
And added the following css
position: sticky;
top: 10px;
float: right; // this is needed in the showcase, might not always be needed
And it worked.
The jquery should be put somewhere in your page where it runs after the component javascript is executed, so best is to do it right before the end of the body.
Keep in mind that the j_idt700 prefix is the dynamic id of the form in the showcase (it does not have a fixed id here), but you can also use different selectors based on the classes or whatever)
Solution 2, changing the source 'locally'
In the javascript source, you can see where the container is technically rendered
render: function() {
//create container
this.jq = $('<div id="' + this.id + '_container" class="ui-growl ui-widget"></div>');
this.jq.appendTo($(document.body));
//render messages
this.show(this.cfg.msgs);
},
Changing the this.jq.appendTo($(document.body)); in some way to have it appended to the current html node ('this'?) will make it work too. Regarding the overriding, you have two options
How do I find and/or override JavaScript in Primefaces component based on widgetVar?
Override a method from a Primefaces specific widget
Solution 3 Changing the source server side
Effectively you do the first part of #2 but patch the source and create a new custom PrimeFaces version
Solution 4 Make this feature avaiable for others too
What can be done here is to create a new attribute on the component and patch the source in some places so it is configurable to have the component behave as it is now or as sticky (they changed the existing 'sticky' attribute to 'keepAlive' in 7.0.x so sticky is avalable again ;-)). Of course this should be submitted as a patch then...
Is there a way to force a new window for this menu action? I can't see anything. i was thinking of adding a class, and some JS code to redirect if the class is there.
If your only intent is to open a window in a new tab, then why don't you set the target="_blank" in your transformation or where ever you are generating the HTML markup?
I am not saying that it's incorrect, however it's just that you can avoid js for this and rather do it in HTML.
Here's what i've done.
In the Navigation panel, i added the class 'nw'. I have this snippet add the target attribute.
// we need to use .nw as a class to indicate that a link should open in a new window.
$('.nw a, a.nw').each(function(i,v){
var $this = $(this);
$this.attr('target','_blank');
});
You can use the JS option and put in JS like: window.open("http://www.google.com");
Why is that the scriptPath variable is out of scope in the bottom of the code?
Shouldn't it be in scope throughout this page? In MVC, if I mark this on top of the page like
#{
string scriptPath = "assets/scripts/",
gkoConfig = "GkoConfig.js";
}
it is available throughout the current View. What am I missing now that I'm back to WebForms for a while?
If I change the code position, It get's weirder as inside the <head> I no longer have access to teh variable, but I do have, inside the <body> now... :-/
When you declare a variable in a Web Forms .aspx file, you’re actually declaring a local variable inside an auto-generated rendering method. ASP.NET generates separate rendering methods for all tags marked runat="server", so you actually get a separate method for your head element. Now, the variable you declare can only exist in one of these methods - hence the 'weird' behavior.
You can see how this works if you pre-compile your application using aspnet_compiler.exe. You will get compiled DLL files for each of your web forms pages; just open one of those up in Reflector to see the generated code. I wrote a minimal equivalent of your code with the variable declared outside the head tag, and here’s the top-level render method that I got:
private void __Render__control1(HtmlTextWriter __w, Control parameterContainer)
{
string str = "scripts/";
__w.Write("\r\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n");
parameterContainer.Controls[0].RenderControl(__w);
__w.Write("\r\n<body>\r\n ");
parameterContainer.Controls[1].RenderControl(__w);
__w.Write("\r\n <script type=\"text/javascript\" src=\"");
__w.Write(str);
__w.Write("jquery-1.4.1.min.js\"></script>\r\n</body>\r\n</html>\r\n");
}
You see that the variable that I declared (here named str) is scoped to this method, and it's calling other methods to render the head (and a form element marked runat="server".)
A quick and dirty solution might be to simply remove the runat="server" from your head tag; however, I’d recommend that you declare a protected variable in your code-behind class for this. Adding a line like this to your code-behind file would work:
protected string scriptPath, gkoConfig;
You can then use these variables anywhere in your Web Forms code.
You could also declare your constants like this:
<script runat="server">
private const string scriptPath = "assets/scripts/";
private const string gkoConfig = "GkoConfig.js";
</script>
I suspect the head of the ASPX page gets processed separately from the body.
This problem is easily solved - all you need to do is use a class field in the code-behind with the access level set to protected.