Window.dimensions is triggered twice when using Elm.fullscreen in Elm - dom

Consider the following program:
module App where
import Color exposing (..)
import Graphics.Collage exposing (..)
import Graphics.Element exposing (..)
import Window
import Debug
view : (Int, Int) -> Element
view (windowWidth, windowHeight) =
let
_ = Debug.log "dimensions" (windowWidth, windowHeight)
in
square 100
|> filled Color.grey
|> List.repeat 1
|> collage windowWidth windowHeight
main : Signal Element
main =
Signal.map view Window.dimensions
When running this program on Try Elm, the square is perfectly centered, and I see a single printout like dimensions: (689,431) in browser's console. This is the expected behaviour.
However, when embedding this program in HTML:
<head>
...
<script type="text/javascript" src="index.js"></script>
</head>
<body>
</body>
<script>
Elm.fullscreen(Elm.App, {
initialSeed: randomlyGeneratedNumber
});
</script>
I see two printouts in browser's console:
dimensions: (384,204)
dimensions: (369,204)
and I see a vertical scrollbar appears:
Any ideas how to fix this?

The fact you see two printouts means that view is being called twice. In general, this means that any signal that view is mapped over could have updated, but here that's only Window.dimensions. (Right?)
It's entirely possible that the runtime is just updating what it thinks the screen dimensions are, just like it will if you resize the window. Then the problem is not that it runs twice but that you're given the wrong size. If you have a vertical scrollbar, the height is too big, and that's the one that stayed the same in your printout.
From a debugging standpoint, have you tried making your HTML and JS as similar as possible to elm-lang/try? For example, removing the initialSeed port value? (If you don't declare the incoming port in Elm, that should be an immediate runtime error, please report if not.) If you resize your browser to a known window size, how do the values differ from that? It's also possible you need to disable margin or padding on the body element.

It looks like bringing up the developer console is causing the dimension change. If I open the developer console first and then refresh, I only see one event.

Related

"Clicking" on a not visible element

So my current situation is that I am trying to click on a marker based in a Google Maps window on a webpage. I have successfully located the markers in two manners: element.all(by.css('.angular-google-map-marker')) and element.all(by.repeater('m in map.markers')).
I have proven that I am obtaining the correct elements by changing the location on the Google Map and using count() to retrieve the number of markers present which returns the correct number in every case.
However, when I try to do for example element.all(by.css('.angular-google-map-marker')).first().click(), I receive the following error:
Failed: element not visible
HTML section
<div ng-transclude="" style="display: none">
<span class="angular-google-map-marker" ng-transclude="" ng-repeat="m in map.markers" options="m.options" coords="m.coords" idkey="m.id" click="onMarkerClick"></span>
<span class="angular-google-maps-window" ng-transclude="" coords="activeMarker.coords" options="windowMapOptions" show="windowMapOptions.show" closeclick="closeInfoWindow" templateurl="'gMapInfoWindow.html'" templateparameter="activeMarker"></span>
</div>
Normally elements that trigger some event due to clicking have an attribute like ng-click= foo(), however the markers above only use click= foo(). In addition if you look the line with the div tag, it says display: none, which might explain the visibility error.
My Question: Is there a way to activate the effect of an attribute like click= foo() without clicking on the element directly?
Aside from trying to make an element visible and then clicking, you can attempt clicking "via JavaScript" (there are some differences though - WebDriver click() vs JavaScript click()):
var marker = $('.angular-google-map-marker');
browser.executeScript("arguments[0].click();", marker.getWebElement());
First of all be sure that you can interact with the element when it is visible, you can do this from within the DevTools of your browser, make it visible by adding a display:block. Then check that if you change the value of the selectbox, the value can also be used with Angular Binding.
If so, you can easily make the element visible with Protractor by injecting a piece of Javascript in the page with the following command:
browser.executeScript('document.querySelector("div").style.display = "block"');
This results in a promise, so be aware of that!

embedding multiple RunKit REPL instances on a single web page

I am creating a web-based presentation using RemarkJS, my preferred tool for presentations. Since I want to demo small bits of nodejs code, I want to use RunKit's REPL embedding capability. I couldn't quite figure out how to embed multiple instances on a single web page, but I managed to kludge something up by running the following code multiple times
var nb1 = RunKit.createNotebook({
// the parent element for the new notebook
element: document.getElementById("div1"),
// specify the source of the notebook
source: source1
})
var nb2 = RunKit.createNotebook({
// the parent element for the new notebook
element: document.getElementById("div2"),
// specify the source of the notebook
source: source2
})
and so on. This actually works, but is super-inefficient. When I launch my presentation, multiple calls to RunKit are made even though the entire page is loaded only once. Not only that, multiple calls to RunKit are made every time I change the slides, which, in RemarkJS, simple hides and displays different parts of the same, single web page. Since the web page itself is being loaded only once, RunKit should be called only once. At least, that is what I think (obviously, it seems I am wrong).
Finally, the actual RunKit REPL frame takes a while before it is rendered. In the beginning, only a few lines of truncated code shows up, but after a while of waiting, the entire frame gets rendered.
What am I doing wrong? Is there a better way of doing this?
I had the same problem and figured it out. So for future users here is how you do it.
<script src="https://embed.runkit.com"></script>
<style>.embed { overflow: visible; }</style>
<pre class="embed" data-gutter="inside">console.log("hello inside");
1 + 1</pre>
<pre class="embed" data-gutter="outside">console.log("hello outside");
1 + 1</pre>
<pre class="embed" data-gutter="none">console.log("hello none");
1 + 1</pre>
<script>
const elements = [...document.getElementsByClassName('embed')]
const notebooks = elements.reduce((notebooks, element) => {
const innerText = element.firstChild
const currentCell = window.RunKit.createNotebook({
element,
gutterStyle: element.getAttribute("data-gutter"),
source: innerText.textContent,
// Remove the text content of the pre tag after the embed has loaded
onLoad: () => innerText.remove()
})
return notebooks
}, [])
</script>
The sample is taken from here: https://runkit.com/docs/embed
Scroll down and you will find it.

Prevent EPiServer from wrapping content in <p> tags

I'm working on a site in EPiServer, and whenever I create a page property with the type set to "XHTML string" (which uses the WYSIWYG content editor in Edit mode), it wraps all content in <p> tags.
Is there any way to prevent this from happening? I can't remove the paragraph margins universally through my CSS (e.g. p {margin: 0 !important;}) since I do need the margins for actual paragraphs of text. I've even tried going to the HTML source view in the editor and manually deleting the <p> tags that it generates, but it immediately adds them back in when I save!
It doesn't happen when the property type is either a long or short string, but that's not always an option since the content might contain images, dynamic controls, etc.
This is becoming a real nuisance since it's very hard to achieve the layout I need when basically every element on the page has extra margins applied to it.
As Johan is saying, they are there for a reason - see more info here. That being said, it's not impossible to remove them. It can be done in one of two ways (taken from world.episerver.com:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
myEditor.InitOptions["force_p_newlines"] = "false";
}
or
<script type="text/javascript">
tinyMCE.init({
force_p_newlines: false
});
</script>
You can add your own custom TinyMCE-config that removes P-elements or strip them out using regular expressions either when saving the page or when rendering the property/page.
I think it's a bad idea though. P-elements are what the editors generate the most and in most cases their content is also semantically correct. Better to wrap your property in a div with a class and adjust margins using CSS like you mention.
If you're using a version of EPiServer with TinyMCE editors, you can insert <br /> elements instead of <p> elements if you type shift-enter instead of enter. This should eliminate your margin problems.
More info at the link below:
http://www.tinymce.com/wiki.php/TinyMCE_FAQ#TinyMCE_produce_P_elements_on_enter.2Freturn_instead_of_BR_elements.3F
EDIT: My comment below answers his question better.
I discovered that while I can't remove the <p> tags from the source view (because it adds them back in automatically), if I replace them with <div> tags, it'll leave things alone. It does mean that I've got an extra <div> wrapping some elements that I don't really need, but at least a <div> doesn't add margins like a <p> does, so...good enough!

IE8 JavaScript Debugger: where the heck is the DOM tree?

I'm using the IE8 debugger to fix a script that works great in FF 3.16 and Chrome 12.0, but doesn't work for beans in IE 8.0 or Safari 5.0. The spot in the script that's giving me trouble is here:
I need to find the number of <td>s in the the table id="main_tbody" whose children[0] is the first row of data. Both FF and Chrome understand this perfectly; IE 8 and Safari 5 do not.
I want to look at the DOM tree in the IE 8 debugger to see what's going on. But I can't find the ding-dong DOM, dang it!
So: where is the DOM in the IE 8 debugger?
Alternatively <ahem!>: what's wrong with my JS code?
Thanks!
EDIT: I should have said that the table is set up like this:
<table id ="main">
<tbody id="main_tbody">
And references to table id ="main" and tbody id="main_tbody" are initialized this way:
main = getRefToDiv( 'main' );
main_tbody = getRefToDiv( 'main_tbody' );
Call the position_col_heads() function after your </body>
My suspicion is that this function is declared inside the head tag or being called before the browser renders the body content.
Just try this.
...
...
</body>
<script type='text/javascript'>
position_col_heads();//Set breakpoint here and see if its accessible.
</script>
</html>
Also, see what response you get for main.children[0] and main_tbody.innerHTML in your watch expression.
Unbelievable. According to quirksmode, ie8 fails to implement childElementCount and I believe it because that's the thing that's coming back == 'undefined'. So I'll rewrite my loop with a new exit condition. That sucks, because now I'm going to get all children, including comments and everything else, not just the elements I was looking for. Incredible. FYI, ie8 also does not implement firstElementChild, lastElementChild, nextElementSibling, or previousElementSibling.

getBoundingClientRect() is returning zero in XUL

I have a problem with my firefox extension
I have a XUL popup panel with a hbox for the tag cloud, and a JS code to add divs to this hbox:
<hbox id="tag_base" ondblclick="alert('done')"/>
JS:
var root = document.getElementById('tag_base');
var tag = document.createElement('div');
tag.textContent = 'test';
root.appendChild(tag);
var rect = tag.getBoundingClientRect()
alert(rect.top)
I need to get the dimensions of each added div, however, getBoundingClientRect simply refuses to work.
If I remove alerts, it's always zero.
With alerts the story is different:
The first time the alert is called it returns zero, although the div appears on the screen.
Any subsequent alerts return the correct coordinates.
If I set a breakpoint in Chromebug, everything is reported correctly.
If I do not interupt the execution in any way, and run a loop, only zeroes got returned.
This has got me quite confused.
Calling "boxObject" produces the same results, while "getClientRects[0]" is undefined on the first call.
Any hints on what might be causing this will be greatly appreciated.
Note :
Caution, if you use getBoundingClientRect with an element which has display:none then it will return 0, anywhere in the dom.
Although I can't find any documentation on this seemingly fundamental issue, the problem you noticed is most likely because the layout (aka "reflow") process has not yet run by the moment you ask for the coordinates.
The layout/reflow process takes the page's DOM with any styles the page has and determines the positions and dimensions of the elements and other portions of the page (you could try to read Notes on HTML reflow, although it's not targeted at web developers and probably is a bit outdated).
This reflow process doesn't run synchronously after any change to the DOM, otherwise code like
elt.style.top = "5px";
elt.style.left = "15px";
would update the layout twice, which is inefficient.
On the other hand, asking for elements position/dimension (at least via .offsetTop) is supposed to force layout to return the correct information. This doesn't happen in your case for some reason and I'm not sure why.
Please create a simple testcase demonstrating the problem and file a bug in bugzilla.mozilla.org (CC me - ***********#gmail.com).
My guess is that this is related to XUL layout, which is less robust than HTML; you could try creating the cloud in an HTML doc in an iframe or at least in a <description> using createElementNS to create real HTML elements instead of xul:div you're creating with your current code.
Be sure the DOM is ready. In my case, even when using the getBoundingClientRect function on click events. The binding of the events needed to happen when the DOM is ready.