6

I am getting weird behavior where Javascript event that I am trying to dispatch is not being interpreted as event while when I inspect it is is Event.

enter image description here

Then it fails with following error:

Uncaught InvalidStateError: Failed to execute 'dispatchEvent' on 'EventTarget': The event provided is null.

JSFiddle

I must be missing something obvious here.

$(function () {
    $("[type='tel']").keydown(function (event) {
        var position = this.selectionStart;
        var $this = $(this);
        var val = $this.val();
        if (position == this.selectionEnd &&
            ((event.keyCode == 8 && val.charAt(position - 1) == "," && val.substr(0, position - 1).indexOf(".") == -1)
            || (event.keyCode == 46 && val.charAt(position) == "," && val.substr(0, position).indexOf(".") == -1))) {
            event.preventDefault();
            if (event.keyCode == 8) {
                $this.val(val.substr(0, position - 2) + val.substr(position));
                position = position - 2;
            } else {
                $this.val(val.substr(0, position) + val.substr(position + 2));
            }
            $this.trigger('keyup', { position: position });
        } else {
            if (event) {
                this.dispatchEvent(event);
            }
        }
    });

    $("[type='tel']").keyup(function (event, args) {
        if (event.which >= 37 && event.which <= 40) {
            event.preventDefault();
        }

        var position = args ? args.position : this.selectionStart;
        var $this = $(this);
        var val = $this.val();
        var parts = val.split(".");
        var valOverDecimalPart = parts[0];
        var commaCountBefore = valOverDecimalPart.match(/,/g) ? valOverDecimalPart.match(/,/g).length : 0;
        var num = valOverDecimalPart.replace(/[^0-9]/g, '');
        var result = parts.length == 1 ? num.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,") : num.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,") + "." + parts[1].replace(/[^0-9.]/g, "");
        $this.val(result);
        var commaCountAfter = $this.val().match(/,/g) ? $this.val().match(/,/g).length : 0;
        position = position + (commaCountAfter - commaCountBefore);
        this.setSelectionRange(position, position);
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input class="tooltip form-control input-validation-error" data-val="true" data-val-number="The field Sale price (£) must be a number." data-val-range="The sale price must be between £10,000 and £50,000,000" data-val-range-max="50000000" data-val-range-min="10000" data-val-regex="Sale price must be numeric characters only" data-val-regex-pattern="^\d+$" data-val-required="Please enter a sale price" id="SalePrice" name="SalePrice" placeholder="" tabindex="7" type="tel" value="">
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265
  • 1
    `event` is a [jQuery event object](http://api.jquery.com/category/events/event-object/) and not a [DOM event](https://developer.mozilla.org/en-US/docs/Web/API/Event) – Andreas Sep 03 '15 at 09:14
  • 1
    You'd have better to explain why would you need to dispatch event here and ya, jq event is different than js event – A. Wolff Sep 03 '15 at 09:16
  • @A.Wolff To get it into infinite recursion. – Matas Vaitkevicius Sep 03 '15 at 09:26
  • 1
    Ok but still sounds like a XY problem, why would you need an infinite recursion? I really don't see the point here. This would give you one infinite recursion: http://jsfiddle.net/x9z2ntuz/1/ – A. Wolff Sep 03 '15 at 09:32
  • @A.Wolff you essentially answered my question could you post it as answer please, It's a shame that it does not allow to dispatch already dispatched event and one has to refire it. Why isn't it adding keys to textbox? – Matas Vaitkevicius Sep 03 '15 at 09:33
  • 1
    @MatasVaitkevicius I cannot really make an answer without understanding the point of it ;) If you explain instead your expected behaviour, i guess there would be better solution/workaround – A. Wolff Sep 03 '15 at 09:36
  • 1
    But what would be the reason to create an infinite loop? The values won't change if the original event is triggered over and over again... O.o – Andreas Sep 03 '15 at 09:36
  • @A.Wolff Expectation was that when you enter key it get's repeated by re-dispatching it, I would have used it for testing. It was supposed to be quick hack at first but when it failed it sorta got interesting. So it does not have any sensible reason to be done this way. :) I am sure you have been in similar situation where something weird happens and you start doing it more to figure out what is going on. – Matas Vaitkevicius Sep 03 '15 at 09:37
  • @MatasVaitkevicius It could make sense for debugging purpose but then i'd suggest you to provide a more relevant sample where this behaviour would be useful and maybe posting it as answer. Anyway, if previous jsFiddle helped you, i'm glad you have find a workaround to fit your needs – A. Wolff Sep 03 '15 at 09:42
  • @A.Wolff The code never was intended to go into production. Thanks. – Matas Vaitkevicius Sep 03 '15 at 09:45
  • @Andreas could you post it as answer please the part that Jquery event != DOM event. It will be useful for future generations to come. – Matas Vaitkevicius Sep 03 '15 at 09:52

2 Answers2

6

I just had this problem, and it was solved by cloning the event:

if (event && event.originalEvent) {
    var oe = event.originalEvent;
    this.dispatchEvent(new oe.constructor(oe.type, oe));
}
montrealist
  • 5,593
  • 12
  • 46
  • 68
Derek Snider
  • 76
  • 1
  • 2
4

The event in your script is not a DOM event but a jQuery event object and this cannot be used as parameter for EventTarget.dispatchEvent.

The original DOM event can be accessed through the property event.originalEvent

Andreas
  • 21,535
  • 7
  • 47
  • 56
  • Thanks for the answer Andreas. I would like to add as a side note that one cannot re-dispatch event so whole exercise above was stupid to begin with. When trying to dispatch dispatched event one will get following error `Uncaught InvalidStateError: Failed to execute 'dispatchEvent' on 'EventTarget': The event is already being dispatched.` http://jsfiddle.net/x9z2ntuz/2/ The workaround is described here http://jsfiddle.net/x9z2ntuz/1/ by A.Wolff for those who still want do do it. – Matas Vaitkevicius Sep 03 '15 at 10:14