Tag Archives: jquery

jQuery/Bootstrap Widget: fileinput

<script type="text/html" id="file-input-template">
    <div class="input-group">
        <input type="text" readonly="readonly" class="form-control" />
        <label class="input-group-btn">
            <span class="btn btn-primary">
                Browse
                <input type="file" class="sr-only" />
            </span>
        </label>
    </div>
</script>

<script type="text/javascript">
    $.widget("scw.fileinput", {
        options: {
            id: "file",
            name: "file",
            disabled: false
        },

        _create: function () {
            var self = this;
            self.$group = $($("#file-input-template").html()).appendTo(self.element);
            self.$file = self.$group.find("input[type='file']");
            self.$file.attr("id", self.options.id);
            self.$file.attr("name", self.options.name);
            self.$text = self.$group.find("input[type='text']");
            self.$button = self.$group.find(".btn");
            self._setDisabled(self.options.disabled);
            self.$file.change(function () {
                self.$text.val(self.$file.val());
            });
        },

        _setDisabled: function (disabled) {
            var self = this;
            self.$text.prop("disabled", disabled);
            self.$file.prop("disabled", disabled);
            self.$button.toggleClass("disabled", disabled);
        },

        _setOption: function (key, value) {
            var self = this;
            self._super(key, value);
            if (key === "disabled") {
                self._setDisabled(value);
            }
        }
    });
</script>

jQuery/Bootstrap Widget: dialog

<script type="text/html" id="modal-template">
    <div class="modal fade">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <span class="modal-title"></span>
                </div>
                <div class="modal-body"></div>
                <div class="modal-footer"></div>
            </div>
        </div>
    </div>
</script>

<script type="text/javascript">
    $.widget("scw.dialog", {
        options: {
            size: "sm",
            title: "",
            body: "",
            buttons: [
                {
                    style: "primary",
                    text: "OK"
                }
            ]
        },

        _create: function () {
            var self = this;
            self.$modal = $($("#modal-template").html()).appendTo(self.element);
            self.$modal.find(".modal-dialog").addClass("modal-" + self.options.size);
            self.$modal.find(".modal-title").text(self.options.title);
            self.$modal.find(".modal-body").html(self.options.body);
            var $footer = self.$modal.find(".modal-footer");
            $.each(self.options.buttons, function () {
                var defaults = {
                    command: $.noop,
                    argument: null
                };
                var options = $.extend(defaults, this);
                var $button = $("<button type='button' class='btn'></button>");
                $button.addClass("btn-" + options.style);
                $button.text(options.text);
                $button.click(function () {
                    self.$modal.one("hidden.bs.modal", function () {
                        options.command(options.argument);
                        self.destroy();
                    });
                    self.$modal.modal("hide");
                });
                $footer.append($button);
            });
            self.$modal.modal({
                backdrop: "static",
                keyboard: false
            });
        },

        _destroy: function () {
            var self = this;
            self.$modal.remove();
        }
    });
</script>

Dirty Checks for HTML Forms

$.fn.extend({
    setDirty: function (dirty) {
        this.data("dirty", dirty);
    }
});
var $forms = $("form");
$forms.setDirty(false);
$forms.change(function () {
    $(this).setDirty(true);
});
$forms.submit(function () {
    $(this).setDirty(false);
});
$(window).on("beforeunload", function () {
    var filter = function () {
        var $this = $(this);
        return $this.data("dirty") && !$this.data("ignore-dirty");
    };
    if ($forms.filter(filter).length > 0) {
        return "This page may have unsaved changes.";
    }
});

Usage:

<form>
    <label>
        First name
        <input type="text" />
    </label>
    <label>
        Last name
        <input type="text" />
    </label>
    <button type="submit">Submit</button>
</form>
<form data-ignore-dirty="true">
    <label>
        Search
        <input type="text" />
    </label>
    <button type="submit">Go</button>
</form>

Knockout Binding Handler: validationPopover

<script type="text/javascript">
    ko.bindingHandlers.validationPopover = {
        init: function (element, valueAccessor, allBindings) {
            if (!allBindings.has("value")) {
                return;
            }
            var $element = $(element);
            var value = allBindings.get("value");
            $element.popover($.extend({}, ko.unwrap(valueAccessor()), {
                content: function () {
                    return value.error();
                },
                trigger: "manual"
            }));
            value.subscribe(function () {
                $element.popover(value.isValid() ? "hide" : "show");
            });
        }
    };
</script>

<input type="text" data-bind="value: name, validationPopover: {}" />

<script type="text/javascript">
    ko.validation.init({
        insertMessages: false
    });
    
    function ViewModel() {
        var self = this;
        self.name = ko.observable().extend({ required: true });
    }
    
    ko.applyBindings(new ViewModel());
</script>

jQuery UI Widget: toggler

$.widget("scw.toggler", {
    options: {
        active: true,
        animated: true,
        duration: "_default",
        cssClass: "toggler-active"
    },
    
    _finish: function () {
        while (this.element.queue().length > 0) {
            this.element.dequeue();
        }
        this.element.finish(false);
        this.element.finish();
    },
    
    _refresh: function (immediate) {
        this._finish();
        var args = [
            this.options.cssClass,
            Boolean(this.options.active)
        ];
        if (!immediate) {
            args.push({
                duration: this.options.duration
            });
        }
        $.fn.toggleClass.apply(this.element, args);
    },
    
    _create: function () {
        this._refresh(true);
    },
    
    _setOption: function (key, value) {
        this._super(key, value);
        if (key === "active") {
            this._refresh(!this.options.animated);
        }
    }
});

Knockout Binding Handler: tooltip

<script type="text/javascript">
    ko.bindingHandlers.tooltip = {
        normalize: function (valueAccessor) {
            var value = ko.unwrap(valueAccessor());
            if (typeof value === "object" && "data" in value) {
                return value;
            } else {
                return { data: value };
            }
        },
        
        getOptions: function (element, valueAccessor) {
            var value = ko.bindingHandlers.tooltip.normalize(valueAccessor);
            return $.extend({}, ko.unwrap(value.options), {
                items: element,
                content: ko.unwrap(value.data)
            });
        },
        
        init: function (element, valueAccessor) {
            var options = ko.bindingHandlers.tooltip.getOptions(element, valueAccessor);
            $(element).tooltip(options);
        },
        
        update: function (element, valueAccessor) {
            var options = ko.bindingHandlers.tooltip.getOptions(element, valueAccessor);
            $(element).tooltip("option", options);
        }
    };
</script>

<div data-bind="tooltip: 'Hypertext Markup Language'">HTML</div>
<div data-bind="
    tooltip: {
        data: now().toLocaleTimeString(),
        options: { track: true }
    }">
    Time
</div>

<script type="text/javascript">
    function ViewModel() {
        var self = this;
        self.now = ko.observable(new Date());
        setInterval(function () {
            self.now(new Date());
        }, 1000);
    }
    
    ko.applyBindings(new ViewModel());
</script>

Knockout Binding Handler: sortable

<script type="text/javascript">
    ko.bindingHandlers.sortable = {
        normalize: function (valueAccessor) {
            var value = ko.unwrap(valueAccessor());
            if (typeof value === "object" && "data" in value) {
                return value;
            } else {
                return { data: valueAccessor() };
            }
        },
        
        getHandlers: function (data) {
            var startIndex;
            return {
                start: function (event, ui) {
                    startIndex = ui.item.index();
                },
                
                stop: function (event, ui) {
                    var stopIndex = ui.item.index();
                    ui.item.remove();
                    var item = data.splice(startIndex, 1)[0];
                    data.splice(stopIndex, 0, item);
                }
            };
        },
        
        init: function (element, valueAccessor) {
            var self = ko.bindingHandlers.sortable;
            var value = self.normalize(valueAccessor);
            var handlers = self.getHandlers(value.data);
            var options = $.extend({}, ko.unwrap(value.options), handlers);
            $(element).sortable(options);
            return ko.bindingHandlers.foreach.init.apply(this, arguments);
        },
        
        update: function () {
            ko.bindingHandlers.foreach.update.apply(this, arguments);
        }
    };
</script>

<ul data-bind="sortable: letters">
    <li data-bind="text: $data"></li>
</ul>

<button type="button" data-bind="click: add">Add</button>
<ul data-bind="
    sortable: {
        data: numbers,
        options: {
            handle: '.handle',
            cancel: ''
        }
    }">
    <li>
        <button type="button" class="handle">Move</button>
        <span data-bind="text: $data"></span>
    </li>
</ul>

<script type="text/javascript">
    function ViewModel() {
        var self = this;
        self.letters = ko.observableArray(["a", "b", "c"]);
        self.numbers = ko.observableArray();
        self.add = function () {
            self.numbers.push(self.numbers().length + 1);
        };
    }
    
    ko.applyBindings(new ViewModel());
</script>

Knockout Binding Handler: slide

<script type="text/javascript">
    ko.bindingHandlers.slide = {
        enabled: true,
        queue: "ko.bindingHandlers.slide",
        
        init: function (element, valueAccessor) {
            var visible = Boolean(ko.unwrap(valueAccessor()));
            $(element).toggle(visible);
        },
        
        update: function (element, valueAccessor) {
            var self = ko.bindingHandlers.slide;
            var $element = $(element);
            $element.stop(self.queue, true);
            var visible = Boolean(ko.unwrap(valueAccessor()));
            if (self.enabled) {
                var slide = visible ? "slideDown" : "slideUp";
                $element[slide]({ queue: self.queue });
                $element.dequeue(self.queue);
            } else {
                $element.toggle(visible);
            }
        }
    };
</script>

<button type="button" data-bind="click: toggle">Toggle</button>
<div data-bind="slide: visible">Hello, world!</div>

<script type="text/javascript">
    function ViewModel() {
        var self = this;
        self.visible = ko.observable(true);
        self.toggle = function () {
            self.visible(!self.visible());
        };
    }
    
    ko.applyBindings(new ViewModel());
</script>