While using the new Dojo Event (on) i'm getting a lot of loops.
I'm calling for the first time as doShowSomeDialog(null).
Why does this function get into a loop?
(dialog has been declared before as dijit/Dialog)
doShowSomeDialog = function ( value ) {
var selectName = 'selector';
if ( value ) {
dialog.set("href", "/url/"+ selectName +"/"+ value );
} else {
dialog.set("href", "/url");
dialog.show();
}
dialog.set("onDownloadEnd", function() {
on( dijit.byId(selectName ), "change", doShowSomeDialog( dijit.byId( selectName ).get('value') ) );
}); }
It seems that "on" executes on the declaration of the event.
This will execute the method when calling on. You should wrap it in it's own function.
doShowSomeDialog( dijit.byId( selectName ).get('value')
should become
function() { doShowSomeDialog( dijit.byId( selectName ).get('value'); }
Related
I am trying to set a observable to the mouse co-ordinate using RxJs. But i am getting error as 'Observable` is not defined.
any one help me here?
here is my code :
$(document).ready(function() {
var mouseMoves = Observable.fromEvent( mouseDown )
.takeUntil( mouseUp )
.map( function( mouseEvent) {
return {
x : mouseEvent.clientX,
y : mouseEvent.clientY
}
})
mouseMoves.subscribe( function ( cords ) {
console.log( cords );
// $('#results').html( cords );
})
});
Live Demo
You can use Rx.Observable instead of Observable:
var mouseMoves = Rx.Observable.fromEvent( mouseDown )
.takeUntil( mouseUp )
.map( function( mouseEvent) {
return {
x : mouseEvent.clientX,
y : mouseEvent.clientY
}
})
I'm trying to find a reliable way to perform a callback when certain text is typed into the editor. I want to run certain code when an # is typed (to then allow a selection of user's to link to).
Currently I am doing it by using the "change" event and then trying to look back at what is before the current selection:
CKEDITOR.plugins.add( 'ipsmentions', {
init: function( editor ) {
/* When the content of the editor is changed, check if it was an # */
editor.on( 'change', function(e) {
/* If we currently have just normal text selected, we're typing normally and there might be an # */
var selection = editor.getSelection();
if ( selection.getType() == CKEDITOR.SELECTION_TEXT ) {
/* Loop the ranges... */
var ranges = selection.getRanges( true );
for ( var i = 0; i < ranges.length; i++ ) {
/* If the start container and end container are the same (meaning we just have a normal caret, indicating normal typing, nothing highlighted) and that is a text node... */
if ( ranges[i].startContainer.equals( ranges[i].endContainer ) && ranges[i].endContainer instanceof CKEDITOR.dom.text ) {
if ( ranges[i].startContainer.getText().substr( ranges[i].startOffset - 1, 1 ) == '#' ) {
console.log('# pressed!');
}
}
}
}
});
}
});
But I'm guessing this isn't the best way. In particular, I notice that if I type # and then hit enter (to start a new paragraph) I get "# pressed" in the console again.
Is there a better way to go about this?
Asynchronous check should help with enter key. I would also use some backwards range.cloneContents because you never know in what type of node the selection might be anchored. JSFiddle.
CKEDITOR.replace( 'editor', {
on: {
change: function() {
CKEDITOR.tools.setTimeout( function() {
var sel = this.getSelection(),
range = sel.getRanges()[ 0 ];
if ( !range.collapsed ) {
console.warn( 'non–collapsed range' );
return;
}
if ( !range.startOffset ) {
console.warn( 'at the beginning of the node' );
return;
}
range.setStart( range.startContainer, 0 );
if ( range.cloneContents().$.textContent.substr( -1 ) == '#' ) {
console.log( '# inserted' );
}
}, 0, this );
}
}
} );
Although there is an example in Ractive docs, I am a starter with promises and I don't understand the mentioned example:
var Promise = Ractive.Promise;
var p = new Promise( function ( fulfil, reject ) {
doSomethingAsync( function ( error, result ) {
if ( error ) {
return reject( error );
}
fulfil( result );
});
});
How can I use Ractive's implementation to run some functions asynchronously?
Edit: An use case example is when I have, in the same function, synchronous and asynchronous operations and I need to return a Promise when all of these operations where processed.
This is more a question about promises than about Ractive, so this MDN article would be worth a read, though it's a bit heavy.
Basically though, if you want to wait until several operations have finished, use Promise.all:
var ready = Promise.all([
getJSON( '/data.json' ), // async (returns a promise)
domReady(), // async
reticulateSplines() // sync
]);
getJSON and domReady will be executed simultaneously. So will reticulateSplines, not that it matters since it's synchronous. The value of ready is now a promise that will fulfil with an array containing the results of those three operations:
ready.then( function ( values ) {
var data = values[0];
var document = values[1];
var splines = values[2];
// some code happens
}).catch( function ( err ) {
// if something went wrong with any of those three
// functions (e.g. couldn't find data.json), we'll
// end up here
});
If you're transpiling your code with something like babel, you can also use destructuring:
ready.then( ([ data, document, splines ]) => {
// some code happens
}).catch( err => {
// handle error
});
Another useful function if you're dealing with maybe-sync-maybe-async stuff (though it really is better to avoid that sort of thing) is Promise.resolve:
function crazyTown () {
if ( Math.random() < 0.5 ) {
return 'sync!';
} else {
return new Promise( function ( fulfil, reject ) {
setTimeout( function () {
fulfil( 'async!' );
}, 500 );
});
}
}
Promise.resolve( crazyTown() ).then( function ( type ) {
console.log( type );
});
If your browser supports promises natively, Ractive will use those (i.e. Ractive.Promise === window.Promise) - if not, it uses its own spec-compliant implementation.
I've been searching around to find why Kendo callbacks are not working with TypeScript but I couldn't find something useful.
So my question is how can kendo use class method as a callback?
Ex:
$("#ipt_tree").kendoTreeView(
{
dataSpriteCssClassField: "sprite",
dataSource: data,
template: "<span data-oid='#= item.oid#'>#= item.text#</span>",
//change: this.Tree_Item_Selected, //doens't get even called
//change: ( item: any ): void => //'this' is not 'this' of the class
//{
// this.Tree_Item_Selected( item );
//}
change: function( item: any ) //using compiler this variable
{
_this.Tree_Item_Selected( item );
}
});
The only solution I've found is to use the _this variable that compiler makes.
Now for the jquery the method callbacks work perfectly.
$( "#ipb_aci_button_edit" ).show().on( "click", this.Info_OnClick_Edit );
private Info_OnClick_Edit = (): void =>
{
//'this' is correct
}
If using the current version of TypeScript (1.0RC), you create a class:
class Demo {
private Tree_Item_Selected(item:any) { }
public Create_Tree(data:any) {
var kendoSettings = {
dataSpriteCssClassField: "sprite",
dataSource: data,
template: "<span>#= item.text#</span>",
change: ( item: any ): void =>
{
this.Tree_Item_Selected( item );
},
change2: function( item: any )
{
_this.Tree_Item_Selected( item );
}
};
}
}
And compile that to JavaScript, the functions change and change2 in the example code both produce the exact same code block:
change: function (item) {
_this.Tree_Item_Selected(item);
},
change2: function (item) {
_this.Tree_Item_Selected(item);
}
The only difference is that the second one produces an error that _this is not found.
In the second example, it's working because it's captured the this correctly. However, you might want to consider a different syntax:
$( "#ipb_aci_button_edit" ).show().on( "click",
(e:JQueryEventObject) => { this.Handle_Info_OnClick_Edit(e) } );
private Handle_Info_OnClick_Edit(e:JQueryEventObject): void
{
// 'this' is correct as it was captured by the event handler code
}
I'm struggling with a MVC pattern around Stateful objects and Observable stores. I can't find clarity on when to use one over another and mixing them isn't as clean as I'd hoped. Any Ah! insight into how to manage an observable collection of stateful items?
If I do a item.set("key", value) I can item.watch("key", cb) but then my observe-er isn't notify-ed.
I can do a item.watch(function() { state.notify(item, item.id); }) to always notify my observer but if my observe-er calls set I get a "Query is out of date, you must observe() the query prior to any data modifications'" error I cannot reconcile.
I can decouple this via a setTimeout but it's not feeling good.
Here's some code to show what I'm trying:
crudify: function ( store, query, crud )
{
var result;
if ( !crud )
{
crud = query;
query = store;
store = null;
}
if ( store )
{
query = store.query( query );
}
result = query.observe( function ( row, deleteIndex, insertIndex )
{
var del = ( 0 <= deleteIndex ), ins = ( 0 <= insertIndex );
!del && ins && crud.c && crud.c( row );
del && ins && crud.u && crud.u( row );
del && !ins && crud.d && crud.d( row );
}, !!crud.u );
crud.c && array.forEach( query, crud.c );
return result;
}
And I have a store wrapper (for layers) which I'm hacking to pieces trying to get the observe-ers notified of data changes without getting errors:
addLayer: function ( item ) {
var that = this;
that.store.add(item);
item.watch && item.watch(function (name, prior, curr) {
if (prior !== curr) {
that._queue.push(item);
// attempting to eliminate queries which indirectly update the store (can't find source of error)
infor.delay(20, "LayerProcessorStoreNotification", function () {
that._queue.forEach(function (item) {
that.store.notify(item, that.getLayerId(item));
});
that._queue = [];
});
}
});
return item;
},
The delay method looks like this:
delay: function ( timeout, id, callback )
{
this.delays = this.delays || [];
var delay = this.delays[id];
if ( delay )
{
clearTimeout( delay );
}
delay = setTimeout( callback, timeout );
this.delays[id] = delay;
},
I can do a item.watch(function() { state.notify(item, item.id); }) to always notify my observer
I didn't have any problems using this pattern, but...
but if my observe-er calls set I get a "Query is out of date, you must observe() the query prior to any data modifications'" error I cannot reconcile.
You shouldn't have watch call notify and also have observe call set. Choose one or the other. Otherwise you're setting yourself up for an infinite loop of callbacks.
The code below works for me. The only change I made to your crudify function was to change array.forEach(query, crud.c) to query.forEach(crud.c).
<script type="text/javascript" src="../javascripts/dojo-release-1.9.3-src/dojo/dojo.js"></script>
<script type="text/javascript">
window.stackoverflow = {
crudify: function ( store, query, crud )
{
var result;
if ( !crud )
{
crud = query;
query = store;
store = null;
}
if ( store )
{
query = store.query( query );
}
result = query.observe( function ( row, deleteIndex, insertIndex )
{
console.log("Observed");
var del = ( 0 <= deleteIndex ), ins = ( 0 <= insertIndex );
!del && ins && crud.c && crud.c( row );
del && ins && crud.u && crud.u( row );
del && !ins && crud.d && crud.d( row );
}, !!crud.u );
crud.c && query.forEach( crud.c );
return result;
}
};
require([
"dojo/store/Memory",
"dojo/store/Observable",
"dojo/Stateful",
"dojo/_base/json",
"dojo/domReady!"
], function(Memory, Observable, Stateful, dojo){
var store = Observable(new Memory({ data: [] }));
var rawData = [ { id: 1, data: "A" }, { id: 2, data: "B" }, { id: 3, data: "C" }]
var myQuery = { id : 3 };
rawData.forEach(function (obj, index) {
statefulObj = new Stateful(obj);
statefulObj.watch(function(name, oldValue, newValue) {
console.log("Watched");
store.notify(statefulObj, statefulObj.id);
});
store.put(statefulObj);
});
window.setTimeout(function() {
// this directly triggers the observe() callback
store.notify(store.get(3), 3);
}, 2000);
window.setTimeout(function() {
// this triggers the watch(), which indirectly triggers observe() through notify()
store.get(3).set("data", "Sea?");
}, 4000);
window.setTimeout(function() {
// this calls no callbacks because it doesn't match the query
store.put({ id: 2, data: "Bee" });
}, 6000);
window.setTimeout(function() {
// this update triggers observe()
store.put(new Stateful({ id: 3, data: "See!?!" }));
// note that we didn't set up a watch() on this new object (see below)
}, 8000);
window.setTimeout(function() {
// whoops, this doesn't trigger a callback because we forgot to call watch() above
store.get(3).set("data", "C4");
}, 10000);
window.setTimeout(function() {
// but the observe() callback still works
store.notify(store.get(3), 3);
}, 12000);
window.setTimeout(function() {
// this deletion triggers observe()
store.remove(3);
}, 14000);
stackoverflow.crudify(
store,
myQuery,
{
u: function(obj) {
console.log("Observed update: obj: " + dojo.toJson(obj));
},
c: function(obj) {
console.log("Observed creation: obj: " + dojo.toJson(obj));
},
d: function(obj) {
console.log("Observed deletion: obj: " + dojo.toJson(obj));
}
});
});
</script>