I read the Apple documentation on how to make use of the DOM events for Quicktime. I am having trouble making it work within JQuery... I'd like to make use of the fade() function - that's why within JQuery.
Here's the code:
function onm_remove_intro(){
$('#basecamp_intro_div').fadeOut(4000);
}; //end function onm_remove_intro()
function onm_add_event_listener(object, event, handlerfunction, capture_bool){
if ( document.addEventListener )
{object.addEventListener(event, handlerfunction, capture_bool)}
else
// IE
{object.attachEvent('on' + event, handlerfunction)};
}; //end function onm_add_event_listener(object, event, handlerfunction, capture_bool)
var listener_object = $('#intro_movie_embed');
onm_add_event_listener(listener_object, 'qt_ended', onm_remove_intro, false);
Unless I comment out the last line, the execution of onm_add_event_listener, any JQuery code after it does not run. So clearly I am doing something illegal, but cannot figure out what.
I verified that the listener object variable does return a valid DOM object in Safari, which is where I am testing for now. Not concerned with IE yet.
Here is a reference to Apple's documentation on the subject:
http://developer.apple.com/library/mac/#documentation/QuickTime/Conceptual/QTScripting_JavaScript/bQTScripting_JavaScri_Document/QuickTimeandJavaScri.html%23//apple_ref/doc/uid/TP40001526-CH001-SW5
Hoping it's something really simple and that I am just too bleary eyed at this point to see it... All I want to do, if it isn't evident from the code example is to fade out the video after it reaches the end.
Thanks in advance,
M
Without having any experience with quicktime DOM events it seems to me the listener_object should be the DOM element, instead of the jquery object.
Have you tried:
var listener_object = $('#intro_movie_embed').get(0);
Related
Commuity,
I have a problem with a specific piece of code I am writing currently. The problem is that i want to delegate the animations. (E.g. I have 3 objects, the first is animated, after that the second and after that the third)
The point is I am trying to make it modular so i can't hard code anything in there.
On start we have following situation:
parentDiv is supposed to contain the objects you want to "fadeIn"
prevDiv is the object which was "fadedIn" recently
onclickDisabled is a class to remove "click" events temporarily
fadeInAnim is the class to trigger needed animation
function prepareChildrenForFadeInAnimation(parentDiv, prevId){
var object = 0;
parentDiv.children().each(function(){
$(this).addClass('onclickDisabled');
addAnimationAfterAnimationEnd($(this)[object].id, prevId);
prevId = $(this)[object].id;
});
}
function addAnimationAfterAnimationEnd(currentSelection, prevSelection){
document.getElementById(prevSelection).addEventListener("webkitAnimationEnd", triggerNextAnimation(currentSelection, prevSelection));
document.getElementById(prevSelection).addEventListener("animationend", triggerNextAnimation(currentSelection, prevSelection));
}
function triggerNextAnimation(selection, prevSelection){
selection = $('#'+selection);
selection.addClass('fadeInAnim');
prevSelection = $('#'+prevSelection);
prevSelection.removeClass('onclickDisabled');
}
I have a feeling that in addAnimationAfterAnimationEnd() the function triggerNextAnimation() is fired, but I don't have a clue how to prevent this since I need to submit parameters (or do I?).
If one of you guys could help me out I would be overjoyed!
PS: I am using "Chrome" and "Firefox" for testing.
The JavaScript at Question is calling the function triggerNextAnimation(currentSelection, prevSelection) immediately instead of referencing the function to be called when event is dispatche at the object.
You can use Function.prototype.bind() or $.proxy() to reference the function which should be called when the event is dispatched and with this set to a specific object and pass parameters.
Also, it is not necessary to use vendor prefix if you are already using jQuery. You can use .on("animationend")
document.getElementById(prevSelection).addEventListener("animationend",
triggerNextAnimation.bind(null, currentSelection, prevSelection))
The problem was that the function, which was supposed to trigger after certain animation, was simply executed.
document.getElementById(prevSelection).addEventListener("animationend",
triggerNextAnimation.bind(null, currentSelection, prevSelection));
The code above solves this problem. "Function.bind()" enables me to specificaly call the function after an event
For several years I've used the waitForKeyElements() function to track changes in webpages from a userscript. However, sometimes I've found it doesn't trigger as expected and have worked around out. I've run into another example of this problem, and so am now trying to figure out what the problem is. The following is the barest example I can create.
Given a simple HTML page that looks like this:
<span class="e1">blah</span>
And some Javascript:
// function defined here https://gist.github.com/BrockA/2625891
waitForKeyElements('.e1', handle_e1, false);
function handle_e1(node) {
console.log(node.text());
alert(node.text());
}
setInterval(function() {
$('.e1').text("updated: "+Math.random());
}, 5000);
I would expect this code to trigger an alert() and a console.log() every 5 seconds. However, it only triggers once. Any ideas?
Here's a codepen that demonstrates this.
By design and default, waitForKeyElements processes a node just once. To tell it to keep checking, return true from the callback function.
You'll also want to compare the string (or whatever) to see if it has changed.
So, in this case, handle_e1() would be something like:
function handle_e1 (jNode) {
var newTxt = jNode.text ();
if (typeof this.lastTxt === "undefined" || this.lastTxt !== newTxt) {
console.log (newTxt);
this.lastTxt = newTxt;
}
return true; // Allow repeat firings for this node.
}
With the constant string comparisons though, performance might be an issue if you have a lot of this on one page. In that scenario, switching to a MutationObserver approach might be best.
I'm using fullcalendar 1.6.3 along with Drupal 7 (thus the need, for now, to be back on 1.6.3). I have some code that I'd like to run every time the view of my calendar changes (via ajax requests) -- forward or backward in time, or between month/week/day view.
Based on some tests, I could do this by hacking the source for renderEvents:
function renderEvents(modifiedEventID) { // TODO: remove modifiedEventID hack
if (elementVisible()) {
currentView.setEventData(events); // for View.js, TODO: unify with renderEvents
currentView.renderEvents(events, modifiedEventID); // actually render the DOM elements
currentView.trigger('eventAfterAllRender');
// my_code_here();
}
}
but that would of course be Wrong. Unfortunately, I can't figure out any other way to do it, probably because of some obvious gap in my Javascript knowledge. I tried setting up an event handler on eventAfterAllRender:
var eventAfterAllRenderEvent = new Event('eventAfterAllRender');
document.addEventListener('eventAfterAllRender', function (e) {my_code_here() }, false);
document.dispatchEvent(eventAfterAllRenderEvent);
but that (for me) only runs on page load, not after the ajax events.
This is probably more of a Javascript question than a fullcalendar question, but is there any advice out there? I'm really trying to not hack core; thanks!
According to the documentation eventAfterAllRender is a callback, so you can do this:
$('#your-calendar-element').fullCalendar({
eventAfterAllRender: function (view) {
// add your code here
}
});
Consider this JSFiddle. It works fine in Firefox (14.0.1), but fails in Chrome (21.0.1180.75), Safari (?) and Opera(12.01?) on both Windows (7) and OS X (10.8). As far as I can tell the issue is with either the setData() or getData() methods on the dataTransfer object. Here's the relevant code from the JSFiddle.
var dragStartHandler = function (e) {
e.originalEvent.dataTransfer.effectAllowed = "move";
e.originalEvent.dataTransfer.setData("text/plain", this.id);
};
var dragEnterHandler = function (e) {
// dataTransferValue is a global variable declared higher up.
// No, I don't want to hear about why global variables are evil,
// that's not my issue.
dataTransferValue = e.originalEvent.dataTransfer.getData("text/plain");
console.log(dataTransferValue);
};
As far as I can tell this should work perfectly fine and if you look at the console while dragging an item you will see the id written out, which means that it's finding the element just fine and grabbing it's id attribute. The question is, is it just not setting the data or not getting the data?
I'd appreciate suggestions because after a week of working on this with three attempts and some 200+ versions, I'm starting to loose my mind. All I know is it used to work back in version 60 or so and that specific code hasn't changed at all...
Actually, one of the major differences between 6X and 124 is that I changed the event binding from live() to on(). I don't think that's the issue, but I've come to see a couple failures from Chrome when it comes to DnD while working on this. This has been debunked. The event binding method has no effect on the issue.
UPDATE
I've created a new JSFiddle that strips out absolutely everything and just leaves the event binding and handlers. I tested it with jQuery 1.7.2 and 1.8 with both on() and live(). The issue persisted so I dropped down a level and removed all frameworks and used pure JavaScript. The issue still persisted, so based on my testing it's not my code that's failing. Instead it appears that Chrome, Safari and Opera are all implementing either setData() or getData() off spec or just failing for some reason or another. Please correct me if I'm wrong.
Anyway, if you take a look at the new JSFiddle you should be able to replicate the issue, just look at the console when you're dragging over an element designated to accept a drop. I've gone ahead and opened a ticket with Chromium. In the end I may still be doing something wrong, but I simply don't know how else to do DnD at this point. The new JSFiddle is as stripped down as it can get...
Ok, so after a bit more digging around, I found that the problem actually isn't with Chrome, Safari, and Opera. What gave it away was that Firefox was supporting it and I just couldn't say the other browsers are failing, since that's something I'd normally accept for IE.
The real cause of the issue is the DnD specification itself. According to the spec for the drag, dragenter, dragleave, dragover and dragend events the drag data store mode is protected mode. What is protected mode you ask? It is:
For all other events. The formats and kinds in the drag data store
list of items representing dragged data can be enumerated, but the
data itself is unavailable and no new data can be added.
That translates to, "you have no access to the data that you set, not even in read only mode! Go f#&# yourself.". Really? Who'se the genius that came up with this?
Now, to get around that limitation you have few choices, and I'm only going to outline two that I've come up with. Your first one is to use an evil global variable and pollute the global namespace. Your second choice is to use the HTML5 localStorage API to perform the EXACT same functionality that the DnD API should have provided to begin with!
If you go down this route, which I have, you're now implementing two HTML5 APIs not because you want to, but because you have to. Now I'm starting to appreciate PPK's rant about the disaster that the HTML5 DnD API is.
The bottom line is this, the spec needs to be changed to allow for access to the stored data even if it's only in read only mode. In my case, with this JSFiddle, I'm actually using the dragenter as a way to look ahead at the drop zone and verify that I should allow a drop to occur or not.
In this case Mozilla apparently opted out of full compliance with the spec which is why my JSFiddle was working just fine in it. It just so happens that this is the one time I fully support not supporting the full specification.
There is a reason for the "protected" bit....drag/drop can span completely different windows, and they didn't want somebody to be able to implement a "listener" DIV that would eavesdrop on the content of everything that was dragged over it (and maybe send those contents by AJAX to some spy server in Elbonia). Only the DROP area (which is more clearly under the user's control) gets the full scoop.
Annoying, but I can see why it might be considered necessary.
var dragStartHandler = function (e) {
e.originalEvent.dataTransfer.effectAllowed = "move";
e.originalEvent.dataTransfer.setData("text/plain", this.id);
};
The problem is with the "text/plain". The standard specification in MSDN documentation for setData is just "text" (without the /plain). Chrome accepts the /plain, but IE does not, in any version I tried.
I struggled with the same problem for several weeks, trying to figure out why my "drop" events weren't firing properly in IE while they did in CHrome. It was because the dataTransfer data hadn't been properly loaded.
I know you already answered this, but this is a useful thread -- I just wanted to add an addendum here -- if you're setting the data yourself, you can always add the data into the field itself (ugly I know), but it prevents having to re-create functionality:
For instance, if setting your own custom data:
dataTransfer.setData('mycustom/whatever', 'data');
append the data as a new data entry, and iterate:
dataTransfer.setData('mycustom/whatever/data/{a json encoded string even}');
querying:
// naive webkit only look at the datatransfer.types
if (dataTransfer.types.indexOf('mycustom/whatever') >= 0) {
var dataTest = 'mycustom/whatever/data/';
// loop through types and create a map
for (var i in types) {
if (types[i].substr(0, dataTest.length) == dataTest) {
// shows:
// {a json encoded string even}
console.log('data:', types[i].substr(dataTest.length));
return; // your custom handler
}
}
}
tested in chrome only
Something also worth noting is that if you leave the execution chain using a timeout, the dataTransfer object won't have your data anymore.
e.g.
function dropEventHandler(event){
var dt = event.dataTransfer.getData("text/plain"); // works
var myEvent = event;
setTimeout(function(){
var dt = myEvent.dataTranfer.getData("text/plain"); // null
}, 1);
}
I was getting same error for below code:
event.originalEvent.dataTransfer.setData("text/plain",
event.target.getAttribute('id'));
I Changed code to:
event.originalEvent.dataTransfer.effectAllowed = "move";
event.originalEvent.dataTransfer.setData("text", event.target.getAttribute('id'));
And it worked for me.
I came across this post because I was having a similar experience with Chrome's dataTransfer.setData() and dataTransfer.getData() functions.
I had code that looked something like this:
HTML:
<div ondragstart="drag(event)" ondrop="newDrop(event)"></div>
JAVASCRIPT:
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function newDrop(ev){
var itemDragged = ev.dataTransfer.getData("text");
var toDropTo = ev.target.id;
}
The code worked perfectly fine in Internet Explorer but when it was tested in Chrome, I was unable to get values set in my dataTransfer object (set in drag function) using the dataTransfer.getData() function in the newDrop function. I was also unable to get the id value from the statement ev.target.id.
After some digging around on the web, I discovered that I was suppose to use the event parameters currentTarget property rather than the events target property. Updated code looked something like this:
JAVASCRIPT:
function drag(ev) {
ev.dataTransfer.setData("text", ev.currentTarget.id);
}
function newDrop(ev){
var itemDragged = ev.dataTransfer.getData("text");
var toDropTo = ev.currentTarget.id;
}
With this change I was able to use the dataTransfer.setData() and dataTransfer.getData() functions in chrome as well as internet explorer. I have not tested anywhere else and I am not sure why this worked. Hope this helps and hopefully someone can give an explanation.
I was working on a website testing with Firefox.
In WAMP on my laptop, code like the OP's worked. However, when I moved the website to HOSTMONSTER, it didn't work there.
I followed Joshua Espana's answer, and it resolved my problem.
failed:
ev.dataTransfer.setData("text/plain", ev.target.id);
worked:
ev.dataTransfer.setData("text", ev.currentTarget.id);
Thank, Joshua!
Anything pased to the dataTransfer only becomes available on ondrop events but ONLY on ondrop events (I believe this is a security consideration to prevent data being exposed to nefarious elements during a drag).
If you try adding an ondrop handler you should see the data exposed. Well at least you would if there weren't for one final trick...
To get the drop event to fire you need call .preventDefault on the dragover event or it prevents the drop event from firing
HTML (Angular)
<div (dragstart)="handleDragStart($event)"
(dragover)="handleDragover($event)"
(dragend)="handleDragEnd($event)"
(drop)="handleDrop($event)">
<div class="sortItem">item 1</div>
<div class="sortItem">item 2</div>
<div class="sortItem" draggable="true">Draggable</div>
<div class="sortItem">item 4</div>
</div>
Handlers (Typescript)
handleDragStart(event: DragEvent){
event.dataTransfer?.setData("text", '{"some": "data"}')
console.log('dragstart data:', event.dataTransfer?.getData("text"))
}
handleDragover(event: DragEvent) {
console.log('dragover data:', event.dataTransfer?.getData("text") || 'none')
event.preventDefault()
}
handleDragEnd(event: DragEvent) {
console.log('drag end data:', event.dataTransfer?.getData("text") || 'none')
}
handleDrop(event: DragEvent) {
console.log('drag drop data:', event.dataTransfer?.getData("text") || 'none')
}
Output from the above
If you drop the item INSIDE the container with the ondrop handler
If you don't cancel the dragover event...
If you drop the item OUTSIDE container with the ondrop handler
If you don't cancel the dragover event...
Other relevant SO questions
SO: Data only available on drop
SO: Drop event not firing
I also faced with this problem but no way worked for me when I set the data in ondrag function and get it back it gives the data but when try in other events like dragover and drop it dose not work.
I went this way maybe its not a proper answer but may help some one
let selectedId = 0;
function onDrag(params) {
// event.dataTransfer.setData("text",params);
selectedId = params
}
function onDragOver(params) {
// event.preventDefault()
// const data = event.dataTransfer.getData("text");
let id = selectedId
}
Still a little "gunshy" about jQuery. Does this simple popup window script look okay? Is my jQuery logic right?
I have a few questions in the code comments that I'm curious about.
$( document ).ready( function()
{
$( "a[target='popup']" ).click( function( event )
{
var $href = $( this ).attr( 'href' ); // should I use "this.href"?
var $name = $( this ).attr( 'target' ); // does the window name matter?
var $config = 'width=590, height=590, top=20, left=60, scrollbars=1';
var $popup = window.open( $href, $name, $config );
if ( window.focus ) // is this even necessary?
// any other conditions I should check instead?
{
$popup.focus();
}
event.preventDefault(); // should this be above $popup.focus()?
});
});
It seems to work, but since this script will be important for acquiring RSS subscribers on my site, I thought I'd make sure.
// should I use "this.href"?
No, use the jquery selector - if you're going to use $(this) a lot, put it into a variable at the start so you don't have the overhead of creating the jquery object each time (you do it twice, so you're creating a jquery object twice).
// does the window name matter?
If you want to do anything with the window later, like close it or change it's location, you'll need the name. It's just a handle to the window.
// is this even necessary?
This just makes sure you can do what you're about to try - it's a feature test to ensure you don't generate an error where the focus() method isn't available.
// any other conditions I should check instead?
Nope - test for the function you will call (you call it when you focus the popup).
// should this be above $popup.focus()?
No. It's better to leave this until last as this is where another developer would look for it. Do all the stuff you want to do first, then pop this in to stop the event from bubbling up.
Finally, what's with the $ prefix on your variable names? You might want to save that practice for PHP as the $ is now a handle on jquery.
$(document).ready( function() {
$("a[target='popup']").click( function(event) {
var myObject = $(this);
var href = myObject.attr("href");
var name = myObject.attr("target");
var config = "width=590, height=590, top=20, left=60, scrollbars=1";
var popup = window.open(href, name, config);
if ( window.focus ) {
popup.focus();
}
event.preventDefault();
});
});
Your javascript function is correct. Here is an explanation for each question:
1) Should I use this.href?
No you shouldn't because thats not the jquery way to do things. Javascript implementations can vary from browser to browser, and this jQuery function will make sure the call returns the correct value in every browser it is intended to support. While this.href might work, there is no guarantee it will, but the jQuery will work (in the browsers it is intended to support).
2) Does the window name matter?
Yes. The point of using this jQuery script is to control the window that comes up, however, the link should work (targeting the named window) even if the user has javascript disabled. This javascript is intended to let you control what the window looks like.
3) Is this necessary?
Yes, this goes back to you not being guaranteed to support certain javascript features. The call to window.focus is just checking if the focus function exists for this element in this browser. If it does exist, it will try to set the focus to that element, and if it does not exist, it will not show as a script error (bad user experience) in the browser.
4) should this be above $popup.focus()?
This is letting the browser know that you successfully created and popped up the window yourself and that the event should stop working (thus canceling the browsers default event of opening the new window).
window.focus
Makes a request to bring the window to
the front. It may fail due to user
settings and the window isn't
guaranteed to be frontmost before this
method returns.
event.preventDefault()
Cancels the event if it is cancelable,
without stopping further propagation
of the event.
I don't think there will be any difference if you give this above the focus method.