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.