PageSourceSearch

https://rydeliverpool.co.uk/_jsapps/inspector/inspector-1.0.js

js rydeliverpool.co.uk collected 2026-10-05 05:59:47 UTC 88,864 bytes, 3,682 lines download raw bytes

1/**
2 *  Cargo CSS Inspector
3 *	For use with all gen 1 designs
4 * 
5 *  © Cargo 2011-2012
6 */ 
7 
8var CssSyntaxEditor = "",
9
10	HtmlSyntaxEditor = "",
11	
12 	InspectOutline = "1px dotted #f09";
13
14
15/**
16 *  CSS object
17 *  Contains methods for setting and getting classes
18 */
19if (typeof (CSS) === "undefined") {
20	CSS = {};
21}
22
23
24if (typeof (Inspector) === "undefined") {
25	Inspector = {};
26}
27
28/**
29 *  #########################################################################################################
30 *  Create an object for finding and setting the CSS classes
31 *  Methods for returning a single class, as well as 
32 *  searching for any 
33 *  #########################################################################################################
34 */
35/* !CSS.Classes */
36CSS.Classes = {
37		
38		/*
39		 *  Add all original classes here
40		 *  Static CSS classes
41		 *  Contains the entire contents of the original sheet
42		 *  eg:
43		 *  Original = Array(
44		 *  	[0] = {
45		 *  		"selector"  : "body",
46		 *  		"class"		: "body { font-size: 12px; }"
47		 *  	}
48		 *  );
49		 */
50		"Original" : [ ],
51		
52		/*
53		 *  Add all preview classes here
54		 *  Dynamic CSS classes
55		 *  Contains the entire contents of the modified sheet
56		 *  eg:
57		 *  Preview = Array(
58		 *  	[0] = {
59		 *  		"selector"  : "body",
60		 *  		"class"		: "body { font-size: 12px; }"
61		 *  	}
62		 *  );
63		 */
64		"Preview" : [ ],
65		
66		/*
67		 *  Add all drilled classes here
68		 *  Contains the contents of the drilled classes
69		 */
70		"Drilled" : [ ],
71		
72		/*
73		 *  Add all related classes here
74		 *  Contains the entire contents of the modified sheet
75		 */
76		"Related" : [ ],
77		
78		/*
79		 *  Active classes are anything that is inside the code editor
80		 */
81		"Active" : [ ],
82		
83		/*
84		 *  Keeps a list of modified class ids when previewing to prevent overlap
85		 */
86		"ModifiedList" : [ ],
87		
88		/*
89		 *  Keeps a list of active class ids when previewing to prevent overlap
90		 */
91		"ActiveList" : [ ],
92		
93		/*
94		 *  Add all transitional classes here
95		 *  Any non-class variable
96		 *  CSS.Classes.Get("Transitional", "drilled_classes")
97		 */
98		"Transitional" : { 
99			"dom_chain"			: { },	// The full dom chain as returned from ReturnCssChain
100			"css_is_modified" 	: "",	// true || false
101			"delay"				: "",	// delay for live preview
102			"delay_timer" 		: ""	// timeout for live preview delay
103			
104		},
105		
106		/**
107		 *  Interceptions
108		 *  This grouping is for classes that will show ONLY the listed classes
109		 *  Each element is separated by class name, Drilled and Related
110		 *  Related elements always include the drilled elements, no need to repeat
111		 *  A * in a class indicates grabbing any element containing this name
112		 */
113		 /* !Interceptions */
114		"Interceptions" : {
115			
116			/*
117			 *  Main elements
118			 */
119			"body" : {
120				"Drilled" : Array(
121					"body"
122				), 
123				"Related" : Array(
124					"body, html"
125				)
126			},
127			
128			".webkit" : {
129				"Drilled" : Array(
130					"body"
131				), 
132				"Related" : Array(
133					"body, html"
134				)
135			},
136			
137			".header_img" : {
138				"Drilled" : Array(
139					".header_img",
140					"#header"
141				), 
142				"Related" : Array(
143					"body"
144				)
145			},
146			
147			"#header" : {
148				"Drilled" : Array(
149					"#header",
150					".header_img"
151				), 
152				"Related" : Array(
153					"body"
154				)
155			},
156			
157			/*
158			 *  Main tags
159			 */
160			"h1" : {
161				"Drilled" : Array(
162					"h1"
163				), 
164				"Related" : Array(
165					"body"
166				)
167			},
168			
169			"h2" : {
170				"Drilled" : Array(
171					"h2"
172				), 
173				"Related" : Array(
174					"body"
175				)
176			},
177			
178			"h3" : {
179				"Drilled" : Array(
180					"h3"
181				), 
182				"Related" : Array(
183					"body"
184				)
185			},
186			
187			"h4" : {
188				"Drilled" : Array(
189					"h4"
190				), 
191				"Related" : Array(
192					"body"
193				)
194			},
195			
196			"blockquote" : {
197				"Drilled" : Array(
198					"blockquote"
199				), 
200				"Related" : Array(
201					"body"
202				)
203			},
204			
205			/*
206			 *  Navigation
207			 */
208			".nav_container" : {
209				"Drilled" : Array(
210					".nav_container",
211					".nav_container a*"
212				), 
213				"Related" : Array(
214					"body"
215				)
216			},
217			
218			".nav_container.horizontal" : {
219				"Drilled" : Array(
220					".nav_container.horizontal*",
221					".nav_container a*"
222				), 
223				"Related" : Array(
224					"body"
225				)
226			},
227			
228			".project_link" : {
229				"Drilled" : Array(
230					".project_link*",
231					".nav_container a"
232				),
233				"Related" : Array(
234					".nav_active*",
235					".nav_container",
236					".nav_container a*"
237				)
238			},
239			
240			".page_link" : {
241				"Drilled" : Array(
242					".page_link*",
243					".nav_container a"
244				),
245				"Related" : Array(
246					".nav_active*",
247					".nav_container",
248					".nav_container a"
249				)
250			},
251			
252			".page_nav" : {
253				"Drilled" : Array(
254					".page_nav*",
255					".feed_nav a",	// Note: explicit because of link_link
256					".feed_nav a:hover",
257					".feed_nav a:active"					
258				),
259				"Related" : Array(
260					".feed_nav"
261				)
262			},
263
264			".feed_nav" : { // Turing
265				"Drilled" : Array(
266					".feed_nav*"					
267				),
268				"Related" : Array(
269					".feed_view",
270					"#feed_views",
271					"#nav_wrapper",
272					"#entry_nav a*"
273				)
274			},
275
276			
277			
278			".link_link" : {
279				"Drilled" : Array(
280					".link_link*",
281					".nav_container a"
282				),
283				"Related" : Array(
284					".nav_container",
285					".nav_container a"
286				)
287			},
288			
289			".icons" : {
290				"Drilled" : Array(
291					".nav_follow a*"
292				),
293				"Related" : Array(
294					".nav_follow",
295					".nav_container"
296				)
297			},
298			
299			".nav_follow" : {
300				"Drilled" : Array(
301					".nav_follow"
302				),
303				"Related" : Array(
304					".nav_follow a*",
305					".nav_container"
306				)
307			},
308			
309			".pagination" : {
310				"Drilled" : Array(
311					".pagination"
312				),
313				"Related" : Array(
314					".pagination a*",
315					".nav_container"
316				)
317			},
318			
319			".next_page" : {
320				"Drilled" : Array(
321					".next_page",
322					".pagination a*"
323				),
324				"Related" : Array(
325					".pagination",
326					".nav_container",
327					".prev_page"
328				)
329			},
330			
331			".prev_page" : {
332				"Drilled" : Array(
333					".prev_page",
334					".pagination a*"
335				),
336				"Related" : Array(
337					".pagination",
338					".nav_container",
339					".next_page"
340				)
341			},
342			
343			/*
344			 *	Special navigation
345			 */
346			".project_nav_title" : {
347				"Drilled" : Array(
348					".project_nav_title*"
349				),
350				"Related" : Array(
351					".project_navigation*"
352				)
353			},
354			
355			".toggle_text" : {
356				"Drilled" : Array(
357					".toggle_text",
358					"a.project_nav_button*"
359				),
360				"Related" : Array(
361					".project_navigation*"
362				)
363			},
364
365			"#prev_entry" : {
366				"Drilled" : Array(
367					"#prev_entry*",
368					"#entry_nav*"
369				),
370				"Related" : Array(
371					"#next_entry*"
372				)
373			},
374
375			"#next_entry" : {
376				"Drilled" : Array(
377					"#next_entry*",
378					"#entry_nav*"
379				),
380				"Related" : Array(
381					"#prev_entry*"
382				)
383			},
384			
385			/*
386			 *  Thumbnails
387			 */
388			".cardimgcrop" : {
389				"Drilled" : Array(
390					".cardimgcrop",
391					".project_thumb",
392					".project_feed_thumb"
393				),
394				"Related" : Array(
395					".project_thumb*",
396					"#content_container",
397					"#items_container",
398					".pr_wrapper",
399					".project_feed_thumb.*",
400					".project_feed_thumb:*",
401					".project_feed_thumb *"
402				)
403			},
404			
405			".project_feed_thumb" : {  // SC only
406				"Drilled" : Array(
407					".project_feed_thumb",
408					".cardimgcrop"
409				),
410				"Related" : Array(
411					".project_feed_thumb.*",
412					".project_feed_thumb:*",
413					".project_feed_thumb *"
414				)
415			},
416			
417			".thumb_title" : {
418				"Drilled" : Array(
419					".thumb_title",
420					".thumb_title .text",
421					".project_thumb .hover*",
422					".project_thumb.active*"
423				),
424				"Related" : Array(
425					"#content_container",
426					".project_feed_thumb",
427					"#items_container"
428				)
429			},
430			
431			".thumb_title .text" : {
432				"Drilled" : Array(
433					".thumb_title .text",
434					".thumb_title a*",
435					".thumb_title"
436				),
437				"Related" : Array(
438					".thumb_title",
439					".project_thumb .hover*",
440					".project_thumb.active*",
441					"#content_container",
442					".project_feed_thumb",
443					".project_feed_thumb .hover*",
444					".project_feed_thumb.active*",
445					"#items_container"
446				)
447			},
448			
449			".thumb_tag" : {
450				"Drilled" : Array(
451					".thumb_tag",
452					".thumb_tag .text",
453					".thumb_tag a*",
454					".project_thumb .hover*",
455					".project_thumb.active*"
456				),
457				"Related" : Array(
458					".thumb_tag.notitle"
459				)
460			},
461			
462			".thumb_tag .text" : {
463				"Drilled" : Array(
464					".thumb_tag .text",
465					".thumb_tag a*"
466				),
467				"Related" : Array(
468					".thumb_tag",
469					".thumb_tag.notitle"
470				)
471			},
472			
473			".excerpt" : {
474				"Drilled" : Array(
475					".excerpt"
476				),
477				"Related" : Array(
478					".project_thumb .nohover",
479					".project_thumb .hover",
480					".project_feed_thumb .nohover",
481					".project_feed_thumb .hover"
482				)
483			},
484			
485			/*
486			 *  Project content
487			 */
488			".bodycopy" : {
489				"Drilled" : Array(
490					"#maincontainer*"
491				),
492				"Related" : Array(
493					"#content_container",
494					"#items_container",
495					".bodycopy*"
496				)
497			},
498			
499			".project_index" : {
500				"Drilled" : Array(
501					".project_index",
502					".project_index a*",
503					".project_header a*"
504				),
505				"Related" : Array(
506					".project_header",
507					".project_header div"
508				)
509			},
510			
511			".project_next" : {
512				"Drilled" : Array(
513					".project_next",
514					".project_header a*",
515					".project_nav_button*"
516				),
517				"Related" : Array(
518					".project_header",
519					".project_header div",
520					".project_navigation*"
521				)
522			},
523			
524			
525			".project_prev" : {
526				"Drilled" : Array(
527					".project_prev",
528					".project_header a*",
529					".project_nav_button*"
530				),
531				"Related" : Array(
532					".project_header",
533					".project_header div",
534					".project_navigation*"
535				)
536			},
537			
538			".project_close" : {
539				"Drilled" : Array(
540					".project_close*",
541					".project_navigation a*"
542				),
543				"Related" : Array(
544					".project_nav_button*",
545					".project_header",
546					".project_header div"
547				)
548			},
549			
550			".project_title" : {
551				"Drilled" : Array(
552					".project_title a*",
553					".project_title"
554				),
555				"Related" : Array(
556					"#content_container",
557					"#items_container"
558				)
559			},
560			
561			".project_content img" : {
562				"Drilled" : Array(
563					".project_content img"
564				),
565				"Related" : Array(
566					".project_content",
567					"#content_container",
568					"#items_container",
569					".entry"
570				)
571			},
572			
573			".project_content" : {
574				"Drilled" : Array(
575					".project_content",
576					"body",
577					".bodycopy*"
578				),
579				"Related" : Array(
580					".project_content img",
581					".entry",
582					"#content_container",
583					"#items_container"
584				)
585			},
586			
587			".project_content a" : {
588				"Drilled" : Array(
589					".project_content a*",
590					".bodycopy a*",
591					".entry a*"
592				),
593				"Related" : Array(
594					".project_content",
595					"body"
596				)
597			},
598			
599			"#content_container" : {
600				"Drilled" : Array(
601					"#content_container"
602				),
603				"Related" : Array(
604					".entry",
605					".project_feed_full*",
606					"body"
607				)
608			},
609			
610			".entry" : {
611				"Drilled" : Array(
612					".entry",
613					"#content_container"
614				),
615				"Related" : Array(
616					"body"
617				)
618			},
619			
620			".project_text" : {
621				"Drilled" : Array(
622					".project_text*",
623					"body"
624				),
625				"Related" : Array(
626					"project_content*"
627				)
628			},
629			
630			"#items_container" : {
631				"Drilled" : Array(
632					"#items_container"
633				),
634				"Related" : Array(
635					".project_feed_full",
636					"body"
637				)
638			},
639			
640			".project_feed_full" : {
641				"Drilled" : Array(
642					".entry",
643					"#content_container",
644					"#items_container"
645				),
646				"Related" : Array(
647					"body"
648				)
649			},
650			
651			"#mainwrapper" : {
652				"Drilled" : Array(
653					"#mainwrapper"
654				),
655				"Related" : Array(
656					"#content_container",
657					"#items_container"
658				)
659			},
660			
661			/*
662			 *  Project footer
663			 */
664			".project_footer" : {
665				"Drilled" : Array(
666					".project_footer"
667				),
668				"Related" : Array(
669					"#content_container",
670					"#items_container",
671					".project_bottom"
672				)
673			},
674			
675			".permalink" : {
676				"Drilled" : Array(
677					".permalink*"
678				),
679				"Related" : Array(
680					".project_footer"
681				)
682			},
683						
684			".project_views" : {
685				"Drilled" : Array(
686					".project_views"
687				),
688				"Related" : Array(
689					".project_footer"
690				)
691			},
692			
693			".tags" : {
694				"Drilled" : Array(
695					".tags*"
696				),
697				"Related" : Array(
698					".project_footer"
699				)
700			},
701			
702			".editlink" : {
703				"Drilled" : Array(
704					".editlink*"
705				),
706				"Related" : Array(
707					".project_footer"
708				)
709			},
710			
711			".comment_link" : {
712				"Drilled" : Array(
713					".comment_link*",
714					".entry a*",
715					".project_content a*"
716				),
717				"Related" : Array(
718					".project_footer"
719				)
720			},
721			
722			".project_info" : {
723				"Drilled" : Array(
724					".project_info",
725					".thumb_tag a*"
726				),
727				"Related" : Array(
728					".thumb_tag",
729					".thumb_tag.notitle",
730					".module*",
731					".index"
732				)
733			},
734			
735			/*
736			 *  Slideshows
737			 */
738			".slideshow_wrapper" : {
739				"Drilled" : Array(
740					".slideshow_wrapper*",
741					".slideshow_component"
742				),
743				"Related" : Array(
744					".slideshow_container"
745				)
746			},
747			
748			".slideshow_container" : {
749				"Drilled" : Array(
750					".slideshow_container",
751					".slideshow_wrapper*",
752					".slideshow_component"
753				),
754				"Related" : Array(
755					
756				)
757			},
758			
759			".slideshow_nav" : {
760				"Drilled" : Array(
761					".slideshow_nav"
762				),
763				"Related" : Array(
764					".slideshow_nav a*"
765				)
766			},
767			
768			".slide_slash" : {
769				"Drilled" : Array(
770					".slide_slash",
771					".slideshow_nav"
772				),
773				"Related" : Array(
774					
775				)
776			},
777			
778			".slideshow_count" : {
779				"Drilled" : Array(
780					".slideshow_count"
781				),
782				"Related" : Array(
783					".slideshow_nav"
784				)
785			},
786			
787			".slide_prev*" : {
788				"Drilled" : Array(
789					".slideshow_nav a*"
790				),
791				"Related" : Array(
792					".slideshow_nav"
793				)
794			},
795			
796			".slide_next*" : {
797				"Drilled" : Array(
798					".slideshow_nav a*"
799				),
800				"Related" : Array(
801					".slideshow_nav"
802				)
803			},
804			
805			".slideshow_thumb" : {
806				"Drilled" : Array(
807					".slideshow_thumb",
808					".slideshow_thumb img",
809					".slideshow_thumb a",
810					".slideshow_thumb a:hover",
811					".slideshow_thumb a img",
812					".slideshow_thumb a:hover img"
813				),
814				"Related" : Array(
815					"a.activeSlide*"
816				)
817			},
818			
819			".activeSlide" : {
820				"Drilled" : Array(
821					".slideshow_thumb",
822					".slideshow_thumb img",
823					".slideshow_thumb a",
824					".slideshow_thumb a:hover",
825					".slideshow_thumb a img",
826					".slideshow_thumb a:hover img"
827				),
828				"Related" : Array(
829					"a.activeSlide*"
830				)
831			},
832			
833			".slideshow_caption" : {
834				"Drilled" : Array(
835					".slideshow_caption"
836				),
837				"Related" : Array(
838					".bodycopy*"
839				)
840			},
841			
842			".slideshow_caption a" : {
843				"Drilled" : Array(
844					".bodycopy a*"
845				),
846				"Related" : Array(
847					
848				)
849			},
850			
851			/*
852			 *  Search page
853			 */
854			 ".search_body" : {
855				"Drilled" : Array(
856					".search_body*",
857					".search_text*"
858				),
859				"Related" : Array(
860					".result",
861					".search_results"
862				)
863			},
864			
865			".search_text" : {
866				"Drilled" : Array(
867					".search_text*"
868				),
869				"Related" : Array(
870					".search_body",
871					".result",
872					".search_results"
873				)
874			},
875			
876			".search_title" : {
877				"Drilled" : Array(
878					".search_title*"
879				),
880				"Related" : Array(
881					".search_text",
882					".result",
883					".search_results"
884				)
885			},
886			
887			".search_tags" : {
888				"Drilled" : Array(
889					".search_tags*"
890				),
891				"Related" : Array(
892					".search_text",
893					".result",
894					".search_results"
895				)
896			},
897			
898			".search_thumb" : {
899				"Drilled" : Array(
900					".search_thumb*"
901				),
902				"Related" : Array(
903					".result",
904					".search_results"
905				)
906			},
907			
908			".search_header" : {
909				"Drilled" : Array(
910					".search_header*"
911				),
912				"Related" : Array(
913					"#search_term*",
914					"#search_form_results"
915				)
916			},
917			
918			"#search_term" : {
919				"Drilled" : Array(
920					"#search_term*"
921				),
922				"Related" : Array(
923					"#search_form",
924					".search_header*",
925					"#search_form_results"
926				)
927			},
928			
929			"#search_form_results" : {
930				"Drilled" : Array(
931					"#search_form_results*"
932				),
933				"Related" : Array(
934					"#search_term*",
935					".search_header"
936				)
937			},
938			
939			/*
940			 *	MISC
941			 */
942			".copyright" : {
943				"Drilled" : Array(
944					".copyright",
945					"#site_footer a*"
946				),
947				"Related" : Array(
948					"#site_footer"
949				)
950			},
951			
952			".view_all" : {
953				"Drilled" : Array(
954					".view_all*",
955					".view_tag_info a*"
956				),
957				"Related" : Array(
958					".view_tag_info"
959				)
960			},
961			
962			".rail_background" : {
963				"Drilled" : Array(
964					".rail_background"
965				),
966				"Related" : Array(
967					"body"
968				)
969			}
970			
971		},
972		
973		/*
974		 *  These classes are "forced" into being seen
975		 *  Used by the ReturnCssChain() method below
976		 *  If a class is specified here, it will return the key
977		 */
978		"ForcedClasses" : {
979			// <a> tag parents
980			".bodycopy" 			: ".bodycopy a",
981			".project_content" 		: ".project_content a",
982			".project_text"			: ".project_content a",
983			".slideshow_caption" 	: ".slideshow_caption a",
984			".text"					: ".thumb_tag .text",
985			
986			// normal tags (like <h1>)
987			"h1"					: "h1",
988			"h2"					: "h2",
989			"h3"					: "h3",
990			"h4"					: "h4",
991			"blockquote"			: "blockquote",
992			
993			// Misc classes to find parents
994			".thumb_title"			: ".thumb_title .text"
995			
996		},
997		
998		/*  Return a class based on the key
999		 * 	Example: key = .nav_container
1000		 *  returns: .nav_container { color:#fff; }
1001		 */
1002		Get : function(type, key) {
1003			return this[type][key] ? this[type][key] : key;
1004		},
1005		
1006		/*  Sets a single value
1007		 */
1008		Set : function(type, key, def) {
1009			this[type][key] = def;
1010		},
1011		
1012		/*  Set a single property
1013		 *  type: Original || Preview
1014		 *  key: int
1015		 */
1016		SetProperty : function(type, key, selector, class_text) {
1017			this[type][key] = this.MakeClass(selector, class_text);
1018		},
1019		
1020		/*  Makes the class object for the class array
1021		 *  Takes in the properties, returns the object
1022		 */
1023		MakeClass : function(selector, class_text) {
1024			return {
1025				"selector"	: selector,
1026				"class"		: class_text
1027			}
1028		},
1029		
1030		/*  Sets a chain of selectors as an array of full classes
1031		 *  type: "Drilled" || "Related"
1032		 *  content: array
1033		 *  eg. this.Drilled = [];
1034		 */
1035		SetChain : function(type, content) {
1036			this[type] = content;
1037		},
1038		
1039		/*  Retrieves a list of classes and returns them
1040		 * 	First scan the array for wildcards, if found, get siblings and loop
1041		 *  selector_list: array
1042		 */
1043		GetClassesFromSlectorList : function(selector_list) {
1044			var class_list = [],
1045				single	   = [];
1046			
1047			for(key in selector_list) {
1048				var selector = selector_list[key];
1049				
1050				// Check for wildcards
1051				if(selector.indexOf("*") >= 0) {
1052					// Get a list of sibling elements
1053					var siblings = CSS.Classes.FindSiblingSelectors( selector.replace("*","") );
1054					// loop through the siblings
1055					for(skey in siblings) {
1056						
1057						single = this.GetSingle(siblings[skey]);
1058						class_list = this.PushSingle( class_list, single );
1059					}
1060				} else {
1061					// Normal selector, grab the class
1062					single = this.GetSingle(selector);
1063					class_list = this.PushSingle( class_list, single );
1064				}
1065			}
1066			
1067			if(typeof class_list[0] == "undefined") {
1068				return this.GetSingle("body");
1069			
1070			} else {
1071				return class_list;
1072			}
1073		},
1074		
1075		/*  Push a single class onto a stack
1076		 *  Sometimes this single is actually multiple values
1077		 *  So loop through and push each loop onto the stack
1078		 */
1079		PushSingle : function(stack, single_list) {
1080			for(single in single_list) {
1081				if(single) {
1082					stack.push( single_list[single] )
1083				}
1084			}
1085			
1086			return stack;
1087		},
1088		
1089		/*  Returns a single class value
1090		 *  selector: string
1091		 
1092		 single = {
1093		 	[2, "html"],
1094		 	[3, "body"]
1095		 }
1096		 */
1097		GetSingle : function(selector) {
1098			var single_list = [];
1099			for(row in this.Preview) {
1100				if(selector == this.Preview[row].selector) {
1101					single_list.push( [row, this.Preview[row]] );
1102				}
1103			}
1104			
1105			return single_list;
1106		},
1107		
1108		/*  Gets all the classes in the Preivew obj
1109		 *  return_array: true|false
1110		 *  Returns an array of classes || string of classes
1111		 */
1112		GetAll : function(return_array) {
1113			var class_list = [];
1114			
1115			for(key in this.Preview) {
1116				if(CSS.Classes.Preview[key] && CSS.Classes.Preview[key].class) {
1117					class_list.push( [key, CSS.Classes.Preview[key]] );
1118				}
1119			}
1120			
1121			if(return_array) {
1122				return class_list;
1123				
1124			} else {
1125				return CSS.Classes.ClassArrayToString(class_list);
1126			}
1127		},
1128		
1129		/* 	Search for all related classes
1130		 *  Example: term = .nav_container
1131		 *  returns: .nav_container, .nav_container a, .nav_container a:hover
1132		 */
1133		FindSiblingSelectors : function( term ) {
1134			var return_set = [];
1135			for(row in this.Preview) {
1136				if(this.Preview[row].selector.indexOf(term) >= 0) {
1137					// Make sure there are no dupes
1138					if($.inArray( this.Preview[row].selector, return_set ) < 0) {
1139						return_set.push(this.Preview[row].selector);
1140					}
1141				}
1142		    }
1143			return return_set;
1144		},
1145		
1146		/*  Changes the set classes from an array to string
1147		 */
1148		ClassArrayToString : function( classes ) {
1149			var output = "";
1150			
1151			for(key in classes) {
1152				if(classes[key]) {
1153					output += classes[key][1].class+"\n\n";
1154				}
1155			}
1156			
1157			return output;
1158		}
1159		
1160		
1161}; // End CSS.Classes
1162
1163
1164/**
1165 *  #########################################################################################################
1166 *  Create an object for use with the full sheet
1167 *  Methods for parsing and setting individual classes within the sheet
1168 *  #########################################################################################################
1169 */
1170/* !CSS.Sheet */
1171CSS.Sheet = {
1172	
1173		/*
1174		 *  Uses the css_data value set from the ajax return value from load
1175		 *  css_data is json 
1176		 *  Parses the sheet to split by class, loads the result into 
1177		 *  Called from the ajax return in loadInspector in cargo.site.package.js
1178		 *
1179		 *  NOTE: The preview classes are being stripped of their space, so they will align properly
1180		 *  	  Having difficulty with making one regex command to strip all cases, so there are two
1181		 */
1182		ParseAndSet : function( css_data ) {
1183			// Parse the raw CSS into an array of values
1184			var css_matches = this.ParseRawCSS( css_data );
1185			
1186			for(var i=0; i<css_matches.length; i++) {
1187				var selector = this.GetSelectors( css_matches[i] )[0];
1188				
1189				// Set the original exactly like the stylesheet. Usually only first load
1190				CSS.Classes.SetProperty("Original", i, selector, css_matches[i]);
1191								
1192				// Set the preview, only if there is a selector associated
1193				if( typeof selector != "undefined") {
1194					CSS.Classes.SetProperty("Preview", i, selector, css_matches[i]);
1195				}
1196			}
1197			
1198		},
1199		
1200		/*
1201		 *  Takes the raw CSS sheet and parses it by line
1202		 *  It will take each line and build an array based on that
1203		 *  It will see all open tags, classes and single lines (like @import)
1204		 * 	returns an array of matches
1205		 */
1206		ParseRawCSS : function(raw_css) {
1207			
1208			var matches          = [],					// A list of final matches
1209			    push_it          = true,				// Conditional to push this content to array or not
1210			    in_class         = false,				// Conditional for when we are inside of a class or not
1211			    resulting_string = "",					// content appended to a final string to push
1212			    lines			= raw_css.split(/\n/);	// Each line of the CSS split by \n
1213	       
1214	       // old school js is faster then jQuery
1215	       for(var i=0; i<lines.length; i++) {
1216			//$.each(lines, function( key, lineContent ) {
1217				var line_content      = lines[i],
1218					next_line_content = lines[i+1];
1219				
1220				// Find open bracket
1221                if(line_content.indexOf("{") >= 0 && !in_class) {
1222                   // If closed bracket is on the same line
1223                   push_it = ( line_content.indexOf("}") >= 0 ) ? true : false;
1224                   in_comment = false;
1225                   in_class = true;
1226                }
1227                // Find close bracket
1228                else if(line_content.indexOf("}") >= 0) {
1229                   if(in_class && line_content.indexOf("{") >= 0) {
1230                       // Found an open and close on same line, like
1231                       // }.another_class {
1232                       var class_split = line_content.split("}");
1233                       resulting_string += class_split[0] + "}\n";
1234                       resulting_string = $.trim( 
1235							resulting_string.
1236							replace(/[^\S\r\n]{2,}/g, "    ").
1237							replace(/[^\S\r\n]{4,}\}/g, "}") 
1238						);
1239						// Push the first exising class on
1240						matches.push( resulting_string );
1241						// Change the line content and reset the result value
1242						line_content = class_split[1];
1243						resulting_string = "";
1244                       
1245					} else {
1246						push_it = true;
1247						in_class = false;
1248					}
1249                }
1250				// Find close comment
1251				else if( line_content.indexOf("*/") >= 0 && !in_class) {
1252				   push_it = true;
1253				}
1254				// Find open comment (but not a close)
1255				else if( line_content.indexOf("/*") >= 0 && line_content.indexOf("*/") < 0 && !in_class) {
1256				   push_it = false;
1257				   in_class = false;
1258				}
1259				// Empty line
1260				else if(resulting_string == "\n") {
1261					// Check for actual content
1262				   if(line_content.replace(/ /g, "") != "") {
1263				       // Check for line end with semi-colon
1264				       push_it = (line_content.indexOf(";") > 0) ? true : false;
1265				       
1266				   }
1267				// Classes on multiple lines seperated by commas
1268				} else if(!in_class && line_content.indexOf(",") > 0) {
1269					in_class = true;
1270					push_it = ( line_content.indexOf("}") >= 0 ) ? true : false;
1271					
1272				// Classes with an open bracket on the next line			
1273				} else if(!in_class && line_content.indexOf(";") < 0 && $.trim(line_content) != "" ) {
1274					if(next_line_content && next_line_content.indexOf("{") >= 0) {
1275						in_class = true;
1276						push_it = ( next_line_content.indexOf("}") >= 0 ) ? true : false;
1277						
1278					}
1279				} 
1280								
1281				// Add a new line to the end of the string
1282				resulting_string += line_content + "\n";
1283
1284				// If we can push onto the stack
1285				if(push_it) {
1286					// trim it, make the class visually flush in the editor
1287					resulting_string = $.trim( 
1288						resulting_string.
1289						replace(/[^\S\r\n]{2,}/g, "    ").
1290						replace(/[^\S\r\n]{4,}\}/g, "}") 
1291					);
1292					// Push the match and reset the string
1293					matches.push(resulting_string);
1294					// Reset the result value
1295					resulting_string = "";
1296					// Reset the in_class value
1297					in_class = false;
1298				}
1299
1300			};
1301			
1302			// Return the array of matches
1303			return matches;
1304		},
1305		
1306		
1307		/*  Converts the entire class array, back into a string line-by-line
1308		 *  Used when saving the sheet and sending to php
1309		 */
1310		ClassArrayToString : function( sheet ) {
1311			var sheet_string = "";
1312			
1313			for(i=0; i<=sheet.length;i++) {
1314				if(sheet[i]) {
1315					sheet_string += sheet[i].class+"\n";
1316				} else {
1317					sheet_string += "\n";
1318				}
1319			}
1320			
1321			return sheet_string;
1322		},
1323		
1324		/* Merge the Preview sheet into the Original
1325		 * Final step before saving
1326		 */
1327		MergeSheets : function() {
1328			var last_row = CSS.Classes.Original.length;
1329			
1330			for(i=0; i<=CSS.Classes.Original.length;i++) {
1331				if(CSS.Classes.Preview[i] && CSS.Classes.Preview[i] != "removed") {
1332					CSS.Classes.Original[i] = CSS.Classes.Preview[i];
1333				
1334				} else if(CSS.Classes.Preview[i] == "removed") {
1335					CSS.Classes.Original[i] = null
1336				}
1337			}
1338
1339		},
1340		
1341		/**
1342		 *  Helper method to get selectors from a sheet
1343		 */
1344		GetSelectors : function(sheet) {
1345			var selectors = [],
1346				selector_array = sheet.split(
1347					new RegExp("([\.|\#|::|@|a-z]([^{|};]*){)")
1348				);
1349
1350				
1351			/*
1352			 *  Loop through each of the class and selector to create final arrays
1353			 */
1354			$.each(selector_array, function(key, value) {
1355				// Find normal selectors
1356				if(selector_array[key].indexOf("{") > 0) {
1357					selectors.push($.trim(selector_array[key].replace("{","")));
1358				}
1359				// Find import tags
1360				else if(selector_array[key].indexOf("@") == 0) {
1361					selectors.push($.trim(selector_array[key]));
1362				}
1363			});
1364			
1365			return selectors;
1366		},
1367		
1368		/*  Matches an incoming class from the editor and updates the Preview value
1369		 *  selector:   string
1370		 *  class_text: string
1371		 */
1372		MatchAndUpdate : function(selector, class_text) {
1373			// Get rid of any return chars for better comparison
1374			selector =  selector.replace(/\r|\n/g, "");
1375			
1376			for(key in CSS.Classes.Active) {
1377				var pkey = CSS.Classes.Active[key][0];
1378				// Remove return chars from selector
1379				var active_selector = CSS.Classes.Active[key][1].selector.replace(/\r|\n/g, "");
1380				
1381				// Compare the incoming selector with this one
1382				if(	selector == active_selector && 
1383					$.inArray(pkey, CSS.Classes.ModifiedList) < 0
1384				) {
1385				
1386					if(CSS.Classes.Active[key][0]) {
1387						// Add this key to the modified chain
1388						CSS.Classes.ModifiedList.push(pkey);
1389						
1390						// Update the contents
1391						if(CSS.Classes.Preview[pkey]) {
1392							CSS.Classes.Preview[pkey].class = class_text;
1393						}
1394						// Let the caller know we found something
1395						return true;
1396					}
1397				}
1398				
1399			}
1400			
1401			// Let the caller know that nothing was found
1402			return false;
1403		},
1404		
1405		/*  Check for removals by comparing lengths of active and matched arrays
1406		 *  Then check selector counds
1407		 *  Finally compare open and closed braces
1408		 *  If matched, find what selector to remove
1409		 */
1410		CompareAndRemove : function( css_matches, sheet ) {
1411			if(CSS.Classes.Active.length > css_matches.length) {
1412				// Make sure the matchs and selector count is equal
1413				var selector_list = this.GetSelectors( sheet );
1414				
1415				if(css_matches.length == selector_list.length) {
1416					// Grab the open and close brace count
1417					// Quick and dirty way to tell if there are more unclosed tags
1418					var open_brace = sheet.split( new RegExp("{") );
1419					var close_brace = sheet.split( new RegExp("}") );
1420					
1421					// If there is not an unclosed tag
1422					if(open_brace.length == close_brace.length) {
1423						// Figure out what key it is
1424						var matched = false;
1425						for(akey in CSS.Classes.Active) {
1426							for(ckey in selector_list) {
1427								if(CSS.Classes.Active[akey][1].selector == selector_list[ckey]) {
1428									// Found this selector, remove from list and move on
1429									selector_list.splice(ckey,1);
1430									matched = true;
1431									continue;
1432								}
1433							}
1434							
1435							if(!matched) {
1436								// Found a missing guy, let's remove it
1437								this.RemoveFromAll( CSS.Classes.Active[akey][0] );
1438								continue;
1439								
1440							} else {
1441								matched = false;
1442								continue;
1443							}
1444							
1445						} // endfor: inner loop
1446					} // endfor: outer loop
1447				} // endif: match vs selector length
1448			} // endif: active vs match length
1449		},
1450		
1451		
1452		/*  Pushes a new class from the inspector onto the stack
1453		 *  Will add the new selector to the' Preview var and the Drilled var
1454		 */
1455		InsertNew : function(selector, class_obj) {
1456			var new_class = CSS.Classes.MakeClass(selector, class_obj);
1457			
1458			// Push this onto the stack
1459			CSS.Classes.Preview.push( new_class );
1460			
1461			// Grab the updated key
1462			var last_key = CSS.Classes.Preview.length-1;
1463			
1464			Cargo.log("inserted key: "+last_key);
1465			
1466			// Also add this to the current view
1467			CSS.Classes.Active.push([last_key, new_class]);
1468			
1469			// Add the key to the modied list
1470			CSS.Classes.ModifiedList.push(last_key);
1471			
1472		},
1473		
1474		/*  Removes any classes from the sheet
1475		 *  This is called when previewing
1476		 *  Remove from: Active, Preview, Drilled, Related
1477		 */
1478		RemoveFromAll : function(remove_key) {
1479			this.RemoveFrom(CSS.Classes.Active,  remove_key);
1480			this.RemoveFrom(CSS.Classes.Drilled, remove_key);
1481			this.RemoveFrom(CSS.Classes.Related, remove_key);
1482			
1483			// Manually remove from Preivew
1484			CSS.Classes.Preview[remove_key] = "removed";
1485		},
1486		
1487		/* Remove from a single sheet
1488		 */
1489		RemoveFrom : function(sheet, remove_key) {
1490			for(key in sheet) {
1491				if(sheet[key][0] == remove_key) {
1492					sheet.splice(key,1);
1493					return;
1494				} 
1495			}
1496		},
1497		
1498		/*
1499		 *  The full stylesheet (for previewing)
1500		 *  Loop through the array in Preview and output
1501		 */
1502		UpdateStylesheet : function() { 
1503			if($("style[rel=preview]").length > 0) {
1504				$("style[rel=preview]").html( CSS.Classes.GetAll() );
1505			
1506			} else {
1507				$("body").prepend('<style rel="preview">'+CSS.Classes.GetAll()+'</style>');
1508			}
1509			
1510		},
1511		
1512		/*
1513		 *  Check if the stylesheet has ever been updated
1514		 *  Done by stripping whitespace and comparing strings
1515		 *  active: array
1516		 */
1517		CheckForModifications : function() {
1518			if(CSS.Classes.Get("Transitional", "css_is_modified") !== true) {
1519				var to_compare = CSS.Classes.ClassArrayToString(CSS.Classes.Active),
1520					active = CssSyntaxEditor.getValue();
1521				
1522				if(to_compare.replace(/\s/g, "") != active.replace(/\s/g, "")) {
1523					$("input#save_css").removeAttr("disabled");
1524					CSS.Classes.Set("Transitional", "css_is_modified", true);
1525					$(".css_tab .change_made").show();
1526				}
1527			}
1528			
1529		},
1530
1531		/**
1532		 *  Saves the CSS by sending a json feed through ajax and php will take care of the rest
1533		 */
1534		Save : function() {
1535			// Add a spinner
1536			$(".save_spinner").show();
1537			$("input#save_css").css("visibility", "hidden");
1538			
1539			this.MergeSheets();
1540			
1541			var sheet_string = this.ClassArrayToString( CSS.Classes.Original );
1542			
1543			// Remove the last double line break
1544			sheet_string = sheet_string.replace(/(\n\n)$/, "");
1545			
1546			$.post(Cargo.Dispatcher.GetUrl("admin/saveLegacyInspectorCSS"), { 
1547					url		 : Cargo.Location.GetCargoUrl(),
1548					sheet	 : JSON.stringify( sheet_string )
1549				
1550				}, function() {
1551					// Reset all the defaults
1552					$(".save_spinner").hide();
1553					$("input#save_css").css("visibility", "visible");
1554					$("input#save_css").attr("disabled", "disabled");
1555					
1556					CSS.Classes.Set("Transitional", "css_is_modified", false);
1557					
1558					$(".css_tab .change_made").hide();
1559					$("#css_confirm_win_saved").show();
1560					setTimeout('$("#css_confirm_win_saved").fadeOut()', 1500);
1561			});
1562		}
1563} // End CSS.Sheet
1564
1565	
1566/**
1567 * 	#########################################################################################################
1568 *  The Inspector
1569 *  Contains all methods relating to the manipulation of the 
1570 *  data, including preview and save
1571 *  #########################################################################################################
1572 */
1573/* !Inspector */
1574Inspector = {
1575		
1576		/**
1577		 *  Positions holds a json for w/h/t/l positions of the inspector
1578		 */
1579		"Position" : { },
1580		
1581		/*  Set what the active inspection type is
1582		 *  Default = CSS
1583		 */
1584		"ActiveInspection" : "CSS",
1585		
1586		/* Switches the editor from CSS to HTML and back
1587		 */
1588		SwitchEditType : function( new_type ) {
1589			if( new_type == "CSS" ) {
1590				Inspector.QuickSelect.show();
1591				Inspector.CSS.Activate();
1592				
1593			} else if( new_type == "HTML" ) {
1594				Inspector.QuickSelect.hide();
1595				Inspector.CustomHTML.Activate();
1596			}
1597			
1598			this.ActiveInspection = new_type;
1599		},
1600			
1601		/**
1602		 *  Updates the code editor with the selected values
1603		 */
1604		updateCodeEditor : function( ) {
1605			// print the selection to the inspector
1606			CssSyntaxEditor.setValue( CSS.Classes.ClassArrayToString(CSS.Classes.Active) );
1607			
1608			// Jump to top of scroll
1609			Inspector.ResetScroll();
1610			
1611			// Clear the quickselect menu
1612			//Inspector.QuickSelect.clear();
1613		},
1614		
1615		/**
1616		 *  Previews the CSS by writting it to a style tag at the bottom of the page
1617		 *  The preview continues to update itself so there are no overlapping styles
1618		 */
1619		Preview : function() {
1620			if( this.ActiveInspection == "CSS" ) {
1621				// Parse the preview selection
1622				Inspector.CSS.ParseSelection();
1623				
1624				// Set the new stylesheet
1625				CSS.Sheet.UpdateStylesheet();
1626			
1627			} else {
1628				Inspector.CustomHTML.LivePreview();
1629			}			
1630		},
1631				
1632		/**
1633		 *  Start the inspector by adding the attribute "inspector" to all elements
1634		 *  Then remove that attribute from the inspector, so that does not get inspected
1635		 *  Also remove from the admin / following icons
1636		 */
1637		Start : function() {
1638			if( this.ActiveInspection == "CSS" ) {
1639				Inspector.CSS.Activate();
1640			}
1641
1642		},
1643		
1644		
1645		
1646		/**
1647		 *  Unbind only link elements and clickable elements
1648		 */
1649		DisableLinks : function() {
1650			$("a[inspector='true'], .project_thumb *")
1651				.removeAttr("inspector")
1652				.reloadHistory();
1653		},
1654		
1655		/**
1656		 *  Resets the scroll position of the content area to 0,0
1657		 */
1658		ResetScroll : function() {
1659			$(".CodeMirror-scroll")
1660				.scrollTop(0)
1661				.scrollLeft(0);
1662		},
1663		
1664		/**
1665		 *  Unload the inspector
1666		 *  Check for unsaved CSS / Html
1667		 *  Save if needed, then stop player and remove
1668		 */
1669		Unload : function() {
1670			if(
1671				CSS.Classes.Get("Transitional", "css_is_modified") === true ||
1672				Inspector.CustomHTML.html_is_modified === true
1673			 ) {
1674				
1675				if( confirm("You have unsaved changes. Are you sure you want to close?") ) {
1676					// Set the custom html back to normal
1677					Inspector.CustomHTML.Revert();
1678					
1679					// Revert the CSS
1680					Inspector.CSS.Revert();
1681					
1682				}
1683			
1684			} else {
1685				// No unsaved changed, unload
1686				Inspector.CSS.Deactivate();
1687				
1688				// Remove from the stage
1689				Inspector.Remove();
1690				
1691			}
1692
1693			$(document).trigger("inspectorUnloaded");
1694			
1695		},
1696		
1697		/**
1698		 *  Make the CSS inspector draggable
1699		 */
1700		EnableDragging : function() {
1701			$("#inspector").draggable({
1702			
1703				// containment : "window",
1704				containment : [
1705								(parseInt($("#inspector").width()) - 50) * -1, 
1706								(parseInt($("#inspector").height()) - 50) * -1,
1707								parseInt($(window).width()) - 50, 
1708								parseInt($(window).height()) - 50
1709							   ],
1710				
1711				cancel: "a, .syntax_container, .CodeMirror, #css_inspector_code, .css_inspector_index, #quick_select_container",
1712				
1713				start : function(event, ui) {
1714					// Stop inspector to remove hovers
1715					Inspector.CSS.Stop();
1716					$(this).addClass("noclick");
1717					Inspector.Chrome.DragActive = true;
1718				},
1719				
1720				stop : function(event, ui) {
1721					Inspector.SavePosition(ui);
1722					Inspector.Start();
1723				}
1724				
1725			}).resizable({
1726				minHeight: 290,
1727				minWidth: 340,
1728				
1729				start : function(event, ui) {
1730					// Stop inspector to remove hovers
1731					Inspector.CSS.Stop();
1732				},
1733				
1734				stop : function(event, ui) {
1735					var fixed_top = -parseInt($(window).scrollTop() - ui.position.top);
1736					var fixed_left = -parseInt($(window).scrollLeft() - ui.position.left);
1737					$("#inspector").css({
1738						"position" 	: "fixed",
1739						"top"		: fixed_top,
1740						"left"		: fixed_left
1741					});
1742					
1743					// Save these positions 
1744					Inspector.SavePosition(ui);
1745					
1746					// Restart the inspecting
1747					Inspector.Start();
1748				}
1749			});
1750			
1751			$("#inspector").css("cursor","move");
1752			
1753		},
1754		
1755		/**
1756		 *  Remove the draggability of the inspector
1757		 */
1758		DisableDragging : function() {
1759			$("#inspector").draggable("destroy");
1760			$("#inspector").css("cursor","auto");
1761		},
1762		
1763		/**
1764		 *  Sets the initial size and position of the inspector on load
1765		 */
1766		SetPosition : function(pos) {
1767			if(pos !== null && pos != "") {
1768				Inspector.Position = $.parseJSON(pos);
1769				
1770				// Verify this position is not offscreen
1771				if(
1772					Inspector.Position.top < $(window).height() 
1773					&& Inspector.Position.left < $(window).width() 
1774					&& Inspector.Position.top > 0
1775					&& Inspector.Position.left > 0
1776				) {
1777					$("#inspector").css({
1778						"top" 		: Inspector.Position.top,
1779						"left" 		: Inspector.Position.left,
1780						"width" 	: Inspector.Position.width,
1781						"height" 	: Inspector.Position.height
1782					});
1783				}
1784			}
1785		},
1786		
1787		/**
1788		 *  Saves the position of the inspector via ajax post
1789		 *  Creates a sringified json feed 
1790		 */
1791		SavePosition : function(positions) {
1792			
1793			Inspector.Position = {
1794		         "top"		: positions.position.top,
1795		         "left"		: positions.position.left,
1796		         "width"	: (positions.size) ? positions.size.width  : Inspector.Position.width,
1797		         "height"	: (positions.size) ? positions.size.height : Inspector.Position.height
1798		     };
1799			
1800			$.post(Cargo.Config.get("css_inspector_position"), { 
1801			    url: $("#url").val(), 
1802			    custom_position: JSON.stringify(Inspector.Position)
1803			});
1804			
1805		},
1806		
1807		/*
1808		 *	Remove the inspector from the stage
1809		 */
1810		Remove : function() {
1811			// Remove the container
1812			$("#inspector").remove();
1813		},
1814		
1815		/**
1816		 *  The chrome of the inspector window
1817		 *  Includes button manipulation
1818		 *  Hides and shows many elements
1819		 */
1820		/* !Inspector.Chrome */
1821		"Chrome" : {
1822			
1823			"DragActive" : false,
1824			
1825			/**
1826			 *  Toggle the Drilled and Related links
1827			 *  which == incoming of "drilled" || "related"
1828			 */
1829			ToggleViewStateLinks : function(which) {
1830				Inspector.QuickSelect.hide();
1831				$("#all_css").show();
1832				
1833				if( CSS.Classes.Drilled == CSS.Classes.Related || which == "single") {
1834					$("#show_related a, #show_drilled a, #css_inspector_toolbar_seperator").hide();
1835				
1836				} else {
1837					$("#css_inspector_toolbar_seperator").show();
1838					if( which == "drilled" ) {
1839						$("#show_related a").show();
1840						$("#show_drilled a").hide();
1841						
1842					} else {
1843						$("#show_related a").hide();
1844						$("#show_drilled a").show();
1845						
1846					}
1847				}
1848			},
1849			
1850			/**
1851			 *  Change the header to show the quick select menu items
1852			 */
1853			ShowQuickSelectState : function() {
1854				$("#show_related a, #show_drilled a, #css_inspector_toolbar_seperator, #all_css").hide();
1855				$(".css_inspector_index, #index_title, #show_editor, #css_inspector_color, #quick_select_container").show();
1856				$("#quick_select_container").removeClass("all_search").addClass("index_search")
1857				$(".syntax_container, .inspector_title_slash, a#full_css, #css_inspector_toolbar_seperator").hide();
1858				$("#all_css").hide();
1859				$("#all_elements").hide();
1860			},
1861			
1862			/**
1863			 *  Change the header to show the inspector editor items
1864			 */
1865			ShowEditorState : function() {				
1866				$(".css_inspector_index, #index_title, #show_editor, #css_inspector_color, #quick_select_container, #quick_select_clear").hide();
1867				$(".syntax_container, .inspector_title_slash, a#full_css").css("display", "block");
1868				$("#all_css").show();
1869			},
1870			
1871			/*
1872			 *  Initialize all of the button handlers
1873			 */
1874			init : function() {
1875				/*
1876				 *  Show the hierarchy
1877				 */
1878				$("#show_related a").live("click", function() {
1879					Inspector.CSS.ShowRelatedClasses();
1880					return false;
1881					
1882				}).hide();
1883				
1884				/*
1885				 *  Show the drilled
1886				 */
1887				$("#show_drilled a").live("click", function() {
1888					// Inspector.CSS.ShowDrilledClasses();					
1889					Inspector.CSS.ShowRelatedClasses();
1890					return false;
1891					
1892				}).hide();
1893				
1894				/*
1895				 *  Show all CSS 
1896				 */
1897				$("#all_css").live("click", function() {
1898					// If there is a search, show the search results
1899					if( $("#quick_select").val() != $("#quick_select").attr("rel") ) {
1900						Inspector.QuickSelect.show();
1901						$("#primary_elements").hide();
1902						$("#all_elements").show();
1903						$("#quick_select_clear").show();
1904					
1905					} else {
1906						// show everything
1907						Inspector.CSS.ShowAllClasses();
1908					}
1909					return false;
1910					
1911				}).hide();
1912				
1913				/*
1914				 *  Preview button
1915				 */
1916				$("input#preview_css").click(function() {
1917					Inspector.Preview();
1918					return false;
1919				});
1920				
1921				/*
1922				 *  Save CSS button
1923				 */
1924				$("input#save_css").click(function() {
1925					// Fire a preview 
1926					Inspector.Preview();
1927					// Then save
1928					CSS.Sheet.Save();
1929					return false;
1930				});
1931				
1932				/*
1933				 *  Save HTML button
1934				 */
1935				$("input#save_html").click(function() {
1936					// Then save
1937					Inspector.CustomHTML.Save();
1938					return false;
1939				});
1940				
1941				/*
1942				 *  Close button
1943				 */
1944				$("#css_inspector_close").click(function() {
1945					Inspector.Unload();
1946					return false;
1947				});
1948				
1949				/*
1950				 *  Minimize toggle
1951				 */
1952				$("#inspector_title").click(function() {
1953				
1954					if(Inspector.Chrome.DragActive == true) {
1955						Inspector.Chrome.DragActive = false;
1956												
1957					} else {
1958					
1959						if($("#inspector").hasClass("css_inspector_micro")) {
1960							$("#inspector")
1961								.removeClass("css_inspector_micro")
1962								.resizable({ disabled: false });
1963							$("#css_inspector_buttons, #html_inspector_buttons, .ui-resizable-se, .css_tab, .html_tab").show();
1964							$("#inspector_micro_title").hide();
1965							
1966							// Restart inspection
1967							Inspector.Start();
1968							
1969						} else {
1970							// Stop the inspection
1971							Inspector.CSS.Deactivate();
1972							
1973							$("#inspector")
1974								.addClass("css_inspector_micro")
1975								.resizable({ disabled: true });
1976							
1977							$("#css_inspector_buttons, #html_inspector_buttons, .ui-resizable-se, .css_tab, .html_tab").hide();
1978							
1979							$("#inspector_micro_title").show();
1980							
1981						}
1982
1983					}
1984					
1985					return false;
1986				});
1987				
1988				/*
1989				 *  CSS to HTML toggle
1990				 */
1991				$("a.css_tab").click(function() {
1992					Inspector.SwitchEditType("CSS");
1993					return false;
1994				});
1995				
1996				/*
1997				 *  CSS to HTML toggle
1998				 */
1999				$("a.html_tab").click(function() {
2000					Inspector.SwitchEditType("HTML");
2001					return false;
2002				});
2003										
2004				/*
2005				 *  The checkbox to allow / disallow clicking
2006				 */
2007				$("#no_link").click(function(e) {
2008					if($(this).attr('checked') === true) {
2009						Inspector.CSS.Stop();
2010						Inspector.Start();
2011					} else {
2012						Inspector.DisableLinks();
2013					}
2014				});
2015				
2016				
2017				/*
2018				 *  Remove the inspectability of the document
2019				 *  when hovering links. This is a hack to fix
2020				 *  issues with Chrome
2021				 */
2022				$("#css_inspector_toolbar a").hover(function(){
2023					$("html").removeAttr("inspector");
2024				});
2025				
2026				/*
2027				 *  Syntax highlight color switcher
2028				 */
2029				$("a#css_inspector_color").click(function() {
2030					var $css_inspector = $("#inspector");
2031										
2032					if ($css_inspector.hasClass("light")) {
2033							
2034						$css_inspector
2035							.removeClass("light")
2036							.addClass("dark");
2037						
2038					} else if ($css_inspector.hasClass("dark")) {
2039					
2040						$css_inspector
2041							.removeClass("dark")
2042							.addClass("light");
2043												}
2044					
2045					$.post(Cargo.Config.get("save_syntax_color"), {
2046						url 	: $("#url").val(),
2047						which 	: "inspector",
2048						content : ""
2049					}, function(data) { 
2050						// completed
2051					}, "json");
2052				  
2053				  return false;
2054				});
2055				
2056				/*
2057				 *  Editor link
2058				 *  Checks if there is anything in the drilled classes (user has clicked)
2059				 *  If there is, show that. Else, show everything
2060				 */
2061				$("a#show_editor").click(function() { 
2062					Inspector.QuickSelect.hide();
2063					
2064					if(CSS.Classes.Drilled.length > 0) {
2065						// Inspector.CSS.ShowDrilledClasses();
2066						Inspector.CSS.ShowRelatedClasses();
2067					} else {
2068						Inspector.CSS.ShowAllClasses();
2069					}
2070					return false;
2071				
2072				});
2073			}
2074		
2075		},
2076		
2077		/**  
2078		 *  Initialize the inspector
2079		 */
2080		init : function( inspector_position ) {
2081			/*
2082			 *  Stop scrolling on the page when hovering over the code mirror
2083			 */
2084			 
2085			$(".syntax_container, .css_inspector_index").hover(function() {
2086				$("body.webkit").css("overflow", "hidden");
2087			}, function() {
2088				$("body.webkit").css("overflow", "auto");
2089			});
2090			
2091			// Don't scroll description text area
2092			var MacVersion = getMacVersion();
2093			if ($.browser.webkit && MacVersion >= 10.7) {
2094				$("body").addClass("webkit");
2095			}
2096			
2097			if( typeof CssSyntaxEditor === "string" ) {				
2098				/*
2099				 *  Instantiate the code mirror for the inspector
2100				 *  NOTE: CssSyntaxEditor variable is defined at top
2101				 */
2102				CssSyntaxEditor = CodeMirror.fromTextArea(document.getElementById("css_inspector_code"), {
2103					theme              : "light",
2104					mode               : "css",
2105					lineNumbers        : false,
2106					height             : "100%",
2107					continuousScanning : 500,
2108					indentUnit         : 4,
2109					tabMode            : "indent",
2110					autofocus          : true,
2111			        onChange           : function() {
2112						// Auto preview
2113						clearTimeout(
2114							CSS.Classes.Get("Transitional","delay")
2115						);
2116						CSS.Classes.Set(
2117							"Transitional",
2118							"delay",
2119							setTimeout("Inspector.Preview()", CSS.Classes.Get("Transitional","delay_timer"))
2120						);
2121						
2122			        }
2123				});
2124			}
2125			
2126			/*
2127			 *  Set the delay of the auto preview
2128			 */
2129			CSS.Classes.Set("Transitional","delay");
2130			CSS.Classes.Set("Transitional","delay_timer",300);
2131			
2132			/*
2133			 *  Remove the user stylesheet and replace with the new one
2134			 */
2135			CSS.Sheet.UpdateStylesheet();
2136			$("#user_stylesheet").remove();
2137			
2138			/*
2139			 *  Initialize the chrome (buttons and window)
2140			 */
2141			Inspector.Chrome.init();
2142			
2143			/*
2144			 *  Start the inspector 
2145			 */
2146			Inspector.Start();
2147			
2148			/*
2149			 *  Set the inspector position
2150			 */
2151			Inspector.SetPosition(inspector_position);
2152			
2153			/*
2154			 *  Load the color picker
2155			 */
2156			Inspector.ColorPicker.init();
2157			
2158			/*
2159			 *  Load the quick select index
2160			 */
2161			Inspector.QuickSelect.init();
2162			
2163			/*
2164			 *  Enable dragging (must be after color init)
2165			 */
2166			Inspector.EnableDragging();
2167			
2168			/*
2169			 *  Add an unload listener
2170			 *  Will use the browser default
2171			 */
2172			
2173			window.onbeforeunload = function() {
2174				if(
2175					CSS.Classes.Get("Transitional", "css_is_modified") === true ||
2176					Inspector.CustomHTML.html_is_modified === true
2177				) {
2178					return "";
2179				}
2180			}
2181			
2182		}
2183	
2184}; // End Inspector
2185
2186/**
2187 * 	#########################################################################################################
2188 *  The Inspector CSS
2189 *  Manages all CSS content manipulation inside of the inspector
2190 *  Works closely with the CSS class from above and is not to be confused
2191 *  #########################################################################################################
2192 */
2193 /* !Inspector.CSS */
2194Inspector.CSS  = {
2195		
2196		/*
2197		 *  Activate the CSS portion of the inspector
2198		 *  Adds the "inspection" to all elements
2199		 *  Modifieds history and sets hover states
2200		 */
2201		Activate : function() {
2202			// Deactivate the HTML
2203			Inspector.CustomHTML.Deactivate();
2204			
2205			// Show the inspector
2206			$("#css_inspector").show();
2207			
2208			// Add an active state to the top tab
2209			$(".css_tab").addClass("active_tab");
2210			
2211			// Add to everything
2212			$("html, body *").attr("inspector","true");
2213			
2214			// Remove from some things
2215			$("#inspector, #inspector *").removeAttr("inspector");
2216			$("#toolset, #toolset *, #toolset_menu, #toolset_menu *, #design_panel, #design_panel *").removeAttr("inspector").unbind();
2217			
2218			// Start inspecting
2219			$("*[inspector='true']").CssInspector();
2220						
2221			// Remap history clicks to double click
2222			$("a[rel='history']").unloadHistory();
2223			
2224			// Activate specific Cargo links
2225			this.AllowCargoLinkClicks();
2226			
2227			// Remove the html inspection when hovering over the inspector
2228			$("#inspector").hover(function() {
2229					$("html").removeAttr("inspector");
2230				},
2231				function() {
2232					if( Inspector.ActiveInspection == "CSS" ) {
2233						$("html").attr("inspector","true");
2234					}
2235			});
2236			
2237		},
2238		
2239		/*
2240		 *  Deactivate the CSS inspector
2241		 *  Will stop everything from being inspected
2242		 *  Will reload history
2243		 */
2244		Deactivate : function() {
2245			// deactivate CSS
2246			Inspector.CSS.Stop();
2247
2248			// Reload the history
2249			$("a[inspector='true'], .project_thumb *").reloadHistory();
2250			
2251			// Hide the css inspector
2252			$("#css_inspector").hide();
2253			
2254			// Remove an active state to the top tab
2255			$(".css_tab").removeClass("active_tab");
2256			
2257			// Init slideshows
2258			Projects.Slideshow.ReCheckAndInit();
2259			
2260			// Check for any custom navigation and re-init it
2261			if( typeof customNavigationInit == "function") {
2262				customNavigationInit();
2263			}
2264		},
2265		
2266		/**
2267		 *  Stop the inspector by unbinding all elements, then removing the inspector attribute
2268		 */
2269		Stop : function() {
2270			// First, remove the ouline
2271			$("*").each(function() {
2272				if($(this).data("outline")) {
2273					$(this).css({
2274						"outline" : $(this).data("outline").join(" "),
2275						"outline-offset" : $(this).data("o-offset")
2276					});
2277					
2278				}
2279			});
2280			
2281			// Next, remove the rest
2282			$("*[inspector='true'], html")
2283				.removeAttr("inspector")
2284				.removeAttr("inspecting");
2285		},
2286		
2287		/**
2288		 *  Helper method to change the click state to double click
2289		 *  	for specific Cargo functionality, like project close
2290		 *  Called from both Start and project load complete
2291		 *  Note: Must use die() to unbind the live event before re-creating
2292		 */
2293		AllowCargoLinkClicks : function() {
2294			// Next project
2295			$(".project_next a").die("dblclick").live("dblclick", function() {
2296				$(document).trigger("showNextProject");
2297			});
2298			
2299			// Close project
2300			$(".project_index a").die("dblclick").live("dblclick", function() {
2301				$(document).trigger("closeProject");
2302			});
2303			
2304			// Next page (pagination)
2305			$("a.next_page").die("dblclick").live("dblclick", function() {
2306				changePage(parseInt($("#current_page").val())+1);
2307			});
2308			
2309			// Prev page (pagination);
2310			$("a.prev_page").die("dblclick").live("dblclick", function() {
2311				changePage(parseInt($("#current_page").val())-1);
2312			});
2313			
2314		},
2315		
2316		/**
2317		 *  Saves the DOM chain from the clicked class on up	
2318		 *  css_chain is an array
2319		 */
2320		SaveChain : function(css_chain) {
2321			// Die quietly if nothing is passed through
2322			if( !css_chain ) return;
2323			
2324			var this_elem = css_chain.pop(),
2325				drilled   = [],
2326				related   = [];
2327			
2328			// If there is nothing defined, set the elem to body
2329			if(!this_elem) this_elem = "body";
2330			
2331			/*
2332			 * 	Check for interceptions in this chain
2333			 * 	Returns an object with drilled and related arrays
2334			 */
2335			var interceptions = this.GetInterceptions( this_elem );
2336			
2337			/*
2338			 *  If no interceptions are found, search for siblings of the selector
2339			 */
2340			if(typeof interceptions != "object") {
2341				drilled = CSS.Classes.FindSiblingSelectors( this_elem );
2342				related = css_chain.slice(1, css_chain.length);
2343				
2344			} else {
2345				drilled = interceptions["Drilled"];
2346				related = interceptions["Related"];
2347			}
2348			
2349			// Set the drilled and related sheets
2350			CSS.Classes.SetChain("Drilled", CSS.Classes.GetClassesFromSlectorList( drilled ) );
2351			CSS.Classes.SetChain("Related", CSS.Classes.GetClassesFromSlectorList( related ) );
2352			
2353		},
2354		
2355		/**
2356		 *  Interceptor 
2357		 *  Uses the Interceptions list to match a paid
2358		 *  A single "elem" (class) value is passed in
2359		 *  Looks for classes with * (wildcard) as well
2360		 *  If a result is found, the drilled and related 
2361		 *  	chain vals are set
2362		 *  Returns the true || false
2363		 */
2364		GetInterceptions : function(this_elem) {
2365			var match_found = false;
2366			
2367			// First, check for an exact match
2368			if( CSS.Classes.Interceptions[this_elem] ) {
2369				match_found = CSS.Classes.Interceptions[this_elem];
2370				
2371			} else if(this_elem) {					
2372			// Otherwise, check for any * wildcards
2373				for(var star_check in CSS.Classes.Interceptions ) {
2374					if(star_check.indexOf("*") >= 0) {
2375						if(this_elem.indexOf( star_check.replace("*", "") ) >= 0) {
2376							match_found = CSS.Classes.Interceptions[star_check];
2377						}
2378					}
2379				}
2380			
2381			}
2382			
2383			if( !match_found ) {
2384				// No matches found
2385				return false;
2386			
2387			} else {
2388				// Return the match array
2389				return match_found;
2390			}
2391			
2392		},
2393		
2394		
2395		/**
2396		 *  Show only one class
2397		 *  Used when looking for an item you searched for
2398		 */
2399		ShowSingleClass : function(single_class) {
2400			
2401			var single_list = [],
2402				class_list	= [];
2403				
2404			// Could be a tag, class or id
2405			single_list.push(single_class);
2406			single_list.push("."+single_class);
2407			single_list.push("#"+single_class);
2408			
2409			for(skey in single_list) {
2410				single = CSS.Classes.GetSingle(single_list[skey]);
2411				class_list = CSS.Classes.PushSingle( class_list, single );
2412			}
2413			
2414			// Set the view state links
2415			Inspector.Chrome.ToggleViewStateLinks("single");
2416			
2417			// Set the active class
2418			CSS.Classes.Active = class_list;
2419			
2420			// print the selection to the inspector
2421			Inspector.updateCodeEditor();
2422			
2423		},
2424		
2425		/**
2426		 *  Show only the drilled classes
2427		 */
2428		ShowDrilledClasses : function() {
2429			// Set the active class
2430			CSS.Classes.Active = CSS.Classes.Drilled;
2431			
2432			// print the selection to the inspector
2433			Inspector.updateCodeEditor();
2434			
2435			// Set the view state links
2436			Inspector.Chrome.ToggleViewStateLinks("drilled");
2437			
2438			
2439		},
2440		
2441		/**
2442		 *  Show all the DOM class heirarchy
2443		 */
2444		ShowRelatedClasses : function() {
2445			// Set the active class
2446			CSS.Classes.Active = this.GetUniqueRelated();
2447			
2448			// print the selection to the inspector
2449			Inspector.updateCodeEditor();
2450			
2451			// Set the view state links
2452			Inspector.Chrome.ToggleViewStateLinks("related");
2453			
2454		},
2455		
2456		/*
2457		 *	Make a single unique array from the drilled and related classes
2458		 *	Finds any dupes and removes them to prevent two of the same class
2459		 */
2460		GetUniqueRelated : function() {
2461			var final_list  = [],
2462				unique_list = [],
2463				merged_list = CSS.Classes.Drilled.concat(CSS.Classes.Related);
2464			
2465			for(row in merged_list) {
2466				// If there are dupes, skip it
2467				if($.inArray( merged_list[row][0], unique_list ) < 0) {
2468					unique_list.push(merged_list[row][0]);
2469					final_list.push(merged_list[row]);
2470				}
2471				
2472			}
2473			
2474			return final_list;
2475		},
2476		
2477		/**
2478		 *  Loads the full CSS into the inspector
2479		 */
2480		ShowAllClasses : function() {
2481			$("#all_css, #show_related a, #show_drilled a, #css_inspector_toolbar_seperator").hide();
2482			$("#quick_select_container").removeClass("index_search").addClass("all_search").show();
2483			
2484			// Set the active class
2485			CSS.Classes.Active = CSS.Classes.GetAll(true);
2486			
2487			// print the selection to the inspector
2488			Inspector.updateCodeEditor();
2489			
2490		},
2491		
2492		/**
2493		 *  Grabs the current value of the syntax editor
2494		 *  Parses through the content and creates a list of classes
2495		 *  Finds a single selector and matches it with the selector from drilled and related
2496		 *  Updates the Preview sheet with the new slector
2497		 */
2498		ParseSelection : function() {
2499			// Check for modifications
2500			CSS.Sheet.CheckForModifications();
2501			
2502			// Get the sheet from codemirror
2503			var sheet = CssSyntaxEditor.getValue();
2504			
2505			// Parse the raw CSS into an array of values
2506			var css_matches = CSS.Sheet.ParseRawCSS( sheet );
2507			
2508			// Remove blank keys
2509			css_matches = $.grep(css_matches,function(n) { return(n); });
2510			
2511			/*  Loop through the found classes and update preview
2512			 *  If no match was found, insert into the stack
2513			 */
2514			for(var i=0; i<css_matches.length; i++) {
2515				var selector = CSS.Sheet.GetSelectors( css_matches[i] )[0];
2516				
2517				if(selector) {
2518					// Update the Preview var
2519					var match_found = CSS.Sheet.MatchAndUpdate( selector, css_matches[i] );
2520					
2521					if(!match_found) {
2522						// Add it to the sheet
2523						CSS.Sheet.InsertNew(selector, css_matches[i]);
2524					}
2525				}
2526			}
2527			
2528			// Check to see if anything needs removal
2529			CSS.Sheet.CompareAndRemove( css_matches, sheet );
2530			
2531			// Reset the Modified key list
2532			CSS.Classes.ModifiedList = [ ];
2533			
2534			CSS.Classes.ActiveList = [ ];
2535			
2536		},
2537		
2538		/*
2539		 *	Revert all changes to the CSS
2540		 */
2541		Revert : function() {
2542			// Revert the CSS
2543			CSS.Classes.Preview = CSS.Classes.Original;
2544			CSS.Sheet.UpdateStylesheet();
2545			
2546			// Set the saved state to false
2547			CSS.Classes.Set("Transitional", "css_is_modified", false);
2548			
2549			// Go ahead and unload
2550			Inspector.CSS.Deactivate();
2551			
2552			// Remove from the stage
2553			Inspector.Remove();
2554		}
2555};
2556
2557/**
2558 * 	#########################################################################################################
2559 *  Custom HTML editing
2560 *  Loads and unloads the custom HTML to be edited
2561 *  Handles preview and save
2562 *  This panel was a slight after though and could use some cleanup
2563 *  #########################################################################################################
2564 */
2565/* !Inspector.CustomHTML */
2566Inspector.CustomHTML = {
2567		
2568		/*  Store the original and preview
2569		 */
2570		"Original" : "",
2571		
2572		"Preview"  : "",
2573		
2574		"html_is_modified" : false,
2575		
2576		/*  Sets the initial data
2577		 */
2578		SetData : function( html_data ) {
2579			this.Original = html_data;
2580			this.Preview  = html_data;
2581			
2582		},
2583		
2584		/*
2585		 *  Activate the custom html inspector
2586		 */
2587		Activate : function() {
2588			// Deactivate the CSS inspector
2589			Inspector.CSS.Deactivate();
2590			
2591			// Show the html inspector
2592			$("#html_inspector").show();
2593			
2594			// Add an active state to the top tab
2595			$(".html_tab").addClass("active_tab");
2596			
2597			// Check to make sure we can inspect the html
2598			if($("#html_inspector_code").length > 0) {			
2599				// Check if we've initailized codemirror yet
2600				this.InitCodemirror();
2601				
2602				// Display the custom HTML
2603				HtmlSyntaxEditor.setValue( this.Preview );
2604			}
2605			
2606						
2607			
2608		},
2609		
2610		
2611		/*
2612		 *  Deactivate the custom HTML inspector
2613		 */
2614		Deactivate : function() {
2615			// Hide the inspector
2616			$("#html_inspector").hide();
2617			
2618			// Remove the active state to the top tab
2619			$(".html_tab").removeClass("active_tab");
2620		},
2621		
2622		/*
2623		 *  Live preview to the page
2624		 *  Callback from codemirror set in "Activate"
2625		 */
2626		LivePreview : function() {
2627			this.Preview = HtmlSyntaxEditor.getValue();
2628			
2629			// Check for modifications
2630			this.CheckForModifications();
2631			
2632			$("customhtml").html( this.Preview );
2633		},
2634		
2635		/*
2636		 *  Save whatever is in the inspector
2637		 */
2638		Save : function() {
2639			$(".save_spinner").show();
2640			$("input#save_html").css("visibility", "hidden");
2641			
2642			$.post(Cargo.Dispatcher.GetUrl("admin/saveLegacyInspectorHTML"), { 
2643					url		 	 : Cargo.Location.GetCargoUrl(),
2644					custom_html	 : JSON.stringify( HtmlSyntaxEditor.getValue() )
2645				
2646				}, function() {
2647					// Reset all the defaults
2648					$(".save_spinner").hide();
2649					$("input#save_html").css("visibility", "visible");
2650					$("input#save_html").attr("disabled", "disabled");
2651					
2652					Inspector.CustomHTML.html_is_modified = false;
2653					
2654					$(".html_tab .change_made").hide();
2655					$("#html_confirm_win_saved").show();
2656					setTimeout('$("#html_confirm_win_saved").fadeOut()', 1500);
2657			});
2658		},
2659		
2660		/*
2661		 *  Check for modifications to the custom HTML
2662		 *  If there are mods, then set a val as such and show the save
2663		 */
2664		CheckForModifications : function() {
2665			var to_compare = this.Original,
2666				active 	   = this.Preview;
2667					
2668			if(to_compare.replace(/\s/g, "") != active.replace(/\s/g, "")) {
2669				this.html_is_modified = true;
2670				$("input#save_html").removeAttr("disabled");
2671				$(".html_tab .change_made").show();
2672				
2673			} else {
2674				this.html_is_modified = false;
2675				$("input#save_html").attr("disabled", "disabled");
2676				$(".html_tab .change_made").hide();
2677			}
2678			
2679			
2680		},
2681		
2682		/*
2683		 *  Checks if code mirror is initialize, if not do it
2684		 *  Checks if the html preview is initialized, if not do it
2685		 */
2686		InitCodemirror : function() {
2687			if( typeof HtmlSyntaxEditor === "string") {
2688				/*
2689				 *  Instantiate the code mirror for the inspector
2690				 *  NOTE: HtmlSyntaxEditor variable is defined at top
2691				 */
2692				HtmlSyntaxEditor = CodeMirror.fromTextArea(document.getElementById("html_inspector_code"), {
2693					theme: "light",
2694					mode: "htmlmixed",
2695					lineNumbers: false,
2696					height: "100%",
2697					continuousScanning: 500,
2698					indentUnit: 4,
2699					tabMode: "indent",
2700			        onChange: function() {
2701						// Auto preview
2702						clearTimeout(
2703							CSS.Classes.Get("Transitional","delay")
2704						);
2705						CSS.Classes.Set(
2706							"Transitional",
2707							"delay",
2708							setTimeout("Inspector.CustomHTML.LivePreview()", CSS.Classes.Get("Transitional","delay_timer"))
2709						);
2710						
2711			        }
2712				});
2713			
2714			}
2715			
2716		},
2717		
2718		/*
2719		 *	Remove the custom HTML and revert to original
2720		 */
2721		Revert : function() {
2722			// Add the custom HTML content back, but wrapped in a tag
2723			$("customhtml").html( this.Original );
2724			
2725			// Allow the page to refresh
2726			this.html_is_modified = false;
2727		}
2728		
2729}; // end Inspector.CustomHTML
2730	
2731
2732
2733/**
2734 * 	#########################################################################################################
2735 *  The Hover list
2736 *  Maintains a list of hovered states in order to find the most drilled
2737 *  #########################################################################################################
2738 */
2739/* !Inspector.HoverList */
2740Inspector.HoverList = {
2741		"BottomElem" : { },
2742		
2743		/**
2744		 *  Optimizes the hoverlist by finding
2745		 *  	the item with the most parents
2746		 */
2747		Optimize : function() {
2748			var bottom_count = 0;
2749						
2750			// Loop through all hovers
2751			$("[inspecting=true]").each(function() {
2752				if($(this).parents().length >= bottom_count) {
2753					Inspector.HoverList.BottomElem = $(this);
2754					bottom_count = $(this).parents().length;
2755				}
2756				
2757			}).css("outline","none");
2758			
2759			// Set the last hover to have the outline
2760			$(Inspector.HoverList.BottomElem).css( { 
2761				"outline" : InspectOutline, 
2762				"outline-offset" : "-1px" 
2763			});
2764			
2765		}
2766	
2767};
2767 // end Inspector.HoverList	
2768	
2769	
2770/**
2771 * 	#########################################################################################################
2772 *  The quick select index
2773 *  Contains all methods for the "index" 
2774 *  Includes quick select, hovers, etc
2775 *  #########################################################################################################
2776 */	
2777/* !Inspector.QuickSelect */
2778Inspector.QuickSelect = {
2779		
2780		init : function() {
2781			
2782			/*
2783			 *  Activate the quicklinks
2784			 *  Create a hover state for them
2785			 */
2786			$("a.quick_link").live("click", function() {
2787				
2788				Inspector.CSS.ShowSingleClass( $(this).html() );
2789				
2790				return false;
2791				
2792			}).hover(function() {
2793				/*
2794				 *  We don't know if the link is a <tag>, .class or #id
2795				 *  	so we have to try all
2796				 */
2797				var elem = $(this).html();
2798				$(elem+", ."+elem+", #"+elem).css("outline", InspectOutline);
2799				
2800				$("html").removeAttr("inspector");
2801			
2802			}, function() {
2803				var elem = $(this).html();
2804				/*
2805				$(elem+", ."+elem+", #"+elem).css({
2806					"outline" : $(elem+", ."+elem+", #"+elem).data("outline").join(" "),
2807					"outline-offset" : $(elem+", ."+elem+", #"+elem).data("o-offset")
2808				});
2809				*/ 
2810				$(elem+", ."+elem+", #"+elem).css("outline", "none");
2811				
2812				$("html").removeAttr("inspector");
2813			
2814			});
2815			
2816			/*
2817			 *  init the quickselect 
2818			 *  Stop the submit
2819			 *  Replace input text based on value
2820			 */
2821			
2822			$("input#quick_select").keyup(function() {
2823				
2824				Inspector.QuickSelect.show();
2825				
2826				$(this).QuickSort();
2827				
2828				/*
2829				 *  If the input is empty show the primary elements
2830				 */
2831				if ($(this).val() == "") {
2832					$("#primary_elements").show();
2833					$("#all_elements").hide();
2834					$("#quick_select_clear").hide();
2835				}
2836				else {
2837					$("#primary_elements").hide();
2838					$("#all_elements").show();
2839					$("#quick_select_clear").show();
2840				}
2841				
2842			}).focus(function() {
2843			
2844				/*
2845				 *  If on focus the value equals the rel attribute, clear the value
2846				 */
2847        		if($(this).val() == $(this).attr("rel")) {
2848        			$(this).val("").addClass("focus");
2849        		}
2850        		
2851   		 	}).blur(function() {
2852   		 	
2853   		 		/*
2854				 *  Otherwise on blur, if the input is blank, set the value to the rel attribute
2855				 */
2856        		if($(this).val() == "") {
2857        			$(this).val($(this).attr("rel")).removeClass("focus");
2858        		}
2859        		
2860    		}).blur();
2861			
2862			
2863			/*
2864			 *  Clear the input and show all classes on click
2865			 */
2866			$("a#quick_select_clear").live("click", function() {
2867				Inspector.QuickSelect.clear();
2868				$(this).hide();
2869				
2870				return false;
2871			});
2872		
2873		},
2874		
2875		clear : function() {
2876			Inspector.CSS.ShowAllClasses();
2877			Inspector.Chrome.ShowEditorState();
2878			$("#all_css").hide();
2879			$("input#quick_select").val("").blur();
2880			$("#quick_select_container").show();
2881		},
2882		
2883		hide : function() {
2884			$("#all_elements").hide();
2885			$(".css_inspector_index").hide();
2886			Inspector.Chrome.ShowEditorState();
2887		},
2888		
2889		show : function() {
2890			$("#all_elements").show();
2891			$(".css_inspector_index").show();
2892			Inspector.Chrome.ShowQuickSelectState();
2893			
2894		}
2895	
2896}; // End quick select
2897	
2898
2899/**
2900 * 	#########################################################################################################
2901 *  The color picker
2902 *  Contains all methods for the color picker
2903 *  Includes swatch control, color update, Code Mirror init
2904 *  #########################################################################################################
2905 */	
2906/* !Inspector.ColorPicker */
2907Inspector.ColorPicker = {
2908	
2909		"ActiveSwatch" : { },
2910		
2911		/**
2912		 * 	Load color picker
2913		 *  Initialize the swatches
2914		 */
2915		init : function() {
2916			/*
2917			 *  Activate the color picker to a hidden input field
2918			 */
2919			$("#hex_color").miniColors({
2920				change: function(hex, rgb) {
2921					Inspector.ColorPicker.UpdateSwatch(hex);
2922				}
2923			});
2924			
2925			/*
2926			 *  Close shortcut
2927			 */
2928			shortcut.add("Esc",function() {
2929				Inspector.ColorPicker.Cancel();
2930			}, {
2931				'type':'keydown',
2932				'keycode':27
2933			});
2934			
2935			/*
2936			 *  Set the swatches to live update from within the code mirror
2937			 */
2938			$(".mini_swatch").live("click", function() {
2939				// Set the Hex value first
2940				$(this).data("Hex", $(this).attr("rel"));
2941				
2942				// Set the value before opening the viewer
2943				Inspector.ColorPicker.ActiveSwatch = $(this);
2944				
2945				// Send the color of the swatch to the color picker as default value
2946				$("#hex_color").miniColors('value', $(this).attr("rel"));
2947				
2948				// Trigger the click even to open the color picker
2949				$(".miniColors-trigger").click();
2950				
2951				return false;
2952			});	
2953			
2954			/*
2955			 *  The "OK" / save button for the color picker
2956			 */
2957			$("#save_hex").live("click", function() {
2958				Inspector.ColorPicker.UpdateCodeMirror();
2959				return false;
2960			});
2961			
2962			/*
2963			 *  The cancel button for the color picker
2964			 */
2965			$(".miniColors-cancel a").live("click", function() {
2966				Inspector.ColorPicker.Cancel();
2967				return false;
2968			});
2969		
2970		},
2971		
2972		/**
2973		 *  Updates the color swatch
2974		 * 	Receives a hex value as input from the color picker
2975		 *  Does a live preview
2976		 */
2977		UpdateSwatch : function(hex) {
2978			// shorthand
2979			var swatch = Inspector.ColorPicker.ActiveSwatch;
2980			
2981			// Set the swatch's hex data value for later
2982			swatch.data("Hex", hex);
2983			
2984			// Update the preview swatch
2985			$(".miniColors-swatch").css("background-color", hex);
2986			
2987			// Select the closest attribute, but is sometimes not right, so pass it along to test
2988			var closest_attr = $.trim(swatch.prevUntil(".cm-variable").prev().text().replace(":",""));
2989			
2990			// Set the value of class and attribute for this obj			
2991			swatch.FindClassAndAttribute(closest_attr);
2992			
2993			// Live preview
2994			$(swatch.data("Class")).css(swatch.data("Attribute"), swatch.data("Related")+" "+hex);
2995		},
2996		
2997		/**
2998		 *  Update Code Mirror with new value
2999		 * 	- Find the position of the cursor
3000		 *  - Search the content for matches to the color swatch
3001		 *  - Assume the match must start before the swatch AND end after the swatch
3002		 *  - Assume the match is on the same line as the swatch
3003		 */
3004		 UpdateCodeMirror : function() {
3005		 	var swatch  = Inspector.ColorPicker.ActiveSwatch;
3006		 	var old_hex = swatch.attr("rel");
3007
3008			/*
3009			 *  Loop through each instance of the var "old_hex"
3010			 *  For each, compare where the cursor is (the swatch) to where the match is
3011			 *  If we found a match, replace the content there and exit the loop
3012			 */		
3013			for (var search_obj = CssSyntaxEditor.getSearchCursor(old_hex); search_obj.findNext();) {
3014    			if(
3015    				(CssSyntaxEditor.getCursor()["ch"]+2) >= search_obj.from()["ch"] &&
3016    				CssSyntaxEditor.getCursor()["ch"] <= search_obj.to()["ch"] &&
3017    				CssSyntaxEditor.getCursor()["line"] == search_obj.to()["line"]
3018    			) {
3019    			
3020	    			if(swatch.data("Hex")) {
3021	    				search_obj.replace(swatch.data("Hex"));
3022	    			}
3023	    			break;
3024	    		}
3025	    		
3026    		}
3027			
3028			// Close the color picker
3029		 	$("#hex_color").miniColors("hide");
3030			
3031		 },
3032		 
3033		 /**
3034		  *  Cancel the color inspector
3035		  *  The hide function triggers "colorPickerHide"
3036		  *  which removes any added style
3037		  */
3038		 Cancel : function() {
3039		 	// Close the color picker
3040		 	$("#hex_color").miniColors("hide");
3041		 	
3042		 	
3043		 }
3044		 
3045	
3046}; // end Color picker
3047	
3048
3049
3050/**
3051 * 	#########################################################################################################
3052 *  jQuery events 
3053 *
3054 * 	#########################################################################################################
3055 */
3056/* !jQuery events */
3057/**
3058 *  Event fired when the color picker is shown
3059 */
3060$(document).bind("colorPickerShow", function(e, hex) {
3061	// Stop the dragging so we can use the color picker
3062	Inspector.DisableDragging();
3063});
3064
3065/**
3066 *  Event fired when the color picker is hidden
3067 */
3068$(document).bind("colorPickerHide", function(e) {
3069	// color picker is gone, restart dragging
3070	Inspector.EnableDragging();
3071	
3072	// remove any style on the active swatch
3073 	var swatch  = Inspector.ColorPicker.ActiveSwatch;
3074 	$(swatch.data("Class")).css(swatch.data("Attribute"), "");
3075 	
3076 	// update the CSS
3077	Inspector.Preview();
3078});
3079
3080/*
3081 *  If a project opens, add the content to the inspector, if allowed
3082 *  Start inspector
3083 */
3084$(document).bind("projectLoadComplete", function(e, pid){ 
3085	// Verify the inspector is still visible
3086	if($("#inspector").length > 0) {
3087		$("#maincontainer *, .project_feed_full *").attr("inspector","true");
3088		$("#maincontainer *[inspector='true'], .project_feed_full *[inspector='true']").CssInspector();
3089		
3090		// Main wrapper close 
3091		$("#mainwrapper, .project_feed_full").attr("inspector","true").CssInspector();
3092		
3093		// If we are in mini-mode, don't start inspector
3094		if($("#inspector").hasClass("css_inspector_micro") || Inspector.ActiveInspection == "HTML") {
3095			Inspector.CSS.Deactivate();
3096		}
3097	}
3098});
3099
3100/*
3101 *  For SC designs - If a project opens, add the content to the inspector, if allowed
3102 *  Start inspector
3103 */
3104$(document).bind("SCprojectLoadComplete", function(e, pid){ 
3105	// Verify the inspector is still visible
3106	if($("#inspector").length > 0) {
3107		$(".project_feed_full *").attr("inspector","true");
3108		$(".project_feed_full *[inspector='true']").CssInspector();
3109		
3110		// Main wrapper close 
3111		$(".project_feed_full").attr("inspector","true").CssInspector();
3112	}
3113});
3114
3115/*
3116 *  Re-activate the pagination on each page
3117 */
3118$(document).bind("pageChangeComplete", function(e, pid){ 
3119	// Verify the inspector is still visible
3120	if($("#inspector").length > 0) {
3121		$("#pagination *").attr("inspector","true");
3122		$("#pagination *[inspector='true']").CssInspector();
3123	}
3124});
3125
3126/*
3127 *  Re-activate the inspector after pagination
3128 */
3129$(document).bind("paginationComplete", function(e, pid){ 
3130	// Verify the inspector is still visible
3131	if($("#inspector").length > 0) {
3132		$("#content_container *[inspector!='true']").attr("inspector","true").CssInspector();
3133	}
3134});
3135
3136/* 
3137 *  Re-add the inspector to the recently closed thumbnail
3138 *  SpaceCollective template only
3139 */
3140$(document).bind("projectCloseComplete", function(e, pid, container){ 
3141	// Only for SC templates
3142	if( $("#template").val() == "spacecollective" ) {
3143		// Put inside of a timeout so the DOM has a chance to reset from the card closure
3144		setTimeout(function() {
3145			$("#item_"+pid+".project_feed_thumb *")
3146				.css("outline", "none")
3147				.attr("inspector","true")
3148				.attr("inspecting","false")
3149				.CssInspector();
3150				
3151			$("#p"+pid).unloadHistory();
3152			$("#p"+pid).reloadHistory();
3153			
3154		}, 1);
3155	}
3156});
3157
3158/*
3159 *  Bubble up the chain to find the last class
3160 *  Only do this if the last elem is not a class/id
3161 */
3162function bubbleUp(chain) {
3163	var total_to_slice = 0;
3164	
3165	if( testForClassOrId(chain[chain.length-1]) ) {
3166		// reverse the chain and rebuild
3167		chain.reverse();
3168		for(i=0; i<chain.length; i++) {
3169			if( testForClassOrId(chain[i]) ) {
3170				total_to_slice++;
3171			} else {
3172				break;
3173			}
3174		}
3175		chain.reverse();
3176	}
3177	
3178	// Return the chain with the tags removed
3179	return chain.slice(0, chain.length-total_to_slice);
3180}
3181
3182/**
3183 *  Test to see if the element passed in is a class or an id
3184 *  return true || false
3185 */
3186function testForClassOrId( elem ) {
3187	return !!( elem && elem.indexOf(".") < 0 && elem.indexOf("#") < 0 );
3188}
3189
3190
3191/**
3192 * 	#########################################################################################################
3193 *  jQuery plugin-style extensions
3194 *  These initiate the user's actions for hover and click
3195 *  #########################################################################################################
3196 */
3197/* !jQuery plugins */ 
3198(function($) {
3199	/**
3200	 *  Initializes the inspector
3201	 *  Sets all properties to have a hover state to visually show element
3202	 *  On click, will return the chain of classes
3203	 *  Only allow click if the "inspector" attribute is available
3204	 */
3205	$.fn.CssInspector = function() {
3206		
3207		$(this).removeAttr("onclick").unbind("click").die("dblclick").hover(
3208			function() { 
3209				if($(this).attr("inspector")) {
3210					// Grab the initial outline and set the data for it
3211					$(this).setOutline();
3212		
3213					// Add the hovering data state
3214					$(this).attr("inspecting", true).data("hovering", true);
3215					// Find the most drilled of all hovers
3216					Inspector.HoverList.Optimize();
3217				}
3218			},
3219			function() {
3220				if($(this).attr("inspector")) {
3221					// Remove the hover state from this element
3222					$(this).attr("inspecting", false).data("hovering", false);
3223					
3224					// Find the most drilled of the remaining hovers
3225					Inspector.HoverList.Optimize();
3226															
3227					// Re-add the old outline
3228					if( $(this).data("outline") ) {
3229						$(this).css({
3230							"outline" : $(this).data("outline").join(" "),
3231							"outline-offset" : $(this).data("o-offset")
3232						});
3233					} else {
3234						$(this).css({
3235							"outline" : "none",
3236							"outline-offset" : "0px"
3237						});
3238					}									
3239				}
3240			}
3241			
3242		).click(function(e) {
3243			
3244			if($(this).attr("inspector")) {
3245				var chain_return = $(this).ReturnCssChain();
3246				
3247				// Only do something if we returned a positive
3248				if( chain_return ) {
3249					// Save the DOM chain from the clicked class on up
3250					Inspector.CSS.SaveChain( chain_return );
3251					
3252					// Show only the drilled classes
3253					// Inspector.CSS.ShowDrilledClasses();
3254					Inspector.CSS.ShowRelatedClasses();
3255					
3256					// If the index is still up, hide it
3257					if($(".css_inspector_index").is(":visible")) {
3258						Inspector.QuickSelect.hide();
3259					}
3260					
3261					$(this).blur();
3262				
3263				}
3264								
3265				return false;
3266			}
3267		
3268		}).dblclick(function(e) {
3269			if( $(this).attr("id") == "mainwrapper") {
3270				$(document).trigger("closeProject");
3271			
3272			} else if( $(this).attr("id") == "search_term" ) { 
3273				$(this).focus();
3274			
3275			}else if( $(this).attr("href") == "#" ) {
3276				// Don't allow # to be clicked
3277				return;
3278			
3279			} else if(!$(this).attr("rel") && $(this).attr("href") ){
3280				// Follow the link
3281				document.location.href = $(this).attr("href");
3282			}
3283						
3284		});
3285		
3286		// Check for any custom navigation and init it
3287		if( typeof customNavigationDblClick == "function") {
3288			customNavigationDblClick();
3289		}
3290		
3291	};
3292	
3293	
3294	/**
3295	 *  Drills down to the lowest element, then bubbles up with each
3296	 *  Returns either array or string
3297	 */
3298	$.fn.ReturnCssChain = function() {
3299	
3300		Cargo.log( $(this) );
3301		
3302		var this_tag  = $(this).map(function() { return this.tagName.toLowerCase(); }).get(),
3303			this_elem = ($(this).attr("class") != "") ? "."+$.trim($(this).attr("class")).split(" ")[0] : "";
3304		
3305		/*	First, validate for a false click
3306		 *	Highlighting something in codemirror -> drag -> click the highlight
3307		 *		will return a value of "html", but html is not being inspected
3308		 *	Return false for this
3309		 *	Else, return "body" 
3310		 */
3311		if( this_tag == "html" ) {
3312			if( $(this).attr("inspecting") == "true") {
3313				return ["body"];
3314			
3315			} else {
3316				return false;
3317			}
3318		}
3319		
3320		
3321		/*
3322		 *  Map all the layers from bottom to top
3323		 *  Returns an array, which is reversed so that it orders top down
3324		 */
3325		var chain = $(this).parents().map(function () { 
3326					/* 	
3327					 *  If there is a class, return that. If not, return the tag name
3328					 */
3329					return (this.className != "") ? "."+$.trim(this.className).split(" ")[0] : this.tagName.toLowerCase();
3330				
3331				}).get().reverse();
3332		
3333		// Loop through each entry. Make sure it is !< 2 chars (prevents "a")
3334		for(key in chain) {
3335			if(chain[key].length < 2) {
3336				chain.splice(key,1);
3337			}
3338		}
3339		
3340		// Add the current elemnt to the chain
3341		if(this_elem && this_elem != "" && this_elem != ".") {
3342			/*
3343			 *  Intervention for the ".text" element 
3344			 *  	which appears in both title and tag
3345			 */
3346			if(this_elem == ".text") {
3347				for(key in CSS.Classes.ForcedClasses) {
3348					if(key == chain[chain.length-1]) {
3349						chain.push(CSS.Classes.ForcedClasses[key]);
3350					}	
3351				}
3352			/*
3353			 *  Intervention with the ".project_link" element
3354			 */
3355			} else if( this_elem == ".project_link" || this_elem == ".page_link" ) {
3356				chain.push(this_elem);
3357				if($(this).hasClass("nav_active")) {
3358					chain.push(".nav_active");
3359				}
3360			
3361			/*
3362			 *	Intervention for nav_container - find horiz or not
3363			 */
3364			} else if( this_elem == ".nav_container") {
3365				if($(this_elem).hasClass("horizontal")) {
3366					chain.push(".nav_container.horizontal");
3367				} else {
3368					chain.push( this_elem );
3369				}
3370				
3371			} else {
3372				chain.push(this_elem);
3373			}
3374		
3375			
3376		} else {
3377			/*
3378			 *  Check the tag of the clicked element
3379			 *  Not something we always want, so let's be specific
3380			 *  Generally, we don't want <a>, but in some cases we do
3381			 *  Generally we don't want tags (like <i>) but we do want <h1>
3382			 *  If found, it will push the value of the new "class" from ForcedClasses
3383			 */
3384	
3385			var this_tag 		= this.get(0).tagName.toLowerCase(),
3386				parent_class 	= chain[chain.length-1];
3387			
3388			switch(this_tag) {
3389				case "a" :
3390					// Check for fullscreen
3391					if(this.attr("id") == "fullscreen") {
3392						chain.push("#fullscreen");
3393						
3394					} else {
3395						/*
3396						 *  Check the parent element
3397						 */
3398						for(key in CSS.Classes.ForcedClasses) {
3399							if(key == chain[chain.length-1]) {
3400								chain.push(CSS.Classes.ForcedClasses[key]);
3401								break;
3402							}	
3403						}
3404						// Bubbles up to find the lowest class
3405						chain = bubbleUp(chain);
3406					}
3407					
3408					break;
3409				
3410				case "img" : 
3411					/*
3412					 *  Single instance, but look for project content as parent
3413					 */
3414					if(chain[chain.length-1] == ".project_content") {
3415						chain.push(".project_content img");
3416						break;
3417						
3418					} else if(chain[chain.length-1] == ".webkit") {
3419						chain.push(".project_content img");
3420						break;
3421					}
3422					break;
3423				
3424				case "div" : 
3425					/*
3426					 *  Single instance, but look for project content as parent
3427					 */
3428					if(chain[chain.length-2] == ".open_project") {
3429						chain.push("#mainwrapper");
3430						break;
3431					
3432					} else if( this.attr("id") == "content_container" ) {
3433						chain.push("#content_container");
3434					
3435					} else if( this.attr("id") == "header" ) {
3436						chain.push("#header");
3437					
3438					} else if( this.attr("id").indexOf("page_") >= 0 ) {
3439						chain.push("#content_container");
3440					}
3441					// Bubbles up to find the lowest class
3442					chain = bubbleUp(chain);
3443					break;
3444				
3445				case "form" : 
3446					/*
3447					 *  Single instance, looking for the id of the form
3448					 */
3449					if( this.attr("id") == "search_form_results" ) {
3450						chain.push("#search_form_results");
3451					}
3452					break;
3453				
3454				case "input" :
3455					/*
3456					 *  Single instance, looking for the id of the input
3457					 */
3458					if( this.attr("id") == "search_term" ) {
3459						chain.push("#search_term");
3460					}
3461					break;
3462				
3463				case "h1" :
3464					chain.push("h1");
3465					break;
3466				
3467				case "h2" :
3468					chain.push("h2");
3469					break;
3470				
3471				case "h3" :
3472					chain.push("h3");
3473					break;
3474					
3475				case "html" :
3476					chain.push("html");
3477					chain.push("body");
3478					break;
3479									
3480				default :
3481					/*
3482					 *  Check the actual element (<h1>, etc) 
3483					 */
3484					for(key in CSS.Classes.ForcedClasses) {
3485						if(key == this_tag) {
3486							chain.push(this_tag);
3487							break;
3488						}	
3489					}
3490					
3491					// Bubbles up to find the lowest class
3492					chain = bubbleUp(chain);
3493					break;
3494			}
3495		}
3496		
3497		Cargo.log(chain);
3498		
3499		//return chain.join(", "); // return string
3500		return chain; // return array
3501	
3502	};
3503	
3504	
3505	/**
3506	 *  Seeks out and returns the exact match CSS class for a single element
3507	 *   - unused
3508	 */
3509	$.fn.ReturnCssClass = function() {
3510		// Make sure the class is not blank
3511		if($(this).attr("class") != "") {
3512			return CSS.Classes.Get("Preview", "."+$(this).attr("class"));
3513		}
3514	};
3515	
3516	/**
3517	 *  Quick sort
3518	 *  Sorts through a list of displayed classes to narrow them down
3519	 *  Uses string comparison to find a part of a word for quick search
3520	 *  Acts like a search
3521	 */
3522	$.fn.QuickSort = function() {
3523		var val 		= $(this).val().trim(),
3524			key_count 	= val.length;
3525		
3526		// Loop through each quick_sort item
3527		$("a[rel=quick_sort]").each(function() {
3528			if(val == "") {
3529				$(this).css("display","table");
3530				
3531			} else if($(this).html().indexOf(val) >= 0) {
3532				$(this).css("display","table");
3533				
3534			} else {
3535				$(this).css("display","none");
3536			}
3537		
3538		});
3539	
3540		
3541	};
3542	
3543	/**
3544	 *  Loops through the siblings of the object
3545	 *  Uses Code Mirror's tags to find the proper class name
3546	 *  It will first look on to the selected class's siblings
3547	 *  If this is not found, it will look for parent's children
3548	 *  Accepts a var of "closest_attr" input. This is the value
3549	 *  of the closest attr (i.e. color, background-color, border, etc)
3550	 *  Set's the obj's data for attr and class
3551	 */
3552	$.fn.FindClassAndAttribute = function(closest_attr) {
3553		var class_name_array 	= [],
3554			chain				= [],
3555			found_open 			= false,
3556			found_sibling 		= false,
3557			color_attr			= false,
3558			related_values		= [];
3559			
3560		
3561		// Look on the same line
3562		$(this).siblings().each(function() {
3563			if($(this).text().indexOf("{") > 0) {
3564				// The class name is on the same line
3565				found_sibling = true;
3566			}
3567			if($(this).hasClass("cm-variable")) {
3568				// This is the attribute (eg: bottom-border)
3569				if(closest_attr == $(this).text()) {
3570					color_attr = $(this).text();
3571				} else if(closest_attr.indexOf(" ") > 0) {
3572					color_attr = $(this).text();
3573				}
3574			}
3575			
3576			if($(this).hasClass("cm-number")) {
3577				// This might be a realted value (ie: 1px solid)
3578				if(closest_attr == $(this).text()) {
3579					related_values.push($(this).text());
3580				} else if(closest_attr.indexOf(" ") > 0) {
3581					related_values.push($(this).text());
3582				}
3583			}
3584			
3585			chain.push($(this));
3586		});
3587		
3588		chain.reverse();
3589					
3590		// Look for parent elements if we did not find the class on the same row
3591		if(found_sibling !== true) {
3592			chain = $(this).parents("pre").prevAll().children().map(function() {
3593						return $(this);
3594					}).get().reverse();
3595		}
3596		
3597		// Loop through the chain to find a match
3598		$.each(chain, function(key, value) {
3599			// Exit the loop if we have what we need
3600			if(value.text().indexOf("}") >= 0 && found_open === true) {
3601				found_open = false;
3602				return false;
3603			}
3604			
3605			// If we found a match, add it to the array
3606			if(value.text().indexOf("{") >= 0 || found_open === true) {
3607				if(value.text().indexOf("{") >= 0) {
3608					found_open = true;
3609				
3610				} else {
3611					class_name_array.push(value.text());
3612				
3613				}
3614			}
3615		});
3616		
3617		// Reverse the array
3618		class_name_array.reverse();
3619		
3620		// Set the data of the element
3621		$(this).data("Class", class_name_array.join(""));
3622		$(this).data("Attribute", color_attr);
3623		$(this).data("Related", related_values.join(" "));
3624		
3625	};
3626	
3627	
3628	/**
3629	 *  reload the history clicks
3630	 *  Unbinds any double click and moves the action to single click
3631	 */
3632	 $.fn.reloadHistory = function() {
3633	 	// Remap history clicks to single click
3634		$(this).unbind("dblclick").click(function() {
3635			Cargo.History.Load( $(this).data("hash") );
3636			return false;
3637		});
3638	 };
3639	 
3640	 /**
3641	  *  unload the history clicks
3642	  *  Unbinds any single click and moves the action to double click
3643	  */
3644	 $.fn.unloadHistory = function() {
3645	 	// Remap history clicks to single click
3646		$(this).unbind("click").dblclick(function() {
3647			Cargo.History.Load( $(this).data("hash") );
3648			return false;
3649		});
3650	 };
3651	 
3652	 /**
3653	  *	When the inspector is started, save the value of the current outline
3654	  *	This is used when hovering and reverting the hover to it's init state
3655	  */
3656	 $.fn.setOutline = function() {
3657	 	if(!$(this).data("outline")) {
3658			var old_outline = [
3659				$(this).css("outline-width"), 
3660				$(this).css("outline-style"), 
3661				$(this).css("outline-color")
3662			];
3663
3664			/* As of Safari version 6, it would return "initial" as
3665			 * a value for "width", so we are replacing this with defaults
3666			 * This hack, brought to you by Josh
3667			 */
3668			if( $(this).css("outline-width") == "initial") {
3669				old_outline = ["0px", "none", "rgb(0, 0, 0)"];
3670			}
3671			
3672			$(this)
3673				.data("outline", old_outline)
3674				.data("o-offset", $(this).css("outline-offset"));
3675		}
3676	 };
3677		
3678})(jQuery);
3679
3680
3681
3682///////////////////////////////////////////////////////////////////////////////////////////////////////////

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.