How can I change iframe background color on design time?
By design time I mean the following:
My class extends CompositeControl where i implement design-time support.
this is part of CreateChildControls():
editor = new HtmlGenericControl("iframe");
editor.ID = "editorID";
editor.Style["background-color"] = "Red";
editor.Style["color"] = "Black";
editor.Style["position"] = "absolute";
editor.Style["left"] ="0px";
editor.Style["top"] = "0px";
editor.Attributes["width"] = editorWidth.ToString() + "px";
editor.Attributes["height"] = editorHeight.ToString() + "px";
editor.Attributes["frameborder"] = "0";
editor.Attributes["scrolling"] = "auto";
You have to set the background of whatever page the iframe is pointed to (the src attribute) ;)
If the iframe is pointing to the same domain as you, then you could use Javascript to alter the background color or add an additional stylesheet - but this isn't at design time, either.
What is this iframe for?
Related
I wonder how can I use css/javascript to adjust the blinking cursor inside the search box with CSS?
Is it possible to replace default blinkig caret to horizontal blinking icon
I don't think it is so hard. I made a quick example, which works in most modern browsers except Safari.
It draws the caret on a canvas, and sets it as a background of the input, on a position calculated from the browsers caret position.
It checks if the browser supports the caret-color css property, and if it doesn't it doesn't do anything, because both the system caret, and our caret will be visible in the same time. From the browsers I tested, only Safari doesn't support it.
$("input").on('change blur mouseup focus keydown keyup', function(evt) {
var $el = $(evt.target);
//check if the carret can be hidden
//AFAIK from the modern mainstream browsers
//only Safari doesn't support caret-color
if (!$el.css("caret-color")) return;
var caretIndex = $el[0].selectionStart;
var textBeforeCarret = $el.val().substring(0, caretIndex);
var bgr = getBackgroundStyle($el, textBeforeCarret);
$el.css("background", bgr);
clearInterval(window.blinkInterval);
//just an examplethis should be in a module scope, not on window level
window.blinkInterval = setInterval(blink, 600);
})
function blink() {
$("input").each((index, el) => {
var $el = $(el);
if ($el.css("background-blend-mode") != "normal") {
$el.css("background-blend-mode", "normal");
} else {
$el.css("background-blend-mode", "color-burn");
}
});
}
function getBackgroundStyle($el, text) {
var fontSize = $el.css("font-size");
var fontFamily = $el.css("font-family");
var font = fontSize + " " + fontFamily;
var canvas = $el.data("carretCanvas");
//cache the canvas for performance reasons
//it is a good idea to invalidate if the input size changes because of the browser text resize/zoom)
if (canvas == null) {
canvas = document.createElement("canvas");
$el.data("carretCanvas", canvas);
var ctx = canvas.getContext("2d");
ctx.font = font;
ctx.strokeStyle = $el.css("color");
ctx.lineWidth = Math.ceil(parseInt(fontSize) / 5);
ctx.beginPath();
ctx.moveTo(0, 0);
//aproximate width of the caret
ctx.lineTo(parseInt(fontSize) / 2, 0);
ctx.stroke();
}
var offsetLeft = canvas.getContext("2d").measureText(text).width + parseInt($el.css("padding-left"));
return "#fff url(" + canvas.toDataURL() + ") no-repeat " +
(offsetLeft - $el.scrollLeft()) + "px " +
($el.height() + parseInt($el.css("padding-top"))) + "px";
}
input {
caret-color: transparent;
padding: 3px;
font-size: 15px;
color: #2795EE;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" />
If there is interest, I can clean it a bit and wrap it in a jQuery plugin.
Edit: forgot about the blinking, so I added it. A better way will be to add it as css animation, in this case the caret should be in a separate html element positioned over the input.
Changing the color of the caret is supported by the latest standards. But not changing its width is not, which I think is a shame because it is a question of accessibility for vision-impaired people.
One approach for implementing such a change yourself is first trying to figure out what is the position the caret is blinking at, then overlaying it with an element that looks like the caret but is perhaps wider etc.
Here's an article on how to go about doing such a thing. It's a good article but the end-solution is kind of complicated as a whole. But see if it solves your problem:
https://medium.com/#jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a
Here is perhaps a simpler explanation for how to find the care x-y position:
How do I get the (x, y) pixel coordinates of the caret in text boxes?
Wirecloud uses iframes to render the html of widgets. This seems to create problems for some advanced svg features that require references to internal definitions (see also this discussion).
The js code producing the svg works fine in single page app or django view.
There are no error messages.
The entire code is too big to post here, but the key relevant elements are:
var canvas = document.getElementById("canvas");
var svgns = "http://www.w3.org/2000/svg";
var svg = document.createElementNS(svgns, 'svg');
then a typical definition (for example a gradient):
var defs = document.createElementNS(svgns, "defs");
var linearGradient = document.createElementNS(svgns, "linearGradient");
and finally the use of the definition
arc.setAttribute('style', "fill:url(about:srcdoc#linearGradient);");
It is the reference (here to #linearGradient) that is not properly linked to when the svg object is created (when inspecting the created graphics the fill attribute is null)
Normally in svg you just use url(#reference). Have tried "about:blank" and "about:srcdoc" as workarounds as suggested elsewhere on SO but somehow they don't seem to work (chrome / firefox)
This seems to be an issue with svg / iframe (not wirecloud specific) but I have not tried to render the svg in iframe outside wirecloud to confirm this.
If there is no workaround this would limit the type of svg graphics that can be rendered within a wirecloud widget programmatically using javascript. Maybe some of the other ways of embedding svg would work (fetching it from the server) but its not optimal design for interactive widgets, or maybe an iframe alternative :-)
All the architecture of WireCloud is based on iframes. Those elements are used for providing the isolation between each of the widgets and operators and, currently, cannot be disabled. Moreover, the proposed alternative (webcomponents) is not matured enough to be a real alternative :(.
Anyway, WireCloud doesn't make use of the srcdoc attribute, so your problem rendering SVG images inside widgets should not be related to the linked question. The problem seems to be related to the use of the <base> element (which is injected by WireCloud into the HTML of the widget). See this answer for more details. We have created a ticket for analysing if we can remove the <base> element, but for now, you will have to use absolute URLs. E.g.:
var baseUrl = window.location.origin + window.location.pathname + window.location.search;
arc.setAttribute("fill", "url(" + baseUrl + "#MyGradient)");
This is the full code of my "SVG example widget":
var baseUrl = window.location.origin + window.location.pathname + window.location.search;
var svgns = "http://www.w3.org/2000/svg";
var svg = document.createElementNS(svgns, 'svg');
document.body.appendChild(svg);
var defs = document.createElementNS(svgns, "defs");
var linearGradient = document.createElementNS(svgns, "linearGradient");
linearGradient.setAttribute("id", "MyGradient");
defs.appendChild(linearGradient);
svg.appendChild(defs);
var stop = document.createElementNS(svgns, "stop");
stop.setAttribute("offset", "5%");
stop.setAttribute("stop-color", "green");
linearGradient.appendChild(stop);
stop = document.createElementNS(svgns, "stop");
stop.setAttribute("offset", "95%");
stop.setAttribute("stop-color", "gold");
linearGradient.appendChild(stop);
var rect = document.createElementNS(svgns, "rect");
rect.setAttribute("x", "10");
rect.setAttribute("y", "10");
rect.setAttribute("width", "100");
rect.setAttribute("height", "100");
rect.setAttribute("fill", "url(" + baseUrl + "#MyGradient)");
All:
Right now, I want to draw a svg and style it with external style. Everything goes well until I try to down load it:
function chartExporter(svg){
// svg is a D3 object
svg.attr("version", 1.1)
.attr("xmlns", "http://www.w3.org/2000/svg");
var svgDOM = svg.node();
var html = svgDOM.outerHTML;
var imgsrc = 'data:image/svg+xml;base64,'+ btoa(html);
imgobj.src = imgsrc;
imgobj.onload = function(){
var a = document.createElement("a");
a.download = "sample.svg";
a.href = imgsrc;
a.click();
}
}
The problem here is: If I use D3 to add inline style or attributes, the svg downloaded seems good, but if I use external css file to include style, those styles can not be applied to svg when converted( it make sense, cos they are not in that html string), I wonder how to bring those style into svg?
Thanks
We can use canvas for drawing custom shapes.
I need to draw my shape dynamically as a canvas item and place it for a div background item.
My pages generates run time and they aren't static html code so i can't use tricky methods.
What's your idea?
Regards
Looks like you searching for toDataURL().
UPD:
Here a usage exaple:
dataUrl = your_canvas.toDataURL();
your_div.style.background='url('+dataUrl+')'
Live demo on jsFiddle
Sounds like you need canvas2image: https://github.com/hongru/canvas2image
You can create a canvas and then get the contents as a png:
var canvas = document.createElement("canvas");
....do stuff here...
var img = Canvas2Image.convertToPNG(canvas, canvas.width, canvas.height);
Then all you need to do is use the png as a background image:
document.body.style.background = "url(" + img.src + ")";
Please correct me if any of this is wrong.
Is it possible to make the background image of a DIV a canvas that can be modified with getContext("2d")?
Well, you could place a canvas element inside of the div, maximize its height and width, set its position to relative and its z-index to a negative value.
However, if you want to use a real CSS background-image:... you would have to create your image inside your canvas. You could then use toDataURL to get a data url which you could use as value for your original background-image:
var canvas = document.getElementById('canvas');
var data = canvas.toDataURL();
var myElement = document.getElementById('myelement');
myElement.style.backgroundImage = 'url('+data+')';
If you don't want to create a new background but manipulate an existing one, load your original background into an Image object (or get a reference) and use drawImage:
var image = new Image();
image.onload = function(){
context.drawImage(this,0,0);
someCallbackToManipulateTheImage();
}
var src = myElement.style.backgroundImage.substr(4);
src.substr(0,src.length - 1);
image.src = src;
Set the background-image of the div to this:
"url('" + canvas.toDataURL() + "')";
Edit: At that point, note that you are also free to do what you wish with the canvas, as the background-image will continue to contain only the image data that was in the canvas at the moment that you called canvas.toDataURL(). Feel free to discard or draw onto the canvas, as it will not affect your div's background at that point.
You can have a canvas inside the div with absolute css position, other elements have to have z-index greater than the canvas.