www.webdeveloper.com
Results 1 to 7 of 7

Thread: Announcing Elementals.js Library, "Not a framework"

  1. #1
    Join Date
    May 2014
    Posts
    900

    Announcing Elementals.js Library, "Not a framework"

    While I like to say it's "Not a framework" I figured this was the best place to mention it. I've made a new library of helper functions and method extensions that's lightweight, assists with class and DOM manipulation, and provides a few ECMA-Script polyfills for usefull string and array methods that not all browsers support yet.

    http://www.elementalsjs.com

    Why do I call it a "library" and "not a framework"? Because to me 'framework' now has a negative connotation associated with it. They are slow, bloated, and many of them by themselves are larger than my ideal target for a page template (not counting content) in terms of HTML + CSS + Scripts + Images -- hellfire and brimstone some of them gzip compressed are larger than entire PAGES on sites I build WITH CONTENT. (assuming you don't count the fat bloated social media garbage).

    To be fair, I say the same thing about nitwit nudnik nonsense like HTML/CSS frameworks like bootstrap, and broken thinking like LESS, SASS and OOCSS which defeat the point of even USING HTML/CSS in the first place!

    More so though, 'frameworks' seem to be built on the idea of doing things for you in JavaScript, even if it's not JavaScript's job... This is even more true with CSS3 on the table now making things like jquery's .fadein or .slidein methods seem not just dated, but slow, jerky, wasteful and unreliable.

    A library on the other hand just gives you tools to do things yourself properly. It doesn't try to 'change how the language works' or 'stop you from learning the language in the first place' -- something libraries, like my favorite whipping-boy jQuery -- excels at.

    Generally speaking a LOT of what people do using jQuery is "gee ain't it neat" bull that to be brutally frank falls into three categories:

    1) could be coded smaller and more efficient in vanilla js. Sounds crazy, but it's often true.

    2) is CSS' job... Particularly with CSS3 now what I'd call "real world deployable" -- much like the rest of CSS3 if someone using an old copy of IE doesn't get a animation, rounded corners, and drop shadows, but the page is still FUNCTIONAL enough for them to use -- who gives a flying purple fish?

    3) Has no business on a website in the first place. In this category we have scripting being used to make sure forms are useless scripting off and buggy/annoying scripting on, over-reliance on client-side processing resulting in opening security holes when people forget to re-check values server-side (since ALL user input is suspect), little if anything resembling graceful degradation, and massive bandwidth wasting "gee ain't it neat" animated nonsense that does nothing to do what's ACTUALLY important on a website, DELIVERING CONTENT.

    so... trying to provide a better, leaner, more practical alternative. I might be charging at windmills full tilt, but after several years of seeing site after site basically turned into useless trash thanks to bloated pointless garbage made with jQuery, prototype, YUI, and their ilk -- I have to at least try.

  2. #2
    Join Date
    Dec 2002
    Location
    Seattle, WA
    Posts
    1,843
    If your library is library, then why does it not follow the conventions of a library? Most of all the functionality in elementals.js should be implemented as functions or as methods to a class. Adding non-polyfills onto built-in objects adds "bloat" (and is bad practice in my opinion).

    The MDN has some very well written polyfills. The "polyfills" in elementals.js are poorly implemented.

    Your arguments against frameworks are invalid. How frameworks are implemented is very important. Using jQuery solely to add a slideshow to a page is a good example of poor implementation.

  3. #3
    Join Date
    May 2014
    Posts
    900
    Yay, my first NEGATIVE response!!! GOOD! No joke, I'm actually pleased by this as it means ACTUAL Criticism on which I can base improvements and garner understanding, instead of the lame back-slapping "everything's good" I get most places.

    I may finally be in the right place.

    Quote Originally Posted by ShrineDesigns View Post
    If your library is library, then why does it not follow the conventions of a library? Most of all the functionality in elementals.js should be implemented as functions or as methods to a class.
    You mean like these?
    http://www.elementalsjs.com/_

    Admittedly only about a third of the codebase, but still...


    Quote Originally Posted by ShrineDesigns View Post
    Adding non-polyfills onto built-in objects adds "bloat" (and is bad practice in my opinion).
    I assume you mean methods... I did beat myself up slightly about doing this at first, but really as I'm encouraging node-walking and pre-fetch over the realtime fetch nonsense like jQ and others do, and that it's STILL plenty fast (if not faster than what most 'frameworks' do) I'm not worried about it from a 'bloat' standpoint. Now, if I was attaching 60+k of methods to objects, THEN I'd be worried about it...

    Though I really wish legacy IE did "Element.prototype" properly. I may still go back through and apply them as Element.prototype on modern browsers and _.extend on legacy.

    I'm just not sold on the 'bad practice' part of extending objects -- my smalltalk and object pascal background screams at me that it's the entire POINT of having objects in the first place; extensibility, inheritance, etc, etc... Not leveraging that extensibility seems very inefficient to me, particularly when the other choice is increasing the amount of data passed on the 'stack' to functions. (assuming JS engines have something remotely resembling a stack).

    I've heard a lot of 'don't do it' but not a lot of legitimate reasons as to 'why'. In fact I started to wonder if it was more 'placebo effect' of people saying it so it must be true even if there's no fact behind it. (kind of like the nonsense of jQuery being easier, HTML 5 being easier, Transitional being easier, OOCSS being easier, LESS being easier... and me quoting Inigo Montoya in response.)

    Basically sounds like people taking a small "don't use it for this one thing" and turning it into a "don't use it ever". See nonsense like "don't use tables for layout" being magically turned into "don't use tables ever" nonsense, or the "strong and EM should be used instead of B and I when providing emphasis" being turned into the complete nonsense fiction of "Strong and EM replace B and I completely" -- to the point some people even go so far as to make wild nonsensical claims about B and I being deprecated.

    Though if you can explain any pitfalls, I'd love to hear it! CONVINCE ME.

    Quote Originally Posted by ShrineDesigns View Post
    The MDN has some very well written polyfills.
    I thought so too -- in fact my Polyfills are based on their code... I just cut out the garbage that didn't seem to do anythign meaningful and seemed to just be left over from way too literal an interpretation of the spec -- a spec that was NOT written from the point of view of implementing those methods in JavaScript, but some other language like C.

    MAYBE you could explain it to me? I asked on another forum and on the MDN mailing list and got some vague references to "Corner cases" that still didn't explain why the code did certain things that make no sense whatsoever in JS.

    Let's use "Array.Every" as an example. The MDN polyfill is:
    Code:
    if (!Array.prototype.every)
    {
      Array.prototype.every = function(fun /*, thisArg */)
      {
        'use strict';
    
        if (this === void 0 || this === null)
          throw new TypeError();
    
        var t = Object(this);
        var len = t.length >>> 0;
        if (typeof fun !== 'function')
            throw new TypeError();
    
        var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
        for (var i = 0; i < len; i++)
        {
          if (i in t && !fun.call(thisArg, t[i], i, t))
            return false;
        }
    
        return true;
      };
    }
    If 'this' is void or null, how the devil is an Array.prototype method even being called? The ONLY excuse would be forcing the issue with Function.prototype.call... which shoving the wrong type of variable to a object method SHOULD blow up in your face. If you're dumb enough to do it, you should get what's coming to you! Besides, how on earth is "this" null or void, while being type Array? How does that make ANY sense whatsoever? (In JavaScript... in C? Sure...) I mean... are people doing something really stupid like actually trying to call a .prototype method designed to process an instatiated Array directly?!?

    Next is the part I really don't get -- the conversion to OBJECT... WHY? What possible reason does this serve? Just TRYING to make this harder to process? I mean, if you're worried about it being the wrong type to iterate, wouldn't converting it to Array make more sense? Again, the only reason to force typecasting would be if you use .call to force feed it an invalid variable, in which case why is plodding forward like nothing is wrong a good thing?!?

    Or is this a really half-assed attempt at dealing with the fact that you might force an object or other variable into it (stupid) and you can convert array to object but can't convert object to array?

    Next is the forcing of length to an integer with a shift-- Object.length or Array.length are integer unless you've forced something into it you NEVER should have forced into it (in which case it should be resolving to 0). That the spec is doing so via typecasting to uInt32 shows that this bit of code has NOTHING to do with implementing the function in JavaScript.

    JS has a perfectly good system of determining if an argument exists or not, so why the devil are they using arguments.length? If the syntax is supposed to be:

    arr.every(callback[, thisArg])

    Why isn't the function declared:
    Array.prototype.every = function(callback, thisArg)

    Then simply checking if (typeof thisArg =='undefined')?!? Sorry, but my BS alarm is going off. Again though, that type of coding check makes perfect sense if you were implementing it in a language that didn't have optional parameter support built in. YES, it's EXACTLY how it's written in the spec, but the spec isn't written from the point of view of writing it in JavaScript because *NEWS FLASH* you don't write JavaScript engines for browsers in JavaScript!

    Then the loop... oh the loop. They for/next through it, then check "if i in t" -- if it's been converted to an object isn't that the job of "for i in this"? I know some people again seem to think "never use for/in" because it fails on Arrays, but this is an OBJECT at this point. The only reason I can figure is that Object properties lose their order, but given that in legacy IE so do their numeric indexes, and that legacy IE is the only place you'd even HAVE this code running...

    Though if they had just left it a bloody array (or typecast it as such), and that arrays auto-compact their numbered indexes, they wouldn't need that extra IF inside the loop, would they?

    hence why my rewrite (verbose) is:

    Code:
    every : function(callback, thisArg) {
    	_.throwNonType(callback, 'function');
    	var len = this.length, k;
    	thisArg = typeof thisArg == 'undefined' ? void 0 : thisArg;
    	for (k=0; k < len; k++) if (!callback.call(thisArg, this[k], k, this)) return false;
    	return true;
    }
    That being from the object that is iterated and tested for against Array.prototype just like their IF statement does... since all the polyfills need that same check, it made more sense to put them into their own object and copy when needed to reduce the amount of code.

    I MIGHT be convinced to add the 'this is null' throw back in (I do have the function for that check after all -- so just _.throwNull(this)) but other than that? in 99% of real world uses I find it doubtful anyone would notice the difference... and if that Object part is really necessary:

    Code:
    every : function(callback, thisArg) {
    	_.throwNull(this);
    	_.throwNonType(callback, 'function');
    	var t = Object(this), k;
    	thisArg = typeof thisArg == 'undefined' ? void 0 : thisArg;
    	for (k in t) if (!callback.call(thisArg, t[k], k, this)) return false;
    	return true;
    }
    Should be functionally identical to what they are doing -- actually no, it would be MORE functional since if you shove an object at it with .call, their implementation could skip over object properties since properties don't numerically collapse like Array indexes does.

    Their polyfills -- particularly on Array -- while working and excellent at explaining what the function does, just seems to have a lot of stuff in it that has NOTHING to do with how JavaScript works -- on ANY browser or implementation I've ever heard of, and reeks of a bad port from C or C++ without taking into account the differences between the languages. Some of them even seem to BREAK compared to the actual browser spec versions -- as I just noted with the for/next integer loop over objects where it could skip over properties!

    The "best" explanation anyone could give me was "It's being literal to the spec" -- I nice ideal but really if you're porting it to a language, shouldn't you maybe... take how that language works into account?!? The spec wasn't written TO JS implementation becuase again, JS engines aren't written in JS!

    If I'm wrong, please EXPLAIN why I'm wrong, and WHY they are doing those things? I've been asking even on the MDN mailing list for a month and a half, and the answers I've gotten back have been little more than "because".

    I would like an ACTUAL explanation. The lack of one is why I pushed on and just did it the way I did.

    ... contined on next post (too long)

  4. #4
    Join Date
    May 2014
    Posts
    900
    Quote Originally Posted by ShrineDesigns View Post
    Your arguments against frameworks are invalid. How frameworks are implemented is very important. Using jQuery solely to add a slideshow to a page is a good example of poor implementation.
    I think you meant used not implemented, to me implementation is how the framework itself is written and provides it's functionality, not how someone uses it on their own project... though that's splitting hairs I guess.

    Honestly, I've never seen anything done using jQuery that didn't fall into my three categories; in fact to be brutally frank I've never seen jQuery used to do anything that wasn't absolute trash -- and the same goes for just about every other "framework" be it JavaScript or HTML/CSS.

    To me they're all a bunch of bull if you took the time to learn JavaScript, learn HTML and learn CSS. But of course, 99% of the people sleazing out websites these days just want to copypasta together a bunch of off the shelf garbage with a "wah, wah, I don't wanna learn" attitude -- and to be frank, this library is NOT for them.

    Though, would you care to elaborate on what exactly you disagree with in my arguments against frameworks? It's hard to defend against "Wah, is not" (no offense) or to figure out what to change based on that.

    Still, it's nice to have something more than shallow flattery as a response for a change.

  5. #5
    Join Date
    Dec 2002
    Location
    Seattle, WA
    Posts
    1,843
    Quote Originally Posted by deathshadow View Post
    Yay, my first NEGATIVE response!!! GOOD! No joke, I'm actually pleased by this as it means ACTUAL Criticism on which I can base improvements and garner understanding, instead of the lame back-slapping "everything's good" I get most places.
    I try to provide good criticism.

    As for the "don't add to the built-in objects...", I read some where (I think on MDN, I tried to find it for citing prior to commenting) that it increases overall memory usage and can cause some undesired side-effects, like iterating over them in a loop.

    I see your points about the overly redundant checks in those polyfills. The this === null check in an Array.prototype method is an epic facepalm.
    Code:
    null.prototype.test = function()
    {
        while (alert('I WIN!!') || true);
    };
    The "copy & paste" web developers have been around for ages, they'll be around long after I hang up my keyboard.

    I am probably not the best person to defend frameworks. I have been looking into some of them, trying to find that "barebones" one that caters specifically to classes and coding.
    To me they're all a bunch of bull if you took the time to learn JavaScript, learn HTML and learn CSS.
    I agree. I have a couple of JavaScript based projects going, I've tried weighting the pros of using a framework for them, I couldn't find a reason to use one. There are benefits to using them, and those benefits are... idk. u_u

  6. #6
    Join Date
    May 2014
    Posts
    900
    Quote Originally Posted by ShrineDesigns View Post
    As for the "don't add to the built-in objects...", I read some where (I think on MDN, I tried to find it for citing prior to commenting) that it increases overall memory usage and can cause some undesired side-effects, like iterating over them in a loop.
    I remember the same thing -- then couldn't find it either; it's like wherever I had heard it just up and disappeared. I was beating myself up over doing it, but when I saw that Prototype does the same thing, I figured "why not"...

    At the low level (I started in machine language over three and a half decades ago) the making them slower in a loop doesn't actually make sense, since objects are instances of pointers, it shouldn't matter when walking over them either as an array of pointers, or via the DOM. It's one of those things I've HEARD... that I'm not sold on.

    Though the increased memory use? That's a good point, but since I'm only extending existing elements on the DOM instead of via prototype (since legacy IE can't do element.prototype) it's not going to hit every instance on the page, just the ones being manipulated or walked. (In theory)... even so in an interpreted language the memory use of a few subroutines on the DOM shouldn't be a big deal... at least not when we're talking about websites. I often laugh when people start going on about JS memory use on something like that, but has no problem with multi-megabytes worth of images in their templates.

    Quote Originally Posted by ShrineDesigns View Post
    I see your points about the overly redundant checks in those polyfills. The this === null check in an Array.prototype method is an epic facepalm.
    That was the one that made me go "WAIT" and look deeper at it. Originally I was literally just going to copypasta their fills, but when I saw that one... I mean, if "this" is null, how did you get into executing the method in the first place? You're right, epic facepalm... and the more I dug, the more things like that I started to question.

    That nobody on the MDN mailing list or IRC channel could give a legitimate answer? That REALLY made me question it.

    Quote Originally Posted by ShrineDesigns View Post
    I am probably not the best person to defend frameworks. I have been looking into some of them, trying to find that "barebones" one that caters specifically to classes and coding.I agree. I have a couple of JavaScript based projects going, I've tried weighting the pros of using a framework for them, I couldn't find a reason to use one. There are benefits to using them, and those benefits are... idk. u_u
    I'm that way with almost all frameworks -- It's part of why (along with the massive size of most of them being bigger than I'd make an entire site template) I generally advise people against using them be it HTML, CSS or JavaScript. Just making this 'library' is a radical departure for me given my attitude on using off the shelf code on projects.

  7. #7
    Join Date
    May 2014
    Posts
    900
    Just an update, version 0.95 RC1 is up on the site now. Fixes include:

    1) Undoing some bad advice I got that broke it working in IE8/earlier. I also went through and fixed a lot of 'capabilities' checks that IE 7 and 8 were choking on; what I get for testing IE6 and assuming if I'm ok in IE6 and IE9, 7 and 8 will be ok. Good lesson in there! Also starting to think I need to stop listening to "experts" and stick to my gut reactions.

    2) Fixing the node walking code; I'm used to proper b-tree structures with real pointers, JS doesn't quite work the same way. Had a bug coming "back up" the tree that was skipping large sections of the DOM.

    3) added 'internal use' (for now) polyfills for Element.querySelector and Element.querySelectorAll. (ugly, but it works)

    4) added 'internal use' _.objectHasProperty function. Needed because legacy IE doesn't have hasOwnProperties, typeof Element[index] is unreliable, and that method doesn't include inherited methods and properties. For now it iterates through all properties using:

    Code:
    for (var index in Object) if (attribute == index) return true;
    Which is slow; trying to find a better alternative. In modern browsers I should probably use Object.keys().indexOf; unless someone has a better idea.

    5) switched to YUI for the minification, as Packer 3.1 was actually breaking some functions... like it matters at 15,461 bytes without minification and 11,315 bytes minified; the difference gzipped being near pointless (700 measly bytes).

    The Beta was feature-complete, but buggy; what a BETA should be. Now that it's at release candidate status it's been debugged and extensively tested... but some early adopters/testing help would be appreciated.

    ... and somehow uncompressed unminified I'm STILL under my 16k target, but it's getting tight in there.
    Java is to JavaScript as Ham is to Hamburger.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles