Solving SignalR $.connection.HubName is null or undefined

July 5, 2017

I added support for SignalR to one of the ASP.Net MVC applications I develop, mainly following this Microsoft tutorial.

I was surprised by the fact that you cannot install the SignalR package from the NuGet GUI (in VS 2013 at least), but need to switch to the Package Manager Console and type

install-package Microsoft.AspNet.SignalR

It worked nevertheless.

I also copied the JS initialization code from there

 $(function () { 
    // Declare a proxy to reference the hub. 
    var chat = $.connection.chatHub;
    chatHub.client.broadcastMessage = function (name, message) { ... };
}

(adjusted, of course, to the hubs defined in my project), only to find that the JavaScript console in Chrome Developer Tools displays the error message

Uncaught TypeError: Cannot read property 'client' of undefined
 at HTMLDocument. (38024:10393)
 at fire (jquery-1.12.4.js:3232)
 at Object.fireWith [as resolveWith] (jquery-1.12.4.js:3362)
 at Function.ready (jquery-1.12.4.js:3582)
 at HTMLDocument.completed (jquery-1.12.4.js:3617)

The error is raised by the line

chatHub.client.broadcastMessage = function (name, message) {

with chatHub being undefined.

I stepped through the JavaScript code and found that the (automagically generated) JavaScript file

< script src="@Url.Content("~/signalr/hubs")" >< /script>

defines the hubs correctly, but somehow the hub definitions are lost when the

$(function() {

is being executed.

It turned out to be a question of JavaScript scopes, and I moved the client callback definition out of the jQuery $(function(){}) directly into the


Debugging Ajax’ed JavaScript and jQuery val() calls

June 8, 2017

I develop a web application which displays data in a read-only form, and loads the edit form upon pressing a button

$(function () {
  $(".btnEdit").click(function () {
    $.ajax({
      url: '@Url.Action("Form", new { id = Model.ID })',
      type: 'post'
    });
  });
});

Now I needed to debug the JavaScript code loaded by the call to $.ajax(), but Chrome does not seem to display the loaded response in its tree of Sources.

An answer on SO provided me with the solution: Simply add the line

//# sourceURL=@Url.Action("Form", new { id = Model.ID })

inside a <script> block in the AJAX-loaded HTML. This will add the requested URL under the (no domain) node

chrome ajax js

Now that I have access to the source file, I needed to find all invocations of the jQuery val() function, since I was tracking down a wrong value in an <input>.

Again SO provided a solution, which I added to my code

(function($){
  var originalVal = $.fn.val;
  $.fn.val = function(){
    var selectorPath = $(this).parents().map(function () {return this.tagName;}).get().reverse().join("->");
    console.log("val( #" + $(this).attr("id") + " " + selectorPath + " , " + JSON.stringify(arguments) + ")");
    var result =originalVal.apply(this,arguments);
    return result;
  };
})(jQuery);

Now that the calls to val() were logged to the Console, it was easy to find where the wrong value was set.


Adding Dropdown Arrow for Chosen Plugin in Multiselect Mode

April 2, 2017

I use the jQuery Chosen plugin in a web application, and recently got the request to display a dropdown arrow in multiselect mode.

I found an answer on SO regarding styling of the dropdown arrow, but that covered only singleselect mode. At least a starting point 😉

Within minutes, I had a CSS-only solution for this particular problem:

<style type="text/css">
.chosen-container-multi.chosen-container .chosen-choices::after {
    background: url(@Url.Content("~/Content/chosen-sprite.png")) no-repeat 3px 4px;
    width: 16px;
    height: 100%;
    content: " ";
    position: absolute;
    right: 0;
    background-color: lightgray;
}
</style>

(Note that this is an ASP.Net MVC application, and @Url.Content() computes the URL relative to application root.)

Only after I solved this, I found that there is a closed (and unresolved) issue on github from 2011, with comments up to 2016, but no solution to a valid feature request…


jQuery Autocomplete Inconsistencies

April 17, 2014

I guess I found an inconsistency in jQuery’s autocomplete() widget, which does not cause a selected value to be reset when clearing the input field.

Steps to reproduce (checked with 1.8.3 and 1.11.0):

  • Type the beginning of a string that is provided by the autocomplete source
  • Tab away from the input
  • “autocompletechange” fires, but the value is not valid, so the input field value is reset
  • Type the beginning of string (as above)
  • Select an entry using cursor keys
  • “select” fires (and sets the corresponding key value for the selected text value in a callback function)
  • Double-click the input to select the full text of the input field
  • Delete selected text (backspace or right-click Cut)
  • Neither “autocompletechange” nor “select” fires
  • Tab away from input field
  • Neither “autocompletechange” nor “select” fires

From the console.log:

blur ” 5:81
mouseup ” 5:90
keyup ‘r’ 5:87
keyup ‘re’ 5:87
keyup ‘rei’ 5:87
keyup ‘re’ 5:87
change ‘re’ 5:84
autocompletechange null 5:78
Nothing selected, input was re common.js:114
blur ” 5:81
mouseup ” 5:90
keyup ‘re’ 5:87
keyup ‘re’ 5:87
keyup ‘rei’ 5:87
keyup ‘6749’ [this is the key value!] 5:87
Selected: [some text] (6749) common.js:114
keyup ‘[some text] 5:87
keyup ‘[some text] 5:87
keyup ‘[some text] 5:87
keyup ” 5:87
change ” 5:84
blur ”

The value displayed in single quotes is the .value property of the input field, “rei” being the string that corresponds to the beginning of a valid value in the source.

The only workaround that comes to mind is to use the keyup and mouseup events to check whether the input’s value property is empty, and then reset the key field accordingly.


A jQuery Alternative for ACT CalendarExtender

April 6, 2014

As I extend an ASP.Net application with MVC functionality, I also need to replace some of the components that the AjaxControlToolkit provides. Case in point, the CalendarExtender.

The CE is declared in markup like this:

<ajax:CalendarExtender id=”ce” runat=”server” TargetControlID=”edDate” Format=”dd.MM.yyyy”>

edDate being the ASP.Net TextBox control containing the selected date.

The simplest replacement is, of course, the Datepicker widget found in the jQuery UI library.

Integration the Datepicker is a bit more effort as compared to the other controls in this series, but not much.

First we need to reference the required .js and .css files of jQuery and jQuery UI:

<script type="text/javascript" src="@Url.Content("~/script/jquery-1.8.3.js")"></script>
<script type="text/javascript" src="@Url.Content("~/script/jquery-ui-1.9.2.custom.min.js")"></script>
<link href="@Url.Content("~/css/jquery-ui-1.9.2.custom.css")" rel="stylesheet" type="text/css" />

Depending on the options you used for the CalendarExtender, the initialization for the Datepicker may look like this:

$("#edDate").datepicker({
  changeMonth: true,
  changeYear: true,
  showButtonPanel: true
});
$("#edDate").datepicker("option", "dateFormat", "dd.mm.yy");
$("#edDate").datepicker("option", $.datepicker.regional["de"]);

For more options, see the sample page and press View Source, or browse the documentation.

Note that while the CE requires “yyyy” for 4-digit years, the Datepicker interprets “yy” as 4-digit years, and will insert the year twice if you use “yyyy”.

I’m not sure whether the localization files are part of the default jQuery UI downloads – if not, you can find the localized strings for Datepicker in the GitHub repository.

Lastly, the CE provides a “Today” button which sets the current date and closes the calendar, whereas Datepicker just navigates to the current date in the calendar control, but does not select it.

To change the Datepicker behavior, I use the code found in an answers on SO:

$.datepicker._gotoToday = function (id) {
    var target = jQuery(id);
    var inst = this._getInst(target[0]);
    if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
        inst.selectedDay = inst.currentDay;
        inst.drawMonth = inst.selectedMonth = inst.currentMonth;
        inst.drawYear = inst.selectedYear = inst.currentYear;
    }
    else {
        var date = new Date();
        inst.selectedDay = date.getDate();
        inst.drawMonth = inst.selectedMonth = date.getMonth();
        inst.drawYear = inst.selectedYear = date.getFullYear();
        this._setDateDatepicker(target, date);
        this._selectDate(id, this._getDateDatepicker(target));
    }
    this._notifyChange(inst);
    this._adjustDate(target);
};

See also here for further discussion.

Finally, if the jQuery UI skins do not fit in the design of your application, open the developer tools of your browser (F12) and find out which jQuery UI CSS classes define the look of the Datepicker control. In my case, I added a bit of CSS to adjust the control:

.ui-datepicker table.ui-datepicker-calendar {
    font-size: 11px;    
}
.ui-datepicker table.ui-datepicker-calendar td
{
    width: 17px;
}
.ui-datepicker table.ui-datepicker-calendar td a 
{
    padding: 0px;
}
.ui-datepicker .ui-datepicker-title select {
    font-size: 0.9em;
    margin: 1px 0;
}
.ui-widget button {
    font-size: 0.8em;
}

Note that the overriding style definition selectors must be more specific than the original jQuery UI declarations.

Aaaand we are done! 😉


A jQuery Alternative for ACT HoverMenuExtender

April 1, 2014

As I extend an ASP.Net application with MVC functionality, I also need to replace some of the components that the AjaxControlToolkit provides. Case in point, the HoverMenuExtender.

The HME is declared in markup like this:

<ajax:HoverMenuExtender ID=”hme” runat=”server” TargetControlID=”tdTable” PopupControlID=”paTable” PopupPosition=”Bottom” OffsetX=”0″ OffsetY=”2″>
</ajax:HoverMenuExtender>

tdTable being, in my case, a TD table cell in a menu bar, and paTable the submenu that is meant to dropdown when hovering over the table cell.

As replacement, I found the Simple jQuery Dropdowns library on CSS-Tricks, and the sample looked similar to the solution I wanted to replace.

Adding the Simple Dropdowns was straight forward, as it consists only of a couple of Javascript lines and some CSS classes. Integration was easy and quickly done.

But then…

As I mentioned, the menu bar was defined as single-row HTML table, and the cells are fixed-width for all drop-down menus, except the one displaying a record identifier – this cell uses a table’s (built-in!) capability to expand so that the table extends over the defined width, no matter how many other fixed-width cells there are and how wide the browser window is.

So I added some display:table* styles like this

<ul class="dropdown" style="width: 99%; display:table">
    <li style="display:table-cell; ">
        <a href="#">Menu 1</a>
        <ul class="sub_menu">
            <li><a href="#">Command 1</a></li>
            <li><a href="#">Command 2</a></li>
        </ul>
    </li>
    <li style="display:table-cell; width: auto" >
        <a href="#">ID</a>
        <ul class="sub_menu">
            <li><a href="#">Command 1</a></li>
            <li><a href="#">Command 2</a></li>
        </ul>
    </li>
      <li style="display:table-cell; ">
        <a href="#">Menu 2</a>
        <ul class="sub_menu">
            <li><a href="#">Command 1</a></li>
            <li><a href="#">Command 2</a></li>
        </ul>
    </li>
    <li style="display:table-cell">&nbsp;</li>
</ul>

Chrome and IE9 displayed the menu as expected, but Firefox insisted on displaying the dropdown left-aligned below to <ul> table, no matter how I changed the individual styles and classes.

Fortunately I found this answer on SO that illustrated a solution that works for Firefox (and the other browsers!): add a <div style=”position:relative”> inside the <td>.

So now my menu bar looks like this:

<ul class="dropdown" style="width: 99%; display:table">
    <li style="display:table-cell; " >
        <div style="position: relative">
            <a href="#">Menu 1</a>
            <ul class="sub_menu">
                <li><a href="#">Command 1</a></li>
                <li><a href="#">Command 2</a></li>
            </ul>
        </div>
    </li>
    <li style="display:table-cell; width: auto" >
        <div style="position: relative">
            <a href="#">ID</a>
            <ul class="sub_menu">
                <li><a href="#">Command 1</a></li>
                <li><a href="#">Command 2</a></li>
            </ul>
        </div>
    </li>
    <li style="display:table-cell; " >
        <div style="position: relative">
            <a href="#">Menu 2</a>
            <ul class="sub_menu">
                <li><a href="#">Command 1</a></li>
                <li><a href="#">Command 2</a></li>
            </ul>
        </div>
    </li>
    <li style="display:table-cell" class="command">&nbsp;</li>
</ul>

A jQuery Alternative for ACT CollapsiblePanelExtender

March 30, 2014

As I extend an ASP.Net application with MVC functionality, I also need to replace some of the components that the AjaxControlToolkit provides. Case in point, the CollapsiblePanelExtender.

The CPE is declared in markup like this:

<ajax:CollapsiblePanelExtender ID=”cpe” runat=”server” CollapseControlID=”paHeader” ExpandControlID=”paHeader” AutoCollapse=”false” AutoExpand=”false” Collapsed=”true” TargetControlID=”paDetail” ExpandedImage=”~/images/collapse_blue.jpg” CollapsedImage=”~/images/expand_blue.jpg” SuppressPostBack=”true” ImageControlID=”imgHeader”>
</ajax:CollapsiblePanelExtender>

paHeader and paDetail are both asp:Panels – clicking on the header toggles the display of the detail panel. The image control is toggled accordingly.

My goal was to create a JavaScript function which uses parameters similar to the markup, omitting those that do not matter in my application.

In MVC, of course, the equivalent of an asp:Panel is a simple HTML <div>.

I started out with a function declaration like this (please forgive non-standard casing):

function CollapsiblePanelExtender(ID, CollapseControlID,
    TargetControlID, ImageControlID) { }

but then noticed that I needed to distinguish between initial states expanded and collapsed, as well as an additional callback after expanding/collapsing.

var CollapsiblePanelExtenders = {};
function CollapsiblePanelExtender(ID, CollapseControlID, 
    TargetControlID, ImageControlID, expanded, fn) {
  var ExpandedImage = '@Url.Content("~/images/collapse_blue.jpg")';
  var CollapsedImage = '@Url.Content("~/images/expand_blue.jpg")';

CollapsiblePanelExtenders is our array of all CPEs on the page. Parameters expanded and fn are optional.

First, we register the CPE in the array, and initialize the image and the detail’s overview setting:

  CollapsiblePanelExtenders[ID] = { collapsed: !(expanded || false) };
  $("#" + ImageControlID).attr("src", (expanded || false) ? ExpandedImage : CollapsedImage);
  $("#" + TargetControlID).attr("overflow", "hidden");

Finally, we add a click handler on the header panel:

  $("#" + CollapseControlID).click(function (pa) {
    if (CollapsiblePanelExtenders[ID].collapsed) {
      $("#" + TargetControlID).css("height", "");
      $("#" + ImageControlID).attr("src", ExpandedImage);
      CollapsiblePanelExtenders[ID].collapsed = false;
    } else {
      $("#" + TargetControlID).css("height", "0px");
      $("#" + ImageControlID).attr("src", CollapsedImage);
      CollapsiblePanelExtenders[ID].collapsed = true;
    }
    if (fn) {
      fn(CollapsiblePanelExtenders[ID].collapsed);
    }
  });
};

The click handler adjusts the detail’s height and sets the expand/collapse image. If a callback function is defined, the function is executed with the collapsed status as parameter.

I was surprised that it only takes a couple of JavaScript lines to implement an ACT control. Note, however, that the presented solution does not invoke any animations – have a look at jQuery Effects, if you need them…