How to implement binding throttling in Kendo UI? - kendo-ui

Could you provide an example of throttling implementation in Kendo UI?
Thanks!

For the Google search record, Kendo UI now includes a built-in throttle method. It can be used to limit the number of calls to a function within a specified time.
Example usage from the Kendo UI docs:
var throttled = kendo.throttle(function() {
console.log("hey! " + new Date());
}, 100);
// will log two times "hey":
// (1) once for the first call
// (2) once for the last call, roughly 100ms after the first one
for (var i = 0; i < 10; i++) {
throttled();
}
Docs: http://docs.telerik.com/kendo-ui/api/javascript/kendo#methods-throttle

You can use the jquery-throttle-debounce library. Here's some snippets of integrating it with Kendo databinding, assuming before you had keyup: updateFromDataSource.
<input id="searchText" type="text" data-value-update="keyup" data-bind="value: searchTextVal, events: { keyup: searchTextKeyed }" />
searchTextKeyed: jQuery.debounce(300, function () { this.updateFromDataSource(); }), ...

Related

Ckeditor issue calling setData during onchange event

I am trying to create a plugin that works similar to the tagging feature here on Stack Overflow. The plugin adds an onchange event to the editor and than checks the data to see if the user entered a tag and replaces any tags found with a div.
CKEDITOR.plugins.add('tagit', {
icons: '',
init: function (editor) {
var tags = ['MyTag'],
tokens = [];
editor.on('change', function (event) {
var tokenUpdated = false;
tokens = tokenize(event.editor.getData());
for (var tokenIndex = 0; tokenIndex < tokens.length; tokenIndex++) {
var token = String(tokens[tokenIndex]);
if (!token.match(/tagit/gmi) && tags.some(function (tag) { return token.indexOf(tag) >= 0; })) {
tokens[tokenIndex] = '<div class="tagit">' + tokens[tokenIndex] + '</div>';
tokenUpdated = true;
}
}
if (tokenUpdated) {
event.editor.setData(tokens.join(''));
}
});
var tokenize = function (data) {
var match = '(<div class="tagit">.*?<\/div>)';
for (var i = 0; i < tags.length; i++) {
match += '|(' + tags[i] + ')';
}
var re = new RegExp(match, "gmi");
return data.split(re);
}
}
});
The problem is when I call setData the change event is fired again and event.editor.getData() returns the html before I called setData. Is the change event fired before the data has actually been set? There's an option internal that I tried setting to true but than the data doesn't appear to be updated.
You are changing editors content so it's natural that change event will be called with editor.setData function. TBO I think that your implementation has a much important problem than circular call - you are comparing HTML content by regex. It's bad practice and you will encounter more problems during this implementation.
This feature is not obvious and requires working with document selection, not simply querying its content (also for performance reasons).
But I have a good information. With CKEditor 4.10 we are shipping new plugins which can easily be used to create feature you are talking about - especially textmatch and textwatcher. Mentioned plugins will be shipped alongside with autocomplete and mentions plugins. You can read more about our progress on GH:
Mentions: https://github.com/ckeditor/ckeditor-dev/issues/1703
Autocomplete: https://github.com/ckeditor/ckeditor-dev/issues/1751
4.10 release is set on 26 June but it could change, check GH milestones for updates.
After release, I can provide some example implementation for your feature - but I'm sure that with new plugins it will be easy as pie.

Is there a way to get the recurrence string from a KendoUI Recurrence Editor?

Because I needed a custom setup for my scheduling setup, I am implementing separate Calendar, Scheduler, and RecurrenceEditor widgets. So far, everything has worked fine, but I can't get the parsed string from the RecurrenceEditor widget. I haven't seen a method to pull the rule as a string in the API documentation (nor is the RecurrenceEditor widget really documented there).
This is how I'm setting up the recurrenceEditor:
$(document).ready(function()
{
$("#recurrence-editor").kendoRecurrenceEditor({
start: new Date(),
change: function(e)
{
var editor = e.sender;
// I want to get the recurrence rule string here.
}
});
});
I'm not seeing anything in Firebug that gives me a hint for the method or property I might try. So far, I've tried:
editor.ruleValue
editor.recurrenceRule
It looks like I have access to some of the information, but I didn't want to write my own selections-to-parseable-string method if I could get it from the recurrence editor itself.
UPDATE: When I set it up this way:
$(document).ready(function()
{
$("#recurrence-editor").kendoRecurrenceEditor({
start: new Date(),
edit: function(e)
{
var editor = e.sender;
var recurrenceString = editor.RecurrenceRule;
return recurrenceString;
}
});
});
The edit event never fires. Probably because I'm not implementing the recurrence editor as part of the Scheduler widget, but as a standalone widget on the page.
Thanks!
Setup the recurrence editor in the Scheduler's edit event, it will fire the change event and the value property is the standard iCal Recurrence Rule.
Here's mine:
// Setup Recurrence Editor
// Telerik support recommends this method over the common inline script
// because it allows us to choose which recurrence editor. However, it does
// break the MVVM two-way bindings, so the current value MUST be explicitly set
// on creation, and the change event must be handled.
var event = e.event,
container = e.container,
recurrenceEditor = container.find("#recurrenceEditor");
if (kendo.support.mobileOS === false) {
recurrenceEditor.kendoRecurrenceEditor({
start: new Date(e.event.start),
value: e.event.recurrenceRule,
timezone: self.scheduleConfig.timezone,
messages: self.scheduleConfig.messages.recurrenceEditor,
change: function (ev) {
event.set("recurrenceRule", this.value());
}
});
} else {
// The Mobile Recurrence Editor requires the parent kendo pane
// be passed as a parameter, otherwise it will crash when the
// user attempts to alter the frequency
var pane = container.parent(".km-pane").data("kendoMobilePane");
recurrenceEditor.kendoMobileRecurrenceEditor({
start: new Date(e.event.start),
value: e.event.recurrenceRule,
timezone: self.scheduleConfig.timezone,
messages: self.scheduleConfig.messages.recurrenceEditor,
pane: pane,
change: function(ev) {
event.set("recurrenceRule", this.value());
}
});
}
And the HTML (inside the custom editor template)
<div class="lineEntry" data-bind="invisible: recurrenceId">
<div id="recurrenceEditor" name="recurrenceRule" data-bind="value: recurrenceRule" class="toInlineBlock">
</div>
</div>
You have to get it from the event you are describing in the editor's event edit/creator modal. Once you get the event, it's just .RecurrenceRule, if memory serves, it's just e.event.RecurrenceRule
Fun fact, the standard used in that string is RFC 5545 3.3.10

About knockoutjs - how to data-bind with text: and click:

How are you guys? I'm new to the framework Knockoutjs, I wonder if I'm doing it right. (Need a little help.) :)
I have a tag and would contain the same data-bind = text: anything and click: any function. The question is: Is it possible to do this? This is the correct way? Follow what I'm talking about: (I am using an example from the website itself) where when the user clicks the "Click Me" he adds +1 on the counter. I want that when the user clicks the tag call the same function. :)
HTML:
<div>You've clicked <span data-bind='text: numberOfClicks, click: registerClick'> </span> times</div>
JS:
var ClickCounterViewModel = function() {
this.numberOfClicks = ko.observable(0);
this.registerClick = function() {
this.numberOfClicks(this.numberOfClicks() + 1);
};
this.resetClicks = function() {
this.numberOfClicks(0);
};
this.hasClickedTooManyTimes = ko.computed(function() {
return this.numberOfClicks() >= 3;
}, this);
};
ko.applyBindings(new ClickCounterViewModel());
Follows the file jsFiddle: Here
Many thanks in advance.
Yes it is possible to have several binding pairs in one data-bind attribute.
You just have separated them with a comma ,
You asked : I want that when the user clicks the tag call the same function.
But you already code it.
You can click on the counter or on the button it increments the counter.

How to create on-change directive for AngularJS?

Normally ng-model updates bound model each time user pushes the key:
<input type="text" ng-model="entity.value" />
This works great in almost every case.
But I need it to update when onchange event occurs instead when onkeyup/onkeydown event.
In older versions of angular there was a ng-model-instant directive which worked same as ng-model works now (at least for the user - i don't know anything about their implementations).
So in older version if I just gave ng-model it was updating the model onchange and when I specified ng-model-instant it was updating the model onkeypup.
Now I need ng-model to use on "change" event of the element. I don't want it to be instant. What's the simplest way of doing this?
EDIT
The input still has to reflect any other changes to the model - if the model will be updated in other place, value of the input should reflect this change.
What I need is to have ng-model directive to work just like it worked in the older versions of angularjs.
Here is an explanation of what I'm trying to do:
http://jsfiddle.net/selbh/EPNRd/
Here I created onChange directive for you. Demo: http://jsfiddle.net/sunnycpp/TZnj2/52/
app.directive('onChange', function() {
return {
restrict: 'A',
scope:{'onChange':'=' },
link: function(scope, elm, attrs) {
scope.$watch('onChange', function(nVal) { elm.val(nVal); });
elm.bind('blur', function() {
var currentValue = elm.val();
if( scope.onChange !== currentValue ) {
scope.$apply(function() {
scope.onChange = currentValue;
});
}
});
}
};
});
See also: the AngularJS ngChange directive.
When applied to an <input> the changes occurs after each key press not on the blur event.
http://docs.angularjs.org/api/ng.directive:ngChange
Angularjs: input[text] ngChange fires while the value is changing : This answer provides a much better solution that allows the custom directive to work with ngModel so you can still use all of the other directives that go along with ngModel.
Also, an even more flexible solution that allows for specifying the event to use (not just blur) and other properties should be built in to angular very soon: https://github.com/angular/angular.js/pull/2129
I'm not sure if there is a better way to do this, but you can achieve this using a custom directive (on any jquery event you want)
<input type="text" ng-model="foo" custom-event="bar" />
<p> {{ bar }} </p>
// create the custom directive
app.directive('customEvent', function() {
return function(scope, element, attrs) {
var dest = attrs.customEvent;
$(element[0]).on('any-jquery-event', function(e) {
e.preventDefault();
// on the event, copy the contents of model
// to the destination variable
scope[dest] = scope.foo;
if (!scope.$$phase)
scope.$apply();
});
}
});

jQuery stops working after ajax request that adds fields to a form in Drupal 7

I don't think this is a Drupal-specific question, but more of a general jquery/ajax issue:
Basically, I'm trying to use javascript to add up form fields and display the result in a "subtotal" field within the same form. Everything is working fine until i click the option to add another field (via ajax), which then changes my "subtotal" field to zero, and won't work again until I remove the field.
Here is the function that adds up the fields:
function calculateInvoiceFields(){
var total = 0;
var rate = 0;
var quantity = 0;
var i = 0;
var $ = jQuery;
$("#field-aminvoice-data-values tr").each(function(){
// quantity field number
quantity = $("#edit-field-aminvoice-data-und-"+i+"-field-aminvoice-quantity-und-0-value").val();
// rate field as number
rate = $("#edit-field-aminvoice-data-und-"+i+"-field-aminvoice-rate-und-0-value").val();
if(!isNaN(quantity) && !isNaN(rate)){
total += quantity*rate;
}
i++;
});
return total;
}
And here are the functions that get fired for .ready and .live:
jQuery(document).ready(function(){
var $ = jQuery;
$(".field-type-commerce-price input").val(calculateInvoiceFields());
});
jQuery(function(){
var $ = jQuery;
$(".form-text").live('change', function(){
$(".field-type-commerce-price input").val(calculateInvoiceFields());
});
});
Any ideas would be a big help. Thanks in advance!
I recommend using 'on' for any binding statement. and 'off' for unbinding.
The reason it doesn't work after an AJAX call, is because you need to be watching for that element to be added to the DOM, and an event attached to it after it gets loaded. If you load a new element in, and there is nothing watching for it, it won't add the event watch to that new DOM element.
As below:
function calculateInvoiceFields(){
/*..*/
return total;
}
$(document).ready(function(){
$(".field-type-commerce-price input").val(calculateInvoiceFields());
$("body").on('change', ".form-text", function(){
$(".field-type-commerce-price input").val(calculateInvoiceFields());
});
});
usually it stops working when an error has been thrown. did you check out your javascript console (firefox firebug, or built in for chrome) for any indication of an error?

Resources