How to disable Evernote web view "max-width" with JavaScript? - javascript

Evernote places a max-width limit on web view content, and I have identified its location in Chrome developer tool(F12). Evidence: Unticking the checkbox beside "max-width" will stretch the table to full window width.
My question is, how can I remove that css statement with JavaScript code?
I have tried this:
document.getElementById("container").style.removeProperty("max-width")
but in vain.
The above web page can be reached at http://www.evernote.com/l/ABXYD6q6bM9MyaAfRs78hQnq6VMINfVJODg/

Given that this statement isn't set as inline style, you won't be able to remove it.
However, you could change its value and set it to none by adding an inline style declaration, which will override the current value.
Demo:
var elem = document.getElementById('container');
elem.style.maxWidth = 'none';

Not sure how webview works, but could you try using javascript to add a new class to it that added a max-width of 100%?
document.getElementById("container").classList.add('no-max-width');
then in the styles.css put
.no-max-width {
max-width: 100%; }
If that's not possible, then try
document.getElementById("container").style.maxWidth('100%');
Though I sometimes have trouble with .styles so not sure if that is exactly right, plus I've read it's better to add classes rather than play with css styles in JS, but also not sure how accurate that is.

Related

Change css property of a widget added via the google tag manager and loaded aynchronously in an iframe

I have added a widget on my web site that shows on the lower-right corner of the screen, but I'd rather it appeared on the bottom-left side. The google tag is a script like this
<script src="https://leadbooster-chat.pipedrive.com/assets/loader.js" async></script>
And after loading the script generates an iframe with appropriate css positioning
HTML
<iframe role="complementary" scrolling="no" id="LeadboosterContainer" class="proactiveChat" style="height:100px !important"></iframe>
CSS
#media (min-width: 576px)
<style>
html body #LeadboosterContainer {
bottom: 28px !important;
right: 28px !important;
}
It turns out the widget is not configurable via their interface to appear on the left hand screen (I'll send them a suggestion), but I have discovered that simply changing the right: 28px !important; to a left is enough to produce a quite acceptable behavior.
I'm aware that the developers may change this property in the future, and that the solution I'm thinking of would be a bit dirty, but is it possible to accurately target the CSS generated AFTER the widget is loaded via the script, and change the right to a left ? As you can see, the challenges here
The script is loading the HTML asynchronously
There is is a media query (and actually there are several rules that would need changing)
there is a !important flag which makes it harder to override this CSS rule in a brand new stylesheet
this is an iframe on another website... so we cannot do anything we want since security policies apply inside the iframe, and we only have the control on the iframe element itself for positioning
How can I do this ? I need to trigger an event after an async script has started, and then find a way to target media queries.
An example of what I'm thinking of adding to my google tag
// TODO : find a way to fire this code after the script has loaded / implement runAfterChatBotHasLoaded
runAfterChatBotHasLoaded( function() {
var pipedriveBot = document.getElementById("LeadboosterContainer");
// TODO : find a way to target each media query
position = pipedriveBot.getAttribute('right');
pipedriveBot.setAttribute('left', position)
pipedriveBot.removeProperty('right'));
});
I have also tried
Adding rules via https://davidwalsh.name/add-rules-stylesheets (I run into a Uncaught DOMException: Failed to execute 'insertRule' on 'CSSStyleSheet': The index provided (1) is larger than the maximum index (0).
Various ideas from Find all CSS rules that apply to an element
If the widget is in the iframe then you require either:
GTM in the iframe, not just the parent window
The post message api to securely call functions between the iframe and parent window (the parent window being where GTM is loading)
If the css you are targeting is in the iframe then you need to treat it as a different website that doesn't have your GTM container loaded on it.
If you're trying to move the iframe to the bottom left then this is working for me in a jsfiddle:
var pipedriveBot = document.getElementById("LeadboosterContainer");
// remove the styling
pipedriveBot.style.setProperty('bottom', '0', 'important');
// Add your own
pipedriveBot.style.position = "fixed";
pipedriveBot.style.left = "0px";
See also this article on removing css properties that are set with !important: How can you remove an important CSS property?
Let me know if I have understood correctly. If you need to wait until the DOM contains LeadboosterContainer then you can set a function to check the DOM periodically and then fire a function.

Can I use javascript to place one element on different places, one for mobile and one for desktop?

I am adding an element in the dom using javascript. I have added an using insertBefore() to place it where I want it on the mobile view. But in desktop it is supposed to be placed on a different space on the website. How can i solve this?
Just using CSS is not an option due to already existing elements that i cant't move.
var priceWrapper = document.querySelector('.price-info-wrap')
var mainContainer = document.querySelector('.price-info')
var addUrgency = document.getElementById('urgency')
priceWrapper.insertBefore(addUrgency, mainContainer)
The code provided is how I have placed "addUrgency" witch is the div I need to put elsewhere on desktop.
You can do it, but it's a bad idea.
Lay out your elements starting with smallest screen width you need, then work outwards from there using CSS Media queries to adjust the layout at specific screen widths as and when you need to.
In this case, if you can't do it any other way you could have both elements where you like them and then show/hide depending on the viewport width. Something like:
#media (min-width:800px) {
//your non-mobile styles and classes go here
.desktop-element{
display: inline-block;
}
.mobile-element{
display:none;
}
}
You could use navigator.userAgent and determine if the browser is a mobile browser. There is also an question with really good answeres on doing that on StackOverflow: Detecting a mobile browser
Another option is to check the viewport-size with javascript. Which can be a better solution in the case you have css-rules in place that are responsive to the viewport-size , like: #media (width):
let width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
After that it is a simple if-else to decide where to place your element.
You can use the onresize event. But, I have to note, that having two identical elements (perhaps using clone() to copy #addUrgency) in the DOM on their right places and display/not display them using CSS media queries instead of using Javascript to re-lay elements every time the viewport is resized is a better solution. However, to answer your question here is the most straightforward approach using your code. It also worth to note, that resize event can fire pretty fast, so you probably will want to throttle the function relay (answers are on StackOverflow).
function relay(){
var addUrgency = document.getElementById('urgency');
if(`mobile view`){ //here goes a condition to determine what view you have.
var priceWrapper = document.querySelector('.price-info-wrap');
var mainContainer = document.querySelector('.price-info');
priceWrapper.insertBefore(addUrgency, mainContainer);
}else{
// Insert where you want it on desktop view
}
}
window.onload = function() {
relay();
document.body.addEventListener("resize", relay);
};
You could do this using JavaScript but I wouldn't recommend this approach as I believe this is achievable in most cases with plain HTML and CSS. One method would be using display: grid and placing the elements in the desired rows/columns on mobile (If you are of course utilizing a mobile-first approach) and then redistributing them on larger screens with media queries. Additionally, you could of course make use of position: absolute whenever this strategy does not completely do the job.
Here is a great article, in case you are not completely familiar with display: grid.

jQuery Add & Remove Class Div Width

How can i add/remove class according as div width ? I tried some codes but I have no idea about jquery codes. I'd like add div class according as antoher div width. Just i need add class like that. If container is smaller than 600px "add class" to content div else "remove class" from content div. These are my codes;
<div class="container">
<div class="content"></div>
</div>
$(window).resizeboxes(function() {
if ($(".container").width < 600){
$( ".content" ).addClass( ".content_600" );
}
});
else{
removeClass('.content_600')
}
$(window).trigger('resizeboxes');
This works, though the code is changed slightly. There were some problems with the syntax also, so I've corrected those (for instance the else statement was slightly misplaced). Here is a working example:
https://jsfiddle.net/vt0nbx36/3/
Here is the code:
var resizeboxes = function() {
if ($(".container").width() < 600)
{
$(".content").addClass("content_600");
}
else
{
$(".content").removeClass("content_600")
}
};
resizeboxes();
$(window).resize(function(){
resizeboxes();
});
For this need exactly, you have jQuery's .toggleClass() function. It takes the class name as a first parameter, and optional second boolean parameter that states wether the class name should be added or removed. You can find the documentation here
$(".content").toggleClass("content_600", ($(".container").width() < 600));
Even tho your question is a JS related question, CSS as a matter of fact can handle this like no other beast can (mostly)!
CSS allows you to use media-queries to resize your content based on the width of the viewport.
The upside of this is that the browser will handle this for you within the rendering engine rather than having JS between your change and the rendering engine.
The major downside is that you can't define the width of element A based on element B but are unfortunately locked to using the viewport as an indicator.
Before I explain why you'd want to use CSS I'd like to point out why you don't want to use JS for this if possible.
The jQuery.resize eventhandler fires inconsistently across browsers and it fires alot of times usually.
This causes your scrolling to clog up and make your webpage feel laggy.
If there's anything your users will dislike it's the fact that scrolling is controlled by something they don't even know of which is slowing you down.
As for a CSS solution, a media query looks like this:
.my-selector {
width: 900px;
}
#media all and (max-width: 600px) {
.my-selector {
width: 600px;
...
}
}
You wrap your code in a sort-of conditional that allows you to be very flexible with manipulating elements on the page.
What happens in the above piece of code is that when the parser reads the CSS it sees the first selector not in a media query so it applies width: 900px; then it sees a media query and sees the other rule for my-selector however it will only apply that rule when the screen is at that width we defined in the #media ... rule. When you resize CSS handles things differently behind the scenes so it's much faster than JS in that case.
I'm not sure if it actually applies to your situation but if your container is sized by the viewport rather than parent elements this should be possible and I thought it'd be nice atleast to show you a good way of playing with element dimensions.
Also, you can use #media to for instance make a webpage print friendly by changing the all to print for example and setting the background-color: transparent for an element - saves ink ^.^ which is an additional extra on top of the general awesomeness of media queries.
Hope it helps, good luck if you wish to make your webpage 5 times faster ;)

Is there something like data-* attributes for css?

I want to pass a value that's set in a stylesheet so it can be read by javascript/jQuery? I thought of creating an invisible element and giving it a value, but then I would have to include that element in all the pages, which is pretty hacky. Just want to know if there's an alternative to that.
I have a js resize script for images that resizes based on area instead of height or width, so I can't feed it a maxwidth or maxheight, per se. if you give it 100, it makes the area of an image = 100^2. I suppose I could set the maxWidth of the element to twice the number I want, but I'm just wondering if there's a classier way to pull it off.
As far as I know, browsers throw away attributes they don't understand, so unfortunately you can't just inject your own data-*. I think you might have to do it via a hidden element, something like below, which uses the content attribute:
# styles.css
.data {
display: none;
content: "my data variable"
}
# index.html
<span class="data"></span>
# javascript
myData = $(".data").css('content')
Update
Playing around in Chrome, it looks like you can set the 'content' of an image and it won't show up. So you could do
# styles.css
img {
content: "100"
}
Not sure how well that works cross browser though, also looking at the w3c spec, it says that 'content' has to be used with :before or :after, so not sure if you'll run into validation issues there.
Why not just use javascript to query the actual element, and read its properties that way? Then you don't rely on the CSS at all.
$('someDiv').getWidth()

Why is my TinyMCE hidden textarea acting up?

I have about 7 textareas on a web page, all of them are rich text editors using TinyMCE. However at page load only 1 of them is visible and the rest of them hidden. The user can click a 'show' link which would display the remaining textareas one by one.
However, I have a weird problem. All the textareas are setup like this:
<textarea cols="40" rows="20"></textarea>
However, only the textarea displayed on page load is the full size I want it to be. The remaining textareas are really small when I show them. So I'm thinking that perhaps they aren't rendered because they are hidden on page load.
How can I remedy this?
Try adding some CSS to textareas that are hidden.
For example, use
<textarea cols="40" rows="20" style="width: 40em; height: 20em"></textarea>
I think I ran into this, where TinyMCE's CSS overrides some of the default CSS behaviour. I ended up having to "re-override" it, and eventually edited the TinyMCE's css pages.
I think this is an MCE bug, or at least a feature that MCE lacks.
Since I wanted to style my input box in CSS, not in HTML (yuck) I tried
visibility: hidden;
instead of
display: none;
and everything worked again.
I believe that the latter causes the element to take up no space, which trips up the MCE code which detects the width and height of the element.
When loading TinyMCE with jQuery, this problem can be solved as such:
1- On your textarea, specify a height in the inline style attribute:
<textarea style="height:200px;" class="tinymce" name="myfield"></textarea>
2- add a callback function when instantiating a TinyMCE editor. e.g. tinymceLoaded
$('textarea.tinymce').tinymce({
// Location of TinyMCE script
script_url : 'PATH_TO_TINYMCE.js',
// General options ...
// Theme options...
// callback function
init_instance_callback : "tinymceLoaded"
});
3- Set the height of your Editors in the tinymceLoaded function:
function tinymceLoaded(inst){
// get the desired height of the editor
var height = $('#' + inst.editorId).height();
// when the editor is hidden, the height calculated is 0
// Lets use the inline style text to solve this problem
if(height == 0){
height = $('#' + inst.editorId).css('height'); // 200px
height = height.replace(/[^0-9]/g, ""); // remove all non-numeric characters to isolate the '200'
}
// set the height of the hidden TinyMCE editor
$('#' + inst.editorId + '_ifr').css({height: height + 'px'});
}
Without having a few more specifics about your actual setup and how you're doing the vaious display/hide functionality it's hard to give a definitive answer.
I can throw a few general thoughts out though:
Do they render properly when you don't hide them on page load? That would give a definative answer for at what point the bug's occuring.
When you toggle the view of the textarea can you explicity set the row/col attributes at the same time?
Can you use css (maybe with !important) to set textarea width and height than to test if that has an effect?
From TinyMCE inside hidden div are not displayed as enabled when we put the div visible, user's slolife answer helped me:
Try calling tinyMCE.init(...) after you unhide the containing div.
I've been having the same issue where the height of the hidden textarea controls that were converted into TinyMCE editors were too small. Setting visibility to none worked but leaves a big empty space in its place.
The following solution worked well for me:
Do not hide your textarea controls initially on page load
Instead, set all of your TinyMCE's init config as follows:
tinyMCE.init({
...
init_instance_callback : "onInstanceInit"
});
In your onInstanceInit function, hide the initialized TinyMCE editor dynamically
If you show this editor afterwards, the height will be normal again just like it was never hidden
If you use production version of TinyMCE, you probably forgot to copy folders that tinymce.min.js needs. You need to have folders langs, plugins, skins and themes in the same folder as your tinymce.min.js file.
Another reason for the hidden thing is when you remove elements from the dom with tinymce initialized on them. You need to remove tinymce from this element first, so you will avoid weird behaviour when initialize new tinymce elements.
So for exemple :
removeElementWithTinymce = function(elementToRemove){
var parent = elementToRemove.parentNode;
tinymce.remove(elementToRemove.getAttribute('id'));
parent.removeChild(elementToRemove);
};
That's it.

Categories