knockout bind doubleclick and singleclick, ignore singleclick if double click - data-binding

I have a click event bound to the following ko function:
self.select = function (entity, event) {
var ctrlPressed = false;
if (event.ctrlKey) { ctrlPressed = true; }
if (!ctrlPressed) {
manager.deselectAll();
this.selected(true);
} else {
this.selected() ? this.selected(false) : this.selected(true);
}
}
It is bound like so:
data-bind="click: select, event: { dblclick: function(){alert('test');}}"
This currently works except that it fires "select" twice when you double click, which I do not want. I tried following the advice in this SO question, but when I create the singleClick() function, I get an error that "ctrlKey is not a function of undefined". So it's not passing the event properly. Further more, the doubleClick() function in the other answer there doesn't work at all. It gives an error on the "handler.call" part saying handler is not defined.
So, how can I successfully call my ko select function on singleClick but NOT on doubleclick?

I don't think this is really a knockout issue. You have at least these two options:
1. Implement some custom logic that prevents processing if a single click has started processing already
2. Prevent the double-click function altogether. JQuery has this handy handler:
$(selector).on("dblclick", function(e){
e.preventDefault(); //cancel system double-click event
});

So I technically got it to work. Here is my new singleClick function
ko.bindingHandlers.singleClick = {
init: function (element, valueAccessor, c, viewModel) {
var handler = valueAccessor(),
delay = 400,
clickTimeout = false;
$(element).click(function (event) {
if (clickTimeout !== false) {
clearTimeout(clickTimeout);
clickTimeout = false;
} else {
clickTimeout = setTimeout(function () {
clickTimeout = false;
handler(viewModel, event);
}, delay);
}
});
}
};
This passes the viewModel and event to the handler so I can still modify observables and capture ctrlKey pressed.
The binding:
data-bind="singleClick: select, event: { dblclick: function(){alert('test');}}"
The problem is that now, obviously, single clicking an item has a delay while it waits to see if it's a double click. This is an inherent and unsolvable issue, I believe, so though this technically answers my question, I will consider a completely different route (ie, no double-clicking at all in my interface)

Related

Is there a way to attach callback what fires whenever a crossfilter dimension filter changes?

I have several charts built with dc.js. I can achieve the desired functionality by attaching a callback to each dc.js chart's .on("filterted", function(chart) {}) but this is annoying because I have to attach the same callback to each chart. And error prone because as new charts are added, someone has to remember to attach an event hander. I would prefer to just attach a callback to the underlying crossfilter. Is that possible?
Is there a way to optimize this...
var ndx = crossfilter(data);
var dimAlpha = ndx.dimension(function(d) {return d.alpha});
var dimBeta = ndx.dimension(function(d) {return d.beta});
var groupAlpha = dimAlpha.group().reduceSum(function(d) {return 1;});
var groupBeta = dimBeta.group().reduceSum(function(d) {return 1;});
dc.pieChart(myDomId1)
.dimension(dimAlpha)
.group(groupAlpha)
.on("filtered", function(chart) {
//do stuff
});
dc.pieChart(myDomId2)
.dimension(dimBeta)
.group(groupBeta)
.on("filtered", function(chart) {
//do stuff
});
into something like this...
var ndx = crossfilter(data);
var dimAlpha = ndx.dimension(function(d) {return d.alpha});
var dimBeta = ndx.dimension(function(d) {return d.beta});
var groupAlpha = dimAlpha.group().reduceSum(function(d) {return 1;});
var groupBeta = dimBeta.group().reduceSum(function(d) {return 1;});
dc.pieChart(myDomId1)
.dimension(dimAlpha)
.group(groupAlpha);
dc.pieChart(myDomId2)
.dimension(dimBeta)
.group(groupBeta);
ndx.on("filtered", function() {
//do stuff
})
If you've got a million charts and don't want to have to attach the event listener to each one manually, you could iterate through the chart registry and add them that way. Ex:
dc.chartRegistry.list().forEach(function(chart) {
chart.on('filtered', function() {
// your event listener code goes here.
});
});
Note that this code must go after the charts have instantiated to work.
In the absence of a way to attach the callback once globally, one thing you could do to mitigate the risk from duplicate code is to define the callback function once and pass in a reference instead of defining it inline on each chart.
function my_func() {
// do stuff
}
dc.pieChart(myDomId2)
.dimension(dimBeta)
.group(groupBeta)
.on("filtered", my_func);
chart and filter can also be passed to the filter function something like:
function my_func(chart,filter) {
// do stuff
}
dc.pieChart(myDomId2)
.dimension(dimBeta)
.group(groupBeta)
.on("filtered", my_func);

XPages Dojo DataStore Get and Cycle Through Return Values

My goal is to grab all the rows in the DataGrid that I display, cycle through each row, grab certain items and values, and update fields in the UI. Based on what I have read, it is best to grab the datastore and go through that.
The user is editing the Dojo datagrid (editable columns) and clicking a Save button to save the changes (RESTService.save()). During the Save button process, I would like to cycle through the datastore.
I am using examples from this:
http://xcellerant.net/2013/06/13/dojo-data-grid-21-locking-columns/
This is my REST Service:
<xp:this.resources>
<xp:dojoModule name="dojo.data.ItemFileWriteStore"></xp:dojoModule></xp:this.resources><xe:restService id="rsVictims" pathInfo="rsVictimsData">
<xe:this.service>
<xe:viewJsonService defaultColumns="true"
viewName="InvoiceMPRVictims">
<xe:this.databaseName><![CDATA[#{javascript:applicationScope.get("appConfig").keywords.appDataStore.join("!!");}]]></xe:this.databaseName>
<xe:this.keys><![CDATA[#{javascript:viewScope.get("mprKeysValue");}]]></xe:this.keys>
</xe:viewJsonService>
</xe:this.service>
</xe:restService>
This is the Save button:
<xp:button value="Save Changes" id="victimsSaveButton">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[// Save the changes...
try{
rsVictims.save();
var jsonStore;
// Get the datastore...
jsonStore = new dojo.data.ItemFileWriteStore({url: "invoices_page1_doc.xsp/rsVictimsData"});
// Cycle through the jsonStore...
}
catch (e) {
alert(e);
}
]]></xp:this.script>
</xp:eventHandler>
</xp:button>
I was hoping to get a few examples on how to cycle through the datastore return. I see ideas in this reference, but not sure which one to use:
http://dojotoolkit.org/reference-guide/1.9/dojo/data/ItemFileWriteStore.html
Also, does saving the REST Service (rsVictims.save();) before grabbing the datastore give me the current values?
Thanks!
-------------- EDIT 1/6/2014 ----------------------
I have updated the Save button to use this code:
try {
rsVictims.save();
var item;
var itemStore;
var itemName;
var itemValue;
// Get the datastore...
itemStore = new dojo.data.ItemFileReadStore( {
url : "invoices_page1_doc.xsp/rsVictimsData"
});
itemName = "month_11";
function failed(error) {
// Do something with the provided error.
alert(error);
}
function gotItem(item) {
if (itemStore.isItem(item)) {
itemValue = itemStore.getValue(item, itemName);
alert(itemValue);
} else {
// This should never occur.
throw new Error("Unable to locate the item with identity [sv]");
}
}
// Invoke the lookup. This is an async call as it may have to call back to a
// server to get data.
itemStore.fetchItemByIdentity( {
identity : itemName,
onItem : gotItem,
onError : failed
});
} catch (e) {
alert(e);
}
However, I do not get any return values in the gotItem function and I receive no errors.
I may have missed something -- any help would be great!
Thanks!

sencha touch - setMasked called from button handler does not render until the handler is finished?

A bit stuck with this one. If I call setMasked from button handler which is processing for a long time, the mask is rendered when the handler function is finished.
Is there a way to force paint the mask within the handler?
Ext.define('ts.view.chartIt', {
extend: 'Ext.Panel',
initialize: function() {
var card = this;
// ...
var submit = Ext.create('Ext.Button', {
handler: function(button, e) {
card.setMasked(true);
// long retrieval operations
card.setMasked(false);
});
// ...
}
});
Define a function outside the button handler and call it, put the setMasked(true) and setMasked(false) inside the processing function.
Example:
myFunction: function(){
card.setMasked(true);
// long retrieval operations
card.setMasked(false);
}
and then inside the handler the code will be:
var submit = Ext.create('Ext.Button', {
handler: function(button, e) {
this.myFunction;
});

Help Debugging an Ajax Server Control Client Script

I am writing an Ajax Server Control in ASP.NET C# 4.0 in VS 2010.
After writing the javascript prototype class by hand, I don't know of a way to compile and debug file. To see why my "onclick" event doesn't work.
I'm creating an Ajax Server control by inheriting from Control & IScriptControl, and trying to get an onclick event handler to work. The written control is actually a "DIV". Can someone tell me why it doesn't work?
Thanks
public class FrebbleSquare : Control, IScriptControl
{
.
.
.
IEnumerable<ScriptReference> IScriptControl.GetScriptReferences()
{
ScriptReference oRef1 = new ScriptReference("FrebbleAjaxControls.FrebbleSquare.js", this.GetType().Assembly.ToString());
ScriptReference oRef2 = new ScriptReference("FrebbleAjaxControls.prototype.js", this.GetType().Assembly.ToString());
ScriptReference oRef3 = new ScriptReference("FrebbleAjaxControls.scriptaculous.js", this.GetType().Assembly.ToString());
ScriptReference oRef4 = new ScriptReference("FrebbleAjaxControls.effects.js", this.GetType().Assembly.ToString());
return new ScriptReference[] { oRef1, oRef2, oRef3, oRef4 };
}
IEnumerable<ScriptDescriptor> IScriptControl.GetScriptDescriptors()
{
ScriptControlDescriptor descriptor = new ScriptControlDescriptor("FrebblesAjax.FrebbleSquare", this.ClientID);
return new ScriptDescriptor[] { descriptor };
}
}
JAVASCRIPT CLIENT FILE :
Type.registerNamespace('FrebblesAjax');
FrebblesAjax.FrebbleSquare = function (element) {
FrebblesAjax.FrebbleSquare.initializeBase(this, [element]);
}
FrebblesAjax.FrebbleSquare.prototype =
{
initialize: function () {
FrebblesAjax.FrebbleSquare.callBaseMethod(this, 'initialize');
this._onclickHandler = Function.createDelegate(this, this._onClick);
$addHandlers(this.get_element(),
{ 'click': this._onClick,
},
this);
},
dispose: function () {
$clearHandlers(this.get_element());
FrebblesAjax.FrebbleSquare.callBaseMethod(this, 'dispose');
},
_onClick: function (e) {
alert('it worked!');
}
}
FrebblesAjax.FrebbleSquare.registerClass('FrebblesAjax.FrebbleSquare', Sys.UI.Control);
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
If you can use Firefox, download the Firebug extension. When the page loads, right-click on the element that you created and select "inspect element". This way you can see all the structure, properties, and functions of the DOM as it currently exists. This is usually preferable to "view source" when you're working with JavaScript. You should be able to see which event handlers are bound and set breakpoints in the JavaScript debugger.

Dropdownlist doesn't postback after Page_ClientValidate()

Update:
I have just found the solution. The following function works (remove the else part):
function confirmSubmit() {
if (Page_ClientValidate("Group1")) {
return window.confirm("Are you sure to submit the form?");
}
}
But I am wondering why it doesn't work when I add the else part.
Question:
I want to have a confirm dialog after user fills in all the data in the form.
I set onclientclick="return confirmSubmit()" in the submit button.
function confirmSubmit() {
if (Page_ClientValidate("Group1")) {
return window.confirm("Are you sure to submit the form?");
} else {
return false;
}
}
If Page_ClientValidate("Group1") returns false, the dropdownlist doesn't cause postback after I first select the item, and the postback only occurs when I select the dropdownlist second time.
What's the problem?
After Page_ClientValidate is called, the variable Page_BlockSubmit gets set to true, which blocks the autopost back. Page_BlockSubmit was getting reset to false on the second click, for what reasons I still don't fully understand. I'm looking more into this, but I have a solution and I'm under the gun so I'm rolling with it....
Just add below code in the code block which executes if Page is not valid.
Page_BlockSubmit = false;
e.g.
function ValidatePage()
{
flag = true;
if (typeof (Page_ClientValidate) == 'function')
{
Page_ClientValidate();
}
if (!Page_IsValid)
{
alert('All the * marked fields are mandatory.');
flag = false;
Page_BlockSubmit = false;
}
else
{
flag = confirm('Are you sure you have filled the form completely? Click OK to confirm or CANCEL to edit this form.');
}
return flag;
}
I have just found the solution. The following function works (remove the else part):
function confirmSubmit() {
if (Page_ClientValidate("Group1")) {
return window.confirm("Are you sure to submit the form?");
}
}

Resources