HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Lightweight shorthand JS library

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
lightweightshorthandlibrary

Problem

Long story short: I wanted some of the time-saving functionality of jQuery without the bulk of the entire library. So, I wrote a lightweight shorthand library inspired by jQuery I'm calling Mozart JS, and I'd like to see how I can further enhance it without major impact on load times.

Thoughts? Full library on GitHub.

Mozart JS

Element Retrieval

Fairly straightforward.

function $get(e, t) {
    if (void 0 === t) t = document;
    if (e.startsWith('#')) return t.getElementById(e.substring(1));
    if (e.startsWith('.')) return t.getElementsByClassName(e.substring(1));
    if (e.startsWith('-')) return t.getElementsByName(e.substring(1));
    return t.getElementsByTagName(e);
}


Example:

var foo = $get('#bar'); //returns element with the Id of "bar"
var zed = $get('.cop'); //returns collection with the classname "cop"


Element Creation

Slightly more complicated; allows the assignment of common properties and all attributes.

function $make(t, p) {
    var o = document.createElement(t);
    if (p.style) o.style.cssText = p.style;
    if (p.class) o.className = p.class;
    if (p.text) o.textContent = p.text;
    if (p.value) o.value = p.value;
    Object.keys(p).forEach((e) => {
        if(e.startsWith("@")) {
            o.setAttribute(e.substring(1), p[e]);            
        }        
    });
    return o;
}


Example:

var h = $make('a', {
    'class': 'myClass',
    'text': 'Google',
    '@id': 'googleLink',
    '@href': 'https://google.com',
    '@target': '_blank'
});

//Equivalent to:

var h = document.createElement('a');
h.className = 'myClass';
h.textContent = 'Google';
h.setAttribute('id','googleLink');
h.setAttribute('href', 'https://google.com');
h.setAttribute('target', '_blank');


Element Sibling Insertion

Designed to mimic most of jQuery's insertBefore() method. Equivalent function exists for insertAfter(); omitted here in order to save space.

```
function $addBefore(e, t) {
if (typeof t === 'string' ||

Solution

I wanted some of the time-saving functionality of jQuery without the bulk of the entire library.

If you don't look back at older browsers, use version 2.x of jQuery. It's smaller than the 1.x as it has less cross-browser compatibility code (See How 2.0 Changed section). You can also custom-build jQuery to your own spec to include what you need. An even smaller yet jQuery-compatible library is Zepto, just ~9k compressed.


Element Retrieval

Pretty straightforward. However, there is querySelectorAll which pretty much acts like jQuery's $. A singular version of it is querySelector. It's native, and has been there for quite a while.

One neat thing about jQuery and jQuery-like libraries is that they encapsulate results, single or multiple, into a set. Methods operate by looping through and applying to each item in the set. No items, no loop, thus no throw.

$('#foo').children().eq().next().remove();


The following example will not throw an error even when there's no #foo in the page.


Element Creation

var h = $make('a', {
    'class': 'myClass',
    'text': 'Google',
    '@id': 'googleLink',
    '@href': 'https://google.com',
    '@target': '_blank'
});


Not entirely sure what's the difference between class and the other attributes when it's also an attribute. What should be different is text since it doesn't actually describe the element. Also, text nodes can be created separately via createTextNode.


Element Sibling Insertion

if (t.startsWith('#')) {            
  $get(t).parentNode.insertBefore(e, $get(t));
} else {
  var arr = $get(t);
  for (var i in arr) {
    var f = e.cloneNode(true);
    arr[i].parentNode.insertBefore(f, arr[i]);
  } 
}


This is one case where your code will start to become unmaintainable. This function is making a special case for singular results. If you go with the set-like behavior of jQuery, singular results are still a set. Your code will always assume a set and be more consistent in operation.


Element Removal

function $remove(e) {    
    if (typeof e === 'string' || e instanceof String) {
        $remove($get(e));
    } else if (e.nodeType === 1 || e.nodeType === 3) {
        e.parentNode.removeChild(e);
    } else {
        for (var i in e) {
            e[i].parentNode.removeChild(e[i]);
        }
    }
}


Again, your code is doing special cases for different things. This could have been easier if you operated with a set of things.

function $remove(input){

  // Building the set
  var set = inputIsAString ? lookForElements(input)
          : inputIsAnElement ? createASet(input)
          : inputIsAlreadyASet ? input
          : [];

  // The actual operation
  set.forEach(function(){
    // element removal code
  });
}

Code Snippets

$('#foo').children().eq().next().remove();
var h = $make('a', {
    'class': 'myClass',
    'text': 'Google',
    '@id': 'googleLink',
    '@href': 'https://google.com',
    '@target': '_blank'
});
if (t.startsWith('#')) {            
  $get(t).parentNode.insertBefore(e, $get(t));
} else {
  var arr = $get(t);
  for (var i in arr) {
    var f = e.cloneNode(true);
    arr[i].parentNode.insertBefore(f, arr[i]);
  } 
}
function $remove(e) {    
    if (typeof e === 'string' || e instanceof String) {
        $remove($get(e));
    } else if (e.nodeType === 1 || e.nodeType === 3) {
        e.parentNode.removeChild(e);
    } else {
        for (var i in e) {
            e[i].parentNode.removeChild(e[i]);
        }
    }
}
function $remove(input){

  // Building the set
  var set = inputIsAString ? lookForElements(input)
          : inputIsAnElement ? createASet(input)
          : inputIsAlreadyASet ? input
          : [];

  // The actual operation
  set.forEach(function(){
    // element removal code
  });
}

Context

StackExchange Code Review Q#117886, answer score: 2

Revisions (0)

No revisions yet.