I'm trying to a menu to the control bar of a video.js player via a plugin. Here's a demo of my end goal. The problem is that the demo is adding a menu to the control bar in video.js itself whereas I want a plugin that adds a menu.
So far I have been able to create a plugin that adds a MenuButton to the control bar, but I'm unable to populate the menu with any menu items.
Here's a demo of where I'm at now.
The problem is when I try to create a new PlaybackRateMenuItem object with new videojs.PlaybackRateMenuItem(this, {rate: rates[i] + 'x'}). The JS console throws the following error on line 805 of video.dev.js:
Uncaught TypeError: Cannot read property 'guid' of undefined
This corresponds to the following function in the unminified version:
vjs.bind = function(context, fn, uid) {
// Make sure the function has a unique ID
if (!fn.guid) {
fn.guid = vjs.guid++;
}
... omitted ...
};
Or more specifically, this line: if (!fn.guid) {.
From stepping through in a debugger, I see that fn is being passed in as undefined and the caller of the function is:
vjs.bind(this.player(), this.player().reportUserActivity);
When this function is being called, this.player() returns a defined value, but once vjs.bind is called, both arguments become undefined and I have no idea why. Any ideas or a point in the right direction? Thanks!
Turns out I had two major problems here.
Overriding the createMenu method instead of the createItems method for my class that extended the videojs.MenuButton class.
The this argument to the constructor of the videojs.MenuItem class must be the videojs player object, not just this. Problem is that the name of this object is mangled in the minified version of video.js. For this situation, I found that using this.c was the player object, but overall, I found it easier to just use the unminified version, video.dev.js, and not have to deal with the name mangling. In that case, using this.player_ was correct.
Related
I am trying to create an replay button in my Adobe Animate CC HTML5 project. I've set the instance name in the property panel to "ReplayBtn". In a frame on my JS layer, I'm trying this :
this.ReplayBtn.addEventListener("click", (function () { this.gotoAndPlay(0); }).bind(this));
But I get an error of "Cannot read property 'addEventListener' of undefined". By inspecting "this", I can see that the instance name is not what I specified but "instance_3" instead. Updating the code to this works fine :
this.instance_3.addEventListener("click", (function () { this.gotoAndPlay(0); }).bind(this));
Why can't I use the instance name I've specified in the property panel ?
Comment #7 on this forum thread pointed me to a solution :
https://forums.adobe.com/thread/2349302
I removed the button from the timeline and re-added it. Bibbity boppity, it works as expected. A bug I guess ?
EDIT: Lesson of the day, add the instance name before you screw around with the instance on the timeline.
According to the Cesium API, to toggle the visibility of an asset's billboard (or label) you can simply assign the billboard.show property to false. When I attempted to do this, Cesium would error with
An error occurred while rendering. Rendering has stopped.
TypeError: undefined is not a function
...
This discussion from the cesium-dev google group includes some example code to toggle billboard visibility on/off. The same code does not work if you attempt show = false on an entity from CZML (this example does not use CZML).
Here is what I tried
var asset = loadedCZML.entities.getById(id);
asset.billboard.show = false; //Error!
(loadedCZML is a Cesium.CzmlDataSource)
The API doc's don't mention that the show property of your entity might not always be a simple boolean property (as the API describes).
When working with a CzmlDataSource's entity, the show property is considered a TimeIntervalCollectionProperty (at least it was with my CZML).
All properties in Cesium must implement a getValue function, and when you go to set your show = false, the setter for the property is unable to apply false to a TimeIntervalCollectionProperty and instead replaces the entire property with a simple value of false.
The error undefined is not a function is a result of the cesium render call attempting to call getValue() on our show property. Regardless, the fix is simple:
Instead of this:
asset.billboard.show = false; //error
Do this:
asset.billboard.show = new Cesium.ConstantProperty(false);
PS: This applies for other Cesium properties, see the following example:
entity.billboard.image = pinBuilder.fromColor(Cesium.Color.CRIMSON, 48); //error
//do this instead
entity.billboard.image = new Cesium.ConstantProperty(pinBuilder.fromColor(Cesium.Color.CRIMSON, 48).toDataURL());
Using default mixitup configuration $('#id').mixitup(), I am adding a filter button dynamically by appending html code for button <li> tag. And calling the same function again instantly after adding html code to the page, in order to make the new button work. After clicking some filter buttons on the page (even if I don't press the new one) animation effects break and on the browser console I see:
Uncaught TypeError: Cannot read property 'left' of undefined error.
The error occurs on line 937:
$toshow.each(function () {
var data = this.data;
data.tX = data.finalPos.left - data.showInterPos.left; //HERE
I saw on documentation how to add new images to the list by using jquery after method, but there are no explanations about how to dynamically add filter buttons and initialize them on the fly.
Is the described behaviour expected?
That means I am doing something wrong. Then, how to initialize the new filter button correctly?
I am using Mixitup 1.5.6 (latest) with jQuery 1.10.2 (Also tried with jQuery 2.0.3).
Thanks in advance!
Your problem is that either data.finalPos or data.showInterPos is undefined. console.log data after you define it to see if you even have those keys
$toshow.each(function () {
var data = this.data;
console.log(data); //here
data.tX = data.finalPos.left - data.showInterPos.left;
In my Firefox extension, I create a popup menu dynamically. Originally, I used this line on each menu item:
menuFunc.setAttribute("oncommand","MainExtension.MyPlugin." + functionName + "();");
where functionName is a string with the name of the function to be called for that menu item. This worked fine. When I uploaded my extension to the Mozilla Addons page, the automated code validation program flagged this line and said that using setAttribute to set oncommand in this way was not secure and that addEventListener should be used instead. I switched to this syntax:
menuFunc.addEventListener("oncommand",function() {MainExtension.MyPlugin[functionName]},false);
but now nothing happens when I click on a menu item.
Is my syntax off or is there something else wrong? I don't think the problem is the common 'this' reference error. I tried removing all uses of 'this' from one of the functions and it still did not work. It seems like the functions are not being called at all. No errors are being generated either.
Update:
The command action is attached using just command, not oncommand:
menuFunc.addEventListener("command", MainExtension.MyPlugin[functionName], false);
You should be able to just do:
menuFunc.oncommand = MainExtension.MyPlugin[functionName];
Just a guess: Does it help to use true instead of false as the third parameter in order to capture the event?
I'm using a jQuery plugin called toggleEdit for inline editing.
Everything works fine when the code is actually used in the page.
However, my test suite fails with the following error:
TypeError: Cannot call method 'remove' of undefined
I tracked it down to be triggered from within the clear method of this particular plugin. Its source file can be found here.
There are two relevant bits in that code:
1- The _init function
self.element.addClass("toggleEdit toggleEdit-edit toggleEdit-edit-" +
self._tag(self.element))
//store reference to preview element
.data("toggleEdit-preview", self.p);
As you can see, when the plugin is first instantiated it uses the data structure on self to store the newly created element.
2- The clear function
self.element.data("toggleEdit-preview").remove();
The clear function then tries to access that structure and retrieve the element. That's when, while inside a jasmine spec, it fails with the aforementioned exception.
Has anyone seen anything similar?
EDIT:
This is my spec, it's the simplest piece of code able to reproduce the error:
it("should update the given attribute on the server", function(){
$('#user-details input, #user-details select').toggleEdit(); //this line triggers the error
});
http://alz.so/static/plugins/toggleedit/jquery.toggleedit.js
I was taking a look at the source for toggleEdit and it seems that the only 2 times the function clear is called is just before self.element.data gets set:
if (typeof self.element.data("toggleEdit-preview") !== "undefined") {
self.clear();
self.disableEvents();
}
And at destroy function:
destroy: function() {
var self = this;
self.clear();
self.disableEvents();
$.Widget.prototype.destroy.apply(self, arguments);
}
Since the first call seems to be protected, I ask you a somewhat dumb question: Is it possible that destroy is being called twice?
Found my problem: old version of the jQuery + jQuery UI duo. Upgrading them resolves the exception.