jQuery-Chains in an AngularJS $timeout - javascript

Am I mistaken or is AngularJS' $timeout function buggy when it comes to jQuery-Chains (in this case jsTree)?
An exception is raised
$.(...).jstree(...).on is not a function
This is my snippet:
$timout(function() {
$("#foo").jstree().on('select_node:jstree', onSelect)
});
When not chaining the .on() but having it in an extra line like
$("#foo").on('select_node:jstree', onSelect)
there is no exception beeing thrown and the onSelect works fine.
Any hint is much appreciated!

you must download jstree and include that your project
https://github.com/vakata/jstree/zipball/3.2.1
Overview
Include a jsTree theme
Setup a container
Include jsTree
Create an instance
Listen for events
Interact with your instances

$(selector).jstree() returns an instance of $.jstree.core, and not a jQuery wrapped object.
Thus, you cannot chain it with the .on() handler setter - problem is completely unrelated from Angular / timeout issues of course.

Related

javascript method writing patterns

This is regarding javascript programming pattern. while working with the gulp, I came across 2 different type of function calling pattern and this is really confusing so someone clarifies Is both functions are doing the same job?
gulp.watch(path.join(conf.paths.src, '/app/**/*.js'),
function(event) {
if(event.type === 'changed') {
callAMethod();
} else {
callBMethod();
}
});
in above method, we can write if else condition
but in this pattern
gulp.watch(path.join(conf.paths.src, '/app/**/*.js'))
.on('change', callAMethod);
If yes then please suggest some links Where I can read about it and which is the better way to handle the errors? also, where do we write else part in the later method style?
They are both different.
The first one is a callback to the gulp.watch method and it gets all the events that the watcher produces
The second one does not provide a callback, instead it subscribes to one event (change) produced.
The watch method returns a Gaze object and to handle errors, subscribe to the error event:
watcher.on('error', function(error) {
// Handle error here
});
Gulp4 which is still in alpha stage uses chokidar. To watch for errors, it's exactly the same as the above:
watcher.on('error', error => log(`Watcher error: ${error}`))
These functions are different.
Gulp uses a utility named glob-watcher for handling file changes and the first one is a callback called by glob-watcher.
The second one is a raw event from Event Emitter (NodeJS Emitter or Chokidar) instance.
Some events from EventEmmiter propagate to glob-watcher callback - for example, "change", so it may look the same on the first look.
For handling errors, I recommend having a look at gulp-plumber plugin.

How do I get a webcam working with AngularJS?

Previously I've put working webcam code into my application, but now it's not working when I updated to AngularJS v1.5.0. I am using webcam-directive which was working perfectly with v1.3.0.
Here is my code:
<webcam placeholder="selfiePlaceHolder"
on-stream="onStream(stream)"
on-access-denied="onError(err)" on-streaming="onSuccess(video)">
</webcam>
But now it's giving following error with AngularJS v1.5.0:
Uncaught Error: [$parse:isecdom] Referencing DOM nodes in Angular expressions is disallowed! Expression: onSuccess(video)
http://errors.angularjs.org/1.5.0/$parse/isecdom?p0=onSuccess(video)
I also tried to use a different solution with AngularJS ng-Camera but even its demo page is not working for me.
Note: I know the issue is that we can't access the DOM from the newer version of AngularJS, but the same code works with the older version. I need to know how to pass the "Video" DOM object to the controller.
I've found the solution to the problem. Two things need to be done:
First In HTML:
<webcam channel="channel"
on-streaming="onSuccess()"
on-error="onError(err)"
on-stream="onStream(stream)"></webcam>
Secondly, in the controller, you can access the DOM video with the following code:
$scope.onSuccess = function () {
// The video element contains the captured camera data
_video = $scope.channel.video;
$scope.$apply(function() {
$scope.patOpts.w = _video.width;
$scope.patOpts.h = _video.height;
//$scope.showDemos = true;
});
};
Here is a working example.
It is a potential error generally occurs when an expression tries to access a DOM node since it is restricted accessing to DOM nodes via expressions by AngularJS because it might cause to execute arbitrary Javascript code.
The $parse:isecdom error is related to an invoke to a function by event handler when an event handler which returns a DOM node, like below:
<button ng-click="myFunction()">Click</button>
$scope.myFunction = function() {
return DOM;
}
To fix this issue, avoid access to DOM nodes and avoid returning DOM nodes from event handlers. (Reference: https://docs.angularjs.org/error/$parse/isecdom)
Adding an explicit return might solve this issue as detailed here: CoffeeScript - Referencing DOM nodes in Angular expressions is disallowed
I was able to get webcam-directive working using the channel suggestion from the comment above, based on the example on the github page.
function MyController($scope) {
$scope.myChannel = {
// the fields below are all optional
videoHeight: 800,
videoWidth: 600,
video: null // Will reference the video element on success
};
}
In the onSuccess(on-streaming attr) and onStream(on-stream attr) callback the video property of myChannel was filled in with the video DOM element (and then it would obviously be available to everything else in the controller too). According to the comment in the example code though, you should wait to access it at least until onSuccess. Here is a working example

How are custom broadcast events implemented in JavaScript (or jQuery)?

I want to implement a custom event that can be "broadcast", rather than sent to specific targets. Only those elements that have registered themselves as listeners for such events will receive them.
What I have in mind would look as follows.
First, in various places of the code, there would be statements of the form
some_subscriber.on_signal( 'some_signal', some_handler );
I'm using the term signal as shorthand for "broadcast event". In the expression above, some_subscriber registers itself as a listener of one type (called 'some_signal') of such signals, by providing a handler for it.
Elsewhere in the code, there would be statements of the form
publisher.signal_types[ 'some_signal' ].broadcast( event_data );
When statements like these get executed, a new event is generated and "broadcast". By this I mean that the code that calls the broadcast method has no direct information about the listeners for the signal it is issuing.
I have implemented a sketch of this idea in this jsFiddle, mostly in order to illustrate what I described in words above1. (It's certainly not production-grade, and I'm not particularly confident that it could be made so.)
The key elements of this implementation are the following. First, publisher objects do not keep track of their subscribers, as can be seen in the implementation of a factory method for such a publisher, shown below:
function make_publisher ( signal_types ) {
// ...
var _
, signal = {}
, ping = function ( type ) {
signal[ type ].broadcast( ... );
}
;
signal_types.forEach( function ( type ) {
signal[ type ] = $.register_signal_type( type );
} );
return { signal_types: signal_types, ping: ping };
}
This publisher object exposes only two items: the types of signals it broadcasts (in signal_types), and a ping method. When its ping method is invoked, the publisher responds by broadcasting a signal:
signal[ type ].broadcast( ... )
The ultimate recipients of this broadcast are nowhere to be seen in this code.
Second, elsewhere in the code, subscribers register themselves as listeners of these broadcast signals, like so
$( some_selector ).on_signal( signal_type, some_handler );
Note: It is basically impossible to illustrate the rationale for this scheme using an example that is both small and realistic. The reason for this is that the strength of this scheme is that it supports very loose coupling between the publisher code and subscriber code, and this is a feature that is never necessary in a small example. On the contrary, in a small example, code that implements such loose coupling invariably comes across as unnecessarily complex. It is therefore important to keep in mind that this apparent excess complexity is an artifact of the context. Loose coupling is very useful in larger projects. In particular, loose coupling via a publisher/subscriber-type pattern is one of the essential features of MVC.
My question is: is there a better (or at least more standard) way to achieve this effect of "broadcasting" custom events?
(I'm interested in both jQuery-based answers as well as "pure JS" ones.)
1An earlier, ill-fated version of this post was met with almost universal incomprehension, and (of course) the all-too-typical down-voting. With one exception, all the comments I got challenged the very premises of the post, and one directly questioned my grasp of the basics of event-driven programming, etc. I'm hoping that by presenting a working example of what I mean at least it won't come across as utterly inconceivable as it did when I described it in words alone. Luckily, the one helpful comment I did get on that earlier post informed me of the function jQuery.Callbacks. This was indeed a useful tip; the sketch implementation mentioned in the post is based on jQuery.Callbacks.
All right.
So I think what you can do is use the native dispatchEvent and addEventListener methods and use document as the only element for both publishing and subscribing to those events. Something like:
var myCustomEvent = new Event('someEvent');
document.dispatchEvent(myCustomEvent);
...
document.addEventListener('someEvent', doSomething, false);
And to make cross-browser, you could:
var myCustomEvent = new Event('someEvent');
document.dispatchEvent(myCustomEvent);
...
if (document.addEventListener) {
document.addEventListener('someEvent', doSomething, false);
} else {
document.attachEvent('someEvent', doSomething);
}
You can read more on the subject here and here. Hope this helps.
My question is: is there a better (or at least more standard) way to
achieve this effect of "broadcasting" custom events?
No, there is not a more standard way of doing publish/subscribe in Javascript. It is not directly built into the language or the browser and there are no platform standards for it that I'm aware of.
You have several options (most of which you seem aware of) to put your own system together.
You could pick a specific object such as the document object or the window object or a new object you create and use jQuery's .on() and .trigger() with that object as a central clearing house to cobble together a publish/subscribe-like model. You could even hide the existence of that object from your actual use by just coding it into a few utility functions if you want.
Or, as you seem to already know, you could use the jQuery.Callbacks functionality. There's even publish/subscribe sample code in the jQuery doc.
Or, you can find a third party library that offers a somewhat traditional publish/subscribe model.
Or, you can build your own from scratch which really just involves keeping a list of callback functions that are associated with a specific event so when that event is triggered, you can call each callback function.
If you came here looking for the jQuery way of doing this, here you go:
Add the event broadcast/dispatch code:
Syntax:
$(<element-name>).trigger(<event-name>);.
Example:
$.ajax({
...
complete: function () {
// signal to registered listeners that event has occured
$(document).trigger("build_complete");
...
}
});
Register a listener for the event:
Syntax:
$(<element-name>).on(<event-name>, function() {...});
Example:
$(document).on("build_complete", function () {
NextTask.Init();
});
Note:
Doing it this way: $(document).build_complete(function() {...}); leads to an error: Uncaught TypeError: $(...).build_complete is not a function.
I know this has been marked as answered back in 2015 -- but a solution that is also elegant and simple could be to use Redux

How can you reset Knockout for each Jasmine test?

I have some feature tests that run with a fixture (loaded with jasmine-jquery) that has some Knockout bindings in the HTML. At the begin of each test I want to start with a viewModel in its initial state.
If I call applyBindings() in the beforeEach() with a new instance of the viewModel I get this error from Knockout
Error: You cannot apply bindings multiple times to the same element.
If I try to revert the properties of the existing viewModel to match its initial state I still get an error. I believe this is because the fixture's HTML is removed after each test - this probably breaks the bindings?
I've also tried a suggestion that came up when Googling which was to use the cleanNode function in Knockout. This isn't part of the API (it only designed to be used by Knockout internally) and no matter what I tried it didn't resolve the issue.
It feels like I'm taking the wrong approach to this. tl;dr; How does everybody else test Knockout with Jasmine?
Thanks for any help
I generally append an element in beforeEach, apply bindings to that element, and ko.removeNode on it in afterEach. Something like:
var fixture;
beforeEach(function() {
fixture = document.createElement("div");
document.body.appendChild(fixture);
});
afterEach(function() {
ko.removeNode(fixture);
});
Then use fixture as the second argument to any applyBindings calls like: ko.applyBindings(myTestViewModel, fixture);
The way I solved this was changing my js to check for jasmine e.g.:
if (!window.jasmine)
ko.applyBindings(viewModel);

HTML5 drag event using a $(function() { ... } library

I have been playing around with HTML5 and Javascript for the first time and I am stuck. My question in short is how do I call a method (in html) inside a JS file which starts with
$(function() { ... }
Basically I used azure which gives you a code project to start but when it gave me the files there was a page.js which started with:
$(function() {
var client = new WindowsAzure.MobileServiceClient('[...]', '[...]'),
todoItemTable = client.getTable('todoitem');
...
The azure service has a very simple database which I need to use to create a Kanban boardesc webpage.
I made my task element draggable and added events to handle it but I am unable to create the event method in this JS file and if I have it in my HTML I am unable to call any of the methods in the .js
I have asked around work and no one seems to have seen the $(function() { ... } thing before and I can't find the info that I need anywhere.
Thanks
You do not call this method directly; the syntax you're looking at is JQuery's document.ready in other words this function gets called when your document is finished loading.
JQuery Link - Document.Ready
That is the jQuery shorthand for the $(document).ready(handler) function. Anything you put in the function will be executed when the document is finished loading.
jQuery ready function
That syntax is jQuery - specifically an an alias of the "DOMReady" function
( http://api.jquery.com/ready/ ) which is called after the DOM has finished loading.
Try looking at this question's suggested answer by Derick Bailey.
Why define an anonymous function and pass it jQuery as the argument?
He includes some sample code of how to write a code using a JavaScript Module pattern.
Good luck!
Anthony

Categories

Resources