How to get the size of a HTA window? - dom

You can SET the size of a HTA window but I can't find a way to GET its size.
All I can think of is reading document.body.offsetWidth and .offsetHeight, but those give you the viewport size not the actual window size.
Is it possible to know that?

It seems there are no properties or methods to get that information. The now beta-released IE9 has the new properties outterWidth and outterHeight, but that is not an option for now.
So I devised a workaround for this:
function addWinSizeGetterFuncs(){
var currViewportWidth = document.body.offsetWidth ;
var currViewportHeight = document.body.offsetHeight ;
resizeTo(currViewportWidth,currViewportHeight) ;
var chromeWidth = currViewportWidth-document.body.offsetWidth ;
var chromeHeight = currViewportHeight-document.body.offsetHeight ;
resizeTo(currViewportWidth+chromeWidth,currViewportHeight+chromeHeight) ;
window.getWidth = new Function('return document.body.offsetWidth+'+chromeWidth) ;
window.getHeight = new Function('return document.body.offsetHeight+'+chromeHeight) ;
}
What that function does is to create two new methods for the window object: window.getWidth() and window.getHeight(). They will get the actual size of the window.
The function requires the existence of the body object so it has to be executed after the BODY tag.
And now that we are at it, the same problem applies for the window position. You can't get the actual window position. What you can get is the viewport position relative to the screen.
So the same workaroud serves for this as well:
function addWinPosGetterFuncs(){
var currViewportLeft = screenLeft ;
var currViewportTop = screenTop ;
moveTo(currViewportLeft,currViewportTop) ;
var viewportOffsetX = screenLeft-currViewportLeft ;
var viewportOffsetY = screenTop-currViewportTop ;
moveTo(currViewportLeft-viewportOffsetX,currViewportTop-viewportOffsetY) ;
window.getScreenX = new Function('return screenLeft-'+viewportOffsetX) ;
window.getScreenY = new Function('return screenTop-'+viewportOffsetY) ;
}
Likewise, the function creates two new methods that will retrieve the actual window position: window.getScreenX() and window.getScreenY()
Problem solved. I'll let you guys figure out how the function works ;)

minified version:
window.pos=new function(w,h,x,y){with(document.body)return(
resizeTo(w=offsetWidth,h=offsetHeight),resizeTo(w+(w=w-offsetWidth),h+(h=h-offsetHeight)),
moveTo (x=screenLeft ,y=screenTop ),moveTo (x-(x=screenLeft-x ),y-(y=screenTop-y )),{
w:function(){return offsetWidth +w},
h:function(){return offsetHeight+h},
x:function(){return screenLeft -x},
y:function(){return screenTop -y}
})};

Related

How to get notified when my element has been attached to the DOM

I'm adding a custom control that uses SVG to a Google Map.
After the map has been loaded and my control is shown, I need to grab the BBox from the svg element. Since I do not control when my element is attached to the DOM, I'm trying to find an event that will allow me to do the work in a callback.
Here's roughly what I have:
map = new google.maps.Map(...);
...
container = document.createElement("div")
svg = createAndDrawSVGElement(...); //this returns an svg element
container.appendChild(svg);
INSERT_THE_RIGHT_EVENT_HERE(function() {
var bbox = svg.getBBox();
... //bbox will be empty if svg isn't attached
}
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(container);
My current, ugly workaround is a setTimeout. I'd like something more predictable.
I was able to resolve this without an event, by attaching my SVG to a hidden DIV temporarily, so I can get the bbox.
Solution here: https://stackoverflow.com/a/45465286/62024
After looking at the API, I would try this (although the doc does not explicitely say whether this is called before or after attaching the element):
var map = new google.maps.Map(...);
...
var container = document.createElement("div")
var svg = createAndDrawSVGElement(...); //this returns an svg element
container.appendChild(svg);
var controls = map.controls[google.maps.ControlPosition.RIGHT_BOTTOM];
var position = controls.length;
google.maps.event.addListenerOnce(controls, "insert_at", function(i) {
if (i === position) {
var bbox = svg.getBBox();
... //etc
}
}
controls.insertAt(pos, container);

How can I select :last-child in d3.js?

I need to manipulate the text elements of the first and last tick of an axis to bring them more towards the center.
I am trying to select them, one at the time, with something like svg.select('.tick:last-child text') but it doesn't work. I'd then apply .transform('translate(4,0)')...
Am I doing something wrong? How can I achieve this?
One thing you could do is to create custom sub-selections by adding methods to d3.selection.prototype. You could create a selection.first() method that selects the first item in a selection, and a selection.last() method that selects the last item. For instance:
d3.selection.prototype.first = function() {
return d3.select(this[0][0]);
};
d3.selection.prototype.last = function() {
var last = this.size() - 1;
return d3.select(this[0][last]);
};
This would let you do the following:
var tickLabels = svg.selectAll('.tick text');
tickLabels.first()
.attr('transform','translate(4,0)');
tickLabels.last()
.attr('transform','translate(-4,0)');
Of course, you need to make sure that you only have one axis if you do it that way. Otherwise, specify the axis in your initial selection:
var tickLabels = svg.selectAll('.axis.x .tick text');
HERE is an example.
Here's the cleanest method I've found:
g.selectAll(".tick:first-of-type text").remove();
g.selectAll(".tick:last-of-type text").remove();
As google brought me here, I also want to add a cleaner method to what Adam Grey wrote.
Sometimes you just want to do it without taking a reference of selectAll .
svg.selectAll('.gridlines').filter(function(d, i,list) {
return i === list.length - 1;
}).attr('display', 'none');
the 3rd parameter of the filter function gives you the selected List of elements.
They don't exist in d3 specifically, but you can use the .firstChild and .lastChild methods on a node.
You can first select all of the parents of the node, and then operate within the scope of a .each() method, like so:
d3.selectAll('.myParentElements').each(function(d,i){
var firstChild = this.firstChild,
lastChild = this.lastChild;
//Do stuff with first and last child
});
Within the scope of .each(), this refers to the individual node, which is not wrapped by a d3 selection, so all of the standard methods on a node are available.
Using .filter() with a function also works selection.filter(filter) :
var gridlines;
gridlines = svg.selectAll('.gridlines');
gridlines.filter(function(d, i) {
return i === gridlines.size() - 1;
}).attr('display', 'none');
It's for D3.js v4
d3.selection.prototype.first = function() {
return d3.select(
this.nodes()[0]
);
};
d3.selection.prototype.last = function() {
return d3.select(
this.nodes()[this.size() - 1]
);
};
Example:
var lines = svg.selectAll('line');
lines.first()
.attr('transform','translate(4,0)');
lines.last()
.attr('transform','translate(-4,0)');
Here is another, even though I used Fered's solution for a problem I met.
d3.select(d3.selectAll('*').nodes().reverse()[0])

Inserting a new text at given cursor position

I am working on customizing the codemirror for my new language mode. As part of this new mode implementation, I am writing a new tool bar where user can select some text and say insert. This command should insert the text where user was typing just before clicking on tool bar.
I could not find any API level support to do so. If there is any other way can someone help me out on this?
Basically get the current cursor positio- line number and position at which cursor is currently present. May be a Position object
API for inserting a text, something like insertText("Text", PositionObject)
Here's how I did it:
function insertTextAtCursor(editor, text) {
var doc = editor.getDoc();
var cursor = doc.getCursor();
doc.replaceRange(text, cursor);
}
How about replaceSelection (http://codemirror.net/doc/manual.html#replaceSelection)?
doc.replaceSelection(replacement: string, ?select: string)
Replace the selection(s) with the given string. By default, the new selection ends up after the inserted text. The optional select argument can be used to change this—passing "around" will cause the new text to be selected, passing "start" will collapse the selection to the start of the inserted text.
To add the new line at the end -
function updateCodeMirror(data){
var cm = $('.CodeMirror')[0].CodeMirror;
var doc = cm.getDoc();
var cursor = doc.getCursor(); // gets the line number in the cursor position
var line = doc.getLine(cursor.line); // get the line contents
var pos = { // create a new object to avoid mutation of the original selection
line: cursor.line,
ch: line.length - 1 // set the character position to the end of the line
}
doc.replaceRange('\n'+data+'\n', pos); // adds a new line
}
Call function
updateCodeMirror("This is new line");
Improved function that, if selection present, replaces the text, if not, inserts in current cursor position
function insertString(editor,str){
var selection = editor.getSelection();
if(selection.length>0){
editor.replaceSelection(str);
}
else{
var doc = editor.getDoc();
var cursor = doc.getCursor();
var pos = {
line: cursor.line,
ch: cursor.ch
}
doc.replaceRange(str, pos);
}
}
You want to use the replaceRange function. Even though the name says "replace", it also serves as "insert" depending on the arguments. From the documentation at the time I write this:
Replace the part of the document between from and to with the given
string. from and to must be {line, ch} objects. to can be left off to
simply insert the string at position from. When origin is given, it
will be passed on to "change" events, and its first letter will be
used to determine whether this change can be merged with previous
history events, in the way described for selection origins.
Final function to insert text at current cursor position in a performant way.
Hope it helps.
function insertStringInTemplate(str)
{
var doc = editor_template.getDoc();
var cursor = doc.getCursor();
var pos = {
line: cursor.line,
ch: cursor.ch
}
doc.replaceRange(str, pos);
}
This function is used to insert to the specified position and move the cursor to the end of the inserted text.
function insertToCodeMirror(text) {
const doc = codeMirrorInstance.getDoc();
const cursor = codeMirrorInstance.getCursor();
doc.replaceRange(text, cursor);
codeMirrorInstance.focus();
setTimeout(() => {
cursor.ch += text.length;
codeMirrorInstance.setCursor(cursor);
}, 0);
}

Data Dynamics : remove a control at run time

Hi I'm trying to remove an Image control at runtime...
var modifiedPic = (DataDynamics.ActiveReports.Picture)reportSection.Controls[controlIdx];
modifiedpic.ResetImage() only resets the image but doesn't remove the control.
I also tried modifiedPic.Image.RemovePropertyItem(771);
This didn't work either. Is there any way to remove the control at runtime?
Also I want to set the control.Location.X value. How can this be achieved?
Try This.
This Shoud remove the control.
var modifiedPic = (DataDynamics.ActiveReports.Picture)reportSection.Controls[controlIdx];
reportSection.Controls.Remove(modifiedPic);
for assigning the loaction.X and location.Y points we have to define
System.Drawing.PointF x= new System.Drawing.PointF();
var modifiedPic = DataDynamics.ActiveReports.Picture)reportSection.Controls[controlIdx];//TargetControl:
var modifiedPic1 = (DataDynamics.ActiveReports.Picture)reportSection.Controls[controlIdx];//Control to get value of X:
x.X = modifiedPic1.Location.X;
modifiedPic.Location = x;

Hide/Show UI elements by MouseOut/MouseOver client handlers

The goal is to mutually replace two elements with each-other by MouseOut/MouseOver events. Specifically the elements are a label and a listbox. There are some UI arrangement in which the implementation works acceptably in Chrome, however it always fails in IE(9). The problem occurs during a selection from the listbox as per browsers ignor the dropped down area as part of the listbox, it triggers the mouseOut handler and hides the listbox.
Is there any solution forcing browsers to consider the listbox together with its dropped down area?
app.createListBox() .setId('listBox');
app.createLabel('Item1') .setId('label')
.addMouseOverHandler(app.createClientHandler()
.forEventSource().setVisible(false)
.forTargets(app.getElementById('listBox')).setVisible(true));
app.getElementById('listBox')
.addItem('Item1')
.addItem('Item2')
.setVisible(false)
.addMouseOutHandler(app.createClientHandler()
.forEventSource().setVisible(false)
.forTargets(app.getElementById('label')).setVisible(true));
Many Thanks
there is a possible workaround using a server handler to hide the listBox. From my tests it behaves quite similarly (if not better ) - you can test it here
function doGet() {
var app = UiApp.createApplication().setStyleAttribute('padding','100px');
var p = app.createVerticalPanel();
var serverHandler = app.createServerHandler('handler').addCallbackElement(p)
var listBox = app.createListBox() .setId('listBox').setName('listBox').addChangeHandler(serverHandler);
var label = app.createLabel('Item1').setId('label')
.addMouseOverHandler(app.createClientHandler()
.forEventSource().setVisible(false)
.forTargets(listBox).setVisible(true));
listBox.addItem('Item1').addItem('Item2').addItem('Item3').addItem('Item4')
.setVisible(false)
p.add(listBox).add(label)
app.add(p)
return app
}
function handler(e){
var app = UiApp.getActiveApplication();
var listBox = app.getElementById('listBox')
var label = app.getElementById('label')
listBox.setVisible(false)
label.setVisible(true).setText(e.parameter.listBox)
return app
}