PageSourceSearch

https://www.projectnextsteps.nl/vendor/yellow/Yellow.js

js projectnextsteps.nl collected 2026-09-25 09:09:58 UTC 26,700 bytes, 954 lines download raw bytes

1/**
2 * Yellow
3 * enrich html with javascript in a clean, non-complicated way
4 * Yellow uses jquery, so include that before Yellow. Config is done through data- attributes
5 * 
6 * Example usage
7 * -------------
8 * <script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
9 * <script 
10 * 	 type="text/javascript" 
11 * 	 src="vendor/yellow/Yellow.js"
12 * 	 data-main="js/build/build.js" <!-- Location to load built script from -->
13 * 	 data-src="js/"	 <!-- Location to load scripts from when they are not included -->
14 * 	 data-console="1"  <!-- Whether output should be sent to the console with y.log -->
15 * ></script>
16 * 
17 * 
18 * 
19 * The following steps are taken on startup
20 * 1. The url provided in data-main is loaded 
21 * 2. The document is scanned for html elements that have attribute y-use
22 * 3. Scripts are loaded for all space separated paths that are provided in these html-elements under y-use="path path path"
23 * 4. For all elements a definition-instance is created for each provided path
24 * 5. the 'start' function is called on all instances
25 * 
26 * 
27 * HTML example snippet
28 * --------------------
29 * <div y-use="people.List">
30 *     <span y-name="header">This is a list</span>
31 * </div>
32 * 
33 * Script example snippet
34 * ----------------------
35 * define('people.List') // Create e definition under the same name
36 * .use('people.Helper') // Use some other script.
37 * .use('http://libary', 'globalname') // Use some vendor script. When it registers as a global, pass along the name of the global
38 * .as(function(y, helper, external){ // The class that is used for the elemens
39 *	this.start = function(scope){ // init function receives jQuery(element) (scope)
40 *	
41 *	}
42 * });
43 * 
44 * Templates can be defined in two places: In the html or in the definition.
45 * 
46 * HTMl template definition:
47 * ------------------------
48 * <div y-use="people.List">
49 *      <script type="text/html" y-name="person.html">
50 *			<div>
51 *				<span>{{firstname}}</span><br />
52 *				<span>{{lastname}}</span>
53 *			</div>
54 *		</script>
55 * </div>
56 * 
57 * 
58 * Script template definition
59 * When a tempalte is defined in the componenet, the second argument will be a template function
60 * to access the defined tempaltes
61 * --------------------------
62 * define('people.List')
63 * .template('person.script' , '\
64 * <div>\
65 *		<span>{{firstname}}</span><br />\
66 *		<span>{{lastname}}</span>
67 * </div>')
68 * .as(function(y, template){ 
69 *	this.init = function(scope){
70 *		y.log(scope.template('person.html'));
71 *		y.log(template('person.script'));
72 *	}
73 * });
74 * 
75 */
76(function(document, window, jQuery)
77{
78	/**
79	 * Get executing (this) script node
80	 * use currentScript for everythis but IE11: fall back on last script for IE
81	 */
82	var script =  document.currentScript ? jQuery(document.currentScript) : script = jQuery('script').last();
83	
84	/**
85	 * Config object that gets it's vars from the script html attributes
86	 * @type Object
87	 */
88	var __config = {
89		define: script.data('define') || 'define',
90		main: script.data('main') || false,
91		src: script.data('src') || '',
92		console: script.data('console') || false
93	};
94	
95	
96	/**
97	 * The public yellow object that will be available in the global namespace
98	 * under the configured name
99	 * Call it with a html element as argument and a jQuery wrapped element will be returned
100	 * Loaded script will use the global object to call define() to register themselves
101	 * Also helper functions like is[Type](), outer() and log()
102	 * 
103	 * @type Object
104	 */
105	var __public = function(element) {
106		return jQuery(element);
107	};
108	
109	
110	/**
111	 * Add Yellow helpers to jQuery
112	 * start: start up an element
113	 * element: get an element with y-name="name"
114	 */
115	jQuery.fn.extend({
116		
117		/**
118		 * attach a definition-instance to an alement, so it can be used to call invoke
119		 */
120		attach: function(instance){
121			// get domnode
122			var node = this[0];
123			// add array with attached instances to the htmlnode
124			if(!__public.isSet(node.instances)){
125				node.instances = [];
126			}		
127			// add the instance to the used instances array on the node
128			node.instances.push(instance);
129			//chainable
130			return this;
131		},
132		
133		/**
134		* Start up a portion of a document
135		* @returns void
136		*/
137		start: function(handlers){
138			// alias for this
139			var scope = this;
140			
141			// add events on elements in scope and scope itself
142			var emitters = scope.find('[y-on]');
143			if(scope.attr('y-on')) {
144				emitters = emitters.add(scope);
145			}
146			emitters.each(function(){
147				// attribute has the form:  click touchstart|stop:dosomething(1) ~ mouseover|stop:dosomethingelse(1 + 4)
148				var emitter = jQuery(this);
149				var attr = emitter.attr('y-on');
150				emitter.removeAttr('y-on');
151				var statements = attr.split('~');
152				for(var i = 0; i < statements.length; i++) {
153					// add handler
154					emitter.handler(statements[i], handlers);
155				}
156			});
157				
158			// get named elements from scope and scope itself
159			// so we can save the original html and make a fresh copy later
160			var named = scope.find('[y-name]');
161			if(scope.attr('y-name')) {
162				named = named.add(scope);
163			}
164			
165			named.each(function(){				
166				// save the original html, so we can make a fresh copy later
167				this.__html = this.outerHTML;
168			});
169
170			// get elements from scope and scope itself
171			var use = scope.find('[y-use]');
172			if(scope.attr('y-use')) {
173				use = use.add(scope);
174			}
175			
176			// the elements by definition path
177			var elements = {};
178			use.each(function(){
179				// save the original html, so we can make a fresh copy later
180				this.__html = this.outerHTML;
181				// the element
182				var element = jQuery(this);
183				// get used paths: spaceseparated names
184				var paths = element.attr('y-use').split(' ');
185				for(var i = 0; i < paths.length; i++){
186					var path = paths[i].trim();
187					if(path.length > 0){
188						// if it doesnt exist, create an array for it
189						if(!__public.isSet(elements[path])){
190							elements[path] = [];
191						}
192						// add to the instances dictionary
193						elements[path].push(element);
194						// add it to the used definitions list
195						__loader.add(path);
196					}
197				}	
198			});
199
200			// Tell loader to process the queue
201			// and pass a callback function
202			__loader.process(function(){
203				// loader queue has resolved: 
204				// create an instance for each used definition
205				// call start on all instances after instantiatiion
206				var instances = [];
207				
208				for(var path in elements){
209					// get the definition
210					var definition = __public.get(path);
211					// check if it exists
212					if(!definition){
213						throw new Error('Unknown definition: ' + path + '. ')
214					}
215					// make an instance for all the elements with this name
216					for(var i = 0; i < elements[path].length; i++){
217						// get element
218						var element = elements[path][i];
219						// create instance 
220						var instance = definition.__instance();
221						// attach the definition to the instance so it is invovakable
222						element.attach(instance);
223									
224						// keep track of all the instance / element pairs, so they can be started later
225						instances.push({
226							instance: instance,
227							element: element
228						});
229					}
230				}
231				// start all the instances at once
232				// if one instance calls invoke on another, this way they will at least all be created at that moment
233				// if invoke was called before __init (and therefore before start()), the invoke method will take care of that
234				for(var j = 0; j < instances.length; j++){
235					instances[j].instance.__init( instances[j].element );
236				}
237			});
238					
239			// chainable
240			return scope;
241		},
242		
243		
244		/**
245		 * Add an eventhandler
246		 * Will use methods in handler, but will also look at all exposed methods in attached instances up to body
247		 * And call the all.
248		 * Unless the stop filter is given
249		 * 
250		 * @param string statement of the form  click touchstart|stop:dosomething(1) or click touchstart|stop:dosomething
251		 * @param object handlers named callbacks that can be referenced in the expression
252		 */
253		handler: function(statement, handlers) {
254			// the element that receives the event
255			var scope = this;
256			
257			// retreive the correct parts from the statement
258			var parts = statement.split(':');
259			var event = parts[0];
260			var filters = event.split('|');
261			event = filters.shift();
262			var expression = __public.isSet(parts[1]) ? parts[1].trim().replace(/\$e/g, 'e').replace(/\$this/g, '__public(scope)') : '';
263			var handler = expression.split('(')[0].trim();
264			
265			// make sure handlers is an object
266			if(! __public.isObject(handlers)) {
267				handlers = {};
268			}
269			
270			// normalize filters
271			var stop = false;
272			var prevent = false;
273			for(var i = 0; i < filters.length; i++){
274				if(filters[i] === 'stop'){
275					stop = true;
276				}
277				if(filters[i] === 'prevent'){
278					prevent = true;
279				}
280			}
281			
282			// finally, register the event
283			scope.on(event, function(e){
284				// use filters
285				if(stop){
286					e.stopPropagation();
287				}
288				if(prevent){
289					e.preventDefault();
290				}
291
292				// try to find a function to use as callback
293				var fn = null;
294				if(__public.isFunction(handlers[handler])) {
295					// function is given in the provided handlers
296					fn = handlers[handler];
297				} else {
298					// function not given, traverse up to find a usable function in y-use instances
299					var receiver = scope.parents('[y-use]');
300					while(receiver.length > 0 && fn === null) {
301						if(__public.isArray(receiver[0].instances)) {
302							var instances = receiver[0].instances;
303							for(var i = 0; i < instances.length; i++){
304								if(__public.isFunction(instances[i][handler])){
305									fn = instances[i][handler];
306									break;
307								}
308							}
309						}
310						receiver = receiver.parents('[y-use]');
311					}
312				}
313				if(__public.isFunction(fn)) {
314					if(handler !== expression) {
315						(function(___fn___) {
316							eval ('var ' + handler + ' = ___fn___; ' + expression + ';');
317						})(fn);
318					} else {
319						fn.call(scope, e);
320					}
321				}
322			});
323		},
324		
325		
326		/**
327		 * Get a html element with y-name attribute
328		 * @param string name
329		 * @param string method jquery method to use instead of 'find'
330		 * @returns element
331		 */
332		fetch: function(name, method) {
333			if(! __public.isSet(name)){
334				var found  = this.find('[y-name]:not(script)');
335				
336				var elements = {};
337				found.each(function(index, element){
338					element = jQuery(element);
339					var names = element.attr('y-name').split(' ');
340					for(var i = 0; i < names.length; i++) {
341						if(__public.isSet(elements[names[i]])) {
342							// add to jquery resultset
343							elements[names[i]] = elements[names[i]].add(element);
344						} else {
345							// add jquery element
346							elements[names[i]] = element;
347						}
348					}
349				});
350				
351				return elements;
352			} else {
353				if(! __public.isSet(method)){
354					method = 'find';
355				}
356				return this[method]('[y-name~="' + name + '"]:not(script)');
357			}
358			
359		},
360		
361
362		/**
363		 * Call a method on an element that has a Yellow component instance tied to it
364		 * In case of multiple components, the first available method with the name will be called and that's it.
365		 * @param string method
366		 * @returns mixed
367		 */
368		invoke : function(method){
369			// get the real dom element, as the used array is attached there
370			var node = this[0];
371			// check if it exists and if there is a 'used' array
372			if(__public.isSet(this[0]) && __public.isArray(this[0].instances)){
373				// check on all the used instances if there are 
374				for(var i = 0; i < node.instances.length; i++){
375					// check is there is a method with the supplied name
376					if(__public.isFunction(node.instances[i][method])){
377						var instance = node.instances[i];
378						// call __init first, just to be sure. If it was called before, that's ok, as init will only run once
379						// the argument is the element
380						instance.__init(this);
381						// shift the first argument (the method name)
382						var args = Array.prototype.slice.call(arguments);
383						args.shift();
384						// call the method with the remaining arguments
385						return instance[method].apply(instance, args);
386					}
387				}
388			}
389		},
390		
391		
392		/**
393		 * Get a html contents of a script with the name y-[name]
394		 * @param String name
395		 * @returns string
396		 */
397		template: function(name){
398			return this.find('script[y-name~="'+name+'"]').html();	
399		},
400		
401		
402		/**
403		 * Create a copy of an element
404		 * @param Booelan start If true is passed, the element will be started automatically
405		 */
406		make: function(start)
407		{
408			if(this[0].__html) {
409				var element = __public(this[0].__html);
410			} else {
411				var element = __public(this[0].outerHTML);
412			}
413			if(start) {
414				element.start();
415			}
416			return element;
417		}
418	});
419	
420	
421
422	/**
423	 * Properties that will be copied over to the __public object
424	 * we could have writen this as __public.prop = ..., but this is shorter
425	 * Will be removed after copying
426	 * @type Object
427	 */
428	var properties = {
429		/**
430		 * Globals
431		 */
432		document: jQuery(document),
433		window: jQuery(window),
434		script: script,
435		jQuery: jQuery,
436		
437		/**
438		 * Definitions
439		 */
440		definitions: {},
441		
442		/**
443		 * Create a definition and set it
444		 * returns a creator object that can be used to further fill in the definition
445		 * @param string path
446		 * @returns Object
447		 */
448		define: function(path){
449			// create a new definition
450			var definition = new __Definition();
451			// store it
452			__public.set(path, definition);
453			// let the loader know this path was loaded and resolve it.
454			// this is used when we load a prcompiled buncle of scripts
455			__loader.resolve(path);
456			// return definition creator to chain additional commands
457			return definition.creator;
458		},
459		
460		/**
461		 * Set a definition
462		 * @param string path
463		 * @param Object definition
464		 * @returns void
465		 */
466		set: function(path, definition) {
467			// check if name is ok
468			if(!__public.isString(path) || ! /^[a-zA-Z0-9\-_\.\:]+$/.test(path)){
469				throw new Error('Trying to define without a valid name: ' + path);
470			}
471			if(__public.isSet(__public.definitions[path])){
472				__public.log('Redefining previously defined ' + path);
473			}
474			__public.definitions[path] = definition;
475		},
476		
477		/**
478		 * Get a definition
479		 * @param string path
480		 * @returns Object
481		 */
482		get: function(path) {
483			if(__public.isSet(__public.definitions[path])) {
484				return __public.definitions[path];
485			}
486		},
487		
488		
489		/**
490		 * Run a definition
491		 * @param string path
492		 * @returns {undefined}
493		 */
494		run: function(path) {
495			// add the path to the loader
496			__loader.add(path);
497			// process the queue
498			__loader.process(function(){
499				// get the definition
500				var definition = __public.get(path);
501				// check if it exists
502				if(!definition){
503					throw new Error('Unknown definition: ' + path + '. ')
504				}
505				// create instance
506				var instance = definition.__instance();
507				// get extra arguments passed to run
508				var args = Array.prototype.slice.call(arguments);
509				args.shift();
510				// call the __init method with the remaining arguments and return the result
511				instance.__init.apply(instance, args);
512			});
513		},
514		
515		
516		/**
517		 * Get outer yellow instance
518		 * @returns {window}
519		 */
520		outer: function() {
521			var traverse = window;
522			var outer = window;
523			// walk through parents to find outermost window with yellow defined
524			// if one is found, use that as yellow
525			while(traverse.parent.location !== traverse.location){
526				traverse = traverse.parent;
527				if(traverse.globalYellowInstance !== null){
528					outer = traverse;
529				}
530			}
531			return outer.globalYellowInstance;
532		},
533		
534		/**
535		* Testers for value type
536		*/
537		isString: function(mixed) {
538			return this.isType(mixed,'[object String]');
539		},
540		isArray: function(mixed){
541			return this.isType(mixed,'[object Array]');
542		},
543		isPlainObject: function(mixed){	
544			if (typeof mixed == 'object' && mixed !== null) {
545				if (typeof Object.getPrototypeOf == 'function') {
546					var proto = Object.getPrototypeOf(mixed);
547					return proto === Object.prototype || proto === null;
548				}
549				return Object.prototype.toString.call(mixed) == '[object Object]';
550			}
551			return false;
552		},
553		isObject: function(mixed){
554			if(this.isSet(mixed) === false){
555				return false;
556			} else {
557				return this.isType(mixed,'[object Object]');
558			}
559		},
560		isFunction: function(mixed){
561			return this.isType(mixed,'[object Function]');
562		},
563		isNumeric: function(mixed){
564			return !isNaN(mixed);
565		},
566		isNumber: function(mixed){
567			return this.isType(mixed,'[object Number]');
568		},
569		isInt: function(mixed){
570			return !isNaN(parseInt(mixed,10)) && (parseFloat(mixed,10) === parseInt(mixed,10));
571		},
572		isFloat: function(mixed){
573			return this.isNumber(mixed) === true && this.isInt(mixed) === false;
574		},
575		isSet: function(mixed){
576			return !(typeof mixed === 'undefined' || mixed === null);
577		},
578		isNull: function(mixed){
579			return mixed === null;
580		},
581		isType: function(mixed, type) {
582			return Object.prototype.toString.call( mixed ) === type;
583		},
584
585	   	/**
586		* Helper: log a variable to console
587		* @param {mixed} variable
588		* @returns {void}
589		*/
590	   log: function(variable, showLineNr) {
591		   if(__config.console && window.console && window.console.log){
592			    window.console.log(variable);
593			   if(showLineNr !== false){
594				   var error = new Error();
595				   if(error.stack){
596					    window.console.log(error.stack.split("\n")[2]);
597				   }
598			   }
599		   }
600	   },
601	   ajax: jQuery.ajax
602	};
603	
604	// copy over the properties to yellow and remove var
605	for(var name in properties){
606		__public[name] = properties[name];
607	}
608	properties = null;
609
610
611	/**
612	 * Loader object that loads scripts
613	 */
614	var __loader = {
615		
616		// the queue that holds paths that should be loaded
617		queue: [],
618		
619		// object that holds paths that are still loading
620		pending: {},
621		
622		// object that holds loaded paths
623		loaded: {},
624		
625		/**
626		 * load a single script from an url, call done when done
627		 * @param string url
628		 * @param function done
629		 * @returns void
630		 */
631		load: function(url, done){
632			// create script tag to load the script
633			var parent = document.getElementsByTagName('body')[0];
634			var script = document.createElement('script');
635			script.src = url;
636			script.setAttribute('async', false);
637			// callback for the script load
638			var callback = function(result){
639				//help garbage collection
640				script.onload = null;
641				script.onerror = null;
642				script.onreadystatechange = null;
643				script.ontimeout = null;
644				parent.removeChild(script);
645				// call callbacks
646				if(__public.isFunction(done)){
647					done(result);
648				}
649			};
650			// add callback
651			if(script.addEventListener){
652				// Modern browsers
653				script.onload = function(){
654					callback('done');
655				};
656				script.onerror = function(){
657					callback('fail');
658				};
659			} else if(script.readyState) {
660				// IE 8-
661				script.onreadystatechange = function(){
662					if(script.readyState == 'loaded' || script.readyState == 'complete'){
663						callback('done');
664					}
665				};
666				script.ontimeout = function(){
667					callback('fail');
668				};
669			}
670			// add script to the page to start loading
671			parent.appendChild(script);
672		},
673		
674		/**
675		 * Add a path to the queue
676		 * 
677		 * @param string path
678		 * @param string globalName when using an extrernal library, there will probably be a global var available to use
679		 * @returns void
680		 */
681		add: function(path){
682			__loader.queue.push(path);
683		},
684		
685		/**
686		 * Process the queue
687		 * @param function done
688		 * @returns void
689		 */
690		process: function(done){
691			// load elements still in the queue
692			while(__loader.queue.length > 0) {
693				var path = __loader.queue.shift();
694				if(! __loader.loaded[path] && ! __loader.pending[path]){
695					
696					// start loading: add this element to the pending scripts
697					__loader.pending[path] = true;
698					if(path.indexOf('http://') === 0 || path.indexOf('https://') === 0 || path.indexOf('//') === 0){
699						// absolute url given
700						var src = path;
701					} else {
702						// dotted path given: create a url
703						var src = __config.src + path.split('.').join('/') + '.js'
704					}
705		
706					// go get it
707					__loader.load(src, (function(p){
708						return function(result) {
709							if(result === 'fail') {
710								throw new Error('Failed to load script: ' + p);
711							}
712							// resolve path
713							__loader.resolve(p);
714
715							// try processing the loader again
716							__loader.process(done);
717						};
718					})(path));
719				} else if(__loader.loaded[path]) {
720					// path was already loaded before: resolve it.
721					__loader.resolve(path);
722				}
723			}
724			
725			// check if there are pending files
726			var pending = false;
727			for(var i in __loader.pending){
728				if(__loader.pending[i] === true){
729					pending = true;
730					break;
731				}
732			}
733			
734			// no pending files: callback!
735			if(! pending) {
736				done();
737			}
738		},
739		
740		/**
741		 * Remove a path from pending and add it to loaded
742		 * @param {type} path
743		 * @returns {undefined}
744		 */
745		resolve: function(path){
746			// remove this path from pending
747			delete __loader.pending[path];
748			// set it to loaded instead, so we dont load it twice.
749			__loader.loaded[path] = true;
750		}
751	};
752
753
754	/**
755	 * A definition instance contains an object called 'creator'
756	 * When __public.define is called, a new definition is created and the creator object is returned.
757	 * A creator object is used to add dependencies, templates, and static properties to the definition
758	 * Lastly the .as function should be called to finalize the definition.
759	 * 
760	 * When a the argument for 'as' is a function, a call to .make will reutn a new instance of the function
761	 * after that, the 'init' function will be called on the new instance, if available with the supplied argumens
762	 * 
763	 * @returns Object
764	 */
765	var __Definition = function()
766	{
767		// array with dependencies to load
768		var _use = [];
769		
770		// templates
771		var _templates = {};
772		
773		// the public definition
774		// only contains a make function
775		// but will receive additional properties while defining 
776		var _definition = {
777			
778			// this yellow object for use in static definitions as this.yellow or this.y
779			y: __public,
780			yellow: __public,
781			
782			// make templates available in defintitions as this.template()
783			template: function(name){
784				if(__public.isSet(_templates[name])){
785					return _templates[name];
786				}
787			},
788			
789			/**
790			 * Set of creator functions that allow modules to define themselves
791			 */
792			creator: {
793				
794				/**
795				* set dependencies
796				*/
797				use: function(path, globalName) {
798					// add it to the use array
799					_use.push([path, globalName]);
800					// chainable
801					return this;
802				},
803				
804				/**
805				* Set static vars & methods
806				*/
807				set: function(object) {
808					if(! __public.isObject(object)){
809						// check if static data is valid
810						throw  new Error('Trying to set invalid data: ' + object);
811						return;
812					}
813					// copy over properties
814					for(var i in object){
815						_definition[i] = object[i];
816					}
817					// chainable
818					return this;
819				},
820				
821				
822				/**
823				* Set template 
824				*/
825				template: function(name, template) {
826					// store template under name
827					_templates[name] = template;
828					// chainable
829					return this;
830				},
831			
832				/**
833				* This is the closing call for a definition
834				* Either pass an object with additional properties or a constructor function
835				* no extra calls, so not chainable
836				* Cleanup & load dependencies afterwards
837				*/
838				as: function(definition) {
839					
840					if(__public.isFunction(definition)){
841						// create an __instance method to create an instance
842						_definition.__instance = function() {
843							// variable arguments for constructor.
844							// always start with yellow
845							var args = [null, __public];
846							
847							// add dependencies
848							for(var i = 0; i < _use.length; i++){
849								if(__public.isString(_use[i][1])){
850									// a global name was given: 
851									// this is a vendor file that registers under a global name
852									args.push(window[_use[i][1]]);
853								} else {
854									args.push(__public.get(_use[i][0]));
855								}
856							}
857							
858							// add template function if there are templates
859							if(Object.keys(_templates).length > 0){
860								args.push(_definition.template)
861							}
862							
863							// add the defintion itself as last argument, so we have access to static vars
864							args.push(_definition);
865							
866							
867							// create instance with variable arguments
868							// check StackOverflow for how this works
869							var instance = new (Function.prototype.bind.apply(definition, args));
870							
871							// add init function that calls start and cleans up start itself
872							instance.__init = function() {
873								if(__public.isFunction(instance.start)){
874									// get the function
875									var fn = instance.start;
876									// start can only run once. so remove it
877									instance.start = null;
878									// pass along arguments that were given to __init()
879									fn.apply(instance, arguments);
880								}
881							};
882							
883							return instance;
884						};
885						
886						// convenient shortcut to call __instantiate() and __init() in order
887						_definition.make = function() {
888							// create instance
889							var instance = _definition.__instance();
890							// pass along arguments that were given to make()
891							instance.__init.apply(null, arguments);
892							// return it
893							return instance;
894						};
895						
896					} else if(__public.isObject(definition)){
897						// copy over extra stuff from definition to _definition
898						for(var i in definition){
899							_definition[i] = definition[i];
900						}
901					} else {
902						// error
903						throw new Error('Trying to define without a valid constructor or object');
904					}
905
906					// remove creator object
907					delete _definition.creator;
908					
909					// load dependencies defined in 'use'
910					// by adding the to the loader queue
911					for(var i = 0; i < _use.length; i++){
912						__loader.add(_use[i][0], _use[i][1]);
913					}
914					
915					// make define.as. chainable
916					return __public;
917				}
918			}
919		};
920		return _definition;
921	};
922	
923
924	// make a public define function that calls __public.define
925	window.globalYellowInstance = __public;
926	window[__config.define] = function(name){
927		return __public.define(name)
928	};
929	
930	// error handler
931	window.addEventListener('error', function (e) {
932		e.preventDefault();
933		var message = ''+e.filename+':' + e.lineno + ': ' + e.message;
934		__public.log(message, false);
935	});
936
937
938	if(__config.main){
939		// load main if one was given
940		__loader.load(__config.main, function(){
941			// when done, process the dependencies set by main
942			__loader.process(function(){
943				// when that is done, start app with document as the scope 
944				__public(document).start();
945			});
946		});
947	} else {
948		// just start it, when no main was given
949		__public(document).start();
950	}
951	
952	// make chainable
953	return __public;
954})(document, window, jQuery)

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.