1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Making new library -- "Not a framework"

Discussion in 'JavaScript' started by deathshadow, Mar 20, 2014.

  1. #1
    This might be a bit long for the TLDR re-re's, but stick with me... there are some questions in here.

    It's pretty well documented at this point my opinion of 'frameworks', particularly for javascript. (though they are just as big a steaming pile of idiotic halfwit BS for HTML/CSS). To me the whole term "framework" now has a negative connotation, as it seems the moment people started calling them frameworks, that's when they went to hell in a handbasket.

    Was having a discussion with a friend about how I use small libraries of useful functions, that even combined without the normal picking and choosing I do would end up well under 16k... So he said "Well, put them all together, organize them, document them, and make a library to show these frameworks how it should be done."

    ... not a bad idea at that.

    ---------------------------------------------

    There are some things I'm REALLY sure I don't want it doing.

    1) NO replicating existing CSS functionality. See idiocy like the old mm_swap crap from Dreamweaver, or jQuery's .fadeIn and .slideIn methods.

    2) NO 'different' methodologies; see jQuery's "daisy chaining" of calls. A lot of "frameworks" by their very nature seem to want to hide the underlying language, or completely change how it works into an inefficient mess, instead of working WITH the DOM and JS' natural functionality.

    3) NO encouraging calling 'get' type methods every time you do something; dev's should get their elements up front at load, not every time a onclick or other operation is called; if you ARE getting the element, you should do so by walking the DOM. (parentNode, event.target, etc). See how EVERY bloody jQuery operation people write -- even inside event handlers -- seems to start out with a blasted selector...

    4) Keep the bloat to a minimum. This means that for right now, I'm setting 16k of 'full text' as the absolute maximum size I'm going to allow this library to reach; likewise it should be 12k after white-space stripping and hopefully less than 4k gzipped. In other words a great big kick to the crotch to prototype's 183k and the latest jQuery's 286k (32k compressed+gzipped).

    5) FIXED API -- future changes / minor revisions should NEVER break existing code, and at best should be compatible bugfixes. If a change DOES break things, that's what a MAJOR revision number is for! (I swear, between the asshattery FF started with 'major revisions every time the wind blows' and even minor revisions to jQuery shtupping the whole thing, much less the WhatWG with their 'living document' crap... do people even know how to use version numbers anymore or why they are important?). I'm not Linus, I'm not interested in pissing off developers because a good stiff breeze blew up my pants so the whole hardware API needs a rewrite from scratch. :p

    ---------------------------------------------

    Then there are things I DO want it doing.

    1) class manipulation -- 90%+ of what 'normal people' do with jquery should actually be done with a class swap and CSS, so good class manipulation functions are a must have. While they've added classList and it's methods to ECMAScript 1.5+, support is still spotty, they're SLOW (even slower than just doing a regex on element.className?!?), and being buried under classList as methods makes calling them a good deal more typing than it should have been. Right now I'm thinking .classAdd, .classRemove, .classExists, .classSwap and .classToggle.

    2) AJAX - a simple AJAX object that has it's own response handler to which you can apply methods for processing levels and http status. I'll cover this more in a future post.

    3) ECMAScript 262 shims. -- At the very least I want the new Array methods (a proper foreach, indexOf, map, some, etc), as well as some of the string ones (like trim).

    4) new string functions -- one I'm really thinking on is a replace that works like how PHP lets you pass arrays to it. I think some auto camel-case and cssName to .js-name conversions might be handy too.

    5) 'make' method to easily create new DOM elements with their content. something like:
    make([selector, [ content, [ attributes, [ parent ] ] ] ]);

    Where if for example you passed it:
    make('div#test.gallery', 'Welcome to our gallery', { onclick : function() {} }, document.body);

    It would make a div with the id 'test' and the class 'gallery', containing a textnode saying 'welcome to our gallery', with an onclick method, as a child of body. I'm thinking that if content is a string or number it's added as a textNode, if it's an object that object is inserted using appendChild. All parameters would be optional, with 'selector' defaulting to 'div' if omitted. (or if you said "#test" it would treat it as "div#test"?). The function would also return a handle to the created element, good if you don't want to declare it's parent yet at that point.

    6) 'get' method using CSS style selectors.
    get('#test) == getElementById
    get('.test') == getElementsByClassName
    get('#test div) == getElementById('test').getElementsByTagName('div')
    ... and so forth. I've actually found laughably I'm able to do my own getElementsByClassName that's FASTER than the real one in everything but FF as I can walk the DOM to build it.

    7) TBODY uSort. This is something I see a lot of people jumping through crazy hoops to do, when it shouldn't take more than a dozen and a half lines to implement if you have the right 'support library' in place. You pass it a sorting function just like an array uSort, and passed to that function are arrays containing the table rows. It strips them all off the DOM, sorts them with the usort function, then inserts them back into the DOM.

    8) DOM walking -- the normal nextSibling, prevSibling attributes are nice, but can be annoying when you want the next TAG, not the next NODE... or if you want a tag or textNode, but don't give a flying purple fish about CDATASections, Comments, whitespace, etc, etc.. I'm thinking NodeNext, NodePrev, NodeFirst and NodeLast, with a boolean argument to say whether to just use nodetype 1, or include nodetype 3. Tagxxx versions letting you target specific tags might help too. Likewise a 'each' method to walk the DOM for you might be handy.

    My glorious one-line walker:
    e = e.firstChild || e.nextSibling || (e.parentNode == this ? null : e.parentNode.nextSibling);
    Code (markup):
    Should make that pretty easy.

    9) parameter check and throw methods -- A lot of shim's use a 'if this var is null, throw an error' or log a warning to the console, providing functions to make doing that a simple function call might be helpful.

    10) child node handling -- a flush (destroy all children), replace (flush and insert new element), replaceText (flush and replace with textNode), text append and prepend functions would also simplify things, particularly when it comes to putting content into the page using JS or generating 'scripting only' elements that have no business in the markup in the first place. (like javascript only controls, wrapping DIV, spinners and so forth).

    11) Form serialization -- if you're gonna have AJAX, it's kind-of a must-have these days.

    ---------------------------------------------

    Now, the hang-ups on developing this is implementation, specifically do I want standalone functions, objects you have to pass elements too, or do I want to risk extending objects on the fly.

    I'm leaning towards the last of those for element specific functions, and the middling for generic library functions. (the shim's will obviously use .prototype). The alleged "risks" of extending objects as needed in terms of legacy IE is easily enough avoided if you have any clue what you are doing... and the 'problems' that plagued prototype early on are easily enough avoided if you bother to check if your extensions/new methods exist first.

    I'm thinking that I'm going to use underscore for the library object 'name'... so for example the above 'make' function would be _.make(); _d will be an alias of document just to make that more convenient, and _d will be 'extended' with element type methods. .get() would be a method added by the "extend" function to an element -- _d will start out extended, anything you get with get() or make with make() will be extended. Likewise I'll probably add a shim to make sure document.head exists and is extended... and extend document.body too while in there.

    So... First up, anything wrong or any warning signs in the above? pitfalls you could see me running into in doing this?

    Second, anything you'd like to see in a JS library that isn't covered above?

    Oh, and I'm also trying to think of good demo's for it... Someone recently posted up a progress bar called 'nProgress' -- 6k and it needs jQuery to do what I think shouldn't take more than a K and a half code... There's lightbox... and image sliders. I'm thinking one each of those. No reason to do a menu since as a rule of thumb there's no reason to use JS on menus apart from adding IE6- support... Though 'accordions' might be a good one since I've been doing those for years.

    Any advice/ideas are welcome. Not sure the time schedule on this; due to the small size and recycling of code it shouldn't take too long.
     
    deathshadow, Mar 20, 2014 IP
  2. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #2
    I would prefer if the sorting function was able to use other parent nodes than TBODY, but that's maybe just me (UL, fx)
    Better array-functionality would be a god-send
    Something akin to "find" on the node-walking would be good too, for instances when you don't know exactly where in the code your element is located - but that might not be part of the specs for this library.

    Would it perhaps be wise to make some sort of CSS-base for this as well? Not as part of the library, just some examples on how one could use CSS to get the same effects and end-goals as many other js-frameworks provide?
     
    PoPSiCLe, Mar 21, 2014 IP
  3. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #3
    For OL/UL that might make sense/be simple. Tables are easy because they have a logical structure -- TBODY's direct children are always TR, and TR always contains TH or TD as their direct children, making it easy to pull each TR's TD, yank the textnodes from them and put them into an array. OL/UL should be similarly easy to implement -- perhaps easier since their direct descendants are always LI.

    I've already got some preliminary code on how I'm handling the TBODY uSort.
    			case 'TBODY': a('uSort', function(f) {
    				var
    					r = [],
    					e = this.nodeFirst();
    					t, c, v;
    				while (e) {
    					if (e.tagName && e.tagName == 'TR') {
    						c = {t : e, d : []};
    						if (v = e.nodeFirst()) do {
    							if (
    								v.tagName && (v.tagName == 'TH' || v.tagName == 'TD')
    							) c.d.push(v.textGet());
    						} while (v = e.nodeNext());
    						r.push(c);
    					}
    					t = e.nodeNext();
    					this.removeChild(e);
    					e = t;
    				}
    				r.sort(f);
    				for (t = 0; t < r.length; t++) this.appendChild(r[t].t);
    			}); break;
    
    Code (markup):
    I know I normally rail and rant about using short/cryptic variable and function names, but given my size restrictions I figure it's better to work that way from the start; it's also where good documentation is REALLY going to help out.

    The 'a' function tests if the element already has a method named that, if not it adds the function. I have several such functions in there so that should in the future anything I'm doign gets adopted into the spec (one can dream) it doesn't conflict with it; one of the things that bit prototype in it's backside early in it's history (which they since fixed) that I'm trying to avoid hitting up against at the start.

    Pretty simple though -- Find the TR, save a copy/handler to an object property, then add another object property that contains a simple array of the textNode content of each TD, put that object in an array then remove the TR from the DOM; lather, rinse, repeat for all direct child elements of TBODY. Leverage Array.sort on our array of objects then plug the sorted values back into the DOM. Could probably be done faster somehow, but it should be 'fast enough' for all but the largest of tables.

    ECMAScript 262 added some really nice methods in that regard, I'm really fond of 'map' and 'indexOf'... problem is they aren't 'real world deployable' since implementations are spotty. MDN has some really nice examples of writing shim's, and I'm basing my versions on theirs. (If you're gonna steal, steal from the best).

    For example, their Array.indexOf page:
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf

    My version is a bit leaner:
    	aA('indexOf', function (v, s) {
    		_.throwNull(this);
    		for (var t = s || 0; t < this.length; t++) if (this[t] == v) return t;
    		return -1;
    	});
    Code (markup):
    But functionally identical. *** EDIT *** My bad, NOT identical, I missed the 'negative value is index from end' -- easy enough to add.

    I've got some short internal (not exposed to the user) functions to simplify adding things.

    	function aP(e, n, f) {
    		if (e[n]) return 0;
    		e.prototype[n] = f;
    		return 1;
    	}
    
    	function aA(n, f) { return aP(Array, n, f); }
    	function aS(n, f) { return aP(String, n, f); }
    	function aC(e, f) { _.throwNull(e); _.throwNonType(f, 'function'); }
    Code (markup):
    String I also add a TRIM if it's not already there. Another thing ECMAScript 262 finally added; by testing before adding I can be sure the native version is used.
    	aS('trim', function() { _.throwNull(this); return this.replace(/^\s+|\s+$/g,''); });
    Code (markup):
    My throw methods are working great:

    	throwNull : function(e) {
    		if (e == null || typeof e == 'undefined') throw new TypeError(
    			'Undefined Variable'
    		);
    	},
    
    	throwNonType : function(e, t) {
    		_.throwNull(e);
    		if (typeof e !== t) throw new TypeError(e + ' is not type "' + t + '"');
    		return 1;
    	},
    
    	throwNonInstance : function(e, i) {
    		_.throwNull(e);
    		if (!e instanceof i) throw new TypeError(e + ' is not an instance of ' + i);
    		return 1;
    	},
    
    	warn : function(m) { if (console) console.warn(m); else alert(m); }
    
    Code (markup):
    What exactly would it be searching for/by? Do you mean looking for an element based on it's content? (that should be possible, I'd have to think on it). Anything to make getting to elements easier in a relative (instead of absolute) fashion is a good idea in my book. Could you elaborate further on what you mean?

    That's where well documented and fully explained demo's comes into play. It often seems like a lot of libraries give demo's but don't take the time to explain them properly... and if I'm good at ANYTHING, it's explaining things -- even if once I get started it's hard to shut me up.

    One thing I'm still laughing at is my class functions:
    		a('classAdd', function(n) {
    			if (!this.classExists(n)) {
    				return this.className += (this.className ? ' ' : '') + n;
    			} return 0;
    		});
    
    		a('classAddFromArray', function(a) {
    			_.throwNonInstance(a, Array);
    			for (var t = 0; t < a.length; t++) this.classAdd(a[t]);
    		});
    
    		a('classExists', function(n) {
    			return RegExp('(\\s|^)' + n + '(\\s|$)').test(this.className);
    		});
    
    		a('classMatchArray', function(a) {
    			_.throwNonInstance(a, Array);
    			if (a.length == 0) return 0;
    			var c = 0;
    			for (var t = 0; t < a.length; t++) {
    				if (this.classExists(a[t])) c++;
    			};
    			return c == a.length;
    		});
    
    		a('classRemove', function(n) {
    			if (this.classExists(n)) {
    				e.className = e.className.replace(
    					new RegExp('(\\s|^)' + n + '(\\s|$)'),' '
    				) . replace(/^\s+|\s+$/g,'');
    				return 1;
    			} return 0;
    		});
    
    		a('classSwap', function(oN, nN) {
    			return this.classRemove(oN) && this.classAdd(nN);
    		});
    
    		a('classToggle', function(n) {
    			if (this.classRemove(n)) return 0;
    				else { this.classAdd(n); return 1; }
    		});
    
    		a('classValue', function(n) {
    			var s = this.className.match(new RegExp('\\b' + n + '_(\\S+)','g'));
    			if (s) {
    				s = String(s).split('_');
    				return s.length == 2 ? s[1] : s.slice(1);
    			}
    			return null;
    		});
    Code (markup):
    Are faster than the new classList methods... I think this is because I avoid using arrays, while classlist is basically an array/object -- I suspect the implementation for those are working on the element.classList array and then building element.className, instead of manipulating element.className and then building element.classList. Kind of laughable when a regex is faster than a native function/method... arrays in Javascript being pointered lists instead of 'real' arrays makes them slow -- painfully so at times.

    I've decided on a function/method naming convention. I'm sticking with the javascript recommendations of CapsCamel for classes/functions and camelCase for methods/vars. The function/method names themselves will be done in the order of what's being manipulated and what type of manipulation is being done. This should make it easier when scanning the documentation to find things, since all 'class' functions will start with class, all text functions will start with text, and so forth. classAdd,classReplace, textAdd, textReplace, and so forth.

    Establishing a naming convention is something good libraries do... and something that often seems to be lacking in most code these days.
     
    Last edited: Mar 21, 2014
    deathshadow, Mar 21, 2014 IP
  4. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #4
    Ok, THIS should be functionally identical to the MDN shim/polyfill of indexOf on an array.
    	aA('indexOf', function (v, s) {
    		_.throwNull(this);
    		var l = this.length, t;
    		for (t = (s ? ( s < 0 ? l + s : s ) : 0); t < l; t++) {
    			if (this[t] == v) return t;
    		}
    		return -1;
    	});
    Code (markup):
    Anyone have any clue why theirs spends so much time dicking around with shifts and "or by zero" for... no comprehensible reason? (much less the bizarre Math.abs?!?)

    Are they running those checks because they are worried that JS' arbitrary precision could result in a value outside the 32 bit limit? Really if you are operating on 4 billion plus array elements in JAVASCRIPT, you're doing something wrong in the first place and should get what's coming to you... NOT something I'd waste code trying to handle...

    If anything, their code for that would make matters worse... particularly if that 32 bit limitation is lifted in the future. I mean it's an ARRAY, we know that array lengths can be processed without all that garbage, so why do they suddenly find it necessary?!? Stuff like that is a perfect example of what I mean by taking something simple and making it hard on purpose.
     
    Last edited: Mar 21, 2014
    deathshadow, Mar 21, 2014 IP
  5. AbstractChaos

    AbstractChaos Member

    Messages:
    58
    Likes Received:
    4
    Best Answers:
    4
    Trophy Points:
    25
    #5
    Will this be opensource deathshadow? If just to learn from the code itself :)
     
    AbstractChaos, Mar 21, 2014 IP
  6. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #6
    As for the "find" I was talking about, finding elements based on content and such would of course be nice, but is probably handled already, isn't it?
    What I was originally talking about was more of a "find element <that> after element <this>" - ie, if you for instance have a parent element with an ID or such, which have several descendants and children, and descendants and children within children and such. Using the nodeNext and nodeSibling and such won't find these, unless you're planning on making them able to run several times on new elements? (But then we'll be back to nested function-calls, which as I understood it, you're trying to avoid).
     
    PoPSiCLe, Mar 21, 2014 IP
  7. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #7
    More open than open -- I plan on releasing it as public domain, the only restriction being that as a copyrighted work credit be given where credit is due.

    Not a big fan of "licenses" since I operate on the principle that if you're going to give something away, for **** sake just give it away! If I 'had' to choose a license, I'd probably go with MIT just as lip-service to get it onto something like google code if desired; though I have no plans for version control since I programmed some twenty years before there even was such a thing, and every project I've ever dealt with that used ANY of them (Git, SubVersion, clearCase) they did more harm than good pissing all over the project being worked on - at least when compared to having a real project manager given "the powers of god" in terms of who does what on a project. Just another of those sleazy shortcuts IMHO that if you 'really' need, you've probably got something wrong with your development process... like "too many cooks", "who does what" or "low man on the totem pole thinks everything is his job"... or worse, the situation I've seen far too many times, "low man on the totem pole is the only one who knows what he's doing"

    Type of crutch I expect Ivy League college ***'s who know *** about *** and had the first 28 years of their life paid for by mommy and daddy to need.
     
    deathshadow, Mar 21, 2014 IP
  8. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #8
    That's called walking the DOM. If you want to iterate through the children of an element -- it's simple node-walking. Let's say we have a variable called 'target' that is your parent element with an ID.

    To walk it's children:

    if (e = parent.nodeFirst()) do {
      // process e
    } while (e = e.nodeNext());
    Code (markup):
    Same as you would with firstChild and nextSibling... You want to walk it's children, test for if it has children. My 'walking' code from above is for precisely that:

    if (e = parent.nodeFirst()) do {
      // process e
    } while (e = e.nodeFirst() || e.nodeNext() || (
      e.parentNode == parent ? null : e.parentNode.nodeNext()
    ));
    Code (markup):
    The above will walk all child nodes of 'parent'... In Soviet Russia, you walk the DOM...

    Though I'm not entirely sure that's what you are asking... I think the 'tag' functions might be more what you are asking. Since tagFirst('h2') to find the first child of that type of tag will be very useful if you aren't sure just where it is and it doesn't have a unique ID on it for targeting... just as tagNext('h2') to find a sibling will make walking through a document far simpler.

    It's also nice that walking through the DOM in an organized fashion is SO much faster and lighter on the memory use than iterating any of the arrays you would come up with using getElementsByTagName or getElementsByClassName methodologies. Again I suspect this is because javascript arrays are slow, and it's just more natural to walk an object list than it is to have the object list turned into an array by the system and then basically do the SAME operation to index through the array.
     
    deathshadow, Mar 21, 2014 IP
  9. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #9
    Ah, yes, my bad for using wrong terminology - I was more thinking of tags - finding/getting to them when you have the main element, but not necessarily a direct way to access it via ID or similar.
     
    PoPSiCLe, Mar 21, 2014 IP
  10. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #10
    Oh, also I don't mind daisy-chaining 'get' methods when searching for an element -- I just find it a confusing mess when you start daisy chaining "processing" operations, since those shouldn't be returning a handle... though daisy-chaining function results does run the risk of failing to have a handle in place should you have a negative result.

    That's something about a lot of frameworks that bugs me -- they spend so much time passing the framework as a result, you don't have anyplace to put a 'failure' condition and no way to trap failures for debugging purposes. Pretty much every function I have is going to return 0, -1, false or null for when something doesn't happen as expected, rather than returning the library as a result. Really that's the thing that bugs me about it most in jQ. It's bad enough they abstract everything to the point it prevents people from learning how to use the underlying language, but it makes debugging more difficult when something goes wrong.

    Javascript functions return the result or a false-type condition for a reason; developers could really learn from that example, and usually don't.
     
    deathshadow, Mar 21, 2014 IP
  11. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #11
    I just got the 'node' functions working. I've combined 'node' and 'tag' versions into single functions where the difference is what you pass for parameters. They all call this same internal function:
    function eS(e, m, t, n) {
    		if (t) {
    			if ((t = t.toUpperCase()) == 'TEXTNODE') {
    				while (e && (e.nodeType != 3)) e = e[m];
    			} else while (e && (e.tagName != t)) e = e[m];
    		} else while (e && (e.nodeType != 1)) {
    			if (n && e.nodeType == 3) break;
    			e = e[m];
    		}
    		return e ? _.extend(e) : null;
    	}
    
    Code (markup):
    'e' would be the originating element

    'm' is the 'method' used to search for the element (firstChild, nextSibling, prevSibling, etc)

    't' is a 'tagName' if desired

    'n' is a boolean for if textNodes's (nodeType 3) should be included.

    That makes the individual node functions very simple to implement.
    		a('nodeFirst', function(t, n) {
    			return eS(this.firstChild, 'nextSibling', t, n);
    		});
    
    		a('nodeLast', function(t, n) {
    			return eS(this.lastChild, 'previousSibling', t, n);
    		});
    
    		a('nodeNext', function(t, n) {
    			return eS(this.nextSibling, 'nextSibling', t, n);
    		});
    
    		a('nodePrev', function(t, n) {
    			return eS(this.prevSibling, 'previousSibling', t, n);
    		});
    
    Code (markup):
    't' again being the desired tagName (if any), 'n' being the boolean of whether or not to include textNodes, otherwise only elementNodes (type 1) will be included.

    *NOTE* the documentation for those will call them 'tagName' and 'includeTextNodes' and not 't' and 'n'. Shortnames are just for implementation.

    You'll notice that you can also pass it "TEXTNODE" as a tagName, that way you can search for textnodes.

    This is coming along nicely, though I'm a bit nervous about it already being at 10k and I've not implemented "get" or "make" yet. Still even with those it should come in at around 14k, giving me 2k of 'play room' on my target.
     
    Last edited: Mar 21, 2014
    deathshadow, Mar 21, 2014 IP
  12. AbstractChaos

    AbstractChaos Member

    Messages:
    58
    Likes Received:
    4
    Best Answers:
    4
    Trophy Points:
    25
    #12
    Hey deathshadow any progress on this?
     
    AbstractChaos, Mar 29, 2014 IP
  13. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #13
    I'm working on documentation right now, I like to have docs before I make anything public, even in the testing stage. I find writing the documentation helps me actually find bugs, pitfalls, and often think of new things to add or better ways of handling things.

    For example I've rewritten the AJAX handling method from scratch. _.ajax will accept an object you can fill with 'handler' functions -- like state_2, state_3, which would trigger on readyStateChanges, or status_200, status400, etc to be called when it hist readystate 4. That way you can blanket declare all your handlers in the first call. It's also going to be async only since synchronous Ajax usually either crashes the browser, makes the OS say the browser is "not responding" (which if you wait it resumes) or gives you the "script is taking too long" warning.

    Right now the codebase is sitting at 13.6k uncompressed, so I'm pretty close to done. I'm recycling a domain I was planning on using for something else, which is going to give it the name -- more on that when I actually launch the site which I'm hoping to do this coming week, but with my borderline health and well being I make no promises.

    Really though, the library is "done", it just needs documentation, demo's, and most important bugtesting. I have a very thorough way of doing each of those, and that's where the real 'gruntwork' of this project lies.

    Oh, and the next person I talk to about this who says use SVN or Git is going to get my boot so far up their arse we'll need to call an orthodontist to untie my laces from around their tonsils. Maybe it's because I wrote software for decades before there even were such things, but I've not ever worked on a project where versioning software wasn't a pointless waste of time that did more harm than good.
     
    deathshadow, Mar 29, 2014 IP
  14. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #14
    I'm not gonna say "use Git/Github" - but in this case I think it could actually be interesting, since it makes it very simple for people using Git to pull the repository and eventually fork it, if need arises (depending on whether or not you'd want that, of course). The point being, since you're solely responsible for the master branch, and can control who has access to doing anything with it, you'd avoid the mess of multiple contributors etc.
    I'm personally quite a fan of Github, as it makes the process of actually getting the things pulled directly to wherever they're supposed to go a bit simpler :D
     
    PoPSiCLe, Mar 30, 2014 IP
  15. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #15
    I think it's just another of those things I just don't get... I don't get the point of it, I find it needlessly and pointlessly convoluted, and I most certainly fail to get how it makes anything "simpler"; in the same way I fail to see how jQuery makes anything "simpler" or blueprint makes anything "simpler" or bootstrap makes anything "simpler" or HTML 5 making things "simpler"...

    [​IMG]

    To me that's a glittering generality; I fail to see how putting code on a website in that fashion or having software manage things for you has any benefits over "here's a zip file, you have a change send it to me so I can control what goes in". Anything else just reeks of "too many cooks" asshattery and sloppy project management skills. Admittedly, part of that could be my habit of using 1/10th the total code most people use to do the same tasks, and understanding why subdirectories in filesystems exist.

    Though again, my programming for some decade and a half before CVS was a twinkle in some shell script-kiddies eye and two and a half decades before it was practical enough for people to crap on real projects with could be a contributor to that attitude. Much like other (IMHO) idiotic halfwit dumbass re-re garbage like LESS, SASS, OOCSS and so forth, they are extra steps and more work you shouldn't need if you have ANY **** clue what you are doing! I just don't get how more steps and more code is "easier".

    Could also just be one of my mental blocks -- I've been programming for thirty-six years, having started out hand assembling RCA 1802 machine language and mastery of x86 machine language --- and I still no matter how many times I try cannot grasp just how the **** visual programming is even supposed to work as it's more of a jumbled mess of unrelated snippets than the peak of what people were crapping out using line numbered BASIC spaghetti code.

    But there's a lot of stuff that makes me scratch my head that programmers say and do that just don't make any sense if you understand the topic -- see the XML wankers who call it "machine readable", the lie that C works more like machine language than line numbered BASIC (it's the other way around actually!), people thinking putting unique CSS inline in the markup is better for caching, or scripttards who seem to think throwing more code at a flat website in the form of "AJAX as framesets" can make their fat bloated poorly coded monstrosities somehow faster.

    Or it could just be the last time I was helping with a project that was on GitHub everyone was spending more time dicking with GitHub's nonsense than they were actually writing code!
     
    Last edited: Mar 30, 2014
    deathshadow, Mar 30, 2014 IP
  16. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #16
    Simpler, as in "I don't have to go to a website, download a file, upload a file, unpack a file (or, if you prefer, switch those two around) etc."
    If I'm using something someone else is working on, and there's an update, I run a shell, and do a git pull - simple and fast. And, if for some reason there's an unknown bug, something that I've tweaked that the new code breaks, a simple git revert <whatevercommitID> will fix that. No need to keep a lot of different files, copy, backup etc. (apart from the regular backups, that is) - it's _easier_ but not necessarily better in any way :)
    And, of course, since I'm often doing this as part of a very small group of devs, maybe 2-3 at most, it's not really all that big a deal to fix mistakes, if they happen.
     
    PoPSiCLe, Mar 31, 2014 IP
  17. AbstractChaos

    AbstractChaos Member

    Messages:
    58
    Likes Received:
    4
    Best Answers:
    4
    Trophy Points:
    25
    #17
    GitHub and other source control systems are useful if there are many developers working on a project.

    My job entails working on a large web application (Using GWT) which has well over a thousand class files, when a applications gets to that size there is a need to keep track of what has been changed, when and by who.
    However for a javascript "not a framework" which I would expect to have very small amount if not just one file and is only really modified by deathshadow I can see how it would become more trouble than its worth to use any sort of version control.
     
    AbstractChaos, Mar 31, 2014 IP
  18. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #18
    ... and that's probably the difference right there, since I'm of the opinion that when something gets that large it's time to put a bullet in it -- to be fair I sit in wonder at how forums and website handling a handful (respectively) of users typically chokes quad core 4 gig Xeon's to death when I used to move more data around on a 486 DX/50 (real DX, 50mhz FSB) to several thousand users in realtime using Netware 3.12 -- many of those users BOOTING their OS from the server... So it is indeed a matter of perspective. Admittedly my bread and butter in the '00's was taking websites that were choking massive servers to death and cutting them down to run smoothly on half or even a quarter the hardware.

    Whenever I hear of projects that large I sit in wonder going "FOR WHAT?!?" -- I mean, it's a web crapplet; what the blue blazes are you doing that would make it that large?

    Admittedly, I say the same thing about turdpress, where if I put my mind to it and buckled down, I could probably replicate the functionality of (plugging the massive gaping design flaws in the process) and still fit it uncompressed on a 360k floppy.

    Now I'm not saying the vast majority of current crapplications are fat bloated steaming train wrecks of idiocy that are ten to twenty times larger than they should be... OH WAIT, no, That's EXACTLY what I'm saying. But of course, nobody cares because they can always just throw more hardware at the problem :p

    It's exactly that type of bloated coding that has me building this library in the first place. People doing things in two to four times the code with a framework than it takes me without a framework.
     
    Last edited: Apr 2, 2014
    deathshadow, Apr 2, 2014 IP
  19. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #19
    Oh, and for an example of what I mean by more code with the framework, take this very nice, very clean looking progress bar that relies on jQuery crap:
    https://forums.digitalpoint.com/threads/nprogress-slim-progress-bar.2711270/

    He's got 5k of js (once you strip comments), 1.2k of CSS ... AND it requires a library. The animation is jerky because it's done by jQuery and timer based ops.... I made a standalone workalike that's 3.2k of js and 2.4k of CSS -- admittedly it needs CSS3 to function 'fully' but it does gracefully degrade, doesn't need some massive library to function, and converted to my new lbrary, it's going to only be 1.6k of scripting that looks a little something like this:

    var jProgress = {
    
    	value : 0,
    	minPercent : 1,
    	timerHandler : false,
    	timerInc : 0,
    	wrapper : _.make('.jProgress.jProgressHide', 0, 0, _d.body),
    	
    	start : function(at) {
    		this.setPercent(at ? at : this.minPercent);
    	},
    	
    	setPercent : function(at, noShow) {
    		if (!noShow) this.wrapper.classSwap('jProgressHide', 'jProgressShow');
    		this.value = at;
    		if (this.value < 0) this.value = 0;
    		if (this.value >= 100) this.done();
    			else this.bar.style.width = this.value + '%';
    	},
    	
    	setFractional : function(at) {
    		this.setPercent(at * 100);
    	},
    	
    	addPercent : function(amount) {
    		this.setPercent(this.value + amount);
    	},
    	
    	addFractional : function(amount) {
    		this.setPercent(this.value + amount * 100);
    	},
    	
    	auto : function(amount) {
    		this.wrapper.classAdd('jProgressAuto');
    		this.timerInc = amount;
    		if (!this.timerHandler) this.timerHandler = setInterval(function() {
    			jProgress.addPercent(jProgress.timerInc);
    		}, 290);
    	},
    	
    	autoStop : function() {
    		this.wrapper.classRemove('jProgressAuto');
    		if (this.timerHandler) {
    			clearInterval(this.timerHandler);
    			this.timerHandler = false;
    		}
    	},
    	
    	done : function() {
    		this.value = 100;
    		this.bar.style.width = '100%';
    		this.autoStop();
    		setTimeout(function() {
    			jProgress.wrapper.classSwap('jProgressShow', 'jProgressHide');
    			setTimeout(function() { jProgress.setPercent(0, true); }, 500);
    		}, 333);
    	}
    	
    };
    
    // you can't reference itself when using instancing
    jProgress.bar = _.make('.jProgressBar', 0, 0, jProgress.wrapper);
    
    // generated content doesn't frame-animate properly :(
    _.make('.jProgressSpinner', 0, 0, jProgress.wrapper);
    Code (markup):
    Since again, with CSS3 the only thing needed for animations, fades, slides, etc, is to just do a class swap and MAYBE positioning/sizing. Sad part is that last _.make shouldn't be necessary apart from a lot of CSS3 not liking generated content just yet.

    YES, that is going to be one of the demo's... YES I am going to back-link to the original because I like the guy's idea, just not the implementation. Half tempted to make "fingerman" one of the demo's too.
     
    deathshadow, Apr 2, 2014 IP
  20. deathshadow

    deathshadow Acclaimed Member

    Messages:
    9,732
    Likes Received:
    1,998
    Best Answers:
    253
    Trophy Points:
    515
    #20
    Wow, I feel like a twit... That last _.make can be moved into .wrapper's declaration since it's a APO element; sort order doesn't matter.

    	wrapper : _.make('.jProgress.jProgressHide', _.make('.jProgressSpinner'), 0, _d.body),
    Code (markup):
    Declare it as a child rather than passing the parent. Duh... Say hello to 1.56k
     
    deathshadow, Apr 2, 2014 IP