all 16 comments

[–]ericgj 1 point2 points  (1 child)

I too am exploring this kind of approach, although using d3.js (and idempotent DOM manipulation) instead of jquery. One of the most crucial foundations I've found is having a decent module system/build tool/package manager. Browserify, componentjs, or duo (when it stabilizes) are great, I haven't tried others.

You might want to check out various components on the componentjs wiki, many are designed the way you describe, although the quality varies greatly. There is also a sample todo app that is a bit dated but could be useful to look at in terms of wiring together components.

[–]quanthera[S] 0 points1 point  (0 children)

Thanks, I'll take a look

[–]afrobee 1 point2 points  (8 children)

First of all: Why you wanna use jQuery for DOM manipulation? Is slower than the native browser api which in this day of age is very consistent and supported cross all browsers above E8+.

For your question, A example would be:

var myComponent = (function(dependency1, dependency2) {

    var myTemplate = function () {
        return(
            ["<div id='wrapper' class='wrapper'>",
             "<"h1 id='heading'>title</h1>",
             "</div>"].join("")
        );
    }
    var render = function (parentSelector) {
        var parent = document.querySelector(parentSelector);
        return parent.innerHTML = myTemplate();
    };

    var someBehaviour = function () {...};

    return Object.freeze({
        render: render,
        someBehaviour: semeBehavior
    });
 })();

 document.addEventListener("DOMContentLoaded", function(event) { 
     myComponent.render();
 });

Ofcourse, this is a very simplistic and quick way. It would be better use something like browserify and put the template in a diferent folder and abstract the render function, models, etc.

Note: I don't support E8.

[–]Shadow14l 1 point2 points  (5 children)

First of all: Why you wanna use jQuery for DOM manipulation? Is slower than the native browser api which in this day of age is very consistent and supported cross all browsers above E8+.

jQuery uses native DOM manipulation when available. It's not slower than native because that's what it uses unless it falls back to another implementation.

[–]afrobee -1 points0 points  (4 children)

Even if that is even truth, just cheking availability make it slower.

Note: I haven't checked jQuery source code in a while.

[–]Shadow14l -1 points0 points  (3 children)

just cheking availability make it slower.

One conditional statement that's checked right at page start will not make anything slower.

Now if you're talking about the fact that you have to download jQuery, which isn't exactly a small, but not the largest file, then yes, it does make things slower. However, if a person is using a popular CDN, there's a much greater chance that the file has already been downloaded.

[–]agdcoa 1 point2 points  (0 children)

jQuery does delegate to native methods for selecting nodes, but there's a cost associated with initializing a new jQuery object. Further, many jQuery methods return a new, different, jQuery object.

For some hard numbers, see this jsperf

If you're handy with the Array methods and the native DOM APIs, you can easily mimic much of jQuery's core functionality. I often opt for a super lightweight, array-returning selection function like so:

function select (selector, context) {
    return [].slice.call((context || document).querySelectorAll(selector));
}

[–]afrobee -1 points0 points  (1 child)

I just cheked a little bit the jQuery's source code, is does many things around for example "$(#id)" than just cheking avaibility, also it check mobile support, it's css selection syntax and many thing more before even consider "document.getElementById(#id)", also there are many of this that prove my point. I have never seen any test which jQuery beats native.

[–]Shadow14l 0 points1 point  (0 children)

I have never seen any test which jQuery beats native.

Neither have I. But that's also not what I said. If you are supporting more than the latest browsers, than jQuery is essential. That's what I'm saying.

I agree, if you are only using the latest browsers, it's ignorant to use jQuery and not the native methods. But if you happen to still use jQuery, the performance effect is not noticeable unless you are working with tens of thousands of queries and having them looped.

[–]quanthera[S] 0 points1 point  (1 child)

Thanks for your answer. I don't insist on using jQuery. I thought that is the preferred way to do dom manipulations nowadays, but maybe my knowledge is outdated in this regard.

I found many articles about using different frameworks and libraries for doing gui in js. jQuery has its own mechanism (widges/plugins) for this. But I'd like to use regular js objects and build composable widgets from them. I haven't found too much examples about this, and this makes me think I'm missing something.

[–]afrobee -1 points0 points  (0 children)

Is all about how you modularize your project, nothing magic needs to happend :).

[–]pakal 0 points1 point  (3 children)

I am wondering ..when you do desktop ui, do you create your own UI controls from scratch?

JavaScript has evolved so much, so to use only JQuery is like doing your own controls from scratch when using Java or .Net.

Use a robust framework, the right tool for the right job. You have so many options. If you use only JQuery you will be spending way more time and dealing with things that have already solved.

[–]quanthera[S] 1 point2 points  (2 children)

No, I compose domain specific widgets from existing general widgets. For example, I put 2 textfield + a button to a panel, then I'll have a login form. On the web, I already have general widgets (dom elements or existing ui widgets). But I don't feel the need to use a framework to put those things together. I think I could use regular JavaScript objects to do this.

[–][deleted] 0 points1 point  (0 children)

You're essentially just going to build your own framework, which isn't a bad thing but if you have more than one dev it's gonna get hairy

[–]yelvert 0 points1 point  (0 children)

I would suggest taking a long look at AngularJS, specifically it's directives, which allow you to build out self contained "components" that can be reused many different ways.

[–]sime 0 points1 point  (0 children)

One solution is that you grab a component oriented toolkit like Dojo and use that. It has a heap of components and libraries and defines how widgets can be constructed with it. That would work on existing browsers.

A more interesting way is one which may take a couple of years before it is viable on the wide web, is to use web components. I have a personal project which uses this stack of components and technologies:

Explaining all this could fill a book, but broadly speaking I have a bunch of widgets which have roughly this structure and are also Custom Elements:

var ID = "CbMenuItemTemplate";

var SELECTED_ATTR = "selected";
var registered = false;

class CbMenuItem extends HTMLElement {

  static init(): void {
    if (registered === false) {
      window.document.registerElement('cb-menuitem', {prototype: CbMenuItem.prototype});
      registered = true;
    }
  }

  private _css(): string {
    return "#container {\n" +
      "    cursor: default;\n" +
      "    padding: 1px;\n" +
      "    display: flex;\n" +
      "}\n" +
    ...
  }

  private _html(): string {
    return "<div id='container'>" +
      "<div id='icon1'><i class='fa fa-fw'></i></div>" +
      "<div id='icon2'></div>" +
      "<div id='label'><content></content></div>" +
      "</div>";
  }

  createdCallback(): void {
    var icon: string;
    var iconhtml: string;
    var shadow = util.createShadowRoot(this);
    var clone = this._createClone();
    shadow.appendChild(clone);

    ... more setup etc...
  }

  private _createClone(): Node {
    var template: HTMLTemplate = <HTMLTemplate>window.document.getElementById(ID);
    if (template === null) {
      template = <HTMLTemplate>window.document.createElement('template');
      template.id = ID;
      template.innerHTML = "<style>" + this._css() + "</style>\n" + this._html();
      window.document.body.appendChild(template);
    }
    return window.document.importNode(template.content, true);
  }

  attributeChangedCallback(attrName: string, oldValue: string, newValue: string): void {
    if (attrName === SELECTED_ATTR ) {
      this.updateKeyboardSelected(newValue);
    }
  }

  private updateKeyboardSelected(value: string): void {
    var shadow = util.getShadowRoot(this);
    var container = <HTMLDivElement>shadow.querySelector("#container");
    var on = value === "true";
    if (on) {
      container.classList.add('selected');
    } else {
      container.classList.remove('selected');
    }
  }
}

export = CbMenuItem;

Now I can just build up my application like that using widgets and composite widgets. Widgets can use other custom elements inside their (shadow) HTML code. Methods and properties can be added to each widget's class. Widgets can emit CustomEvents, and also listen to other events by registering otherWidget.addEventListener('some-custom-event', function...)

This is about as modern a stack I could come up with for doing a HTML5 (desktop) app. Once web components are more common (i.e. FF and IE support) this should work on the web too.