I'm trying to use this code to add an anchor element and set it's onclick event to some Javascript. But no event is being loaded. Looking at the DOM through Firebug tells me that Mootools is indeed added. The element has almost all of the Mootools element functions. But it lacks addEvent.
var delete_ctl = new Element('a',
{
'href' : '#',
'events' :
{
'click' : function() { alert('foo'); }
}
});
delete_ctl.appendText('Remove');
delete_ctl.inject(root);
delete_ctl.addEvent('click', function() { alert('foo'); });
The rendered code in Firebug lacks any indication that the onclick event has been set. When the code is run, Firebug reports a Javascript error: "addEvent is not a function." I feel like I'm missing something basic here.
You code works fine on my machine. I get twice alerts of 'foo'.
Make sure you use the right version of mootools.
Make sure root really references an HTML element in the DOM.
Make sure you run this code after the DOM finished loading (onload or domready events).
Good luck.
Related
Let me preface this by saying I want a spinner...
I don't necessarily care whether it loads when the page first starts up, or later. The problem I'm experiencing also doesn't seem to care, as I've tried it both ways.
Right this moment, I don't declare it at the top of the page. Because I have a lot of visualization stuff going on, I start that up and immediately pass some info to the spinner (which also starts it up):
google.load('visualization', '1', {packages:['controls'], callback: initializeTables});
function initializeTables() {
provideInfo("loading proficiencies (Step 1/12)");
//etc... }
function provideInfo(text) {
$.mobile.loading( "show", {
text: text,
textVisible: true
});
}
So that starts... fine... ish...
The problem is that there's actually two spinners started when that starts - one in front, one behind. Because the one in front is slightly offset from the one behind, I can see both.
If I later call:
$.mobile.loading( "hide" );
It only hides the front one, not the back one.
I've found I can hide both by saying:
$(".ui-loader").hide();
Which is great. But, I'd like to not see two in the first place. I've tried to puzzle out the jquery mobile documentation page, to no avail (it also mentions a "global method docs" but I haven't been able to find that link):
//This does not work:
$( ".ui-loader" ).loader( "option", "text", "Loading Page..." );
//Nor does this:
$( "#notify_div" ).loader( "show" );
$( "#notify_div" ).loader( "option", "text", "Loading Page..." );
Anyone know how to get it all into one spinner, or why it's loading two?
Sadly, the current JQM documentation is for the 1.5 version which hasn't be released yet. You need to look directly at the source code of the 1.4.5 version.
There is a JQM default which is showing the spinner when a page is loading. You can override this behavior at JQM initialization.
<script type="application/javascript" src="js/jquery-2.2.4.js"></script>
<script>
$(document).on("mobileinit", function () {
$.mobile.changePage.defaults.showLoadMsg = false;
});
</script>
<script type="application/javascript" src="js/jquery.mobile-1.4.5.js"></script>
If You look at line 5847 of the JQM uncompressed source code, You will find all the configurable settings for that.
Moreover, just for the sake of completeness, there is another setting where You can tell JQM to not show the spinner for already cached pages. Just look at line 5122 of the JQM uncompressed source code:
// This delay allows loads that pull from browser cache to
// occur without showing the loading message.
loadMsgDelay: 50
Hope this help.
How can I listen to the events play/stop/pause of a HTML5 video?
I tried with the following code:
$("video").on('play',function(){
//my code here
});
but it does not work.
Alternatively I would be fine also intercept the click that stop and start the video (in fact I would prefer), but even this code not works:
$('video').on('click', function(event) {
//my code here
});
I think because often above the video element is placed a div with associated events start and stop, but I do not know how to select via jQuery or Javascript:
P.S. This code should work on pages that are composed dynamically / not generated by me, so I can not refer the elements indicating their ID or a specific class.
UPDATE
I did not realize that the page on which I was testing had a video inside an iframe.
The syntax is best suited to my needs:
doc.querySelector("video").addEventListener('play', function(e) {
//my code here
}, true);
See here:
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events
So... :
$("video")[0].onplay = function () {
// Do play stuff here
};
Hope that helps!
Your first attempt should work. But you need to make sure that jQuery is actually finding video elements. You say that the page is generated dynamically, so perhaps it's possible that your code is running before the video elements are added. This would also be the case if your script is higher up in the document than the video elements (e.g., in the <head>).
Try placing the following code immediately before the code you have there and check the output:
console.log($("video"));
If the output is an empty array, then you aren't finding any video elements. Try placing your script at the very end of the page or inside a DOMContentLoaded event. Or, if another script is generating the video elements, make sure your script runs after that one.
A few other notes on your question:
There is no stop event. Here's a list of media events.
I don't think the click event is what you want. That will fire no matter where on the video the user clicks: play button, volume control, etc.
The video being placed inside a div shouldn't have any effect on these events. I'm not sure why you'd have start and end events on a div, so maybe I'm not following.
Give this a try!
//Direct
<video id="videoThis" src="blahhh.mp4" onended="yourFunction()"></videoThis>
-or-
//JavaScript (HTML5)
document.querySelector("#videoThis").addEventListener("ended",yourFunction,false);
-or-
//jQuery
$("#videoThis").bind("ended",yourFunction);
Does anyone know of a method to trigger a click on an element with mootools at the dom level?
foo.fireEvent('click') will, for instance, only fire events added by mootools, which is not very helpful for this particular application.
Here's a fiddle with a toy example - you can see that clicking the top button will fire off both event handler functions, while trying to use the lower button to trigger a click will only fire off the 2nd function.
http://jsfiddle.net/Tc4Bv/
Any help would be appreciated - thanks!
modern browsers have an Element.click method available, so you could try something like this:
Element.implement({
synteticClick: function() {
var click = 'click';
(this[click] && !(this[click]())) || this.dispatchEvent(new Event(click));
return this;
}
});
http://jsfiddle.net/dimitar/LUPYK/
works/tested in latest FF, Chrome, also IE9 and IE9 in IE7 mode (compat).
keep in mind that the event object may be basic, i.e. lacking clientX/Y etc - so it very much depends on what you do at the other side...
Is it possible to extend the addEvent function in mootools to do something and also calls the normal addEvent method? Or if someone has a better way to do what I need I'm all years.
I have different 'click' handlers depending on which page I'm on the site. Also, there might be more than one on each page. I want to have every click on the page execute a piece of code, besides doing whatever that click listener will do. Adding that two lines on each of the handlers, would be a PITA to say the least, so I thought about overriding the addEvent that every time I add a 'click' listener it will create a new function executing the code and then calling the function.
Any idea how I could do it?
Whereas this is not impossible, it's a questionable practice--changing mootools internal apis. Unless you are well versed with mootools and follow dev direction on github and know your change won't break future compatibility, I would recommend against it.
The way I see it, you have two routes:
make a new Element method via implement that does your logic. eg: Element.addMyEvent that does your thing, then calls the normal element.addEvent after. this is preferable and has no real adverse effects (see above)
change the prototype directly. means you don't get to refactor any code and it will just work. this can mean others that get to work with your code will have difficulties following it as well as difficulties tracing/troubleshooting- think, somebody who knows mootools and the standard addEvent behaviour won't even think to check the prototypes if they get problems.
mootools 2.0 coming will likely INVALIDATE method 2 above if mootools moves away from Element.prototype modification in favour of a wrapper (for compatibility with other frameworks). Go back to method 1 :)
I think solution 1 is better and obvious.
as for 2: http://jsfiddle.net/dimitar/aTukP/
(function() {
// setup a proxy via the Element prototype.
var oldProto = Element.prototype.addEvent;
// you really need [Element, Document, Window] but this is fine.
Element.prototype.addEvent = function(type, fn, internal){
console.log("added " + type, this); // add new logic here. 'this' == element.
oldProto.apply(this, arguments);
};
})();
document.id("foo").addEvent("click", function(e) {
e.stop();
console.log("clicked");
console.log(e);
});
it is that simple. keep in mind Element.events also should go to document and window. also, this won't change the Events class mixin, for that you need to refactor Events.addEvent instead.
In Google Chrome's extension developer section, it says
The HTML pages inside an extension
have complete access to each other's
DOMs, and they can invoke functions on
each other. ... The popup's contents
are a web page defined by an HTML file
(popup.html). The popup doesn't need
to duplicate code that's in the
background page (background.html)
because the popup can invoke functions
on the background page
I've loaded and tested jQuery, and can access DOM elements in background.html with jQuery, but I cannot figure out how to get access to DOM elements in popup.html from background.html.
can you discuss why you would want to do that? A background page is a page that lives forever for the life time of your extension. While the popup page only lives when you click on the popup.
In my opinion, it should be refactored the other way around, your popup should request something from the background page. You just do this in the popup to access the background page:
chrome.extension.getBackgroundPage()
But if you insist, you can use simple communication with extension pages with sendRequest() and onRequest. Perhaps you can use chrome.extension.getViews
I understand why you want to do this as I have run into the problem myself.
The easiest thing I could think of was using Google's method of a callback - the sendRequest and onRequest methods work as well, but I find them to be clunky and less straightforward.
Popup.js
chrome.extension.getBackgroundPage().doMethod(function(params)
{
// Work with modified params
// Use local variables
});
Background.html
function doMethod(callback)
{
if(callback)
{
// Create/modify params if needed
var params;
// Invoke the callback
callback(params);
}
}
As other answers mention, you can call background.js functions from popup.js like so:
var _background = chrome.extension.getBackgroundPage();
_background.backgroundJsFunction();
But to access popup.js or popup.html from background.js, you're supposed to use the messages architecture like so:
// in background.js
chrome.runtime.sendMessage( { property: value } );
// in popup.js
chrome.runtime.onMessage.addListener(handleBackgroundMessages);
function handleBackgroundMessages(message)
{
if (message.property === value)
// do stuff
}
However, it seems that you can synchronously access popup.js from background.js, just like you can synchronously access the other way around. chrome.extension.getViews can get you the popup window object, and you can use that to call functions, access variables, and access the DOM.
var _popup = chrome.extension.getViews( { type: 'popup' } )[0];
_popup.popupJsFunction();
_popup.document.getElementById('element');
_popup.document.title = 'poop'
Note that getViews() will return [] if the popup is not open, so you have to handle that.
I'm not sure why no one else mentioned this. Perhaps there's some pitfalls or bad practices to this that I've overlooked? But in my limited testing in my own extension, it seems to work.