Given Safari does not support adoptedStyleSheets to attach a constructed CSSStyleSheet, what alternative is there to achieve the same intent?
Apart from creating a <style> with CSS inside it, I'm not aware of any other method.
Reference: https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot/adoptedStyleSheets
You can use the following:
export default function generateStyles(styleCollection) {
if (document.adoptedStyleSheets) { //adoptedStyleSheets is supported
//Add to existing collection
document.adoptedStyleSheets = [...document.adoptedStyleSheets, styleCollection]
} else {
//Construct style text and add to head
var styleString = ''
for (let i = 0; i < styleCollection.cssRules.length; i++) {
styleString = styleString.concat(styleCollection.cssRules[i].cssText)
}
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = styleString;
document.getElementsByTagName('head')[0].appendChild(style);
}
}
Related
I have a lot of css filter classes that can be applied to an image using the the CSS filter. My goal is to convert the image with the filter applied to dataURL.
To do so, I'm placing the image into a canvas then saving the image after I applied the filter. Here's an example
const img = this.img // my <img />
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
context.filter = 'grayscale(2)'
context.drawImage(img, 0, 0)
const finalImg = canvas.toDataURL()
While this works fine applying a single filter, I have more than 30 filters made in my css class, and I would like to know if there's a way to apply a css class to a canvas object. Worst case scenario is for me to convert all of my filters into an array of string objects, but I'm just very curious. Thanks!
Link for reference to canvas context: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D
You can simply read the value returned by getComputedStyle(canvasElement).filter and use it as your context's filter.
var img=new Image();img.crossOrigin=1;img.onload=draw;
img.src="https://upload.wikimedia.org/wikipedia/commons/5/55/John_William_Waterhouse_A_Mermaid.jpg";
function draw() {
canvas.width = this.width/4; canvas.height = this.height/4;
var ctx = canvas.getContext('2d');
ctx.font = '15px sans-serif';
ctx.fillStyle = 'white';
for(var i=1; i<5; i++) {
// set the class
canvas.className = 'filter' + i;
// retrieve the filter value
ctx.filter = getComputedStyle(canvas).getPropertyValue('filter');
ctx.drawImage(img, 0,0, img.width/4, img.height/4);
ctx.filter = 'none';
ctx.fillText('filter' + i, 20, 20);
// export
canvas.toBlob(saveAsIMG);
}
ctx.drawImage(img, 0,0, img.width/4, img.height/4);
ctx.fillText('canvas - no filter', 20, 20);
}
function saveAsIMG(blob) {
var img = new Image();
img.onload = function(){URL.revokeObjectURL(img.src);};
img.src = URL.createObjectURL(blob);
document.body.appendChild(img);
}
.filter1 {
filter: blur(5px);
}
.filter2 {
filter: grayscale(60%) brightness(120%);
}
.filter3 {
filter: invert(70%);
}
.filter4 {
filter: none;
}
<canvas id="canvas"></canvas>
I have a use case in CKEditor where a user may need to insert a Unordered or Ordered list, but due to the site's brand guidelines, we need to provide the option to color the bullets or numbers. I have looked at the List Style plugin (http://ckeditor.com/addon/liststyle) but it does not provide that featureset nor does it provide any insight on how to add that kind of setting in the plugin itself. What are my best options to add this functionality to CKEditor?
You can create a plugin or modify an existing plugin to color the list items with this code:
var colorStyleLi = {
element: 'li',
styles: { 'color': '#(color)' }
};
var sel = editor.getSelection();
var ranges = sel.getRanges();
var st = new CKEDITOR.style(colorStyleLi, { color: color } );
for (var i = 0, len = ranges.length; i < len; ++i) {
var walker = new CKEDITOR.dom.walker(ranges[i]),
node;
while((node = walker.next())) {
if(node.type==CKEDITOR.NODE_ELEMENT) {
st.applyToObject(node, editor);
} else {
var p = node.getParent();
st.applyToObject(p, editor);
}
}
}
I have been trying to create a Placemark that I can hide and show (like turning visibility on and off) on demand (on click)... I am using this to make the placemark:
function placemark(lat, long, name, url, iconsrc){
var placemark = ge.createPlacemark(name);
ge.getFeatures().appendChild(placemark);
placemark.setName(name);
// Create style map for placemark
var icon = ge.createIcon('');
if(iconsrc == "0")
icon.setHref('http://maps.google.com/mapfiles/kml/paddle/red-circle.png');
else{
icon.setHref(iconsrc);
}
var style = ge.createStyle('');
style.getIconStyle().setIcon(icon);
if(iconsrc != "0")
style.getIconStyle().setScale(2.5);
placemark.setStyleSelector(style);
// Create point
var point = ge.createPoint('');
point.setLatitude(lat);
point.setLongitude(long);
//point.setAltitudeMode(1500);
placemark.setGeometry(point);
google.earth.addEventListener(placemark, 'click', function(event) {
// Prevent the default balloon from popping up.
event.preventDefault();
var balloon = ge.createHtmlStringBalloon('');
balloon.setFeature(placemark); // optional
balloon.setContentString(
'<iframe src="'+ url +'" frameborder="0"></iframe>');
ge.setBalloon(balloon);
});
}
I have tried everything... from this:
function hidePlacemark(name){
var children = ge.getFeatures().getChildNodes();
for(var i = 0; i < children.getLength(); i++) {
var child = children.item(i);
if(child.getType() == 'KmlPlacemark') {
if(child.getId()== name)
child.setVisibility(false);
}
}
}
to using this ge.getFeatures().removeChild(child);
can anyone point me to the right direction on creating a function that will allow me to turn the visibility on/off on demand please.
Your hidePlacemark function is missing some {} in your final IF statement
if(child.getId()== name)
you have
function hidePlacemark(name){
var children = ge.getFeatures().getChildNodes();
for(var i = 0; i < children.getLength(); i++) {
var child = children.item(i);
if(child.getType() == 'KmlPlacemark') {
if(child.getId()== name)
child.setVisibility(false);
}
}
}
make it
function hidePlacemark(name){
var children = ge.getFeatures().getChildNodes();
for(var i = 0; i < children.getLength(); i++) {
var child = children.item(i);
if(child.getType() == 'KmlPlacemark') {
if(child.getId()== name) {
child.setVisibility(false);
}
}
}
}
HOWEVER ------- you are better off doing this as it is much faster as you don't need to loop through ALL your placemarks
function hidePlacemark(name) {
var placemark = ge.getElementById(name);
placemark.setVisibility(false);
}
I think the plain ge.getFeatures().removeChild(placemark); works.
I played with this GooglePlayground, and just added the following code to line 8 (that is empty in this GooglePlayground Sample):
addSampleButton('Hide Placemark', function(){
ge.getFeatures().removeChild(placemark);
});
Clicking the button Hide Placemark hides the placemark like a charm here. Any chances your problem is somewhere else in your code?
I did change some features style (through check-boxes) using style property :
var features = layer.features;
for( var i = 0; i < features.length; i++ ) {
//features[i].style = { visibility: 'hidden' };
features[i].style = 'none';
}
layer.redraw();
Now if I check the box again, it supposed to display again but nothing happens!
I tried:
features[i].style = 'block';
OR
features[i].style = 'delete';
then redraw the layer.. but this doesn't work
Any Idea ?
Try this:
// set style
features[i].style = null;
// or
features[i].style = {display:'none'};
// redraw feature
layer.drawFeature(features[i]);
I'm using tinyMCE for small site, that is used by people to write simple articles. Usualy they write in MS word and copy text to tinyMCE and submit this.
That's why I only allowed few tags:
valid_elements: "a[href|target],strong/b,em/i,div[align],br,p[style|align],ul,li,ol,table,tr,td,iframe[*],img[*]",
But despite allowing img[*] after inserting image by 'Insert/edit image' only:
<img alt=""/>
appears in code. Same goes for iframe (which is complitly removed)
I've already tried every combination of valid_elements with full list of img and iframe attributes and with extended_valid_elements.
When I remove valid_elements clause everything works fine, but then word formatting which is not allowed (h1, h2, etc) is messing up styles.
TinyMCE version is 3.4.2.
I am using the paste_preprocess setting with the tinymce paste plugin and i filter out unwanted tags there. Here is an example:
in your tinymce init:
paste_preprocess : function(pl, o) {
//if(console) console.log('Object', o);
//if(console) console.log('Content:', o.content);
// usage param1 = the string to strip out tags from, param2 = tags to keep in the string
o.content = ir.im.strip_tags( o.content,'<p><div><br><br/>' );
},
Help function to strip out tags:
strip_tags = function (str, allowed_tags) {
var key = '', allowed = false;
var matches = []; var allowed_array = [];
var allowed_tag = '';
var i = 0;
var k = '';
var html = '';
var replacer = function (search, replace, str) {
return str.split(search).join(replace);
};
// Build allowes tags associative array
if (allowed_tags) {
allowed_array = allowed_tags.match(/([a-zA-Z0-9]+)/gi);
}
str += '';
// Match tags
matches = str.match(/(<\/?[\S][^>]*>)/gi);
// Go through all HTML tags
for (key in matches) {
if (isNaN(key)) {
// IE7 Hack
continue; }
// Save HTML tag
html = matches[key].toString();
// Is tag not in allowed list? Remove from str!
allowed = false;
// Go through all allowed tags
for (k in allowed_array) { // Init
allowed_tag = allowed_array[k];
i = -1;
if (i != 0) { i = html.toLowerCase().indexOf('<'+allowed_tag+'>');}
if (i != 0) { i = html.toLowerCase().indexOf('<'+allowed_tag+' ');}
if (i != 0) { i = html.toLowerCase().indexOf('</'+allowed_tag) ;}
// Determine
if (i == 0) { allowed = true;
break;
}
}
if (!allowed) {
str = replacer(html, "", str); // Custom replace. No regexing
}
}
return str;
};