Is it possible to get the offset of the page/window in the main Firefox window from inside an extension? To make things clear: It's not a DOM related question, I think it's an XPCOM question. I'll try to give an idea of what I need:
[Firefox]------------------------------------------------[ - # X ]
| Tab1 Title | Tab2 Title | |
------------------------------------------------------------------
| http://address.com/ | > |
------------------------------------------------------------------
* <- (X, Y) Offset of the page inside the main Firefox window |
| |
| |
| Page contents... |
| |
. .
. .
. .
Examples of basic bootstrap:
https://gist.github.com/Noitidart/9025999
This one has some extra stuff like the Services module imported, you need to import this module to use Services.wm; But to import Services you need the component Cu. see the top of the gist here:
https://gist.github.com/Noitidart/9026493
Now Services.wm.getMostRecentWindow('navigator:browser') gets only one window. If you want to iterate through all browser windows copy paste this. I include how to iterate over each each HTML window in the tabs in each browser as well.
const {interfaces: Ci, utils: Cu} = Components;
Cu.import('resource://gre/modules/Services.jsm');
//on this line can do Services.wm.getMostRecentBrowser('navigator:browser').gBrowser.contentDocument to get the currently focused tab document of the most recent browser window OR or continue to the loop below and it will do all windows and all tabs.
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
//aDOMWindow.gBrowser can be accesed here
//to go through all tabs in the gBrowser do this:
if (aDOMWindow.gBrowser && aDOMWindow.gBrowser.tabContainer) {
var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
for (var i = 0; i < tabs.length; i++) {
Cu.reportError('DOING tab: ' + i);
var tabBrowser = tabs[i].linkedBrowser;
var aHTMLWindow = tabBrowser.contentWindow;
var aHTMLDocument = aHTMLWindow.document;
}
}
}
yes run this code to get the offset, you mean page offset right?
gBrowser.contentDocument.getBoundingClientRect().left
you just access the dom of the main page and you can do anything there
Related
I'm using CKEditor and I want to indent just the first line of the paragraph. What I've done before is click "Source" and edit the <p> style to include text-indent:12.7mm;, but when I click "Source" again to go back to the normal editor, my changes are gone and I have no idea why.
My preference would be to create a custom toolbar button, but I'm not sure how to do so or where to edit so that clicking a custom button would edit the <p> with the style attribute I want it to have.
Depending on which version of CKE you use, your changes most likely disappear because ether the style attribute or the text-indent style is not allowed in the content. This is due to the Allowed Content Filter feature of CKEditor, read more here: http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter
Like Ervald said in the comments, you can also use CSS to do this without adding the code manually - however, your targeting options are limited. Either you have to target all paragraphs or add an id or class property to your paragraph(s) and target that. Or if you use a selector like :first-child you are restricted to always having the first element indented only (which might be what you want, I don't know :D).
To use CSS like that, you have to add the relevant code to contents.css, which is the CSS file used in the Editor contents and also you have to include it wherever you output the Editor contents.
In my opinion the best solution would indeed be making a plugin that places an icon on the toolbar and that button, when clicked, would add or remove a class like "indentMePlease" to the currently active paragraph. Developing said plugin is quite simple and well documented, see the excellent example at http://docs.ckeditor.com/#!/guide/plugin_sdk_sample_1 - if you need more info or have questions about that, ask in the comments :)
If you do do that, you again need to add the "indentMePlease" style implementation in contents.css and the output page.
I've got a way to indent the first line without using style, because I'm using iReport to generate automatic reports. Jasper does not understand styles. So I assign by jQuery an onkeydown method to the main iframe of CKEditor 4.6 and I check the TAB and Shift key to do and undo the first line indentation.
// TAB
$(document).ready(function(){
startTab();
});
function startTab() {
setTimeout(function(){
var $iframe_document;
var $iframe;
$iframe_document = $('.cke_wysiwyg_frame').contents();
$iframe = $iframe_document.find('body');
$iframe.keydown(function(e){
event_onkeydown(e);
});
},300);
}
function event_onkeydown(event){
if(event.keyCode===9) { // key tab
event.preventDefault();
setTimeout(function(){
var editor = CKEDITOR.instances['editor1'], //get your CKEDITOR instance here
range = editor.getSelection().getRanges()[0],
startNode = range.startContainer,
element = startNode.$,
parent;
if(element.parentNode.tagName != 'BODY') // If you take an inner element of the paragraph, get the parentNode (P)
parent = element.parentNode;
else // If it takes BODY as parentNode, it updates the inner element
parent = element;
if(event.shiftKey) { // reverse tab
var res = parent.innerHTML.toString().split(' ');
var aux = [];
var count_space = 0;
for(var i=0;i<res.length;i++) {
// console.log(res[i]);
if(res[i] == "")
count_space++;
if(count_space > 8 || res[i] != "") {
if(!count_space > 8)
count_space = 9;
aux.push(res[i]);
}
}
parent.innerHTML = aux.join(' ');
}
else { // tab
var spaces = " ";
parent.innerHTML = spaces + parent.innerHTML;
}
},200);
}
}
I create a single xlib window with the relevant code below. When I try to move the window, the cursor briefly changes to the grab cursor and I am unable to drag the window. However, if I change focus to another app, then return to my app, I am able to drag the window. I am new to xlib, and don't understand why I cannot drag the window after creation?
ms_display = XOpenDisplay(NULL);
int screen = DefaultScreen(ms_display);
Window rootWindow = RootWindow(ms_display,screen);
XSetWindowAttributes windowAttrib;
windowAttrib.background_pixel = 0;
windowAttrib.border_pixel = 0;
windowAttrib.colormap = XCreateColormap(ms_display,rootWindow,m_visual,AllocNone);
windowAttrib.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | PointerMotionMask | FocusChangeMask | EnterWindowMask | LeaveWindowMask;
int width = m_displayInfo.m_windowWidth;
int height = m_displayInfo.m_windowHeight;
unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
ms_window = XCreateWindow(ms_display,rootWindow,0,0,width,height, 0, pVisInfo->depth,
InputOutput,pVisInfo->visual,mask,&windowAttrib);
XMapWindow(ms_display, ms_window);
XFlush(ms_display);
XSizeHints sizeHints;
sizeHints.x = (WidthOfScreen(ScreenOfDisplay(ms_display, screen)) - width) / 2;
sizeHints.y = (HeightOfScreen(ScreenOfDisplay(ms_display, screen)) - height) / 2;
sizeHints.width = width;
sizeHints.height = height;
sizeHints.flags = USPosition | USSize;
XSetWMSizeHints(ms_display,ms_window,&sizeHints,XInternAtom(ms_display,"WM_SIZE_HINTS",False));
XMoveResizeWindow(ms_display,ms_window,sizeHints.x,sizeHints.y,width,height);
I did run into a somewhat similar situation, where a newly created window would not get focus, receive mouse clicks or keyboard input until I called XSetWMHints(), even with a completely empty structure, e.g. the following was enough to get it working:
XWMHints xwmh;
xwmh.flags = 0;
XSetWMHints (m_display, m_window, &xwmh);
Weird, but it solved my problem.
I'd like my add-on to restart Firefox and upon restart have a pre-defined webpage displayed.
When I restart the browser via nsIAppStartup.quit(), all of the tabs I had been viewing will be re-opened after restart. I have tried to cope with this manually by closing all the tabs before restarting (see code below), but I find that although I can visually confirm that all of the tabs are closed, they will be present again after a restart.
I assume that some session restore mechanism is re-creating them after the restart. I have found several preferences regarding "SessionStore" (browser.sessionstore.max_tabs_undo, browser.sessionstore.resume_from_crash, etc), but toggling them does not seem to help me resolve this issue.
How should I go about ensuring that the old tabs are closed after a restart? Thank you!
// get gBrowser reference
var mainWindow = Cc["#mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getMostRecentWindow("navigator:browser");
var gBrowser = mainWindow.gBrowser;
// build a collection of tabs to close
var tabsToClose = [];
for( var i = 0; i < gBrowser.mTabContainer.childNodes.length - 1; i++ ){
tabsToClose.push( gBrowser.mTabContainer.childNodes[i] );
}
// Open homepage in new tab
gBrowser.addTab(DEFAULT_HOMEPAGE);
// Close all tabs except for homepage
for( var i = 0; i < tabsToClose.length; i++ ){
gBrowser.removeTab( tabsToClose[i] );
}
// restart browser
Cc["#mozilla.org/toolkit/app-startup;1"].getService(nsIAppStartup).quit(nsIAppStartup.eRestart | nsIAppStartup.eAttemptQuit);
I changed your code a bit and came up with this solution:
var Cc = Components.classes;
var Ci = Components.interfaces;
var pref = Cc["#mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
pref.setBoolPref("browser.tabs.warnOnCloseOtherTabs",false);
var mainWindow = Cc["#mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator).getMostRecentWindow("navigator:browser");
var gBrowser = mainWindow.gBrowser;
var newTab = gBrowser.addTab("www.google.com");
// Easier solution than having two loops to identify the open tabs
gBrowser.removeAllTabsBut(newTab);
var nsIAppStartup = Ci.nsIAppStartup; // You were missing this part on your question
Cc["#mozilla.org/toolkit/app-startup;1"].getService(nsIAppStartup).quit(nsIAppStartup.eRestart | nsIAppStartup.eAttemptQuit);
The preference that you need to change is browser.tabs.warnOnCloseOtherTabs so you don't get a warning when closing multiple tabs. The other sessionstore prefs i didn't touch.
Hope it helps.
i'm developing a firefox extension and i want to be able to close a specific tab. For example if there are many open tabs in the browser o want to close only the tab with a specific url.
I know that i can use gBrowser.removeTab(tab) but i don't know how to get tab object.
On the other hand i can get the browser that corresponds to the url but the param of the removeTab() function must be a "tab object". How cat i get the tab object.
Any ideas?
tabbrowser.getBrowserForTab() method is actually the easiest way of associating browsers with tabs. So you would do something like this:
var tabs = gBrowser.tabs;
for (var i = tabs.length - 1; i >= 0; i--)
{
var tab = tabs[i];
var browser = gBrowser.getBrowserForTab(tab);
if (browser.currentURI && browser.currentURI.spec == "...")
gBrowser.removeTab(tab);
}
I think you can use this method: gBrowser.removeCurrentTab(); this example closes the currently selected tab.
For more code, please refers this link: https://developer.mozilla.org/en/Code_snippets/Tabbed_browser
I am dynamically populating the contents of a StackPanel in my application by reading an XML file. Each child of the StackPanel is itself another StackPanel which contains different UIElement objects. The reason for the nested StackPanel design is because I want to associate one of 3 different ContextMenus with of these child StackPanels.
So the structure looks like this:
---- StackPanel parent
|
---- StackPanel child
| |
| ---- TextBlock
|
---- StackPanel child
| |
| ---- TextBox
|
---- StackPanel child
| |
| ---- Image
|
.
.
.
For each StackPanel child I'm choosing from amongst 3 ContextMenus and attaching them as follows:
var stackPanels = parentStackPanel.Children.OfType<StackPanel>();
for( int i = 0; i < stackPanels.Count(); ++i ) {
if( someCondition ) {
ContextMenuService.SetContextMenu( stackPanels.ElementAt( i ), MyContextMenu1 );
} else if( someOtherCondition ) {
ContextMenuService.SetContextMenu( stackPanels.ElementAt( i ), MyContextMenu2 );
} else {
ContextMenuService.SetContextMenu( stackPanels.ElementAt( i ), MyContextMenu3 );
}
}
All MenuItems under all 3 ContextMenus have the same Click handler.
Now, finally, the question: How do I determine which StackPanel child's ContextMenu was invoked and clicked? Inspecting the sender object within the click handler in the debugger shows that a ContextMenu has an internal DependencyObject named Owner which contains a reference to the StackPanel, this is exactly what I want but of course, I can't access it in code that way.
I could solve the problem by adding a MouseLeftButtonDown handler to each child StackPanel, saving the one that was last selected and then retrieving this within the ContextMenu handler but this solution feels a little ugly. Is there a better way to do this?
Thanks in advance for your help!
If you cast the sender as a UIElement in the click event handler you should be able to get at whatever you need to identify the actual item which was clicked.
(sender as UIElement).Property
Alternatively cast as a DependencyObject (if possible) and use that to walk the visual Tree:
VisualTreeHelper.GetParent((sender as DependencyObject))