How can I remove class completely? - actionscript-3

I have a class file that has some netstreams and connections and I'm trying to remove the class completely. Here's my code:
function onTestProcessed(e:CustomEvent2):void {
// Remove
rtmp_test.removeEventListener(CustomEvent2.PASS_PARAMS, onTestProcessed);
e.currentTarget.parent.removeChild(e.currentTarget);
// Validation comparison
if (e.boo == false) {
trace("event.boo = ", e.boo);
} else {
trace("event.boo = ", e.boo);
}
}
This code removes the display of video but not its sound. Do I have to find each variable in the class and remove them one by one?

Seems like this solved the problem:
function onTestProcessed(e:CustomEvent2):void {
// Remove
rtmp_test.removeEventListener(CustomEvent2.PASS_PARAMS, onTestProcessed);
rtmp_test.netStreamObj.close();
// rtmp_test.netStreamObj = null;
rtmp_test.vid.clear();
e.currentTarget.parent.removeChild(e.currentTarget);
// Validation comparison
if (e.boo == false) {
trace("event.boo = ", e.boo);
} else {
trace("event.boo = ", e.boo);
}
}
as3 - How to stop video and detach NetStream

Related

What is the minimal implementation for custom elements example mentioned in the specifications?

https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-autonomous-example:htmlelement
In the specification they've provided an example for Creating an autonomous custom element. However, they've left _updateRendering() method implementation for the readers.
class FlagIcon extends HTMLElement {
constructor() {
super();
this._countryCode = null;
}
static observedAttributes = ["country"];
attributeChangedCallback(name, oldValue, newValue) {
// name will always be "country" due to observedAttributes
this._countryCode = newValue;
this._updateRendering();
}
connectedCallback() {
this._updateRendering();
}
get country() {
return this._countryCode;
}
set country(v) {
this.setAttribute("country", v);
}
_updateRendering() {
// Left as an exercise for the reader. But, you'll probably want to
// check this.ownerDocument.defaultView to see if we've been
// inserted into a document with a browsing context, and avoid
// doing any work if not.
}
}
An issue has been raised to provide the remaining implementation for better understanding of the topic and quickly move on.
Issue: https://github.com/whatwg/html/issues/3029
What code can we put there to get the required functionality?
Your solution fails, once the flag is set you can never change the value.
That "exercise" is old.. very old.. and contrived to show everything Custom Elements can do.
And it is plain wrong.. key is WHEN attributeChanged runs, and what the old/new values are
And attributeChangedCallback runs BEFORE connectedCallback; that is why https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected was added.
Your code gets 3 parameters in attributeChangedCallback, but you can't do anything with them, because execution always goes to the _updateRendering method.
If the point of the exercise is to learn when Observed attributes change I would use:
Code also available in JSFiddle: https://jsfiddle.net/dannye/43ud1wvn/
<script>
class FlagIcon extends HTMLElement {
static observedAttributes = ["country"];
log(...args) {
document.body.appendChild(document.createElement("div"))
.innerHTML = `${this.id} - ${args.join` `}`;
}
attributeChangedCallback(name, oldValue, newValue) {
this.log("<b>attributeChangedCallback:</b>", `("${name}" , "${oldValue}", "${newValue}" )`);
if (this.isConnected) {
if (newValue == oldValue) this.log(`Don't call SETTER ${name} again!`);
else this[name] = newValue; // call SETTER
} else this.log("is not a DOM element yet!!!");
}
connectedCallback() {
this.log("<b>connectedCallback</b>, this.img:", this.img || "not defined");
this.img = document.createElement("img");
this.append(this.img); // append isn't available in IE11
this.country = this.getAttribute("country") || "EmptyCountry";
}
get country() { // the Attribute is the truth, no need for private variables
return this.getAttribute("country");
}
set country(v) {
this.log("SETTER country:", v);
// Properties and Attributes are in sync,
// but setAttribute will trigger attributeChanged one more time!
this.setAttribute("country", v);
if (this.img) this.img.src = `//flagcdn.com/20x15/${v}.png`;
else this.log("can't set country", v);
}
}
customElements.define("flag-icon", FlagIcon);
document.body.onclick = () => {
flag1.country = "nl";
flag2.setAttribute("country", "nl");
}
</script>
<flag-icon id="flag1" country="in"></flag-icon><br>
<flag-icon id="flag2" country="us"></flag-icon><br>
This is just one way, it all depends on what/when/how your Custom Elements needs to do updates.
It also matters WHEN the CustomElement is defined; before or after the DOM is parsed. Most developers just whack deferred or method on their scripts, without understanding what it implies.
Always test your Web Component with code that defines the Custom Element BEFORE it is used in the DOM.
A Real World <flag-icon> Web Component
Would be optimized:
<script>
customElements.define("flag-icon", class extends HTMLElement {
static observedAttributes = ["country"];
attributeChangedCallback() {
this.isConnected && this.connectedCallback();
}
connectedCallback() {
this.img = this.img || this.appendChild(document.createElement("img"));
this.img.src = `//flagcdn.com/120x90/${this.country}.png`;
}
get country() {
return this.getAttribute("country") || console.error("Missing country attribute",this);
}
set country(v) {
this.setAttribute("country", v);
}
});
</script>
<flag-icon id="flag1" country="gb"></flag-icon>
<flag-icon id="flag2" country="eu"></flag-icon>
Or NO External Images at all
Using the FlagMeister Web Component which creates all SVG client-side
<script src="//flagmeister.github.io/elements.flagmeister.min.js"></script>
<div style="display:grid;grid-template-columns: repeat(3,1fr);gap:1em">
<flag-jollyroger></flag-jollyroger>
<flag-un></flag-un>
<flag-lgbt></flag-lgbt>
</div>
Here is the complete code to achieve the same requirements:
<!DOCTYPE html>
<html lang="en">
<body>
<flag-icon country="in"></flag-icon><br>
<flag-icon country="nl"></flag-icon><br>
<flag-icon country="us"></flag-icon><br>
</body>
<script>
class FlagIcon extends HTMLElement {
constructor() {
super();
this._countryCode = null;
}
static observedAttributes = ["country"];
attributeChangedCallback(name, oldValue, newValue) {
// name will always be "country" due to observedAttributes
this._countryCode = newValue;
this._updateRendering();
}
connectedCallback() {
this._updateRendering();
}
get country() {
return this._countryCode;
}
set country(v) {
this.setAttribute("country", v);
}
_updateRendering() {
//**remaining code**
if (this.ownerDocument.defaultView && !this.hasChildNodes()) {
var flag = document.createElement("img");
flag.src = "https://flagcdn.com/24x18/" + this._countryCode + ".png";
this.appendChild(flag);
}
}
}
customElements.define("flag-icon", FlagIcon);
</script>
</html>
Note: images may take time to load depending on the internet speed.
Let me know if I've missed anything.

Why does the ToolController's getPriority return 0 for my tool?

According to a prior SO answer, you can implement getPriority for a forge viewer Tool. And according to another SO answer extending the ToolInterface does not work. Hence, me not extending the ToolInterface implementing my Tool like so:
class MyCustomExtension extends Autodesk.Viewing.Extension {
constructor(viewer, options) {
super(viewer, options);
this.theiaUtil = new TheiaUtil(this);
}
getPriority() {
console.log("Theia#getPriority called! ", (this.getPriority && this.getPriority() || 0));
return 100000;
}
...
}
My tool's priority is returned as 0 in the ToolController, although it shouldn't:
function getPriority(tool)
{
return tool.getPriority instanceof Function && tool.getPriority() || 0;
}
I don't know why this function returns 0 as tool.getPriority instanceof Function returns true if I call MyCustomExtension.getPriority myself.
Note that ToolInterface is implemented like so:
function ToolInterface()
{
this.names = [ "unnamed" ];
this.getNames = function() { return this.names; };
this.getName = function() { return this.names[0]; };
this.getPriority = function() { return 0; };
this.register = function() {};
this.deregister = function() {};
this.activate = function(name, viewerApi) {};
this.deactivate = function(name) {};
this.update = function(highResTimestamp) { return false; };
this.handleSingleClick = function( event, button ) { return false; };
this.handleDoubleClick = function( event, button ) { return false; };
this.handleSingleTap = function( event ) { return false; };
this.handleDoubleTap = function( event ) { return false; };
// ...
}
Because of that, simply extending the ToolInterface class won't work because all these properties and functions added to the instance in the constructor will take precedence over your actual class methods. This is also likely the reason why you're seeing the priority value returned as zero - when you call myTool.getPriority(), you are not actually calling your getPriority method, but rather the default function which was assigned to this.getPriority in ToolInterface's constructor.
To work around this issue I would recommend explicitly deleting the corresponding fields in your class' constructor (something I explain in my blog post on implementing custom Forge Viewer tools):
class DrawTool extends Autodesk.Viewing.ToolInterface {
constructor() {
super();
this.names = ['box-drawing-tool', 'sphere-drawing-tool'];
// Hack: delete functions defined *on the instance* of the tool.
// We want the tool controller to call our class methods instead.
delete this.register;
delete this.deregister;
delete this.activate;
delete this.deactivate;
delete this.getPriority;
delete this.handleMouseMove;
delete this.handleButtonDown;
delete this.handleButtonUp;
delete this.handleSingleClick;
}
register() {
console.log('DrawTool registered.');
}
deregister() {
console.log('DrawTool unregistered.');
}
activate(name, viewer) {
console.log('DrawTool activated.');
}
deactivate(name) {
console.log('DrawTool deactivated.');
}
getPriority() {
return 42; // Or feel free to use any number higher than 0 (which is the priority of all the default viewer tools)
}
// ...
}
TL;DR: Activate the tool in button click event from a toolbar button instead of the extension's load method.
class MyExtension extends Autodesk.Viewing.Extension {
...
onToolbarCreated(toolbar) {
const MyToolName = 'My.Tool.Name'
let button = new Autodesk.Viewing.UI.Button('my-tool-button');
button.onClick = (e) => {
const controller = this.viewer.toolController;
if (controller.isToolActivated(MyToolName)) {
controller.deactivateTool(MyToolName);
button.setState(Autodesk.Viewing.UI.Button.State.INACTIVE);
} else {
controller.activateTool(MyToolName);
button.setState(Autodesk.Viewing.UI.Button.State.ACTIVE);
}
};
}
...
}
I activated the tool instantly after registering it in the Extension's load method. Petr Broz's github repo from his blog post loads the tool from a button in the toolbar. So I moved the activation of the tool to a button click in the toolbar which worked for me.

Error creating a Web component

I'm new to Web components and I am trying to create a very simple component to understand how it works. But I have a problem creating one. I followed the steps mentioned in both chrome and Mozilla docs but I still cant create one successfully and also couldn't find the problem.
class toolTip extends HTMLElement {
var msg = this.getAttribute('msg');
var value = this.getAttribute('value');
console.log(msg);
console.log(value);
this.innerHTML = msg + ' - ' + value;
}
customElements.define('mdm-tooltip', toolTip);
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Web Components</title>
</head>
<body>
<mdm-tooltip value='1st tooltip' msg='this the 1st tooltip created using WC'></mdm-tooltip>
<mdm-tooltip value='2nd tooltip' msg='I replaced the existing text'>Im the existing text</mdm-tooltip>
</body>
<script src="main.js" defer></script>
</html>
This is the error browser throws,
I'm running this code in Chrome V67.0.3396.99
Within a class, you need to define methods that actually contain executable code. In your case, your code looks a lot like initialization code, so a constructor seems appropriate.
class ToolTip extends HTMLElement {
constructor() {
let msg = this.getAttribute('msg');
let value = this.getAttribute('value');
console.log(msg);
console.log(value);
this.innerHTML = msg + ' - ' + value;
}
}
customElements.define('mdm-tooltip', ToolTip);
Also, one of the naming conventions in JavaScript is that classes should be pascal-cased (start with a capital letter).
J.P. ten Berge is mostly correct. But... According to the rules of a Web Component Constructor you can not and should not do several things:
https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-conformance
4.13.2 Requirements for custom element constructors
When authoring custom element constructors, authors are bound by the following conformance requirements:
A parameter-less call to super() must be the first statement in the constructor body, to establish the correct prototype chain and this value before any further code is run.
A return statement must not appear anywhere inside the constructor body, unless it is a simple early-return (return or return this).
The constructor must not use the document.write() or document.open(type, replace) methods.
The element's attributes and children must not be inspected, as in the non-upgrade case none will be present, and relying on upgrades makes the element less usable.
The element must not gain any attributes or children, as this violates the expectations of consumers who use the createElement or createElementNS methods.
In general, work should be deferred to connectedCallback as much as possible—especially work involving fetching resources or rendering. However, note that connectedCallback can be called more than once, so any initialization work that is truly one-time will need a guard to prevent it from running twice.
In general, the constructor should be used to set up initial state and default values, and to set up event listeners and possibly a shadow root.
Moving the code into the connectedCallback is a better plan:
class ToolTip extends HTMLElement {
connectedCallback() {
var msg = this.getAttribute('msg');
var value = this.getAttribute('value');
console.log(msg);
console.log(value);
this.innerHTML = msg + ' - ' + value;
}
}
customElements.define('mdm-tooltip', ToolTip);
<mdm-tooltip msg="help me" value="10"></mdm-tooltip>
But you can also change it to something like this:
class ToolTip extends HTMLElement {
constructor() {
super();
this._msg = '';
this._value = '';
}
static get observedAttributes() {
return [ 'value', 'msg' ];
}
connectedCallback() {
this._render();
}
attributeChangedCallback(attr, oldVal, newVal) {
if (oldVal !== newVal) {
this['_'+attr] = newVal; // This will set either `this._msg` or `this._value`
this._render();
}
}
_render() {
this.innerHTML = `${this._msg} - ${this._value}`;
}
}
customElements.define('mdm-tooltip', ToolTip);
setTimeout(() => {
var el = document.querySelector('mdm-tooltip');
el.setAttribute('value', 'Free');
el.setAttribute('msg', 'I like getting stuff for');
}, 1000);
<mdm-tooltip msg="Help Me" value="10"></mdm-tooltip>
In this example we use observedAttributes and attributeChangedCallback to see when either the value or msg attributes change. When they do we re-render the component.
You can also use properties when setting values:
class ToolTip extends HTMLElement {
constructor() {
super();
this._msg = '';
this._value = '';
}
static get observedAttributes() {
return [ 'value', 'msg' ];
}
connectedCallback() {
this._render();
}
attributeChangedCallback(attr, oldVal, newVal) {
if (oldVal !== newVal) {
this['_'+attr] = newVal; // This will set either `this._msg` or `this._value`
this._render();
}
}
get msg() {
return this._msg;
}
set msg(val) {
if (this._msg !== val) {
this._msg = val;
this._render();
}
}
get value() {
return this._value;
}
set value(val) {
if (this._value !== val) {
this._value = val;
this._render();
}
}
_render() {
this.innerHTML = `${this._msg} - ${this._value}`;
}
}
customElements.define('mdm-tooltip', ToolTip);
var el = document.createElement('mdm-tooltip');
el.value = 10;
el.msg = 'Five times two equals';
document.querySelector('.here').append(el);
setTimeout(() => {
var el = document.querySelector('mdm-tooltip');
el.value = [1,2,3];
el.msg = 'I like getting stuff for';
}, 2000);
<div class="here"></div>
In this example I added properties for value and msg. Now, instead of having to use setAttribute you can now set the properties directly and the properties do not need to be strings like the attributes do.

scala - swing - listener and reactions for TextField to pass data

issue:
reaction += EditDone is not passing proper parameter that i am requesting from listener(this).
question:
am i handling passing the data to the listener or reactions incorrectly? if either, can you please illustrate the issue with an example and where exactly the issue resides?
much appreciated
desired outcome:
to process the TextField input and print the output to a TextArea
contents += new TextField(16)
{
val textField2:TextField = new TextField(16)
{
val reg = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])$"
listenTo(this)
try
{
if (contents == reg)
{
reactions += {
case e: EditDone =>
if (textField2 != reg)
{
println("Please type a valid num.")
}
else
{
println("just testing print")
textArea.text = myFunctionToProcessTextInput(textField2).toString
}
}
}
else
{
println("Please type a valid num.")
}
}
catch
{
case e: Throwable => println("There was an error. \n" + e.getStackTrace())
}
val button:Button = new Button("Click to process")
{
listenTo(mouse.clicks)
}
contents += button
}

windows phone 8 download and play audio on background

I'm using background file transfer and background audio player.
in the TransferStatusChanged event i save the file to the isolated storage then play it with the audio player,
It works fine if the application is active and i want to do the same if the application is not active.
In WP8.0 it isn't possible as your TransferStatusChanged is in your App process which is stopped when you navigate away from it:
When the user navigates forward, away from an app, after the Deactivated event is raised, the operating system will attempt to put the app into a dormant state. In this state, all of the application’s threads are stopped and no processing takes place, but the application remains intact in memory.
You can make it work under LockScreen by disabling IdleDetection but it won't work when your App is put into dormant/tombstoned state.
You may consider to start playing when you activate the App or put some logic in BAP where you can check for example upon TrackChange if the file was downloaded and then play it.
edit
thanks to #Romasz suggestion of use empty track to play while the file complete downloading
then in TrackChange i check if the file downloaded and remove it from the download queue -this can be done in the audio background- things work fine now. here is some code
private AudioTrack GetNextTrack(bool isStart = false)
{
AudioTrack track = null;
using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
{
if (isStart)
{
currentSongIndex = -1;
}
currentSongIndex++;
if (currentSongIndex == _ProgressList.Count())
{
//currentSongIndex = 0;
return track;
}
if (ISF.FileExists("shared/transfers/" + _ProgressList[currentSongIndex].FileName))
{
var request = requests.Where(it => it.Key == _ProgressList[currentSongIndex].FileName).FirstOrDefault().Value;
if (request != null)
{
bool isDone = ProcessTransfer(request, _ProgressList[currentSongIndex].Directory);
if(!isDone )
{
if(request.BytesReceived > LastDownloadedSize)
{
NumberOfTrialsToLoadNextTrack = 0;
LastDownloadedSize = request.BytesReceived;
}
else
{
++NumberOfTrialsToLoadNextTrack;
}
}
}
}
else
{
++NumberOfTrialsToLoadNextTrack;
}
if (ISF.FileExists(_ProgressList[currentSongIndex].Directory+_ProgressList[currentSongIndex].FileName))
{
track = playList[currentSongIndex];
NumberOfTrialsToLoadNextTrack = 0;
LastDownloadedSize = 0;
}
else
{
currentSongIndex--;
if (NumberOfTrialsToLoadNextTrack < 10)
{
track = new AudioTrack(new Uri("halfsec.mp3", UriKind.Relative),
"empty",
"empty",
"empty",
null);
}
}
}
return track;
}
private bool ProcessTransfer(BackgroundTransferRequest transfer, string directory = "")
{
bool isDone = false;
switch (transfer.TransferStatus)
{
case TransferStatus.Completed:
if (transfer.StatusCode == 200 || transfer.StatusCode == 206)
{
RemoveTransferRequest(transfer.RequestId);
using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
string filename = transfer.Tag;
System.Diagnostics.Debug.WriteLine(directory + filename);
if (isoStore.FileExists(directory + filename))
{
isoStore.DeleteFile(directory + filename);
}
if (isoStore.FileExists(transfer.DownloadLocation.OriginalString))
{
isoStore.MoveFile(transfer.DownloadLocation.OriginalString, directory + filename);
}
}
isDone = true;
}
else
{
RemoveTransferRequest(transfer.RequestId);
if (transfer.TransferError != null)
{
}
}
break;
}
return isDone;
// NotifyComplete();
}
private void RemoveTransferRequest(string transferID)
{
// Use Find to retrieve the transfer request with the specified ID.
BackgroundTransferRequest transferToRemove = BackgroundTransferService.Find(transferID);
// try to remove the transfer from the background transfer service.
try
{
BackgroundTransferService.Remove(transferToRemove);
}
catch (Exception)
{
}
}
protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)
{
switch (playState)
{
case PlayState.TrackEnded:
player.Track = GetNextTrack();
break;
case PlayState.TrackReady:
player.Play();
break;
case PlayState.Shutdown:
// TODO: Handle the shutdown state here (e.g. save state)
break;
case PlayState.Unknown:
break;
case PlayState.Stopped:
break;
case PlayState.Paused:
break;
case PlayState.Playing:
break;
case PlayState.BufferingStarted:
break;
case PlayState.BufferingStopped:
break;
case PlayState.Rewinding:
break;
case PlayState.FastForwarding:
break;
}
NotifyComplete();
}
this code in the AudioPlayer class, the files added to the download queue in the xaml.cs normally