I wrote a PanelMenu.Button-derived class for shell 3.36 by following the tutorial at:
https://wiki.gnome.org/Projects/GnomeShell/Extensions/Writing
Everything works (after a few 3.36-related tweaks I had to do) but now I would like to have a single left click show/hide the application and single right click open the menu. For that I wanted to catch a 'clicked' signal but PanelMenu.Button only emits menu-set. I'd need something like this:
indicator.connect("clicked", () => GLib.spawn_command_line_async("my_app"));
Is there a widget that supports the 'clicked' signal?
I think looking for a another widget might be more work than it's worth. If you look here at the implementation, they're really just overriding the event vfunc to open the menu.
vfunc_event(event) {
if (this.menu &&
(event.type() == Clutter.EventType.TOUCH_BEGIN ||
event.type() == Clutter.EventType.BUTTON_PRESS))
this.menu.toggle();
return Clutter.EVENT_PROPAGATE;
}
If you've subclassed yourself and don't need the menu, you can simply do a similar thing just by redefining the virtual function like so (just put this in your subclass like a regular function):
vfunc_event() {
if ((event.type() == Clutter.EventType.TOUCH_BEGIN ||
event.type() == Clutter.EventType.BUTTON_PRESS))
GLib.spawn_command_line_async("my_app");
return Clutter.EVENT_PROPAGATE;
}
However, you may want to change the events to BUTTON_RELEASE and TOUCH_END so it happens when the user releases the button, giving them a chance to change their mind by dragging the mouse away.
Did you try:
indicator.connect("button-press-event", () => GLib.spawn_command_line_async("my_app"));
The signal you are looking for should be: button-press-event.
A single left mouse button click will trigger the button-press-event.
This signal works for me. My GNOME shell version is: 3.36.9
Regarding your second question:
is there a preferred way to show/hide a window of a running application?
This link may be able to help you or will hopefully at least give you some pointers in the right direction:
https://github.com/amivaleo/Show-Desktop-Button/blob/master/extension.js
Good Luck!
Related
I'm new to learning JavaScript and I took it on myself to build a TicTacToe game for learning purposes.
Here is what the game so far looks like, as you can see it is very basic:
https://rjo.000webhostapp.com/
I'm having the user choose either "X" or "O" to start off. I had a function prviously that was "onclick" within the HTML code but after doing some online research I found out that is bad practice within the industry.
Doing the "onclick" within the HTML such as <div class="XO" onclick="userChoice"> allowed it so my user had to click on the X or O and it behaved exactly how I wanted it to.
Doing this method with an event listener seems to make it messy - the user can click to the far left of the "X" or a tad to the right and it is still chosen as X. Even to the right of the "O" it will choose X. Any suggestions? I uploaded my mini project so you can take a look at what I'm doing.
Here is the JS for the EventListener:
document.addEventListener('DOMContentLoaded', function(domReadyEvent) {
//observe clicks on the document
document.addEventListener('click', function(clickEvent) {
if (clickEvent.target.className.indexOf('X') > -1) {
alert('clicked on X');
//handle click on X
} else if (clickEvent.target.className.indexOf('O') > -1) {
alert('clicked on O');
//handle click on O
}
});
});
I want this to be done in strictly JavaScript as well. I am familiar with HTML, CSS and more complex languages such as C/C++ but little to no experience with JS.
I also had an issue that my "O" wasn't selecting, it was thankfully helped out:
The issue is that you have not set a class for O
Needs to be: O
The issue is that you have not set a class for
<span id="O" )"="">O</span>
Needs to be:
<span id="O" class="0")"="">O</span>
(and ideally use either class or id - not both)
Also to answer your other question, its better to just target elements like:
var naught = document.getElementById('0');
naught.addEventListener('click', function(clickEvent) {
alert('clicked on 0');
// handle 0 event
});
instead of doing those indexOf checks
I have a (fairly simple) issue and I'm breaking my head over it.
The issue is pretty simple - scroll event won't fire (ever).
I'm writing this angular project, so I've tried the following:
angular.element($window).bind('scroll', ()=> {
console.log('scroll!');
if (!scope.scrollPosition) {
scope.scrollPosition = 0;
}
// Alerting for test cause wtf is going on
scope.boolChangeClass = this.pageYOffset > 600 ? alert(true) : alert(false);
scope.scrollPosition = this.pageYOffset;
scope.$apply();
}
);
but nothing happened. (assume $window is intact and that i'm using webpack etc.)
This example works great if I change the scroll to click. weird.
So I've tried vanilla~~!
window.addEventListener('scroll',function(){
console.log('test')
})
This attempt works on every other website except mine (gotta admit it's classic).
So - has anyone ever dealt with this and knows what's going on?
I assume that some other element is consuming this event at early stage thus not letting it bubble up. Yet this is just an assumption.'
Would love to understand this :)
=== EDIT ===
I've tried to see all the fired events using monitorEvents(window) (using Chrome) and I see every event that's being fire except the scroll..
Looks like it's the body element that is scrolling. Try adding the following code in the console.
document.body.addEventListener('scroll', function() {
console.log('test');
});
I'm trying to optimize my Wordpress install - and one of the culprits I'm seeing, is the "Pin It" button widget for Pinterest. I'm now trying to find a way to dynamically load the JS code (when they initially hover over the button), and then apply it to the page. So far I've only managed to get this far:
jQuery(document).on("mouseenter click",'.pinItSidebar', function() {
jQuery.getScript("http://assets.pinterest.com/js/pinit_main.js", function() {
// do something here?
});
});
I can't seem to find a function that I can call (as a callback, after the JS is loaded). Obviously I will only do this once per page load (the above is just a very basic version at the moment)
Does anyone have any suggestions on how I can achieve this? The end game of how I want it to function, is with:
Working solution:
Here is a working solution I've now got, which will allow you to load the pinterest stuff ONLY when they click the button (and then trigger the opener as well). The idea behind this, is that it saves a ton of Pinterest JS/CSS / onload calls, which were slowing the page down.
jQuery(document).on("click",'.pinItSidebar', function() {
if (typeof PinUtils == "undefined") {
jQuery.getScript("http://assets.pinterest.com/js/pinit_main.js", function() {
PinUtils.build();
PinUtils.pinAny();
});
} else {
PinUtils.pinAny();
}
});
...and just call with:
foo
Hopefully this helps save someone else some time :)
Extra tweak: I'm just playing around, to see if I can make this even more awesome :) Basically, I want to be able to decide which images are pinnable. Below this will do that for you:
jQuery("img").each(function() {
if (jQuery(this).data('pin-do')) {
// its ok, lets pin
} else {
jQuery(this).attr('nopin',"1");
}
});
All you need to do to make an image pinnable, is have the data-pin-do="1" param set the images you want to allow them to share :)
Am playing around with this for a new site, and works great & easy to implement: http://nnattawat.github.io/slideReveal/
But one issue I can't determine, of you have multiple sliders, and one is already "out" from a previous event, how do you first make sure all other sliders are "closed" and THEN open the current slider?
I could do an if/then to check aach individual one, but I figure there must be a more elegant way...
I think the best way of solving this problem is to create a "page-level controller". What this does is acts as a container and controller of sorts for events that happen in the page.
So you essentially have to "proxy" sliding open an closed a side (and adding a dependency of closing the other slide area), since the API doesn't seem to have any hooks or events that it emits like "onSlideOpen". That's what your controller will handle.
var PageController = function(){
var $leftSlide = $('#leftSlider').slideReveal(), // You'll want to sub in
$rightSlide = $('#rightSlider').slideReveal(); // your selector names
return {
openLeft: function() {
$leftSlide.slideReveal('show');
$rightSlide.slideReveal('hide');
},
openRight: function() {
$rightSlide.slideReveal('show');
$leftSlide.slideReveal('hide');
}
};
};
var pageController = new PageController();
pageController.openLeft(); // will slide reveal left side
pageController.openRight(); // will simultaneously open right and close left
Now you can even do things like check on the state of those slides in case you have other cross-dependencies.
A lot of people would probably handle this kind of thing by emitting events and catching them, but I really don't like the pub-sub model. It tends to get very brittle very quickly.
Use .slideReveal("hide") on all of the sliders, then use .slideReveal("show") on the one you want revealed.
One way to do this, would be to give all the sliders a class and use that as the selector
i.e.
$(".slider").slideReveal("hide");
$("#sliderYouWantToShow").slideReveal("show");
I wrote this extension that basically changes the look of a website using CSS and JS. But now I want to add some checkbox settings to the extension so users can toggle features of the website.
I tried reading the documentation, and searched all over the web. Even tried to look for demo extensions that I could reverse engineer, but to no avail.
Let's say I want to add a "Check Box", title it "sidebar" and given it a "key" value of "tg_sidebar". Can someone explain how I would add an event listener for this, and then trigger some jquery code?
[I think this StackOverflow query [http://stackoverflow.com/questions/3032945/safari-extension-how-to-respond-to-settings-changes] makes things clear, but it still doesn't explain much.]
Here's one thing that worked.
function numberChanged(event)
{
if(event.key == "tg_sidebar")
alert("Number has changed!");
}
safari.extension.settings.addEventListener("change",numberChanged,false);
[Screenshot of the Extension Settings window: http://dznr.org/56wi]
Now whenever I toggle the setting, I get an error. But replacing that alert function with say adding or removing a CSS class doesn't work.
I also tried using the code by the answerer below, but that doesn't do anything. Would have been perfect to be able to look at the code of some extension…
One more thing, in case it wasn't clear, is that the setting should make the change permanent. That is, when the setting is ticked, it should do that action every time the page loads.
Assuming you have it setup in your extensions.
It's pretty simple. Every time your function is called in your global.html call this:
var type = safari.extension.settings.yourSettingsCall;
example:
var type;
function performCommand(event)
{
if (event.command === "start-event") {
type = safari.extension.settings.tg_sidebar;
}
safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("type", type);
}
then your inject.js add these:
safari.self.addEventListener("message", handleMessage, false);
and
function handleMessage(event){
if (event.name === "type") {
//run code
}
}