├── .bowerrc ├── .gitignore ├── .htaccess ├── README.md ├── css ├── fonts │ ├── Chunkfive-webfont.eot │ ├── Chunkfive-webfont.svg │ ├── Chunkfive-webfont.ttf │ ├── Chunkfive-webfont.woff │ ├── League_Gothic-webfont.eot │ ├── League_Gothic-webfont.svg │ ├── League_Gothic-webfont.ttf │ └── League_Gothic-webfont.woff ├── jquery.qtip.min.css └── style.css ├── ext.zip ├── ext ├── _locales │ └── en │ │ └── messages.json ├── icons │ ├── icon128.png │ ├── icon16.png │ ├── icon19.png │ └── icon48.png ├── js │ ├── angular │ │ ├── angular.js │ │ ├── angular.min.js │ │ └── component.json │ └── jquery │ │ ├── .gitignore │ │ ├── component.json │ │ ├── jquery.js │ │ └── jquery.min.js ├── manifest.json └── src │ ├── bg │ ├── background.html │ └── background.js │ ├── browser_action │ └── browser_action.html │ ├── inject │ ├── inject.css │ └── inject.js │ ├── options │ └── index.html │ ├── options_custom │ ├── README.md │ ├── css │ │ ├── main.css │ │ └── setting.css │ ├── custom.css │ ├── i18n.js │ ├── icon.png │ ├── index.html │ ├── js │ │ ├── classes │ │ │ ├── fancy-settings.js │ │ │ ├── search.js │ │ │ ├── setting.js │ │ │ └── tab.js │ │ └── i18n.js │ ├── lib │ │ ├── default.css │ │ ├── mootools-core.js │ │ └── store.js │ ├── manifest.js │ └── settings.js │ ├── override │ └── override.html │ └── page_action │ └── page_action.html ├── favicon.png ├── img ├── bg.png ├── bp_logo.png ├── bp_logo2.png ├── github-logo.png ├── help.png ├── icon16.png ├── noise.png └── preview.png ├── index.html ├── js ├── libs │ ├── jquery-1.8.3.min.js │ ├── jquery.qtip.min.js │ └── modernizr-2.0.6.min.js └── script.js └── zip ├── dataview.js ├── deflate.js ├── inflate.js ├── mime-types.js ├── zip-ext.js ├── zip-fs.js └── zip.js /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory" : "/ext/js", 3 | "json" : "component.json" 4 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .settings 3 | composer.json 4 | 5 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Options +FollowSymLinks 3 | IndexIgnore */* 4 | RewriteEngine On 5 | RewriteCond %{REQUEST_FILENAME} !-f 6 | RewriteCond %{REQUEST_FILENAME} !-d 7 | RewriteRule (.*) index.html 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Extensionizr.com](http://extensionizr.com)! 2 | ============= 3 | [![extensionizr](https://raw.github.com/altryne/extensionizr/master/img/bp_logo.png)](http://extensionizr.com) 4 | 5 | Build yourself a chrome extension in 15sec. Check it out [here](http://extensionizr.com) 6 | ------------------------- 7 | 8 | Another *izr? When will this stop 9 | --------------------------------- 10 | Extensionizr is a simple way to jump start your chrome extension development. Just select the type of extension you want, choose permissions and you're off. 11 | 12 | Why does this exist? 13 | -------------------- 14 | Because I got super tired creating the file structure for a new extension over and over again. 15 | Extensionizr will be always updated with the latest chrome manifest changes. 16 | In addition, I wanted to create a client-side only tool. Extensionizr doesn't use server side code! Don't believe me? Checkout the github repo. 17 | 18 | Based on open source 19 | -------------------- 20 | Extensionizr is 90% based on open source pieces I put together. 21 | It's heavily inspired by Initializr by Jonathan Verrecchia. 22 | 23 | Source from : 24 | 25 | * https://github.com/Swader/ChromeSkel_a 26 | * https://github.com/gildas-lormeau/zip.js 27 | * https://github.com/mahemoff/chrome-boilerplate 28 | * https://github.com/verekia/initializr-website 29 | 30 | License 31 | ------- 32 | Copyright (c) 2012 Alex Wolkov. Licensed under the MIT, GPL licenses. See here for more details. -------------------------------------------------------------------------------- /css/fonts/Chunkfive-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/css/fonts/Chunkfive-webfont.eot -------------------------------------------------------------------------------- /css/fonts/Chunkfive-webfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This is a custom SVG webfont generated by Font Squirrel. 6 | Copyright : Generated in 2009 by FontLab Studio Copyright info pending 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /css/fonts/Chunkfive-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/css/fonts/Chunkfive-webfont.ttf -------------------------------------------------------------------------------- /css/fonts/Chunkfive-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/css/fonts/Chunkfive-webfont.woff -------------------------------------------------------------------------------- /css/fonts/League_Gothic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/css/fonts/League_Gothic-webfont.eot -------------------------------------------------------------------------------- /css/fonts/League_Gothic-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/css/fonts/League_Gothic-webfont.ttf -------------------------------------------------------------------------------- /css/fonts/League_Gothic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/css/fonts/League_Gothic-webfont.woff -------------------------------------------------------------------------------- /css/jquery.qtip.min.css: -------------------------------------------------------------------------------- 1 | /*! qtip2 v2.0.0pre | http://craigsworks.com/projects/qtip2/ | Licensed MIT, GPL */.qtip,.qtip{position:absolute;left:-28000px;top:-28000px;display:none;max-width:280px;min-width:50px;font-size:10.5px;line-height:12px;direction:ltr}.qtip-content{position:relative;padding:5px 9px;overflow:hidden;text-align:left;word-wrap:break-word}.qtip-titlebar{position:relative;padding:5px 35px 5px 10px;overflow:hidden;border-width:0 0 1px;font-weight:700}.qtip-titlebar+.qtip-content{border-top-width:0!important}.qtip-close{position:absolute;right:-9px;top:-9px;cursor:pointer;outline:medium none;border-width:1px;border-style:solid;border-color:transparent}.qtip-titlebar .qtip-close{right:4px;top:50%;margin-top:-9px}* html .qtip-titlebar .qtip-close{top:16px}.qtip-titlebar .ui-icon,.qtip-icon .ui-icon{display:block;text-indent:-1000em;direction:ltr;vertical-align:middle}.qtip-icon,.qtip-icon .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;text-decoration:none}.qtip-icon .ui-icon{width:18px;height:14px;text-align:center;text-indent:0;font:normal bold 10px/13px Tahoma,sans-serif;color:inherit;background:transparent none no-repeat -100em -100em}.qtip-focus{}.qtip-hover{}.qtip-default{border-width:1px;border-style:solid;border-color:#F1D031;background-color:#FFFFA3;color:#555}.qtip-default .qtip-titlebar{background-color:#FFEF93}.qtip-default .qtip-icon{border-color:#CCC;background:#F1F1F1;color:#777}.qtip-default .qtip-titlebar .qtip-close{border-color:#AAA;color:#111}/*! Light tooltip style */.qtip-light{background-color:#fff;border-color:#E2E2E2;color:#454545}.qtip-light .qtip-titlebar{background-color:#f1f1f1}/*! Dark tooltip style */.qtip-dark{background-color:#505050;border-color:#303030;color:#f3f3f3}.qtip-dark .qtip-titlebar{background-color:#404040}.qtip-dark .qtip-icon{border-color:#444}.qtip-dark .qtip-titlebar .ui-state-hover{border-color:#303030}/*! Cream tooltip style */.qtip-cream{background-color:#FBF7AA;border-color:#F9E98E;color:#A27D35}.qtip-cream .qtip-titlebar{background-color:#F0DE7D}.qtip-cream .qtip-close .qtip-icon{background-position:-82px 0}/*! Red tooltip style */.qtip-red{background-color:#F78B83;border-color:#D95252;color:#912323}.qtip-red .qtip-titlebar{background-color:#F06D65}.qtip-red .qtip-close .qtip-icon{background-position:-102px 0}.qtip-red .qtip-icon{border-color:#D95252}.qtip-red .qtip-titlebar .ui-state-hover{border-color:#D95252}/*! Green tooltip style */.qtip-green{background-color:#CAED9E;border-color:#90D93F;color:#3F6219}.qtip-green .qtip-titlebar{background-color:#B0DE78}.qtip-green .qtip-close .qtip-icon{background-position:-42px 0}/*! Blue tooltip style */.qtip-blue{background-color:#E5F6FE;border-color:#ADD9ED;color:#5E99BD}.qtip-blue .qtip-titlebar{background-color:#D0E9F5}.qtip-blue .qtip-close .qtip-icon{background-position:-2px 0}.qtip-shadow{-webkit-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);-moz-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);box-shadow:1px 1px 3px 1px rgba(0,0,0,.15)}.qtip-rounded,.qtip-tipsy,.qtip-bootstrap{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.qtip-youtube{-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 3px #333;-moz-box-shadow:0 0 3px #333;box-shadow:0 0 3px #333;color:#fff;border-width:0;background:#4A4A4A;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0, #4A4A4A),color-stop(100%,black));background-image:-webkit-linear-gradient(top, #4A4A4A 0,black 100%);background-image:-moz-linear-gradient(top, #4A4A4A 0,black 100%);background-image:-ms-linear-gradient(top, #4A4A4A 0,black 100%);background-image:-o-linear-gradient(top, #4A4A4A 0,black 100%)}.qtip-youtube .qtip-titlebar{background-color:#4A4A4A;background-color:rgba(0,0,0,0)}.qtip-youtube .qtip-content{padding:.75em;font:12px arial,sans-serif;filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#4a4a4a, EndColorStr=#000000);-ms-filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#4a4a4a, EndColorStr=#000000);"}.qtip-youtube .qtip-icon{border-color:#222}.qtip-youtube .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-jtools{background:#232323;background:rgba(0,0,0,.7);background-image:-webkit-gradient(linear,left top,left bottom,from( #717171),to( #232323));background-image:-moz-linear-gradient(top, #717171, #232323);background-image:-webkit-linear-gradient(top, #717171, #232323);background-image:-ms-linear-gradient(top, #717171, #232323);background-image:-o-linear-gradient(top, #717171, #232323);border:2px solid #ddd;border:2px solid rgba(241,241,241,1);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 12px #333;-moz-box-shadow:0 0 12px #333;box-shadow:0 0 12px #333}.qtip-jtools .qtip-titlebar{background-color:transparent;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171, endColorstr=#4A4A4A);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171, endColorstr=#4A4A4A)"}.qtip-jtools .qtip-content{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A, endColorstr=#232323);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A, endColorstr=#232323)"}.qtip-jtools .qtip-titlebar,.qtip-jtools .qtip-content{background:transparent;color:#fff;border:0 dashed transparent}.qtip-jtools .qtip-icon{border-color:#555}.qtip-jtools .qtip-titlebar .ui-state-hover{border-color:#333}.qtip-cluetip{-webkit-box-shadow:4px 4px 5px rgba(0,0,0,.4);-moz-box-shadow:4px 4px 5px rgba(0,0,0,.4);box-shadow:4px 4px 5px rgba(0,0,0,.4);background-color:#D9D9C2;color:#111;border:0 dashed transparent}.qtip-cluetip .qtip-titlebar{background-color:#87876A;color:#fff;border:0 dashed transparent}.qtip-cluetip .qtip-icon{border-color:#808064}.qtip-cluetip .qtip-titlebar .ui-state-hover{border-color:#696952;color:#696952}.qtip-tipsy{background:#000;background:rgba(0,0,0,.87);color:#fff;border:0 solid transparent;font-size:11px;font-family:'Lucida Grande',sans-serif;font-weight:700;line-height:16px;text-shadow:0 1px black}.qtip-tipsy .qtip-titlebar{padding:6px 35px 0 10;background-color:transparent}.qtip-tipsy .qtip-content{padding:6px 10}.qtip-tipsy .qtip-icon{border-color:#222;text-shadow:none}.qtip-tipsy .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-tipped{border:3px solid #959FA9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-color:#F9F9F9;color:#454545;font-weight:400;font-family:serif}.qtip-tipped .qtip-titlebar{border-bottom-width:0;color:#fff;background:#3A79B8;background-image:-webkit-gradient(linear,left top,left bottom,from( #3A79B8),to( #2E629D));background-image:-webkit-linear-gradient(top, #3A79B8, #2E629D);background-image:-moz-linear-gradient(top, #3A79B8, #2E629D);background-image:-ms-linear-gradient(top, #3A79B8, #2E629D);background-image:-o-linear-gradient(top, #3A79B8, #2E629D);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8, endColorstr=#2E629D);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8, endColorstr=#2E629D)"}.qtip-tipped .qtip-icon{border:2px solid #285589;background:#285589}.qtip-tipped .qtip-icon .ui-icon{background-color:#FBFBFB;color:#555}.qtip-bootstrap{font-size:14px;line-height:20px;color:#333;padding:1px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.qtip-bootstrap .qtip-titlebar{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.qtip-bootstrap .qtip-titlebar .qtip-close{right:11px;top:45%;border-style:none}.qtip-bootstrap .qtip-content{padding:9px 14px}.qtip-bootstrap .qtip-icon{background:transparent}.qtip-bootstrap .qtip-icon .ui-icon{width:auto;height:auto;float:right;font-size:20px;font-weight:700;line-height:18px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.qtip-bootstrap .qtip-icon .ui-icon:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}.qtip:not(.ie9haxors) div.qtip-content,.qtip:not(.ie9haxors) div.qtip-titlebar{filter:none;-ms-filter:none}.qtip .qtip-tip{margin:0 auto;overflow:hidden;z-index:10}.qtip .qtip-tip,.qtip .qtip-tip .qtip-vml{position:absolute;color:#123456;background:transparent;border:0 dashed transparent}.qtip .qtip-tip canvas{top:0;left:0}.qtip .qtip-tip .qtip-vml{behavior:url(#default#VML);display:inline-block;visibility:visible}#qtip-overlay{position:fixed;left:-10000em;top:-10000em}#qtip-overlay.blurs{cursor:pointer}#qtip-overlay div{position:absolute;left:0;top:0;width:100%;height:100%;background-color:#000;opacity:.7;filter:alpha(opacity=70);-ms-filter:"alpha(Opacity=70)"}.qtipmodal-ie6fix{position:absolute!important} -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; } 2 | audio[controls], canvas, video { display: inline-block; *display: inline; *zoom: 1; } 3 | html { font-size: 100%; overflow-y: scroll; -webkit-overflow-scrolling: touch; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } 4 | body { margin: 0; font-size: 13px; line-height: 1.231; } 5 | body, button, input, select, textarea { font-family: sans-serif; color: #222; } 6 | 7 | a { color: #00e; } 8 | a:visited { color: #551a8b; } 9 | a:focus { outline: thin dotted; } 10 | a:hover, a:active { outline: 0; } 11 | abbr[title] { border-bottom: 1px dotted; } 12 | b, strong { font-weight: bold; } 13 | blockquote { margin: 1em 40px; } 14 | dfn { font-style: italic; } 15 | hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; } 16 | ins { background: #ff9; color: #000; text-decoration: none; } 17 | mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; } 18 | pre, code, kbd, samp { font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 1em; } 19 | pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } 20 | q { quotes: none; } 21 | q:before, q:after { content: ""; content: none; } 22 | small { font-size: 85%; } 23 | sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } 24 | sup { top: -0.5em; } 25 | sub { bottom: -0.25em; } 26 | ul, ol { margin: 1em 0; padding: 0 0 0 40px; } 27 | dd { margin: 0 0 0 40px; } 28 | nav ul, nav ol { list-style: none; margin: 0; padding: 0; } 29 | img { border: 0; -ms-interpolation-mode: bicubic; } 30 | svg:not(:root) { 31 | overflow: hidden; 32 | } 33 | figure { margin: 0; } 34 | form { margin: 0; } 35 | fieldset { border: 0; margin: 0; padding: 0; } 36 | legend { border: 0; *margin-left: -7px; padding: 0; } 37 | label { cursor: pointer; } 38 | button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; } 39 | button, input { line-height: normal; *overflow: visible; } 40 | button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; } 41 | input[type="checkbox"], input[type="radio"] { box-sizing: border-box; } 42 | input[type="search"] { -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; } 43 | button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } 44 | textarea { overflow: auto; vertical-align: top; } 45 | input:valid, textarea:valid { } 46 | input:invalid, textarea:invalid { background-color: #f0dddd; } 47 | table { border-collapse: collapse; border-spacing: 0; } 48 | 49 | 50 | 51 | 52 | 53 | 54 | @font-face { 55 | font-family: 'ChunkFiveRegular'; 56 | src: url('fonts/Chunkfive-webfont.eot'); 57 | src: url('fonts/Chunkfive-webfont.eot?#iefix') format('embedded-opentype'), 58 | url('fonts/Chunkfive-webfont.woff') format('woff'), 59 | url('fonts/Chunkfive-webfont.ttf') format('truetype'), 60 | url('fonts/Chunkfive-webfont.svg#ChunkFiveRegular') format('svg'); 61 | font-weight: normal; 62 | font-style: normal; 63 | } 64 | 65 | @font-face { 66 | font-family: 'LeagueGothicRegular'; 67 | src: url('fonts/League_Gothic-webfont.eot'); 68 | src: url('fonts/League_Gothic-webfont.eot?#iefix') format('embedded-opentype'), 69 | url('fonts/League_Gothic-webfont.woff') format('woff'), 70 | url('fonts/League_Gothic-webfont.ttf') format('truetype'), 71 | url('fonts/League_Gothic-webfont.svg#LeagueGothicRegular') format('svg'); 72 | font-weight: normal; 73 | font-style: normal; 74 | } 75 | 76 | 77 | 78 | /* =================================================== 79 | Initializr styles 80 | http://verekia.com/initializr/responsive-template 81 | Author: Jonathan Verrecchia 82 | =================================================== */ 83 | 84 | body{ font:16px/26px Helvetica, Helvetica Neue, Arial; } 85 | 86 | .wrapper{ 87 | width:90%; 88 | margin:0 5%; 89 | } 90 | 91 | /* =================== 92 | ALL: Orange Theme 93 | =================== */ 94 | 95 | #header-container{ padding-bottom:13px; position: relative;} 96 | 97 | #header-container{ 98 | background:url(../img/bp_logo.png) no-repeat 50% 0% ,url("../img/bg.png") repeat 9px -32px; 99 | } 100 | #header-container::after{ 101 | position: absolute; 102 | content:""; 103 | bottom:0; 104 | height: 13px; 105 | background: url(../img/noise.png) repeat; 106 | width:100%; 107 | left:0; 108 | border-top:1px solid rgba(255,255,255,0.7) 109 | } 110 | 111 | #title{ 112 | color:white; 113 | font-family:'ChunkFiveRegular'; 114 | font-weight:normal; 115 | font-size:4em; 116 | margin-bottom:20px; 117 | } 118 | 119 | #header-container h2{ 120 | color:white; 121 | font-size:16px; 122 | } 123 | 124 | #header-container header{ 125 | text-align:center; 126 | } 127 | 128 | ::-moz-selection { background: #e6443c; color: #fff; text-shadow: none; } 129 | ::selection { background: #e6443c; color: #fff; text-shadow: none; } 130 | 131 | 132 | 133 | /* WEBSITE */ 134 | 135 | #html5-logo-container{ 136 | display:none; 137 | } 138 | 139 | #follow-container{ 140 | display:none; 141 | } 142 | 143 | 144 | #badges{ 145 | margin:0 auto; 146 | width:265px; 147 | margin-top:10px; 148 | line-height:18px; 149 | font-size:14px; 150 | color:white; 151 | font-weight:bold; 152 | font-style:italic; 153 | 154 | } 155 | 156 | #badges li{ 157 | float:left; 158 | background:#eee; 159 | color:#444; 160 | text-align:center; 161 | width:85px; 162 | height:85px; 163 | /* border:10px solid #E44D26; */ 164 | -webkit-border-radius:999px; 165 | -moz-border-radius:999px; 166 | border-radius:999px; 167 | margin-left:5px; 168 | text-shadow:0 2px 1px white; 169 | box-shadow:1px 1px 1px rgba(0, 0, 0, 0.4); 170 | } 171 | 172 | #badges li:first-child{ 173 | margin-left:0; 174 | } 175 | 176 | .badge-label{ 177 | margin-top:26px; 178 | } 179 | 180 | #badges ul{ 181 | float:right; 182 | margin:0; 183 | list-style-type:none; 184 | padding:0; 185 | } 186 | 187 | 188 | .separator{ 189 | font-family:LeagueGothicRegular; 190 | text-align:center; 191 | font-weight:normal; 192 | font-size:3em; 193 | color:#e6443c; 194 | margin:50px 0; 195 | } 196 | 197 | .separator:before, 198 | .separator:after{ 199 | width:20%; 200 | height:4px; 201 | display:block; 202 | background:#eee; 203 | content:""; 204 | margin-top:14px; 205 | display:none; 206 | } 207 | 208 | 209 | .separator:before{ 210 | float:left; 211 | } 212 | 213 | .separator:after{ 214 | float:right; 215 | } 216 | 217 | #fine-tuning-separator{ 218 | margin:30px 0 20px; 219 | } 220 | 221 | .blank-background button, 222 | .blank-background a{ 223 | background:#bbb; 224 | } 225 | 226 | .blank-background button:hover, 227 | .blank-background a:hover{ 228 | background:#c4c4c4; 229 | } 230 | 231 | .blank-background button:active{ 232 | background:#888; 233 | } 234 | 235 | 236 | 237 | .initializr-background button, 238 | .initializr-background a{ 239 | background:#e6443c; 240 | } 241 | 242 | .initializr-background button:hover, 243 | .initializr-background a:hover{ 244 | background: #f1453d; 245 | } 246 | 247 | .initializr-background button:active{ 248 | background: #cd3e36; 249 | } 250 | 251 | .bootstrap-background button, 252 | .bootstrap-background a{ 253 | background:#328ae2; 254 | } 255 | 256 | .bootstrap-background button:hover, 257 | .bootstrap-background a:hover{ 258 | background: #339cf5; 259 | } 260 | 261 | .bootstrap-background button:active{ 262 | background:#4070df; 263 | } 264 | 265 | #preconfig-section{ 266 | padding-bottom:10px; 267 | } 268 | 269 | .preconfig-container{ 270 | display:block; 271 | width:100%; 272 | } 273 | 274 | .preconfig-block{ 275 | border:none; 276 | display:block; 277 | width:100%; 278 | } 279 | 280 | #preconfig-section h3, 281 | #download-section a 282 | { 283 | font-weight:normal; 284 | font-family:ChunkFiveRegular; 285 | font-size:2em; 286 | color:white; 287 | margin:0; 288 | text-align:center; 289 | padding:25px 0; 290 | text-shadow:0 -2px 2px rgba(0, 0, 0, 0.1); 291 | color:white; 292 | letter-spacing: 1px; 293 | } 294 | 295 | .preconfig-links-container{ 296 | width:100px; 297 | margin:6px auto; 298 | } 299 | 300 | #preconfig-section a{ 301 | padding:4px; 302 | color:white; 303 | font-weight:bold; 304 | text-decoration:none; 305 | margin:0px; 306 | -webkit-border-radius:0 3px 3px 0; 307 | -moz-border-radius:0 3px 3px 0; 308 | border-radius:0 3px 3px 0; 309 | } 310 | 311 | #preconfig-section a.first{ 312 | -webkit-border-radius:3px 0 0 3px; 313 | -moz-border-radius:3px 0 0 3px; 314 | border-radius:3px 0 0 3px; 315 | } 316 | 317 | 318 | #main{ 319 | padding:30px 0; 320 | } 321 | 322 | #customize-section label{ 323 | background:white; 324 | -webkit-border-radius:4px; 325 | -moz-border-radius:4px; 326 | border-radius:4px; 327 | 328 | border:1px solid #ccc; 329 | border-top:0; 330 | border-left:0; 331 | 332 | padding:4px 8px; 333 | display:block; 334 | margin:0 5px 5px 0; 335 | position: relative; 336 | -moz-user-select: none; 337 | -webkit-user-select: none; 338 | -ms-user-select: none; 339 | user-select: none; 340 | } 341 | 342 | #customize-section label:hover{ 343 | background:#f5f5f5; 344 | } 345 | 346 | #customize-section input{ 347 | margin-right:6px; 348 | } 349 | 350 | .customize-section h3{ 351 | text-align:center; 352 | font-weight:normal; 353 | font-family:LeagueGothicRegular; 354 | font-size:2em; 355 | } 356 | 357 | .second-h5bp-label, 358 | .third-h5bp-label{ 359 | display:none; 360 | visibility:hidden; 361 | } 362 | 363 | .customize-section a{ 364 | color:#E44D26; 365 | text-decoration:none; 366 | } 367 | 368 | textarea{ 369 | display:block; 370 | width:700px; 371 | } 372 | 373 | .special-section{ 374 | width:100% !important; 375 | } 376 | .special-section label{ 377 | display: inline-block; 378 | } 379 | .special-section input[type="text"]{ 380 | background:white; 381 | -webkit-border-radius:4px; 382 | -moz-border-radius:4px; 383 | border-radius:4px; 384 | 385 | border:1px solid #ccc; 386 | border-top:0; 387 | border-left:0; 388 | 389 | padding:4px 8px; 390 | 391 | margin:0 5px 5px 0; 392 | background:#f5f5f5; 393 | display: inline-block; 394 | width: 60%; 395 | font-size: 25px; 396 | color: #2f2f2f; 397 | font-family: arial; 398 | letter-spacing: 1.2px; 399 | 400 | } 401 | #download-section{ 402 | margin-top:50px; 403 | } 404 | 405 | #download-section a{ 406 | background:url(../img/noise.png); 407 | display:block; 408 | text-decoration:none; 409 | margin-bottom:20px; 410 | } 411 | 412 | #download-section a:hover, 413 | #download-section a:focus{ 414 | background: rgb(50, 138, 226); 415 | } 416 | #download-section a:active{ 417 | background: rgb(33, 97, 157); 418 | } 419 | 420 | #gen-link.loading { 421 | cursor: progress; 422 | } 423 | 424 | #about-container{ 425 | background:#eee; 426 | padding:30px 0; 427 | } 428 | 429 | #about-container h3{ 430 | font-weight:normal; 431 | font-family:LeagueGothicRegular; 432 | font-size:2em; 433 | } 434 | 435 | #about-container a{ 436 | color:#E44D26; 437 | /* font-weight:bold; */ 438 | text-decoration:none; 439 | } 440 | 441 | #github-container img{ 442 | display:none; 443 | } 444 | 445 | 446 | #email:before{ 447 | content:"extensionizr@alexw.me"; 448 | } 449 | 450 | /* =============== 451 | ALL: IE Fixes 452 | =============== */ 453 | 454 | .ie7 #title{ padding-top:20px; } 455 | 456 | 457 | 458 | /* ============================================================================= 459 | Non-semantic helper classes 460 | Please define your styles before this section. 461 | ========================================================================== */ 462 | 463 | /* For image replacement */ 464 | .ir { display: block; text-indent: -999em; overflow: hidden; background-repeat: no-repeat; text-align: left; direction: ltr; } 465 | .ir br { display: none; } 466 | 467 | /* Hide for both screenreaders and browsers: 468 | css-discuss.incutio.com/wiki/Screenreader_Visibility */ 469 | .hidden { display: none; visibility: hidden; } 470 | 471 | /* Hide only visually, but have it available for screenreaders: by Jon Neal. 472 | www.webaim.org/techniques/css/invisiblecontent/ & j.mp/visuallyhidden */ 473 | .visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } 474 | 475 | /* Extends the .visuallyhidden class to allow the element to be focusable when navigated to via the keyboard: drupal.org/node/897638 */ 476 | .visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; } 477 | 478 | /* Hide visually and from screenreaders, but maintain layout */ 479 | .invisible { visibility: hidden; } 480 | 481 | /* Contain floats: nicolasgallagher.com/micro-clearfix-hack/ */ 482 | .clearfix:before, .clearfix:after { content: ""; display: table; } 483 | .clearfix:after { clear: both; } 484 | .clearfix { zoom: 1; } 485 | 486 | 487 | /* ==|== media queries ====================================================== */ 488 | 489 | @media only screen and (min-width: 540px) { 490 | 491 | /* ==================== 492 | INTERMEDIATE: Menu 493 | ==================== */ 494 | 495 | #header-container{ 496 | -webkit-box-shadow:0 5px 8px rgba(0, 0, 0, 0.15); 497 | -moz-box-shadow:0 5px 8px rgba(0, 0, 0, 0.15); 498 | box-shadow:0 5px 8px rgba(0, 0, 0, 0.15); 499 | } 500 | 501 | #header-container header{ 502 | text-align:left; 503 | height:133px; 504 | } 505 | 506 | 507 | .ie7 #header-container header, 508 | .ie8 #header-container header{ 509 | height:auto; 510 | } 511 | 512 | #title, 513 | #header-container h2, 514 | #follow-container p{ 515 | text-shadow:0 -2px 2px rgba(0, 0, 0, 0.1); 516 | } 517 | 518 | #title-container{ 519 | float:left; 520 | width:63%; 521 | } 522 | 523 | #html5-logo-container{ 524 | float:left; 525 | width:0; 526 | } 527 | 528 | #follow-iframes-container{ 529 | width:230px; 530 | float:left; 531 | } 532 | 533 | .twitter-share-button{ 534 | float:right; 535 | width:146px!important; 536 | width:180px !important; 537 | margin-bottom:6px; 538 | } 539 | 540 | .ie9 #follow-iframes-container iframe, 541 | .ie8 #follow-iframes-container iframe, 542 | .ie7 #follow-iframes-container iframe{ 543 | width:135px!important; 544 | } 545 | 546 | 547 | #follow-container{ 548 | float:right; 549 | width:37%; 550 | display:block; 551 | } 552 | 553 | #follow-container p{ 554 | text-align:right; 555 | color:white; 556 | font-weight:bold; 557 | margin:12px 0; 558 | } 559 | 560 | 561 | 562 | #follow-container a{ 563 | color:white; 564 | } 565 | 566 | #intro p{ 567 | /* float:left; */ 568 | margin-right:285px; 569 | } 570 | 571 | #badges{ 572 | float:right; 573 | } 574 | 575 | .separator:before, 576 | .separator:after{ 577 | width:20%; 578 | display:block; 579 | } 580 | 581 | .preconfig-container{ 582 | float:left; 583 | width:48%; 584 | margin:0 1%; 585 | } 586 | 587 | .preconfig-block{ 588 | } 589 | 590 | .preconfig-container:last-child{ 591 | margin:auto; 592 | float:none; 593 | clear:both; 594 | } 595 | 596 | #hidden-section{ 597 | /*display:none;*/ 598 | } 599 | 600 | .customize-section{ 601 | float:left; 602 | width:50%; 603 | } 604 | 605 | .customize-section:nth-child(2n + 1){ 606 | clear:both; 607 | } 608 | 609 | .second-h5bp-label{ 610 | display:block; 611 | } 612 | 613 | #download-section a{ 614 | width:48%; 615 | } 616 | 617 | #download-section a:first-child{ 618 | margin:0 auto; 619 | } 620 | 621 | #about-container{ 622 | -webkit-box-shadow: inset 0 10px 15px rgba(0, 0, 0, 0.1); 623 | -moz-box-shadow: inset 0 10px 15px rgba(0, 0, 0, 0.1); 624 | box-shadow: inset 0 10px 15px rgba(0, 0, 0, 0.1); 625 | 626 | } 627 | 628 | #about-container article{ 629 | width:100%; 630 | } 631 | 632 | #github-container{ 633 | margin:auto; 634 | width:480px; 635 | } 636 | 637 | #github-container img{ 638 | float:left; 639 | display:block; 640 | } 641 | 642 | #github-repositories{ 643 | float:right; 644 | margin-top:20px; 645 | } 646 | 647 | #github-repositories h3{ 648 | text-align:center; 649 | } 650 | 651 | } 652 | 653 | @media only screen and (min-width: 860px) { 654 | 655 | #title-container{ 656 | float:left; 657 | width:40%; 658 | } 659 | 660 | #html5-logo-container{ 661 | display:block; 662 | float:left; 663 | width:20%; 664 | } 665 | 666 | #html5-logo-container img{ 667 | display:block; 668 | margin:auto; 669 | } 670 | 671 | #follow-iframes-container{ 672 | width:240px; 673 | float:right; 674 | background: rgba(255,255,255,0.4); 675 | border: 1px solid #fff; 676 | padding-top: 5px; 677 | padding-left: 45px; 678 | } 679 | 680 | #follow-container{ 681 | float:right; 682 | width:40%; 683 | } 684 | 685 | #follow-container p:before{ 686 | content:"By "; 687 | } 688 | 689 | #follow-iframes-container iframe{ 690 | /*float:left;*/ 691 | /*width:auto!important;*/ 692 | /*min-width:185px;*/ 693 | /*margin-bottom:6px;*/ 694 | } 695 | .twitter-follow-button{ 696 | float:left; 697 | /*width:auto!important;*/ 698 | min-width:185px; 699 | margin-bottom:6px; 700 | } 701 | .twitter-share-button{ 702 | float:left; 703 | width:100px !important; 704 | } 705 | .facebook_like{ 706 | float: left; 707 | width:100px !important; 708 | } 709 | 710 | .ie9 #follow-iframes-container iframe, 711 | .ie8 #follow-iframes-container iframe, 712 | .ie7 #follow-iframes-container iframe{ 713 | width:auto!important; 714 | } 715 | 716 | #intro p{ 717 | /* width:56%; */ 718 | } 719 | 720 | #intro #badges{ 721 | /* width:44%; */ 722 | } 723 | 724 | .separator:before, 725 | .separator:after{ 726 | width:31%; 727 | } 728 | 729 | .preconfig-container{ 730 | width:32%; 731 | margin-right:2%; 732 | margin-left:0; 733 | } 734 | 735 | .preconfig-block{ 736 | } 737 | 738 | .ie8 .preconfig-container, 739 | .ie7 .preconfig-container{ 740 | width:31.33%; 741 | } 742 | 743 | .preconfig-container:last-child{ 744 | margin:0; 745 | float:left; 746 | clear:none; 747 | } 748 | 749 | 750 | .first-h5bp-label{ 751 | visibility:hidden; 752 | } 753 | 754 | .second-h5bp-label{ 755 | visibility:visible; 756 | } 757 | 758 | .third-h5bp-label{ 759 | display:block; 760 | } 761 | 762 | 763 | 764 | .customize-section{ 765 | width:33.3%; 766 | } 767 | 768 | .customize-section:nth-child(2n + 1){ 769 | clear:none; 770 | } 771 | 772 | .customize-section:nth-child(3n + 1){ 773 | clear:both; 774 | } 775 | 776 | 777 | #about-container article{ 778 | width:530px; 779 | } 780 | 781 | #github-container{ 782 | float:right; 783 | } 784 | 785 | #github-container img{ 786 | float:none; 787 | margin:0; 788 | } 789 | 790 | #github-repositories{ 791 | float:none; 792 | margin:0; 793 | } 794 | 795 | #github-container{ 796 | width:auto; 797 | } 798 | 799 | 800 | } 801 | 802 | 803 | @media only screen and (min-width: 1140px) { 804 | 805 | /* =============== 806 | Maximal Width 807 | =============== */ 808 | 809 | .wrapper{ 810 | width:1026px; /* 1140px - 10% for margins */ 811 | margin:0 auto; 812 | } 813 | } 814 | 815 | .more_info{ 816 | opacity: 0; 817 | /*-webkit-transition: all 150ms ease;*/ 818 | /*-moz-transition: all 150ms ease;*/ 819 | /*-ms-transition: all 150ms ease;*/ 820 | /*-o-transition: all 150ms ease;*/ 821 | /*transition: all 150ms ease;*/ 822 | 823 | right:5px; 824 | top:10px; 825 | width:18px; 826 | height:18px; 827 | background: url(../img/help.png) no-repeat; 828 | position: absolute; 829 | } 830 | h3{ 831 | position: relative; 832 | } 833 | label:hover .more_info, 834 | h3 .more_info{ 835 | opacity: 1; 836 | } 837 | h3 .more_info{ 838 | position: relative; 839 | display: inline-block; 840 | top:0; 841 | left:5px; 842 | } 843 | .qtip{ 844 | font-size: 16px !important; 845 | line-height: 20px !important; 846 | background: #328ae2 !important; 847 | border: none !important; 848 | color:#fff !important; 849 | box-shadow:0px 0px 5px rgba(0,0,0,0.5) !important; 850 | box-shadow:none !important; 851 | text-shadow:0 -1px 1px rgba(0,0,0,0.2) !important; 852 | pointer-events:none; 853 | } 854 | .qtip-content::after{ 855 | content:"*Click for more info (external)"; 856 | display: block; 857 | font-size:14px; 858 | padding-top:5px; 859 | } 860 | 861 | h1 a{ 862 | color: #fff !important; 863 | text-decoration: none; 864 | } 865 | 866 | /* ============================================================================= 867 | Print styles. 868 | Inlined to avoid required HTTP connection: www.phpied.com/delay-loading-your-print-css/ 869 | ========================================================================== */ 870 | 871 | @media print { 872 | * { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: sanbeiji.com/archives/953 */ 873 | a, a:visited { color: #444 !important; text-decoration: underline; } 874 | a[href]:after { content: " (" attr(href) ")"; } 875 | abbr[title]:after { content: " (" attr(title) ")"; } 876 | .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } /* Don't show links for images, or javascript/internal links */ 877 | pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } 878 | thead { display: table-header-group; } /* css-discuss.incutio.com/wiki/Printing_Tables */ 879 | tr, img { page-break-inside: avoid; } 880 | img { max-width: 100% !important; } 881 | @page { margin: 0.5cm; } 882 | p, h2, h3 { orphans: 3; widows: 3; } 883 | h2, h3{ page-break-after: avoid; } 884 | } 885 | -------------------------------------------------------------------------------- /ext.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/ext.zip -------------------------------------------------------------------------------- /ext/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "l10nTabName": { 3 | "message":"Localization" 4 | ,"description":"name of the localization tab" 5 | } 6 | ,"l10nHeader": { 7 | "message":"It does localization too! (this whole tab is, actually)" 8 | ,"description":"Header text for the localization section" 9 | } 10 | ,"l10nIntro": { 11 | "message":"'L10n' refers to 'Localization' - 'L' an 'n' are obvious, and 10 comes from the number of letters between those two. It is the process/whatever of displaying something in the language of choice. It uses 'I18n', 'Internationalization', which refers to the tools / framework supporting L10n. I.e., something is internationalized if it has I18n support, and can be localized. Something is localized for you if it is in your language / dialect." 12 | ,"description":"introduce the basic idea." 13 | } 14 | ,"l10nProd": { 15 | "message":"You are planning to allow localization, right? You have no idea who will be using your extension! You have no idea who will be translating it! At least support the basics, it's not hard, and having the framework in place will let you transition much more easily later on." 16 | ,"description":"drive the point home. It's good for you." 17 | } 18 | ,"l10nFirstParagraph": { 19 | "message":"When the options page loads, elements decorated with data-l10n will automatically be localized!" 20 | ,"description":"inform that elements will be localized on load" 21 | } 22 | ,"l10nSecondParagraph": { 23 | "message":"If you need more complex localization, you can also define data-l10n-args. This should contain $containerType$ filled with $dataType$, which will be passed into Chrome's i18n API as $functionArgs$. In fact, this paragraph does just that, and wraps the args in mono-space font. Easy!" 24 | ,"description":"introduce the data-l10n-args attribute. End on a lame note." 25 | ,"placeholders": { 26 | "containerType": { 27 | "content":"$1" 28 | ,"example":"'array', 'list', or something similar" 29 | ,"description":"type of the args container" 30 | } 31 | ,"dataType": { 32 | "content":"$2" 33 | ,"example":"string" 34 | ,"description":"type of data in each array index" 35 | } 36 | ,"functionArgs": { 37 | "content":"$3" 38 | ,"example":"arguments" 39 | ,"description":"whatever you call what you pass into a function/method. args, params, etc." 40 | } 41 | } 42 | } 43 | ,"l10nThirdParagraph": { 44 | "message":"Message contents are passed right into innerHTML without processing - include any tags (or even scripts) that you feel like. If you have an input field, the placeholder will be set instead, and buttons will have the value attribute set." 45 | ,"description":"inform that we handle placeholders, buttons, and direct HTML input" 46 | } 47 | ,"l10nButtonsBefore": { 48 | "message":"Different types of buttons are handled as well. <button> elements have their html set:" 49 | } 50 | ,"l10nButton": { 51 | "message":"in a button" 52 | } 53 | ,"l10nButtonsBetween": { 54 | "message":"while <input type='submit'> and <input type='button'> get their 'value' set (note: no HTML):" 55 | } 56 | ,"l10nSubmit": { 57 | "message":"a submit value" 58 | } 59 | ,"l10nButtonsAfter": { 60 | "message":"Awesome, no?" 61 | } 62 | ,"l10nExtras": { 63 | "message":"You can even set data-l10n on things like the <title> tag, which lets you have translatable page titles, or fieldset <legend> tags, or anywhere else - the default Boil.localize() behavior will check every tag in the document, not just the body." 64 | ,"description":"inform about places which may not be obvious, like , etc" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ext/icons/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/ext/icons/icon128.png -------------------------------------------------------------------------------- /ext/icons/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/ext/icons/icon16.png -------------------------------------------------------------------------------- /ext/icons/icon19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/ext/icons/icon19.png -------------------------------------------------------------------------------- /ext/icons/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/ext/icons/icon48.png -------------------------------------------------------------------------------- /ext/js/angular/component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular", 3 | "version": "1.0.6", 4 | "main": "./angular.js", 5 | "dependencies": {}, 6 | "gitHead": "463e638a6eaf523c1e41210a40951683a83e0ecd", 7 | "_id": "AngularJS@1.0.6", 8 | "readme": "ERROR: No README.md file found!", 9 | "description": "ERROR: No README.md file found!", 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/angular/bower-angular.git" 13 | } 14 | } -------------------------------------------------------------------------------- /ext/js/jquery/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | jquery-migrate.js 3 | jquery-migrate.min.js 4 | -------------------------------------------------------------------------------- /ext/js/jquery/component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "version": "2.0.0", 4 | "description": "jQuery component", 5 | "keywords": [ 6 | "jquery", 7 | "component" 8 | ], 9 | "scripts": [ 10 | "jquery.js" 11 | ], 12 | "license": "MIT", 13 | "gitHead": "46f8412bd1bb9b1b30b5b0eb88560e2d4196509c", 14 | "readme": "jQuery Component\n================\n\nShim repository for jQuery.\n", 15 | "readmeFilename": "README.md", 16 | "_id": "jquery@2.0.0", 17 | "repository": { 18 | "type": "git", 19 | "url": "git://github.com/components/jquery.git" 20 | } 21 | } -------------------------------------------------------------------------------- /ext/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"CHANGE THIS : Extension boilerplate", 3 | "version":"0.0.1", 4 | "manifest_version" : 2, 5 | 6 | "description":"This extension was created with the awesome extensionizr.com", 7 | "homepage_url" : "http://extensionizr.com", 8 | "icons":{ 9 | "16":"icons/icon16.png", 10 | "48":"icons/icon48.png", 11 | "128":"icons/icon128.png" 12 | }, 13 | "default_locale":"en", 14 | 15 | "background": { 16 | "page": "src/bg/background.html", 17 | "scripts" : ["src/bg/background.js"], 18 | "persistent": true 19 | }, 20 | 21 | "options_page":"src/options/index.html", 22 | "options_custom_page":"src/options_custom/index.html", 23 | 24 | "browser_action":{ 25 | "default_icon":"icons/icon19.png", 26 | "default_title":"browser action demo", 27 | "default_popup":"src/browser_action/browser_action.html" 28 | }, 29 | 30 | "page_action":{ 31 | "default_icon":"icons/icon19.png", 32 | "default_title":"page action demo", 33 | "default_popup":"src/page_action/page_action.html" 34 | }, 35 | 36 | "chrome_url_overrides":{ 37 | "newtab":"src/override/override.html", 38 | "history" : "src/override/override.html", 39 | "bookmarks" : "src/override/override.html" 40 | }, 41 | 42 | "permissions":[ 43 | "http://*.google.com/", 44 | "bookmarks", 45 | "chrome://favicon/", 46 | "clipboardRead", 47 | "clipboardWrite", 48 | "contextMenus", 49 | "cookies", 50 | "fileBrowserHandler", 51 | "geolocation", 52 | "history", 53 | "idle", 54 | "management", 55 | "notifications", 56 | "tabs", 57 | "tts", 58 | "ttsEngine", 59 | "unlimitedStorage" 60 | ], 61 | 62 | "omnibox":{ 63 | "keyword":"extensionizr" 64 | }, 65 | 66 | "content_scripts":[ 67 | { 68 | "matches":["https://www.google.com/*"], 69 | "css":["src/inject/inject.css"] 70 | }, 71 | { 72 | "matches":["https://www.google.com/*"], 73 | "js":["src/inject/inject.js"] 74 | } 75 | ] 76 | } 77 | -------------------------------------------------------------------------------- /ext/src/bg/background.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <script type="text/javascript" src="background.js"></script> 5 | </head> 6 | </html> -------------------------------------------------------------------------------- /ext/src/bg/background.js: -------------------------------------------------------------------------------- 1 | // if you checked "fancy-settings" in extensionizr.com, uncomment the following lines 2 | 3 | // var settings = new Store("settings", { 4 | // "sample_setting": "This is how you use Store.js to remember values" 5 | // }); 6 | 7 | 8 | //example of using a message handler from the inject scripts 9 | chrome.runtime.onMessage.addListener( 10 | function(request, sender, sendResponse) { 11 | chrome.pageAction.show(sender.tab.id); 12 | sendResponse(); 13 | }); 14 | -------------------------------------------------------------------------------- /ext/src/browser_action/browser_action.html: -------------------------------------------------------------------------------- 1 | <!doctype html> 2 | <style type="text/css"> 3 | #mainPopup { 4 | padding: 10px; 5 | height: 200px; 6 | width: 400px; 7 | font-family: Helvetica, Ubuntu, Arial, sans-serif; 8 | } 9 | h1 { 10 | font-size: 2em; 11 | } 12 | </style> 13 | 14 | <div id="mainPopup"> 15 | <h1>Hello extensionizr!</h1> 16 | <p>To shut this popup down, edit the manifest file and remove the "default popup" key. To edit it, just edit ext/browser_action/browser_action.html. The CSS is there, too.</p> 17 | </div> -------------------------------------------------------------------------------- /ext/src/inject/inject.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Place your custom CSS styles here. 3 | **/ 4 | -------------------------------------------------------------------------------- /ext/src/inject/inject.js: -------------------------------------------------------------------------------- 1 | chrome.runtime.sendMessage({}, function(response) { 2 | var readyStateCheckInterval = setInterval(function() { 3 | if (document.readyState === "complete") { 4 | clearInterval(readyStateCheckInterval); 5 | 6 | // ---------------------------------------------------------- 7 | // This part of the script triggers when page is done loading 8 | console.log("Hello. This message was sent from scripts/inject.js"); 9 | // ---------------------------------------------------------- 10 | 11 | } 12 | }, 10); 13 | }); 14 | -------------------------------------------------------------------------------- /ext/src/options/index.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html> 3 | <head> 4 | <title> 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ext/src/options_custom/README.md: -------------------------------------------------------------------------------- 1 | # [Fancy Settings 1.2](https://github.com/frankkohlhepp/fancy-settings) 2 | *Create fancy, chrome-look-alike settings for your Chrome or Safari extension in minutes!* 3 | 4 | ### Howto 5 | Welcome to Fancy Settings! Are you ready for tabs, groups, search, good style? 6 | Let's get started, it only takes a few minutes... 7 | 8 | Settings can be of different types: text input, checkbox, slider, etc. Some "settings" are not actual settings but provide functionality that is relevant to the options page: description (which is simply a block of text), button. 9 | 10 | Settings are defined in the manifest.js file as JavaScript objects. Each setting is defined by specifying a number of parameters. All types of settings are configured with the string parameters tab, group, name and type. 11 | 12 | ###Basic example: 13 | ```javascript 14 | { 15 | "tab": "Tab 1", 16 | "group": "Group 1", 17 | "name": "checkbox1", 18 | "type": "checkbox" 19 | } 20 | ``` 21 | 22 | "name" is used as a part of the key when storing the setting's value in localStorage. 23 | If it's missing, nothing will be saved. 24 | 25 | ###Additionally, all types of settings are configured with their own custom parameters: 26 | 27 | ###Description ("type": "description") 28 | 29 | text (string) the block of text, which can include HTML tags. You can continue multiple lines of text by putting a \ at the end of a line, just as with any JavaScript file. 30 | 31 | #### 32 | Button ("type": "button") 33 | ``` 34 | Label (string) text shown in front of the button 35 | 36 | Text (string) text shown on the button 37 | ``` 38 | 39 | ####Text ("type": "text") 40 | ``` 41 | label (string) text shown in front of the text field 42 | 43 | text (string) text shown in the text field when empty 44 | 45 | masked (boolean) indicates a password field 46 | ``` 47 | 48 | ####Checkbox ("type": "checkbox") 49 | ``` 50 | label (string) text shown behind the checkbox 51 | ``` 52 | 53 | ####Slider ("type": "slider") 54 | ``` 55 | label (string) text shown in front of the slider 56 | 57 | max (number) maximal value of the slider 58 | 59 | min (number) minimal value of the slider 60 | 61 | step (number) steps between two values 62 | 63 | display (boolean) indicates whether to show the slider display 64 | 65 | displayModifier (function) a function to modify the value shown in the display 66 | ``` 67 | 68 | ####PopupButton ("type": "popupButton"), ListBox ("type": "listBox") & RadioButtons ("type": "radioButtons") 69 | ``` 70 | label (string) text shown in front of the options 71 | 72 | options (array of options) 73 | 74 | where an option can be one of the following formats: 75 | ``` 76 | 77 | ####"value" 78 | ``` 79 | ["value", "displayed text"] 80 | 81 | {value: "value", text: "displayed text"} 82 | ``` 83 | The "displayed text" field is optional and is displayed to the user when you don't want to display the internal value directly to the user. 84 | 85 | #### You can also group options so that the user can easily choose among them (groups may only be applied to popupButtons): 86 | 87 | ```javascript 88 | "options": { 89 | "groups": [ 90 | "Hot", "Cold", 91 | ], 92 | "values": [ 93 | { 94 | "value": "hot", 95 | "text": "Very hot", 96 | "group": "Hot", 97 | }, 98 | { 99 | "value": "Medium", 100 | "group": 1, 101 | }, 102 | { 103 | "value": "Cold", 104 | "group": 2, 105 | }, 106 | ["Non-existing"] 107 | ], 108 | }, 109 | 110 | ``` 111 | 112 | ### License 113 | Fancy Settings is licensed under the **LGPL 2.1**. 114 | For details see *LICENSE.txt* -------------------------------------------------------------------------------- /ext/src/options_custom/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | // Copyright (c) 2011 Frank Kohlhepp 3 | // https://github.com/frankkohlhepp/fancy-settings 4 | // License: LGPL v2.1 5 | */ 6 | .fancy { 7 | text-shadow: #F5F5F5 0 1px 0; 8 | } 9 | 10 | #sidebar { 11 | position: absolute; 12 | background-color: #EDEDED; 13 | background-image: linear-gradient(top, #EDEDED, #F5F5F5); 14 | background-image: -webkit-gradient( 15 | linear, 16 | left top, 17 | left 500, 18 | color-stop(0, #EDEDED), 19 | color-stop(1, #F5F5F5) 20 | ); 21 | background-image: -moz-linear-gradient( 22 | center top, 23 | #EDEDED 0%, 24 | #F5F5F5 100% 25 | ); 26 | background-image: -o-linear-gradient(top, #EDEDED, #F5F5F5); 27 | width: 219px; 28 | top: 0; 29 | left: 0; 30 | bottom: 0; 31 | border-right: 1px solid #C2C2C2; 32 | box-shadow: inset -8px 0 30px -30px black; 33 | } 34 | 35 | #icon { 36 | position: absolute; 37 | width: 30px; 38 | height: 30px; 39 | top: 12px; 40 | left: 12px; 41 | } 42 | 43 | #sidebar h1 { 44 | position: absolute; 45 | top: 13px; 46 | right: 25px; 47 | font-size: 26px; 48 | color: #707070; 49 | } 50 | 51 | #tab-container { 52 | position: absolute; 53 | top: 50px; 54 | left: 0; 55 | right: 0; 56 | bottom: 0; 57 | overflow-y: auto; 58 | overflow-x: hidden; 59 | text-align: right; 60 | } 61 | 62 | #tab-container .tab { 63 | height: 28px; 64 | padding-right: 25px; 65 | border-top: 1px solid transparent; 66 | border-bottom: 1px solid transparent; 67 | font-size: 12px; 68 | line-height: 28px; 69 | color: #808080; 70 | cursor: pointer; 71 | } 72 | 73 | #search-container { 74 | margin-top: 5px; 75 | margin-bottom: 5px; 76 | padding-right: 23px !important; 77 | cursor: default !important; 78 | } 79 | 80 | #search-container input { 81 | width: 130px; 82 | } 83 | 84 | #tab-container .tab.active, body.searching #search-container { 85 | background-color: #D4D4D4; 86 | border-color: #BFBFBF; 87 | color: black; 88 | text-shadow: #DBDBDB 0 1px 0; 89 | box-shadow: inset -12px 0 30px -30px black; 90 | } 91 | 92 | body.searching #tab-container .tab.active { 93 | background-color: transparent; 94 | border-color: transparent; 95 | color: #808080; 96 | text-shadow: inherit; 97 | box-shadow: none; 98 | } 99 | 100 | #content { 101 | position: absolute; 102 | top: 0; 103 | left: 220px; 104 | right: 0; 105 | bottom: 0; 106 | overflow: auto; 107 | } 108 | 109 | .tab-content { 110 | display: none; 111 | position: absolute; 112 | width: 840px; 113 | top: 0; 114 | left: 0; 115 | bottom: 0; 116 | padding: 20px; 117 | padding-top: 15px; 118 | } 119 | 120 | body.searching .tab-content { 121 | display: none !important; 122 | } 123 | 124 | body.searching #search-result-container { 125 | display: block !important; 126 | } 127 | 128 | body.measuring .tab-content, body.measuring #search-result-container { 129 | display: block !important; 130 | opacity: 0; 131 | overflow: hidden; 132 | } 133 | -------------------------------------------------------------------------------- /ext/src/options_custom/css/setting.css: -------------------------------------------------------------------------------- 1 | /* 2 | // Copyright (c) 2011 Frank Kohlhepp 3 | // https://github.com/frankkohlhepp/fancy-settings 4 | // License: LGPL v2.1 5 | */ 6 | .tab-content h2 { 7 | margin: 0; 8 | padding-bottom: 5px; 9 | font-size: 26px; 10 | color: #707070; 11 | line-height: 1; 12 | } 13 | 14 | .setting.group { 15 | border-top: 1px solid #EEEEEE; 16 | margin-top: 10px; 17 | padding-top: 5px; 18 | padding-left: 2px; 19 | } 20 | 21 | .setting.group-name { 22 | width: 140px; 23 | padding: 0; 24 | font-size: 14px; 25 | font-weight: bold; 26 | vertical-align: top; 27 | } 28 | 29 | .setting.bundle { 30 | max-width: 600px; 31 | margin-bottom: 5px; 32 | } 33 | 34 | .setting.bundle.list-box { 35 | margin-bottom: 10px; 36 | } 37 | 38 | .setting.label.radio-buttons + .setting.container.radio-buttons { 39 | margin-top: 3px; 40 | } 41 | 42 | .setting.label, .setting.element-label { 43 | margin-right: 15px; 44 | font-size: 13px; 45 | font-weight: normal; 46 | } 47 | 48 | .setting.label.checkbox, .setting.element-label { 49 | margin-left: 5px; 50 | margin-right: 0; 51 | } 52 | 53 | .setting.label.checkbox { 54 | position: relative; 55 | top: 1px; 56 | } 57 | 58 | .setting.element.slider { 59 | position: relative; 60 | width: 150px; 61 | top: 4px; 62 | } 63 | 64 | .setting.element.list-box { 65 | display: block; 66 | height: 100px; 67 | width: 100%; 68 | } 69 | 70 | .setting.display.slider { 71 | margin-left: 5px; 72 | color: #666666; 73 | } 74 | 75 | #nothing-found { 76 | display: none; 77 | margin-top: 10px; 78 | font-size: 18px; 79 | font-weight: lighter; 80 | color: #999999; 81 | } 82 | -------------------------------------------------------------------------------- /ext/src/options_custom/custom.css: -------------------------------------------------------------------------------- 1 | /* 2 | // Add your own style rules here, not in css/main.css 3 | // or css/setting.css for easy updating reasons. 4 | */ 5 | -------------------------------------------------------------------------------- /ext/src/options_custom/i18n.js: -------------------------------------------------------------------------------- 1 | // SAMPLE 2 | this.i18n = { 3 | "settings": { 4 | "en": "Settings", 5 | "de": "Optionen" 6 | }, 7 | "search": { 8 | "en": "Search", 9 | "de": "Suche" 10 | }, 11 | "nothing-found": { 12 | "en": "No matches were found.", 13 | "de": "Keine Übereinstimmungen gefunden." 14 | }, 15 | 16 | 17 | 18 | "information": { 19 | "en": "Information", 20 | "de": "Information" 21 | }, 22 | "login": { 23 | "en": "Login", 24 | "de": "Anmeldung" 25 | }, 26 | "username": { 27 | "en": "Username:", 28 | "de": "Benutzername:" 29 | }, 30 | "password": { 31 | "en": "Password:", 32 | "de": "Passwort:" 33 | }, 34 | "x-characters": { 35 | "en": "6 - 12 characters", 36 | "de": "6 - 12 Zeichen" 37 | }, 38 | "x-characters-pw": { 39 | "en": "10 - 18 characters", 40 | "de": "10 - 18 Zeichen" 41 | }, 42 | "description": { 43 | "en": "This is a description. You can write any text inside of this.
\ 44 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut\ 45 | labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores\ 46 | et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem\ 47 | ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et\ 48 | dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.\ 49 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.", 50 | 51 | "de": "Das ist eine Beschreibung. Du kannst hier beliebigen Text einfügen.
\ 52 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut\ 53 | labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores\ 54 | et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem\ 55 | ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et\ 56 | dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.\ 57 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." 58 | }, 59 | "logout": { 60 | "en": "Logout", 61 | "de": "Abmeldung" 62 | }, 63 | "enable": { 64 | "en": "Enable", 65 | "de": "Aktivieren" 66 | }, 67 | "disconnect": { 68 | "en": "Disconnect:", 69 | "de": "Trennen:" 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /ext/src/options_custom/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/ext/src/options_custom/icon.png -------------------------------------------------------------------------------- /ext/src/options_custom/index.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 40 |
41 |
42 |

43 |
44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /ext/src/options_custom/js/classes/fancy-settings.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011 Frank Kohlhepp 3 | // https://github.com/frankkohlhepp/fancy-settings 4 | // License: LGPL v2.1 5 | // 6 | (function () { 7 | var FancySettings = this.FancySettings = new Class({ 8 | "tabs": {}, 9 | 10 | "initialize": function (name, icon) { 11 | // Set title and icon 12 | $("title").set("text", name); 13 | $("favicon").set("href", icon); 14 | $("icon").set("src", icon); 15 | $("settings-label").set("text", (i18n.get("settings") || "Settings")); 16 | $("search-label").set("text", (i18n.get("search") || "Search")); 17 | $("search").set("placeholder", (i18n.get("search") || "Search") + "..."); 18 | 19 | this.tab = new Tab($("tab-container"), $("content")); 20 | this.search = new Search($("search"), $("search-result-container")); 21 | }, 22 | 23 | "create": function (params) { 24 | var tab, 25 | group, 26 | row, 27 | content, 28 | bundle; 29 | 30 | // Create tab if it doesn't exist already 31 | if (this.tabs[params.tab] === undefined) { 32 | this.tabs[params.tab] = {"groups":{}}; 33 | tab = this.tabs[params.tab]; 34 | 35 | tab.content = this.tab.create(); 36 | tab.content.tab.set("text", params.tab); 37 | this.search.bind(tab.content.tab); 38 | 39 | tab.content = tab.content.content; 40 | (new Element("h2", { 41 | "text": params.tab 42 | })).inject(tab.content); 43 | } else { 44 | tab = this.tabs[params.tab]; 45 | } 46 | 47 | // Create group if it doesn't exist already 48 | if (tab.groups[params.group] === undefined) { 49 | tab.groups[params.group] = {}; 50 | group = tab.groups[params.group]; 51 | 52 | group.content = (new Element("table", { 53 | "class": "setting group" 54 | })).inject(tab.content); 55 | 56 | row = (new Element("tr")).inject(group.content); 57 | 58 | (new Element("td", { 59 | "class": "setting group-name", 60 | "text": params.group 61 | })).inject(row); 62 | 63 | content = (new Element("td", { 64 | "class": "setting group-content" 65 | })).inject(row); 66 | 67 | group.setting = new Setting(content); 68 | } else { 69 | group = tab.groups[params.group]; 70 | } 71 | 72 | // Create and index the setting 73 | bundle = group.setting.create(params); 74 | this.search.add(bundle); 75 | 76 | return bundle; 77 | }, 78 | 79 | "align": function (settings) { 80 | var types, 81 | type, 82 | maxWidth; 83 | 84 | types = [ 85 | "text", 86 | "button", 87 | "slider", 88 | "popupButton" 89 | ]; 90 | type = settings[0].params.type; 91 | maxWidth = 0; 92 | 93 | if (!types.contains(type)) { 94 | throw "invalidType"; 95 | } 96 | 97 | settings.each(function (setting) { 98 | if (setting.params.type !== type) { 99 | throw "multipleTypes"; 100 | } 101 | 102 | var width = setting.label.offsetWidth; 103 | if (width > maxWidth) { 104 | maxWidth = width; 105 | } 106 | }); 107 | 108 | settings.each(function (setting) { 109 | var width = setting.label.offsetWidth; 110 | if (width < maxWidth) { 111 | if (type === "button" || type === "slider") { 112 | setting.element.setStyle("margin-left", (maxWidth - width + 2) + "px"); 113 | setting.search.element.setStyle("margin-left", (maxWidth - width + 2) + "px"); 114 | } else { 115 | setting.element.setStyle("margin-left", (maxWidth - width) + "px"); 116 | setting.search.element.setStyle("margin-left", (maxWidth - width) + "px"); 117 | } 118 | } 119 | }); 120 | } 121 | }); 122 | 123 | FancySettings.__proto__.initWithManifest = function (callback) { 124 | var settings, 125 | output; 126 | 127 | settings = new FancySettings(manifest.name, manifest.icon); 128 | settings.manifest = {}; 129 | 130 | manifest.settings.each(function (params) { 131 | output = settings.create(params); 132 | if (params.name !== undefined) { 133 | settings.manifest[params.name] = output; 134 | } 135 | }); 136 | 137 | if (manifest.alignment !== undefined) { 138 | document.body.addClass("measuring"); 139 | manifest.alignment.each(function (group) { 140 | group = group.map(function (name) { 141 | return settings.manifest[name]; 142 | }); 143 | settings.align(group); 144 | }); 145 | document.body.removeClass("measuring"); 146 | } 147 | 148 | if (callback !== undefined) { 149 | callback(settings); 150 | } 151 | }; 152 | }()); 153 | -------------------------------------------------------------------------------- /ext/src/options_custom/js/classes/search.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011 Frank Kohlhepp 3 | // https://github.com/frankkohlhepp/fancy-settings 4 | // License: LGPL v2.1 5 | // 6 | (function () { 7 | this.Search = new Class({ 8 | "index": [], 9 | "groups": {}, 10 | 11 | "initialize": function (search, searchResultContainer) { 12 | var setting, 13 | find; 14 | 15 | this.search = search; 16 | this.searchResultContainer = searchResultContainer; 17 | this.setting = new Setting(new Element("div")); 18 | 19 | // Create setting for message "nothing found" 20 | setting = new Setting(this.searchResultContainer); 21 | this.nothingFound = setting.create({ 22 | "type": "description", 23 | "text": (i18n.get("nothing-found") || "No matches were found.") 24 | }); 25 | this.nothingFound.bundle.set("id", "nothing-found"); 26 | 27 | // Create event handlers 28 | find = (function (event) { 29 | this.find(event.target.get("value")); 30 | }).bind(this); 31 | 32 | this.search.addEvent("keyup", (function (event) { 33 | if (event.key === "esc") { 34 | this.reset(); 35 | } else { 36 | find(event); 37 | } 38 | }).bind(this)); 39 | this.search.addEventListener("search", find, false); 40 | }, 41 | 42 | "bind": function (tab) { 43 | tab.addEvent("click", this.reset.bind(this)); 44 | }, 45 | 46 | "add": function (setting) { 47 | var searchSetting = this.setting.create(setting.params); 48 | setting.search = searchSetting; 49 | searchSetting.original = setting; 50 | this.index.push(searchSetting); 51 | 52 | setting.addEvent("action", function (value, stopPropagation) { 53 | if (searchSetting.set !== undefined && stopPropagation !== true) { 54 | searchSetting.set(value, true); 55 | } 56 | }); 57 | searchSetting.addEvent("action", function (value) { 58 | if (setting.set !== undefined) { 59 | setting.set(value, true); 60 | } 61 | setting.fireEvent("action", [value, true]); 62 | }); 63 | }, 64 | 65 | "find": function (searchString) { 66 | // Exit search mode 67 | if (searchString.trim() === "") { 68 | document.body.removeClass("searching"); 69 | return; 70 | } 71 | 72 | // Or enter search mode 73 | this.index.each(function (setting) { setting.bundle.dispose(); }); 74 | Object.each(this.groups, function (group) { group.dispose(); }); 75 | document.body.addClass("searching"); 76 | 77 | // Filter settings 78 | var result = this.index.filter(function (setting) { 79 | if (setting.params.searchString.contains(searchString.trim().toLowerCase())) { 80 | return true; 81 | } 82 | }); 83 | 84 | // Display settings 85 | result.each((function (setting) { 86 | var group, 87 | row; 88 | 89 | // Create group if it doesn't exist already 90 | if (this.groups[setting.params.group] === undefined) { 91 | this.groups[setting.params.group] = (new Element("table", { 92 | "class": "setting group" 93 | })).inject(this.searchResultContainer); 94 | 95 | group = this.groups[setting.params.group]; 96 | row = (new Element("tr")).inject(group); 97 | 98 | (new Element("td", { 99 | "class": "setting group-name", 100 | "text": setting.params.group 101 | })).inject(row); 102 | 103 | group.content = (new Element("td", { 104 | "class": "setting group-content" 105 | })).inject(row); 106 | } else { 107 | group = this.groups[setting.params.group].inject(this.searchResultContainer); 108 | } 109 | 110 | setting.bundle.inject(group.content); 111 | }).bind(this)); 112 | 113 | if (result.length === 0) { 114 | this.nothingFound.bundle.addClass("show"); 115 | } else { 116 | this.nothingFound.bundle.removeClass("show"); 117 | } 118 | }, 119 | 120 | "reset": function () { 121 | this.search.set("value", ""); 122 | this.search.blur(); 123 | this.find(""); 124 | } 125 | }); 126 | }()); 127 | -------------------------------------------------------------------------------- /ext/src/options_custom/js/classes/setting.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011 Frank Kohlhepp 3 | // https://github.com/frankkohlhepp/fancy-settings 4 | // License: LGPL v2.1 5 | // 6 | (function () { 7 | var settings, 8 | Bundle; 9 | 10 | settings = new Store("settings"); 11 | Bundle = new Class({ 12 | // Attributes: 13 | // - tab 14 | // - group 15 | // - name 16 | // - type 17 | // 18 | // Methods: 19 | // - initialize 20 | // - createDOM 21 | // - setupDOM 22 | // - addEvents 23 | // - get 24 | // - set 25 | "Implements": Events, 26 | 27 | "initialize": function (params) { 28 | this.params = params; 29 | this.params.searchString = "•" + this.params.tab + "•" + this.params.group + "•"; 30 | 31 | this.createDOM(); 32 | this.setupDOM(); 33 | this.addEvents(); 34 | 35 | if (this.params.id !== undefined) { 36 | this.element.set("id", this.params.id); 37 | } 38 | 39 | if (this.params.name !== undefined) { 40 | this.set(settings.get(this.params.name), true); 41 | } 42 | 43 | this.params.searchString = this.params.searchString.toLowerCase(); 44 | }, 45 | 46 | "addEvents": function () { 47 | this.element.addEvent("change", (function (event) { 48 | if (this.params.name !== undefined) { 49 | settings.set(this.params.name, this.get()); 50 | } 51 | 52 | this.fireEvent("action", this.get()); 53 | }).bind(this)); 54 | }, 55 | 56 | "get": function () { 57 | return this.element.get("value"); 58 | }, 59 | 60 | "set": function (value, noChangeEvent) { 61 | this.element.set("value", value); 62 | 63 | if (noChangeEvent !== true) { 64 | this.element.fireEvent("change"); 65 | } 66 | 67 | return this; 68 | } 69 | }); 70 | 71 | Bundle.Description = new Class({ 72 | // text 73 | "Extends": Bundle, 74 | "addEvents": undefined, 75 | "get": undefined, 76 | "set": undefined, 77 | 78 | "initialize": function (params) { 79 | this.params = params; 80 | this.params.searchString = ""; 81 | 82 | this.createDOM(); 83 | this.setupDOM(); 84 | }, 85 | 86 | "createDOM": function () { 87 | this.bundle = new Element("div", { 88 | "class": "setting bundle description" 89 | }); 90 | 91 | this.container = new Element("div", { 92 | "class": "setting container description" 93 | }); 94 | 95 | this.element = new Element("p", { 96 | "class": "setting element description" 97 | }); 98 | }, 99 | 100 | "setupDOM": function () { 101 | if (this.params.text !== undefined) { 102 | this.element.set("html", this.params.text); 103 | } 104 | 105 | this.element.inject(this.container); 106 | this.container.inject(this.bundle); 107 | } 108 | }); 109 | 110 | Bundle.Button = new Class({ 111 | // label, text 112 | // action -> click 113 | "Extends": Bundle, 114 | "get": undefined, 115 | "set": undefined, 116 | 117 | "initialize": function (params) { 118 | this.params = params; 119 | this.params.searchString = "•" + this.params.tab + "•" + this.params.group + "•"; 120 | 121 | this.createDOM(); 122 | this.setupDOM(); 123 | this.addEvents(); 124 | 125 | if (this.params.id !== undefined) { 126 | this.element.set("id", this.params.id); 127 | } 128 | 129 | this.params.searchString = this.params.searchString.toLowerCase(); 130 | }, 131 | 132 | "createDOM": function () { 133 | this.bundle = new Element("div", { 134 | "class": "setting bundle button" 135 | }); 136 | 137 | this.container = new Element("div", { 138 | "class": "setting container button" 139 | }); 140 | 141 | this.element = new Element("input", { 142 | "class": "setting element button", 143 | "type": "button" 144 | }); 145 | 146 | this.label = new Element("label", { 147 | "class": "setting label button" 148 | }); 149 | }, 150 | 151 | "setupDOM": function () { 152 | if (this.params.label !== undefined) { 153 | this.label.set("html", this.params.label); 154 | this.label.inject(this.container); 155 | this.params.searchString += this.params.label + "•"; 156 | } 157 | 158 | if (this.params.text !== undefined) { 159 | this.element.set("value", this.params.text); 160 | this.params.searchString += this.params.text + "•"; 161 | } 162 | 163 | this.element.inject(this.container); 164 | this.container.inject(this.bundle); 165 | }, 166 | 167 | "addEvents": function () { 168 | this.element.addEvent("click", (function () { 169 | this.fireEvent("action"); 170 | }).bind(this)); 171 | } 172 | }); 173 | 174 | Bundle.Text = new Class({ 175 | // label, text, masked 176 | // action -> change & keyup 177 | "Extends": Bundle, 178 | 179 | "createDOM": function () { 180 | this.bundle = new Element("div", { 181 | "class": "setting bundle text" 182 | }); 183 | 184 | this.container = new Element("div", { 185 | "class": "setting container text" 186 | }); 187 | 188 | this.element = new Element("input", { 189 | "class": "setting element text", 190 | "type": "text" 191 | }); 192 | 193 | this.label = new Element("label", { 194 | "class": "setting label text" 195 | }); 196 | }, 197 | 198 | "setupDOM": function () { 199 | if (this.params.label !== undefined) { 200 | this.label.set("html", this.params.label); 201 | this.label.inject(this.container); 202 | this.params.searchString += this.params.label + "•"; 203 | } 204 | 205 | if (this.params.text !== undefined) { 206 | this.element.set("placeholder", this.params.text); 207 | this.params.searchString += this.params.text + "•"; 208 | } 209 | 210 | if (this.params.masked === true) { 211 | this.element.set("type", "password"); 212 | this.params.searchString += "password" + "•"; 213 | } 214 | 215 | this.element.inject(this.container); 216 | this.container.inject(this.bundle); 217 | }, 218 | 219 | "addEvents": function () { 220 | var change = (function (event) { 221 | if (this.params.name !== undefined) { 222 | settings.set(this.params.name, this.get()); 223 | } 224 | 225 | this.fireEvent("action", this.get()); 226 | }).bind(this); 227 | 228 | this.element.addEvent("change", change); 229 | this.element.addEvent("keyup", change); 230 | } 231 | }); 232 | 233 | Bundle.Checkbox = new Class({ 234 | // label 235 | // action -> change 236 | "Extends": Bundle, 237 | 238 | "createDOM": function () { 239 | this.bundle = new Element("div", { 240 | "class": "setting bundle checkbox" 241 | }); 242 | 243 | this.container = new Element("div", { 244 | "class": "setting container checkbox" 245 | }); 246 | 247 | this.element = new Element("input", { 248 | "id": String.uniqueID(), 249 | "class": "setting element checkbox", 250 | "type": "checkbox", 251 | "value": "true" 252 | }); 253 | 254 | this.label = new Element("label", { 255 | "class": "setting label checkbox", 256 | "for": this.element.get("id") 257 | }); 258 | }, 259 | 260 | "setupDOM": function () { 261 | this.element.inject(this.container); 262 | this.container.inject(this.bundle); 263 | 264 | if (this.params.label !== undefined) { 265 | this.label.set("html", this.params.label); 266 | this.label.inject(this.container); 267 | this.params.searchString += this.params.label + "•"; 268 | } 269 | }, 270 | 271 | "get": function () { 272 | return this.element.get("checked"); 273 | }, 274 | 275 | "set": function (value, noChangeEvent) { 276 | this.element.set("checked", value); 277 | 278 | if (noChangeEvent !== true) { 279 | this.element.fireEvent("change"); 280 | } 281 | 282 | return this; 283 | } 284 | }); 285 | 286 | Bundle.Slider = new Class({ 287 | // label, max, min, step, display, displayModifier 288 | // action -> change 289 | "Extends": Bundle, 290 | 291 | "initialize": function (params) { 292 | this.params = params; 293 | this.params.searchString = "•" + this.params.tab + "•" + this.params.group + "•"; 294 | 295 | this.createDOM(); 296 | this.setupDOM(); 297 | this.addEvents(); 298 | 299 | if (this.params.name !== undefined) { 300 | this.set((settings.get(this.params.name) || 0), true); 301 | } else { 302 | this.set(0, true); 303 | } 304 | 305 | this.params.searchString = this.params.searchString.toLowerCase(); 306 | }, 307 | 308 | "createDOM": function () { 309 | this.bundle = new Element("div", { 310 | "class": "setting bundle slider" 311 | }); 312 | 313 | this.container = new Element("div", { 314 | "class": "setting container slider" 315 | }); 316 | 317 | this.element = new Element("input", { 318 | "class": "setting element slider", 319 | "type": "range" 320 | }); 321 | 322 | this.label = new Element("label", { 323 | "class": "setting label slider" 324 | }); 325 | 326 | this.display = new Element("span", { 327 | "class": "setting display slider" 328 | }); 329 | }, 330 | 331 | "setupDOM": function () { 332 | if (this.params.label !== undefined) { 333 | this.label.set("html", this.params.label); 334 | this.label.inject(this.container); 335 | this.params.searchString += this.params.label + "•"; 336 | } 337 | 338 | if (this.params.max !== undefined) { 339 | this.element.set("max", this.params.max); 340 | } 341 | 342 | if (this.params.min !== undefined) { 343 | this.element.set("min", this.params.min); 344 | } 345 | 346 | if (this.params.step !== undefined) { 347 | this.element.set("step", this.params.step); 348 | } 349 | 350 | this.element.inject(this.container); 351 | if (this.params.display !== false) { 352 | if (this.params.displayModifier !== undefined) { 353 | this.display.set("text", this.params.displayModifier(0)); 354 | } else { 355 | this.display.set("text", 0); 356 | } 357 | this.display.inject(this.container); 358 | } 359 | this.container.inject(this.bundle); 360 | }, 361 | 362 | "addEvents": function () { 363 | this.element.addEvent("change", (function (event) { 364 | if (this.params.name !== undefined) { 365 | settings.set(this.params.name, this.get()); 366 | } 367 | 368 | if (this.params.displayModifier !== undefined) { 369 | this.display.set("text", this.params.displayModifier(this.get())); 370 | } else { 371 | this.display.set("text", this.get()); 372 | } 373 | this.fireEvent("action", this.get()); 374 | }).bind(this)); 375 | }, 376 | 377 | "get": function () { 378 | return Number.from(this.element.get("value")); 379 | }, 380 | 381 | "set": function (value, noChangeEvent) { 382 | this.element.set("value", value); 383 | 384 | if (noChangeEvent !== true) { 385 | this.element.fireEvent("change"); 386 | } else { 387 | if (this.params.displayModifier !== undefined) { 388 | this.display.set("text", this.params.displayModifier(Number.from(value))); 389 | } else { 390 | this.display.set("text", Number.from(value)); 391 | } 392 | } 393 | 394 | return this; 395 | } 396 | }); 397 | 398 | Bundle.PopupButton = new Class({ 399 | // label, options[{value, text}] 400 | // action -> change 401 | "Extends": Bundle, 402 | 403 | "createDOM": function () { 404 | this.bundle = new Element("div", { 405 | "class": "setting bundle popup-button" 406 | }); 407 | 408 | this.container = new Element("div", { 409 | "class": "setting container popup-button" 410 | }); 411 | 412 | this.element = new Element("select", { 413 | "class": "setting element popup-button" 414 | }); 415 | 416 | this.label = new Element("label", { 417 | "class": "setting label popup-button" 418 | }); 419 | 420 | if (this.params.options === undefined) { return; } 421 | 422 | // convert array syntax into object syntax for options 423 | function arrayToObject(option) { 424 | if (typeOf(option) == "array") { 425 | option = { 426 | "value": option[0], 427 | "text": option[1] || option[0], 428 | }; 429 | } 430 | return option; 431 | } 432 | 433 | // convert arrays 434 | if (typeOf(this.params.options) == "array") { 435 | var values = []; 436 | this.params.options.each((function(values, option) { 437 | values.push(arrayToObject(option)); 438 | }).bind(this, values)); 439 | this.params.options = { "values": values }; 440 | } 441 | 442 | var groups; 443 | if (this.params.options.groups !== undefined) { 444 | groups = {}; 445 | this.params.options.groups.each((function (groups, group) { 446 | this.params.searchString += (group) + "•"; 447 | groups[group] = (new Element("optgroup", { 448 | "label": group, 449 | }).inject(this.element)); 450 | }).bind(this, groups)); 451 | } 452 | 453 | if (this.params.options.values !== undefined) { 454 | this.params.options.values.each((function(groups, option) { 455 | option = arrayToObject(option); 456 | this.params.searchString += (option.text || option.value) + "•"; 457 | 458 | // find the parent of this option - either a group or the main element 459 | var parent; 460 | if (option.group && this.params.options.groups) { 461 | if ((option.group - 1) in this.params.options.groups) { 462 | option.group = this.params.options.groups[option.group-1]; 463 | } 464 | if (option.group in groups) { 465 | parent = groups[option.group]; 466 | } 467 | else { 468 | parent = this.element; 469 | } 470 | } 471 | else { 472 | parent = this.element; 473 | } 474 | 475 | (new Element("option", { 476 | "value": option.value, 477 | "text": option.text || option.value, 478 | })).inject(parent); 479 | }).bind(this, groups)); 480 | } 481 | }, 482 | 483 | "setupDOM": function () { 484 | if (this.params.label !== undefined) { 485 | this.label.set("html", this.params.label); 486 | this.label.inject(this.container); 487 | this.params.searchString += this.params.label + "•"; 488 | } 489 | 490 | this.element.inject(this.container); 491 | this.container.inject(this.bundle); 492 | } 493 | }); 494 | 495 | Bundle.ListBox = new Class({ 496 | // label, options[{value, text}] 497 | // action -> change 498 | "Extends": Bundle.PopupButton, 499 | 500 | "createDOM": function () { 501 | this.bundle = new Element("div", { 502 | "class": "setting bundle list-box" 503 | }); 504 | 505 | this.container = new Element("div", { 506 | "class": "setting container list-box" 507 | }); 508 | 509 | this.element = new Element("select", { 510 | "class": "setting element list-box", 511 | "size": "2" 512 | }); 513 | 514 | this.label = new Element("label", { 515 | "class": "setting label list-box" 516 | }); 517 | 518 | if (this.params.options === undefined) { return; } 519 | this.params.options.each((function (option) { 520 | this.params.searchString += (option.text || option.value) + "•"; 521 | 522 | (new Element("option", { 523 | "value": option.value, 524 | "text": option.text || option.value 525 | })).inject(this.element); 526 | }).bind(this)); 527 | }, 528 | 529 | "get": function () { 530 | return (this.element.get("value") || undefined); 531 | } 532 | }); 533 | 534 | Bundle.Textarea = new Class({ 535 | // label, text, value 536 | // action -> change & keyup 537 | "Extends": Bundle, 538 | 539 | "createDOM": function () { 540 | this.bundle = new Element("div", { 541 | "class": "setting bundle textarea" 542 | }); 543 | 544 | this.container = new Element("div", { 545 | "class": "setting container textarea" 546 | }); 547 | 548 | this.element = new Element("textarea", { 549 | "class": "setting element textarea" 550 | }); 551 | 552 | this.label = new Element("label", { 553 | "class": "setting label textarea" 554 | }); 555 | }, 556 | 557 | "setupDOM": function () { 558 | if (this.params.label !== undefined) { 559 | this.label.set("html", this.params.label); 560 | this.label.inject(this.container); 561 | this.params.searchString += this.params.label + "•"; 562 | } 563 | 564 | if (this.params.text !== undefined) { 565 | this.element.set("placeholder", this.params.text); 566 | this.params.searchString += this.params.text + "•"; 567 | } 568 | 569 | if (this.params.value !== undefined) { 570 | this.element.appendText(this.params.text); 571 | } 572 | 573 | this.element.inject(this.container); 574 | this.container.inject(this.bundle); 575 | }, 576 | 577 | "addEvents": function () { 578 | var change = (function (event) { 579 | if (this.params.name !== undefined) { 580 | settings.set(this.params.name, this.get()); 581 | } 582 | 583 | this.fireEvent("action", this.get()); 584 | }).bind(this); 585 | 586 | this.element.addEvent("change", change); 587 | this.element.addEvent("keyup", change); 588 | } 589 | }); 590 | 591 | Bundle.RadioButtons = new Class({ 592 | // label, options[{value, text}] 593 | // action -> change 594 | "Extends": Bundle, 595 | 596 | "createDOM": function () { 597 | var settingID = String.uniqueID(); 598 | 599 | this.bundle = new Element("div", { 600 | "class": "setting bundle radio-buttons" 601 | }); 602 | 603 | this.label = new Element("label", { 604 | "class": "setting label radio-buttons" 605 | }); 606 | 607 | this.containers = []; 608 | this.elements = []; 609 | this.labels = []; 610 | 611 | if (this.params.options === undefined) { return; } 612 | this.params.options.each((function (option) { 613 | var optionID, 614 | container; 615 | 616 | this.params.searchString += (option.text || option.value) + "•"; 617 | 618 | optionID = String.uniqueID(); 619 | container = (new Element("div", { 620 | "class": "setting container radio-buttons" 621 | })).inject(this.bundle); 622 | this.containers.push(container); 623 | 624 | this.elements.push((new Element("input", { 625 | "id": optionID, 626 | "name": settingID, 627 | "class": "setting element radio-buttons", 628 | "type": "radio", 629 | "value": option.value 630 | })).inject(container)); 631 | 632 | this.labels.push((new Element("label", { 633 | "class": "setting element-label radio-buttons", 634 | "for": optionID, 635 | "text": option.text || option.value 636 | })).inject(container)); 637 | }).bind(this)); 638 | }, 639 | 640 | "setupDOM": function () { 641 | if (this.params.label !== undefined) { 642 | this.label.set("html", this.params.label); 643 | this.label.inject(this.bundle, "top"); 644 | this.params.searchString += this.params.label + "•"; 645 | } 646 | }, 647 | 648 | "addEvents": function () { 649 | this.bundle.addEvent("change", (function (event) { 650 | if (this.params.name !== undefined) { 651 | settings.set(this.params.name, this.get()); 652 | } 653 | 654 | this.fireEvent("action", this.get()); 655 | }).bind(this)); 656 | }, 657 | 658 | "get": function () { 659 | var checkedEl = this.elements.filter((function (el) { 660 | return el.get("checked"); 661 | }).bind(this)); 662 | return (checkedEl[0] && checkedEl[0].get("value")); 663 | }, 664 | 665 | "set": function (value, noChangeEvent) { 666 | var desiredEl = this.elements.filter((function (el) { 667 | return (el.get("value") === value); 668 | }).bind(this)); 669 | desiredEl[0] && desiredEl[0].set("checked", true); 670 | 671 | if (noChangeEvent !== true) { 672 | this.bundle.fireEvent("change"); 673 | } 674 | 675 | return this; 676 | } 677 | }); 678 | 679 | this.Setting = new Class({ 680 | "initialize": function (container) { 681 | this.container = container; 682 | }, 683 | 684 | "create": function (params) { 685 | var types, 686 | bundle; 687 | 688 | // Available types 689 | types = { 690 | "description": "Description", 691 | "button": "Button", 692 | "text": "Text", 693 | "textarea": "Textarea", 694 | "checkbox": "Checkbox", 695 | "slider": "Slider", 696 | "popupButton": "PopupButton", 697 | "listBox": "ListBox", 698 | "radioButtons": "RadioButtons" 699 | }; 700 | 701 | if (types.hasOwnProperty(params.type)) { 702 | bundle = new Bundle[types[params.type]](params); 703 | bundle.bundleContainer = this.container; 704 | bundle.bundle.inject(this.container); 705 | return bundle; 706 | } else { 707 | throw "invalidType"; 708 | } 709 | } 710 | }); 711 | }()); 712 | -------------------------------------------------------------------------------- /ext/src/options_custom/js/classes/tab.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011 Frank Kohlhepp 3 | // https://github.com/frankkohlhepp/fancy-settings 4 | // License: LGPL v2.1 5 | // 6 | (function () { 7 | var Bundle = new Class({ 8 | "initialize": function (creator) { 9 | this.creator = creator; 10 | 11 | // Create DOM elements 12 | this.tab = new Element("div", {"class": "tab"}); 13 | this.content = new Element("div", {"class": "tab-content"}); 14 | 15 | // Create event handlers 16 | this.tab.addEvent("click", this.activate.bind(this)); 17 | }, 18 | 19 | "activate": function () { 20 | if (this.creator.activeBundle && this.creator.activeBundle !== this) { 21 | this.creator.activeBundle.deactivate(); 22 | } 23 | this.tab.addClass("active"); 24 | this.content.addClass("show"); 25 | this.creator.activeBundle = this; 26 | }, 27 | 28 | "deactivate": function () { 29 | this.tab.removeClass("active"); 30 | this.content.removeClass("show"); 31 | this.creator.activeBundle = null; 32 | } 33 | }); 34 | 35 | this.Tab = new Class({ 36 | "activeBundle": null, 37 | 38 | "initialize": function (tabContainer, tabContentContainer) { 39 | this.tabContainer = tabContainer; 40 | this.tabContentContainer = tabContentContainer; 41 | }, 42 | 43 | "create": function () { 44 | var bundle = new Bundle(this); 45 | bundle.tab.inject(this.tabContainer); 46 | bundle.content.inject(this.tabContentContainer); 47 | if (!this.activeBundle) { bundle.activate(); } 48 | return bundle; 49 | } 50 | }); 51 | }()); 52 | -------------------------------------------------------------------------------- /ext/src/options_custom/js/i18n.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011 Frank Kohlhepp 3 | // https://github.com/frankkohlhepp/fancy-settings 4 | // License: LGPL v2.1 5 | // 6 | (function () { 7 | var lang = navigator.language; 8 | if (this.i18n === undefined) { this.i18n = {}; } 9 | this.i18n.get = function (value) { 10 | if (value === "lang") { 11 | return lang; 12 | } 13 | 14 | if (this.hasOwnProperty(value)) { 15 | value = this[value]; 16 | if (value.hasOwnProperty(lang)) { 17 | return value[lang]; 18 | } else if (value.hasOwnProperty("en")) { 19 | return value["en"]; 20 | } else { 21 | return Object.values(value)[0]; 22 | } 23 | } else { 24 | return value; 25 | } 26 | }; 27 | }()); 28 | -------------------------------------------------------------------------------- /ext/src/options_custom/lib/default.css: -------------------------------------------------------------------------------- 1 | /* 2 | // Copyright (c) 2007 - 2010 blueprintcss.org 3 | // Modified and extended by Frank Kohlhepp in 2011 4 | // https://github.com/frankkohlhepp/default-css 5 | // License: MIT-license 6 | */ 7 | 8 | /* 9 | // Reset the default browser CSS 10 | */ 11 | html { 12 | margin: 0; 13 | padding: 0; 14 | border: 0; 15 | } 16 | 17 | body, div, span, object, iframe, 18 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 19 | a, abbr, acronym, address, code, 20 | del, dfn, em, img, q, dl, dt, dd, ol, ul, li, 21 | fieldset, form, label, legend, 22 | table, caption, tbody, tfoot, thead, tr, th, td, 23 | article, aside, dialog, figure, footer, header, 24 | hgroup, nav, section { 25 | margin: 0; 26 | padding: 0; 27 | border: 0; 28 | font-family: inherit; 29 | font-size: 100%; 30 | font-weight: inherit; 31 | font-style: inherit; 32 | vertical-align: baseline; 33 | } 34 | 35 | article, aside, dialog, figure, footer, header, 36 | hgroup, nav, section { 37 | display: block; 38 | } 39 | 40 | body { 41 | background-color: white; 42 | line-height: 1.5; 43 | } 44 | 45 | table { 46 | border-collapse: separate; 47 | border-spacing: 0; 48 | } 49 | 50 | caption, th, td { 51 | text-align: left; 52 | font-weight: normal; 53 | } 54 | 55 | table, th, td { 56 | vertical-align: middle; 57 | } 58 | 59 | blockquote:before, blockquote:after, q:before, q:after { 60 | content: ""; 61 | } 62 | 63 | blockquote, q { 64 | quotes: "" ""; 65 | } 66 | 67 | a img { 68 | border: none; 69 | } 70 | 71 | /* 72 | // Default typography 73 | */ 74 | html { 75 | font-size: 100.01%; 76 | } 77 | 78 | body { 79 | background-color: white; 80 | font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; 81 | font-size: 75%; 82 | color: #222222; 83 | } 84 | 85 | /* Headings */ 86 | h1, h2, h3, h4, h5, h6 { 87 | font-weight: normal; 88 | color: #111111; 89 | } 90 | 91 | h1 { 92 | margin-bottom: 0.5em; 93 | font-size: 3em; 94 | line-height: 1; 95 | } 96 | 97 | h2 { 98 | margin-bottom: 0.75em; 99 | font-size: 2em; 100 | } 101 | 102 | h3 { 103 | margin-bottom: 1em; 104 | font-size: 1.5em; 105 | line-height: 1; 106 | } 107 | 108 | h4 { 109 | margin-bottom: 1.25em; 110 | font-size: 1.2em; 111 | line-height: 1.25; 112 | } 113 | 114 | h5 { 115 | margin-bottom: 1.5em; 116 | font-size: 1em; 117 | font-weight: bold; 118 | } 119 | 120 | h6 { 121 | font-size: 1em; 122 | font-weight: bold; 123 | } 124 | 125 | h1 img, h2 img, h3 img, 126 | h4 img, h5 img, h6 img { 127 | margin: 0; 128 | } 129 | 130 | /* Text elements */ 131 | p { 132 | margin: 0 0 1.5em; 133 | } 134 | 135 | .left { 136 | float: left !important; 137 | } 138 | 139 | p .left { 140 | margin: 1.5em 1.5em 1.5em 0; 141 | padding: 0; 142 | } 143 | 144 | .right { 145 | float: right !important; 146 | } 147 | 148 | p .right { 149 | margin: 1.5em 0 1.5em 1.5em; 150 | padding: 0; 151 | } 152 | 153 | a:focus, a:hover { 154 | color: #0099FF; 155 | } 156 | 157 | a { 158 | color: #0066CC; 159 | text-decoration: underline; 160 | } 161 | 162 | blockquote { 163 | margin: 1.5em; 164 | font-style: italic; 165 | color: #666666; 166 | } 167 | 168 | strong, dfn { 169 | font-weight: bold; 170 | } 171 | 172 | em, dfn { 173 | font-style: italic; 174 | } 175 | 176 | sup, sub { 177 | line-height: 0; 178 | } 179 | 180 | abbr, acronym { 181 | border-bottom: 1px dotted #666666; 182 | } 183 | 184 | address { 185 | margin: 0 0 1.5em; 186 | font-style: italic; 187 | } 188 | 189 | del { 190 | color: #666666; 191 | } 192 | 193 | pre { 194 | margin: 1.5em 0; 195 | white-space: pre; 196 | } 197 | 198 | pre, code, tt { 199 | font: 1em "andale mono", "lucida console", monospace; 200 | line-height: 1.5; 201 | } 202 | 203 | /* Lists */ 204 | li ul, li ol { 205 | margin: 0; 206 | } 207 | 208 | ul, ol { 209 | margin: 0 1.5em 1.5em 0; 210 | padding-left: 1.5em; 211 | } 212 | 213 | ul { 214 | list-style-type: disc; 215 | } 216 | 217 | ol { 218 | list-style-type: decimal; 219 | } 220 | 221 | dl { 222 | margin: 0 0 1.5em 0; 223 | } 224 | 225 | dl dt { 226 | font-weight: bold; 227 | } 228 | 229 | dd { 230 | margin-left: 1.5em; 231 | } 232 | 233 | /* Tables */ 234 | table { 235 | width: 100%; 236 | margin-bottom: 1.4em; 237 | } 238 | 239 | th { 240 | font-weight: bold; 241 | } 242 | 243 | table.zebra thead th, table.zebra tfoot th { 244 | background-color: #BFBFBF; 245 | } 246 | 247 | th, td, caption { 248 | padding: 4px 10px 4px 5px; 249 | } 250 | 251 | table.zebra tbody tr:nth-child(even) td, table.zebra tbody tr.even td { 252 | background-color: #E6E6E6; 253 | } 254 | 255 | caption { 256 | background-color: #EEEEEE; 257 | } 258 | 259 | /* Misc classes */ 260 | .fancy { 261 | text-shadow: white 0 1px 0; 262 | } 263 | 264 | .bfancy { 265 | text-shadow: black 0 1px 0; 266 | } 267 | 268 | .fancyt { 269 | text-shadow: white 0 -1px 0; 270 | } 271 | 272 | .bfancyt { 273 | text-shadow: black 0 -1px 0; 274 | } 275 | 276 | .no-fancy { 277 | text-shadow: none; 278 | } 279 | 280 | .select { 281 | cursor: auto; 282 | user-select: auto; 283 | -webkit-user-select: auto; 284 | -moz-user-select: auto; 285 | -o-user-select: auto; 286 | } 287 | 288 | img.select, .select img { 289 | user-drag: auto; 290 | -webkit-user-drag: auto; 291 | -moz-user-drag: auto; 292 | -o-user-drag: auto; 293 | } 294 | 295 | .no-select { 296 | cursor: default; 297 | user-select: none; 298 | -webkit-user-select: none; 299 | -moz-user-select: none; 300 | -o-user-select: none; 301 | } 302 | 303 | img.no-select, .no-select img { 304 | user-drag: none; 305 | -webkit-user-drag: none; 306 | -moz-user-drag: none; 307 | -o-user-drag: none; 308 | } 309 | 310 | .focus:focus, .focus :focus { 311 | outline: auto; 312 | } 313 | 314 | .no-focus:focus, .no-focus :focus { 315 | outline: 0; 316 | } 317 | 318 | .small { 319 | margin-bottom: 1.875em; 320 | font-size: .8em; 321 | line-height: 1.875em; 322 | } 323 | 324 | .large { 325 | margin-bottom: 1.25em; 326 | font-size: 1.2em; 327 | line-height: 2.5em; 328 | } 329 | 330 | .show { 331 | display: block !important; 332 | } 333 | 334 | .show-inline { 335 | display: inline-block !important; 336 | } 337 | 338 | .hide { 339 | display: none; 340 | } 341 | 342 | .quiet { 343 | color: #666666; 344 | } 345 | 346 | .loud { 347 | color: black; 348 | } 349 | 350 | .highlight { 351 | background-color: yellow; 352 | } 353 | 354 | .added { 355 | background-color: #006600; 356 | color: white; 357 | } 358 | 359 | .removed { 360 | background-color: #990000; 361 | color: white; 362 | } 363 | 364 | .first { 365 | margin-left: 0; 366 | padding-left: 0; 367 | } 368 | 369 | .last { 370 | margin-right: 0; 371 | padding-right: 0; 372 | } 373 | 374 | .top { 375 | margin-top: 0; 376 | padding-top: 0; 377 | } 378 | 379 | .bottom { 380 | margin-bottom: 0; 381 | padding-bottom: 0; 382 | } 383 | 384 | /* 385 | // Default styling for forms 386 | */ 387 | fieldset { 388 | margin: 0 0 1.5em 0; 389 | padding: 0 1.4em 1.4em 1.4em; 390 | border: 1px solid #CCCCCC; 391 | } 392 | 393 | legend { 394 | margin-top: -0.2em; 395 | margin-bottom: 1em; 396 | font-weight: bold; 397 | font-size: 1.2em; 398 | } 399 | 400 | /* Form fields */ 401 | input[type=text], input[type=password], textarea { 402 | background-color: white; 403 | border: 1px solid #BBBBBB; 404 | } 405 | 406 | input[type=text], input[type=password], 407 | textarea, select { 408 | margin: 0.5em 0; 409 | } 410 | 411 | input[type=text], input[type=password] { 412 | width: 300px; 413 | padding: 4px; 414 | } 415 | 416 | textarea { 417 | width: 450px; 418 | height: 170px; 419 | padding: 5px; 420 | } 421 | 422 | /* success, info, notice and error boxes */ 423 | .success, .info, .notice, .error { 424 | margin-bottom: 1em; 425 | padding: 0.8em; 426 | border: 2px solid #DDDDDD; 427 | } 428 | 429 | .success { 430 | background-color: #E6EFC2; 431 | border-color: #C6D880; 432 | color: #264409; 433 | } 434 | 435 | .info { 436 | background-color: #D5EDF8; 437 | border-color: #92CAE4; 438 | color: #205791; 439 | } 440 | 441 | .notice { 442 | background-color: #FFF6BF; 443 | border-color: #FFD324; 444 | color: #514721; 445 | } 446 | 447 | .error { 448 | background-color: #FBE3E4; 449 | border-color: #FBC2C4; 450 | color: #8A1F11; 451 | } 452 | 453 | .success a { 454 | color: #264409; 455 | } 456 | 457 | .info a { 458 | color: #205791; 459 | } 460 | 461 | .notice a { 462 | color: #514721; 463 | } 464 | 465 | .error a { 466 | color: #8A1F11; 467 | } 468 | -------------------------------------------------------------------------------- /ext/src/options_custom/lib/store.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2011 Frank Kohlhepp 3 | // https://github.com/frankkohlhepp/store-js 4 | // License: MIT-license 5 | // 6 | (function () { 7 | var Store = this.Store = function (name, defaults) { 8 | var key; 9 | this.name = name; 10 | 11 | if (defaults !== undefined) { 12 | for (key in defaults) { 13 | if (defaults.hasOwnProperty(key) && this.get(key) === undefined) { 14 | this.set(key, defaults[key]); 15 | } 16 | } 17 | } 18 | }; 19 | 20 | Store.prototype.get = function (name) { 21 | name = "store." + this.name + "." + name; 22 | if (localStorage.getItem(name) === null) { return undefined; } 23 | try { 24 | return JSON.parse(localStorage.getItem(name)); 25 | } catch (e) { 26 | return null; 27 | } 28 | }; 29 | 30 | Store.prototype.set = function (name, value) { 31 | if (value === undefined) { 32 | this.remove(name); 33 | } else { 34 | if (typeof value === "function") { 35 | value = null; 36 | } else { 37 | try { 38 | value = JSON.stringify(value); 39 | } catch (e) { 40 | value = null; 41 | } 42 | } 43 | 44 | localStorage.setItem("store." + this.name + "." + name, value); 45 | } 46 | 47 | return this; 48 | }; 49 | 50 | Store.prototype.remove = function (name) { 51 | localStorage.removeItem("store." + this.name + "." + name); 52 | return this; 53 | }; 54 | 55 | Store.prototype.removeAll = function () { 56 | var name, 57 | i; 58 | 59 | name = "store." + this.name + "."; 60 | for (i = (localStorage.length - 1); i >= 0; i--) { 61 | if (localStorage.key(i).substring(0, name.length) === name) { 62 | localStorage.removeItem(localStorage.key(i)); 63 | } 64 | } 65 | 66 | return this; 67 | }; 68 | 69 | Store.prototype.toObject = function () { 70 | var values, 71 | name, 72 | i, 73 | key, 74 | value; 75 | 76 | values = {}; 77 | name = "store." + this.name + "."; 78 | for (i = (localStorage.length - 1); i >= 0; i--) { 79 | if (localStorage.key(i).substring(0, name.length) === name) { 80 | key = localStorage.key(i).substring(name.length); 81 | value = this.get(key); 82 | if (value !== undefined) { values[key] = value; } 83 | } 84 | } 85 | 86 | return values; 87 | }; 88 | 89 | Store.prototype.fromObject = function (values, merge) { 90 | if (merge !== true) { this.removeAll(); } 91 | for (var key in values) { 92 | if (values.hasOwnProperty(key)) { 93 | this.set(key, values[key]); 94 | } 95 | } 96 | 97 | return this; 98 | }; 99 | }()); 100 | -------------------------------------------------------------------------------- /ext/src/options_custom/manifest.js: -------------------------------------------------------------------------------- 1 | // SAMPLE 2 | this.manifest = { 3 | "name": "My Extension", 4 | "icon": "icon.png", 5 | "settings": [ 6 | { 7 | "tab": i18n.get("information"), 8 | "group": i18n.get("login"), 9 | "name": "username", 10 | "type": "text", 11 | "label": i18n.get("username"), 12 | "text": i18n.get("x-characters") 13 | }, 14 | { 15 | "tab": i18n.get("information"), 16 | "group": i18n.get("login"), 17 | "name": "password", 18 | "type": "text", 19 | "label": i18n.get("password"), 20 | "text": i18n.get("x-characters-pw"), 21 | "masked": true 22 | }, 23 | { 24 | "tab": i18n.get("information"), 25 | "group": i18n.get("login"), 26 | "name": "myDescription", 27 | "type": "description", 28 | "text": i18n.get("description") 29 | }, 30 | { 31 | "tab": i18n.get("information"), 32 | "group": i18n.get("logout"), 33 | "name": "myCheckbox", 34 | "type": "checkbox", 35 | "label": i18n.get("enable") 36 | }, 37 | { 38 | "tab": i18n.get("information"), 39 | "group": i18n.get("logout"), 40 | "name": "myButton", 41 | "type": "button", 42 | "label": i18n.get("disconnect"), 43 | "text": i18n.get("logout") 44 | }, 45 | { 46 | "tab": "Details", 47 | "group": "Sound", 48 | "name": "noti_volume", 49 | "type": "slider", 50 | "label": "Notification volume:", 51 | "max": 1, 52 | "min": 0, 53 | "step": 0.01, 54 | "display": true, 55 | "displayModifier": function (value) { 56 | return (value * 100).floor() + "%"; 57 | } 58 | }, 59 | { 60 | "tab": "Details", 61 | "group": "Sound", 62 | "name": "sound_volume", 63 | "type": "slider", 64 | "label": "Sound volume:", 65 | "max": 100, 66 | "min": 0, 67 | "step": 1, 68 | "display": true, 69 | "displayModifier": function (value) { 70 | return value + "%"; 71 | } 72 | }, 73 | { 74 | "tab": "Details", 75 | "group": "Food", 76 | "name": "myPopupButton", 77 | "type": "popupButton", 78 | "label": "Soup 1 should be:", 79 | "options": { 80 | "groups": [ 81 | "Hot", "Cold", 82 | ], 83 | "values": [ 84 | { 85 | "value": "hot", 86 | "text": "Very hot", 87 | "group": "Hot", 88 | }, 89 | { 90 | "value": "Medium", 91 | "group": 1, 92 | }, 93 | { 94 | "value": "Cold", 95 | "group": 2, 96 | }, 97 | ["Non-existing"] 98 | ], 99 | }, 100 | }, 101 | { 102 | "tab": "Details", 103 | "group": "Food", 104 | "name": "myListBox", 105 | "type": "listBox", 106 | "label": "Soup 2 should be:", 107 | "options": [ 108 | ["hot", "Hot and yummy"], 109 | ["cold"] 110 | ] 111 | }, 112 | { 113 | "tab": "Details", 114 | "group": "Food", 115 | "name": "myRadioButtons", 116 | "type": "radioButtons", 117 | "label": "Soup 3 should be:", 118 | "options": [ 119 | ["hot", "Hot and yummy"], 120 | ["cold"] 121 | ] 122 | } 123 | ], 124 | "alignment": [ 125 | [ 126 | "username", 127 | "password" 128 | ], 129 | [ 130 | "noti_volume", 131 | "sound_volume" 132 | ] 133 | ] 134 | }; 135 | -------------------------------------------------------------------------------- /ext/src/options_custom/settings.js: -------------------------------------------------------------------------------- 1 | window.addEvent("domready", function () { 2 | // Option 1: Use the manifest: 3 | new FancySettings.initWithManifest(function (settings) { 4 | settings.manifest.myButton.addEvent("action", function () { 5 | alert("You clicked me!"); 6 | }); 7 | }); 8 | 9 | // Option 2: Do everything manually: 10 | /* 11 | var settings = new FancySettings("My Extension", "icon.png"); 12 | 13 | var username = settings.create({ 14 | "tab": i18n.get("information"), 15 | "group": i18n.get("login"), 16 | "name": "username", 17 | "type": "text", 18 | "label": i18n.get("username"), 19 | "text": i18n.get("x-characters") 20 | }); 21 | 22 | var password = settings.create({ 23 | "tab": i18n.get("information"), 24 | "group": i18n.get("login"), 25 | "name": "password", 26 | "type": "text", 27 | "label": i18n.get("password"), 28 | "text": i18n.get("x-characters-pw"), 29 | "masked": true 30 | }); 31 | 32 | var myDescription = settings.create({ 33 | "tab": i18n.get("information"), 34 | "group": i18n.get("login"), 35 | "name": "myDescription", 36 | "type": "description", 37 | "text": i18n.get("description") 38 | }); 39 | 40 | var myButton = settings.create({ 41 | "tab": "Information", 42 | "group": "Logout", 43 | "name": "myButton", 44 | "type": "button", 45 | "label": "Disconnect:", 46 | "text": "Logout" 47 | }); 48 | 49 | // ... 50 | 51 | myButton.addEvent("action", function () { 52 | alert("You clicked me!"); 53 | }); 54 | 55 | settings.align([ 56 | username, 57 | password 58 | ]); 59 | */ 60 | }); 61 | -------------------------------------------------------------------------------- /ext/src/override/override.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ext/src/page_action/page_action.html: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 |
15 |

Hello extensionizr!

16 |

To shut this popup down, edit the manifest file and remove the "default popup" key. To edit it, just edit ext/page_action/page_action.html. The CSS is there, too.

17 |
-------------------------------------------------------------------------------- /favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/favicon.png -------------------------------------------------------------------------------- /img/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/img/bg.png -------------------------------------------------------------------------------- /img/bp_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/img/bp_logo.png -------------------------------------------------------------------------------- /img/bp_logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/img/bp_logo2.png -------------------------------------------------------------------------------- /img/github-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/img/github-logo.png -------------------------------------------------------------------------------- /img/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/img/help.png -------------------------------------------------------------------------------- /img/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/img/icon16.png -------------------------------------------------------------------------------- /img/noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/img/noise.png -------------------------------------------------------------------------------- /img/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/altryne/extensionizr/1ce45cc1582b3d253f11ef9103403badc634de66/img/preview.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Extensionizr - boilerplate for your chrome extension 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
30 |

Extensionizr

31 |

Start a chrome extension in 15 seconds!

32 |
33 |
34 |
35 |
36 |

Alex Wolkov

37 |
38 | 39 | 40 | 41 | 42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | 51 |
52 |

53 | Extensionizr helps you create the basis for your own awesome chrome extension! 54 |

55 |
56 |

57 | 1 - Name your extension 58 |

59 | 60 |
61 |
62 | 65 | 66 | 67 | 68 |
69 |
70 | 73 | 74 | 75 | 76 |
77 |
78 | 81 | 82 | 83 | 84 |
85 |
86 |
87 |

88 | 2 - Fine tuning 89 |

90 | 91 |
92 | 93 |
94 |

Extension type

95 | 98 | 101 | 104 |
105 |
106 |

Background page

107 | 110 | 113 | 116 | 117 |
118 |
119 |

Options page

120 | 123 | 127 | 128 |
129 |
130 |

Override

131 | 134 | 137 | 140 | 141 |
142 |
143 |

Content scripts

144 | 147 | 150 |
151 |
152 |

Misc addons

153 | 156 | 159 | 162 |
163 |
164 |

URL permissions 165 | 166 |

167 | 168 | Separated by ";" (https://*/* ; http://google.com/*) 169 |
170 |
171 |

Permissions 172 | 173 |

174 | 177 | 180 | 183 | 186 | 189 |
190 |
191 |

Permissions 192 | 193 |

194 | 197 | 200 | 203 | 206 | 209 | 210 |
211 |
212 |

Permissions 213 | 214 |

215 | 218 | 221 | 224 | 227 | 230 | 233 |
234 | 235 |
236 | 237 | 238 |
239 | Download it! 240 | 241 |
242 | 243 |
244 |
245 |
246 | 247 |
248 |
249 |
250 | Github logo 251 |
252 |

Open source baby!

253 | 254 |
    255 |
  • This webapp is on github!
  • 256 |
257 | 258 |

Thanx to these guys :

259 | 265 |
266 |
267 |
268 |

Another *izr? When will this stop

269 |

Extensionizr is a simple way to jump start your chrome extension development. Just select the type of extension you want, 270 | choose permissions and you're off.

271 | 272 |

Why does this exist?

273 |

274 | Because I got super tired creating the file structure for a new extension over and over again.
275 | Extensionizr will be always updated with the latest chrome manifest changes.
276 | In addition, I wanted to create a client-side only tool. Extensionizr doesn't use server side code! Don't believe me? Checkout the github repo. 277 | 278 |

279 | 280 | 281 |

Based on open source

282 |

283 | Extensionizr is 90% based on open source pieces I put together. It's heavily inspired by 284 | Initializr by Jonathan Verrecchia. 285 |

286 | 287 | 288 |

Contact

289 |

Email me at , or mention @altryne.

290 | 291 |
292 | 293 |
294 |
295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 316 | 317 | 318 | -------------------------------------------------------------------------------- /js/libs/modernizr-2.0.6.min.js: -------------------------------------------------------------------------------- 1 | /* Modernizr 2.0.6 | MIT & BSD 2 | * Contains: All core tests, html5shiv, yepnope, respond.js. Get your own custom build at www.modernizr.com/download/ 3 | */ 4 | ;window.Modernizr=function(a,b,c){function I(){e.input=function(a){for(var b=0,c=a.length;b",a,""].join(""),k.id=i,k.innerHTML+=f,g.appendChild(k),h=c(k,a),k.parentNode.removeChild(k);return!!h},w=function(b){if(a.matchMedia)return matchMedia(b).matches;var c;v("@media "+b+" { #"+i+" { position: absolute; } }",function(b){c=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).position=="absolute"});return c},x=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=D(e[d],"function"),D(e[d],c)||(e[d]=c),e.removeAttribute(d))),e=null;return f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),y,z={}.hasOwnProperty,A;!D(z,c)&&!D(z.call,c)?A=function(a,b){return z.call(a,b)}:A=function(a,b){return b in a&&D(a.constructor.prototype[b],c)};var H=function(c,d){var f=c.join(""),g=d.length;v(f,function(c,d){var f=b.styleSheets[b.styleSheets.length-1],h=f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"",i=c.childNodes,j={};while(g--)j[i[g].id]=i[g];e.touch="ontouchstart"in a||j.touch.offsetTop===9,e.csstransforms3d=j.csstransforms3d.offsetLeft===9,e.generatedcontent=j.generatedcontent.offsetHeight>=1,e.fontface=/src/i.test(h)&&h.indexOf(d.split(" ")[0])===0},g,d)}(['@font-face {font-family:"font";src:url("https://")}',["@media (",o.join("touch-enabled),("),i,")","{#touch{top:9px;position:absolute}}"].join(""),["@media (",o.join("transform-3d),("),i,")","{#csstransforms3d{left:9px;position:absolute}}"].join(""),['#generatedcontent:after{content:"',m,'";visibility:hidden}'].join("")],["fontface","touch","csstransforms3d","generatedcontent"]);r.flexbox=function(){function c(a,b,c,d){a.style.cssText=o.join(b+":"+c+";")+(d||"")}function a(a,b,c,d){b+=":",a.style.cssText=(b+o.join(c+";"+b)).slice(0,-b.length)+(d||"")}var d=b.createElement("div"),e=b.createElement("div");a(d,"display","box","width:42px;padding:0;"),c(e,"box-flex","1","width:10px;"),d.appendChild(e),g.appendChild(d);var f=e.offsetWidth===42;d.removeChild(e),g.removeChild(d);return f},r.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},r.canvastext=function(){return!!e.canvas&&!!D(b.createElement("canvas").getContext("2d").fillText,"function")},r.webgl=function(){return!!a.WebGLRenderingContext},r.touch=function(){return e.touch},r.geolocation=function(){return!!navigator.geolocation},r.postmessage=function(){return!!a.postMessage},r.websqldatabase=function(){var b=!!a.openDatabase;return b},r.indexedDB=function(){for(var b=-1,c=p.length;++b7)},r.history=function(){return!!a.history&&!!history.pushState},r.draganddrop=function(){return x("dragstart")&&x("drop")},r.websockets=function(){for(var b=-1,c=p.length;++b";return(a.firstChild&&a.firstChild.namespaceURI)==q.svg},r.smil=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"animate")))},r.svgclippaths=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"clipPath")))};for(var J in r)A(r,J)&&(y=J.toLowerCase(),e[y]=r[J](),u.push((e[y]?"":"no-")+y));e.input||I(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)A(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return;b=typeof b=="boolean"?b:!!b(),g.className+=" "+(b?"":"no-")+a,e[a]=b}return e},B(""),j=l=null,a.attachEvent&&function(){var a=b.createElement("div");a.innerHTML="";return a.childNodes.length!==1}()&&function(a,b){function s(a){var b=-1;while(++b=u.minw)&&(!u.maxw||u.maxw&&l<=u.maxw))m[u.media]||(m[u.media]=[]),m[u.media].push(f[u.rules])}for(var t in g)g[t]&&g[t].parentNode===j&&j.removeChild(g[t]);for(var t in m){var v=c.createElement("style"),w=m[t].join("\n");v.type="text/css",v.media=t,v.styleSheet?v.styleSheet.cssText=w:v.appendChild(c.createTextNode(w)),n.appendChild(v),g.push(v)}j.insertBefore(n,o.nextSibling)}},s=function(a,b){var c=t();if(!!c){c.open("GET",a,!0),c.onreadystatechange=function(){c.readyState==4&&(c.status==200||c.status==304)&&b(c.responseText)};if(c.readyState==4)return;c.send()}},t=function(){var a=!1,b=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new XMLHttpRequest}],c=b.length;while(c--){try{a=b[c]()}catch(d){continue}break}return function(){return a}}();m(),respond.update=m,a.addEventListener?a.addEventListener("resize",u,!1):a.attachEvent&&a.attachEvent("onresize",u)}}(this,Modernizr.mq("only all")),function(a,b,c){function k(a){return!a||a=="loaded"||a=="complete"}function j(){var a=1,b=-1;while(p.length- ++b)if(p[b].s&&!(a=p[b].r))break;a&&g()}function i(a){var c=b.createElement("script"),d;c.src=a.s,c.onreadystatechange=c.onload=function(){!d&&k(c.readyState)&&(d=1,j(),c.onload=c.onreadystatechange=null)},m(function(){d||(d=1,j())},H.errorTimeout),a.e?c.onload():n.parentNode.insertBefore(c,n)}function h(a){var c=b.createElement("link"),d;c.href=a.s,c.rel="stylesheet",c.type="text/css";if(!a.e&&(w||r)){var e=function(a){m(function(){if(!d)try{a.sheet.cssRules.length?(d=1,j()):e(a)}catch(b){b.code==1e3||b.message=="security"||b.message=="denied"?(d=1,m(function(){j()},0)):e(a)}},0)};e(c)}else c.onload=function(){d||(d=1,m(function(){j()},0))},a.e&&c.onload();m(function(){d||(d=1,j())},H.errorTimeout),!a.e&&n.parentNode.insertBefore(c,n)}function g(){var a=p.shift();q=1,a?a.t?m(function(){a.t=="c"?h(a):i(a)},0):(a(),j()):q=0}function f(a,c,d,e,f,h){function i(){!o&&k(l.readyState)&&(r.r=o=1,!q&&j(),l.onload=l.onreadystatechange=null,m(function(){u.removeChild(l)},0))}var l=b.createElement(a),o=0,r={t:d,s:c,e:h};l.src=l.data=c,!s&&(l.style.display="none"),l.width=l.height="0",a!="object"&&(l.type=d),l.onload=l.onreadystatechange=i,a=="img"?l.onerror=i:a=="script"&&(l.onerror=function(){r.e=r.r=1,g()}),p.splice(e,0,r),u.insertBefore(l,s?null:n),m(function(){o||(u.removeChild(l),r.r=r.e=o=1,j())},H.errorTimeout)}function e(a,b,c){var d=b=="c"?z:y;q=0,b=b||"j",C(a)?f(d,a,b,this.i++,l,c):(p.splice(this.i++,0,a),p.length==1&&g());return this}function d(){var a=H;a.loader={load:e,i:0};return a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=r&&!s,u=s?l:n.parentNode,v=a.opera&&o.call(a.opera)=="[object Opera]",w="webkitAppearance"in l.style,x=w&&"async"in b.createElement("script"),y=r?"object":v||x?"img":"script",z=w?"img":y,A=Array.isArray||function(a){return o.call(a)=="[object Array]"},B=function(a){return Object(a)===a},C=function(a){return typeof a=="string"},D=function(a){return o.call(a)=="[object Function]"},E=[],F={},G,H;H=function(a){function f(a){var b=a.split("!"),c=E.length,d=b.pop(),e=b.length,f={url:d,origUrl:d,prefixes:b},g,h;for(h=0;h 0){ 269 | manifest.permissions = permissions; 270 | }else{ 271 | delete manifest.permissions; 272 | } 273 | } 274 | 275 | 276 | /*********** 277 | HELPERS 278 | ***********/ 279 | 280 | if (!Array.indexOf){ 281 | Array.prototype.indexOf = function(searchedElement){ 282 | for (var i = 0; i < this.length; i++){ 283 | if (this[i] === searchedElement) 284 | return i; 285 | }; 286 | return -1; 287 | }; 288 | } 289 | if(!Array.has){ 290 | Array.prototype.has = function(searchedElement){ 291 | var i = this.indexOf(searchedElement); 292 | return (i > -1) ? true : false; 293 | } 294 | } 295 | 296 | Array.prototype.remove = function(searchedElement){ 297 | var i = this.indexOf(searchedElement); 298 | if (i != -1) 299 | this.splice(i, 1); 300 | }; 301 | 302 | /*********** 303 | MAIN 304 | ***********/ 305 | var filesystem, zipFs = new zip.fs.FS(); 306 | var genButton = $('#gen-link'); 307 | var downloadButton = $('#download-link')[0]; 308 | 309 | // if ($('input:checked').length > 0) 310 | // $('#hidden-section').fadeIn(0); 311 | init(); 312 | 313 | var elms = $('.more_info'); 314 | $('
').qtip({ 315 | content : {text:"a"}, 316 | style: { 317 | classes: 'qtip-shadow qtip-blue' 318 | }, 319 | position : { 320 | target : 'event', 321 | at : "top center", 322 | my : "bottom center", 323 | viewport: $('#main'), 324 | adjust: { 325 | y: -5, 326 | method : 'flip none' 327 | } 328 | }, 329 | show : { 330 | target : elms 331 | }, 332 | hide : { 333 | target : elms 334 | }, 335 | events: { 336 | show: function(event, api) { 337 | var target = $(event.originalEvent.target); 338 | api.set('content.text', target.data('content').replace('. ','
')); 339 | } 340 | } 341 | }); 342 | 343 | genButton.on('click',function(){ 344 | processZip(); 345 | event.preventDefault(); 346 | return false; 347 | }); 348 | 349 | function onerror(message) { 350 | console.error(message); 351 | } 352 | 353 | zip.workerScriptsPath = "zip/"; 354 | imported_zip_root = "ext/"; 355 | 356 | function importZip(callback){ 357 | zipFs.importHttpContent("ext.zip", false, function() { 358 | extFs = zipFs.root.children[0]; 359 | manifestFs = extFs.getChildByName('manifest.json'); 360 | manifestFs.getText(function(data){ 361 | window.manifest = JSON.parse(data); 362 | if(typeof callback == 'function'){ 363 | callback(); 364 | } 365 | }); 366 | }, onerror); 367 | }; 368 | importZip(); 369 | function processZip(_data){ 370 | if (!downloadButton.download) { 371 | console.log('generating the zip file eyooooooo'); 372 | manifest = _data || manifest; 373 | manifestJson = JSON.stringify(manifest,null,2); 374 | for (var i = 0; i < dirs_to_remove.length; i++) { 375 | var dir = dirs_to_remove[i]; 376 | var dirFs = zipFs.find(imported_zip_root + dir); 377 | console.log('removing directory: ' + dir); 378 | zipFs.remove(dirFs); 379 | } 380 | for (var i = 0; i < files_to_remove.length; i++) { 381 | var file = files_to_remove[i]; 382 | var fileFs = zipFs.find(imported_zip_root + file); 383 | console.log('removing file: ' + file); 384 | zipFs.remove(fileFs); 385 | } 386 | 387 | //remove old cluncky manifest file from zip 388 | zipFs.remove(manifestFs); 389 | //write new manifest to filesystem API 390 | extFs.addText('manifest.json', manifestJson); 391 | genButton.html('Generating download!').addClass('loading'); 392 | zipFs.exportData64URI(function (data) { 393 | genButton.html('Download ready!').removeClass('loading'); 394 | 395 | var clickEvent = document.createEvent("MouseEvent"); 396 | clickEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); 397 | downloadButton.href = data; 398 | _gaq.push(['_trackEvent', 'Buttons', "download-button"]); 399 | downloadButton.download = 'extensionizr_custom' + Date.now() + '.zip'; 400 | downloadButton.dispatchEvent(clickEvent); 401 | event.preventDefault(); 402 | return false; 403 | 404 | }, $.noop, function(){ 405 | genButton.html('Something went wrong').removeClass('loading'); 406 | }); 407 | }else{ 408 | //redownload 409 | var clickEvent = document.createEvent("MouseEvent"); 410 | clickEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); 411 | downloadButton.dispatchEvent(clickEvent); 412 | event.preventDefault(); 413 | return false; 414 | } 415 | } 416 | 417 | }); 418 | -------------------------------------------------------------------------------- /zip/dataview.js: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * DataView.js: 4 | * An implementation of the DataView class on top of typed arrays. 5 | * Useful for Firefox 4 which implements TypedArrays but not DataView. 6 | * 7 | * Copyright 2011, David Flanagan 8 | * 9 | * All rights reserved. 10 | * 11 | * Redistribution and use in source and binary forms, with or without modification, 12 | * are permitted provided that the following conditions are met: 13 | * 14 | * Redistributions of source code must retain the above copyright notice, 15 | * this list of conditions and the following disclaimer. 16 | * 17 | * Redistributions in binary form must reproduce the above copyright notice, 18 | * this list of conditions and the following disclaimer in the documentation. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 29 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | "use strict"; 32 | 33 | (function(global) { 34 | // If DataView already exists, do nothing 35 | if (global.DataView) return; 36 | 37 | // If ArrayBuffer is not supported, fail with an error 38 | if (!global.ArrayBuffer) fail("ArrayBuffer not supported"); 39 | 40 | // If ES5 is not supported, fail 41 | if (!Object.defineProperties) fail("This module requires ECMAScript 5"); 42 | 43 | // Figure if the platform is natively little-endian. 44 | // If the integer 0x00000001 is arranged in memory as 01 00 00 00 then 45 | // we're on a little endian platform. On a big-endian platform we'd get 46 | // get bytes 00 00 00 01 instead. 47 | var nativele = new Int8Array(new Int32Array([1]).buffer)[0] === 1; 48 | 49 | // A temporary array for copying or reversing bytes into. 50 | // Since js is single-threaded, we only need this one static copy 51 | var temp = new Uint8Array(8); 52 | 53 | // The DataView() constructor 54 | global.DataView = function DataView(buffer, offset, length) { 55 | if (!(buffer instanceof ArrayBuffer)) fail("Bad ArrayBuffer"); 56 | 57 | // Default values for omitted arguments 58 | offset = offset || 0; 59 | length = length || (buffer.byteLength - offset); 60 | 61 | if (offset < 0 || length < 0 || offset + length > buffer.byteLength) fail("Illegal offset and/or length"); 62 | 63 | // Define the 3 read-only, non-enumerable ArrayBufferView properties 64 | Object.defineProperties(this, { 65 | buffer: { 66 | value: buffer, 67 | enumerable: false, 68 | writable: false, 69 | configurable: false 70 | }, 71 | byteOffset: { 72 | value: offset, 73 | enumerable: false, 74 | writable: false, 75 | configurable: false 76 | }, 77 | byteLength: { 78 | value: length, 79 | enumerable: false, 80 | writable: false, 81 | configurable: false 82 | }, 83 | _bytes: { 84 | value: new Uint8Array(buffer, offset, length), 85 | enumerable: false, 86 | writable: false, 87 | configurable: false 88 | } 89 | }); 90 | } 91 | 92 | // The DataView prototype object 93 | global.DataView.prototype = { 94 | constructor: DataView, 95 | 96 | getInt8: function getInt8(offset) { 97 | return get(this, Int8Array, 1, offset); 98 | }, 99 | getUint8: function getUint8(offset) { 100 | return get(this, Uint8Array, 1, offset); 101 | }, 102 | getInt16: function getInt16(offset, le) { 103 | return get(this, Int16Array, 2, offset, le); 104 | }, 105 | getUint16: function getUint16(offset, le) { 106 | return get(this, Uint16Array, 2, offset, le); 107 | }, 108 | getInt32: function getInt32(offset, le) { 109 | return get(this, Int32Array, 4, offset, le); 110 | }, 111 | getUint32: function getUint32(offset, le) { 112 | return get(this, Uint32Array, 4, offset, le); 113 | }, 114 | getFloat32: function getFloat32(offset, le) { 115 | return get(this, Float32Array, 4, offset, le); 116 | }, 117 | getFloat64: function getFloat32(offset, le) { 118 | return get(this, Float64Array, 8, offset, le); 119 | }, 120 | 121 | 122 | setInt8: function setInt8(offset, value) { 123 | set(this, Int8Array, 1, offset, value); 124 | }, 125 | setUint8: function setUint8(offset, value) { 126 | set(this, Uint8Array, 1, offset, value); 127 | }, 128 | setInt16: function setInt16(offset, value, le) { 129 | set(this, Int16Array, 2, offset, value, le); 130 | }, 131 | setUint16: function setUint16(offset, value, le) { 132 | set(this, Uint16Array, 2, offset, value, le); 133 | }, 134 | setInt32: function setInt32(offset, value, le) { 135 | set(this, Int32Array, 4, offset, value, le); 136 | }, 137 | setUint32: function setUint32(offset, value, le) { 138 | set(this, Uint32Array, 4, offset, value, le); 139 | }, 140 | setFloat32: function setFloat32(offset, value, le) { 141 | set(this, Float32Array, 4, offset, value, le); 142 | }, 143 | setFloat64: function setFloat64(offset, value, le) { 144 | set(this, Float64Array, 8, offset, value, le); 145 | } 146 | }; 147 | 148 | // The get() utility function used by the get methods 149 | 150 | 151 | function get(view, type, size, offset, le) { 152 | if (offset === undefined) fail("Missing required offset argument"); 153 | 154 | if (offset < 0 || offset + size > view.byteLength) fail("Invalid index: " + offset); 155 | 156 | if (size === 1 || !! le === nativele) { 157 | // This is the easy case: the desired endianness 158 | // matches the native endianness. 159 | // Typed arrays require proper alignment. DataView does not. 160 | if ((view.byteOffset + offset) % size === 0) return (new type(view.buffer, view.byteOffset + offset, 1))[0]; 161 | else { 162 | // Copy bytes into the temp array, to fix alignment 163 | for (var i = 0; i < size; i++) 164 | temp[i] = view._bytes[offset + i]; 165 | // Now wrap that buffer with an array of the desired type 166 | return (new type(temp.buffer))[0]; 167 | } 168 | } else { 169 | // If the native endianness doesn't match the desired, then 170 | // we have to reverse the bytes 171 | for (var i = 0; i < size; i++) 172 | temp[size - i - 1] = view._bytes[offset + i]; 173 | return (new type(temp.buffer))[0]; 174 | } 175 | } 176 | 177 | // The set() utility function used by the set methods 178 | 179 | 180 | function set(view, type, size, offset, value, le) { 181 | if (offset === undefined) fail("Missing required offset argument"); 182 | if (value === undefined) fail("Missing required value argument"); 183 | 184 | if (offset < 0 || offset + size > view.byteLength) fail("Invalid index: " + offset); 185 | 186 | if (size === 1 || !! le === nativele) { 187 | // This is the easy case: the desired endianness 188 | // matches the native endianness. 189 | if ((view.byteOffset + offset) % size === 0) { 190 | (new type(view.buffer, view.byteOffset + offset, 1))[0] = value; 191 | } else { 192 | (new type(temp.buffer))[0] = value; 193 | // Now copy the bytes into the view's buffer 194 | for (var i = 0; i < size; i++) 195 | view._bytes[i + offset] = temp[i]; 196 | } 197 | } else { 198 | // If the native endianness doesn't match the desired, then 199 | // we have to reverse the bytes 200 | // Store the value into our temporary buffer 201 | (new type(temp.buffer))[0] = value; 202 | 203 | // Now copy the bytes, in reverse order, into the view's buffer 204 | for (var i = 0; i < size; i++) 205 | view._bytes[offset + i] = temp[size - 1 - i]; 206 | } 207 | } 208 | 209 | function fail(msg) { 210 | throw new Error(msg); 211 | } 212 | }(this)); -------------------------------------------------------------------------------- /zip/zip-ext.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Gildas Lormeau. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the distribution. 13 | 14 | 3. The names of the authors may not be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, 18 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, 20 | INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 23 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | (function() { 30 | 31 | var ERR_HTTP_RANGE = "HTTP Range not supported."; 32 | 33 | var Reader = zip.Reader; 34 | var Writer = zip.Writer; 35 | 36 | var ZipDirectoryEntry; 37 | 38 | var appendABViewSupported; 39 | try { 40 | appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0; 41 | } catch (e) { 42 | } 43 | 44 | function HttpReader(url) { 45 | var that = this; 46 | 47 | function getData(callback, onerror) { 48 | var request; 49 | if (!that.data) { 50 | request = new XMLHttpRequest(); 51 | request.addEventListener("load", function() { 52 | if (!that.size) 53 | that.size = Number(request.getResponseHeader("Content-Length")); 54 | that.data = new Uint8Array(request.response); 55 | callback(); 56 | }, false); 57 | request.addEventListener("error", onerror, false); 58 | request.open("GET", url); 59 | request.responseType = "arraybuffer"; 60 | request.send(); 61 | } else 62 | callback(); 63 | } 64 | 65 | function init(callback, onerror) { 66 | var request = new XMLHttpRequest(); 67 | request.addEventListener("load", function() { 68 | that.size = Number(request.getResponseHeader("Content-Length")); 69 | callback(); 70 | }, false); 71 | request.addEventListener("error", onerror, false); 72 | request.open("HEAD", url); 73 | request.send(); 74 | } 75 | 76 | function readUint8Array(index, length, callback, onerror) { 77 | getData(function() { 78 | callback(new Uint8Array(that.data.subarray(index, index + length))); 79 | }, onerror); 80 | } 81 | 82 | that.size = 0; 83 | that.init = init; 84 | that.readUint8Array = readUint8Array; 85 | } 86 | HttpReader.prototype = new Reader(); 87 | HttpReader.prototype.constructor = HttpReader; 88 | 89 | function HttpRangeReader(url) { 90 | var that = this; 91 | 92 | function init(callback, onerror) { 93 | var request = new XMLHttpRequest(); 94 | request.addEventListener("load", function() { 95 | that.size = Number(request.getResponseHeader("Content-Length")); 96 | if (request.getResponseHeader("Accept-Ranges") == "bytes") 97 | callback(); 98 | else 99 | onerror(ERR_HTTP_RANGE); 100 | }, false); 101 | request.addEventListener("error", onerror, false); 102 | request.open("HEAD", url); 103 | request.send(); 104 | } 105 | 106 | function readArrayBuffer(index, length, callback, onerror) { 107 | var request = new XMLHttpRequest(); 108 | request.open("GET", url); 109 | request.responseType = "arraybuffer"; 110 | request.setRequestHeader("Range", "bytes=" + index + "-" + (index + length - 1)); 111 | request.addEventListener("load", function() { 112 | callback(request.response); 113 | }, false); 114 | request.addEventListener("error", onerror, false); 115 | request.send(); 116 | } 117 | 118 | function readUint8Array(index, length, callback, onerror) { 119 | readArrayBuffer(index, length, function(arraybuffer) { 120 | callback(new Uint8Array(arraybuffer)); 121 | }, onerror); 122 | } 123 | 124 | that.size = 0; 125 | that.init = init; 126 | that.readUint8Array = readUint8Array; 127 | } 128 | HttpRangeReader.prototype = new Reader(); 129 | HttpRangeReader.prototype.constructor = HttpRangeReader; 130 | 131 | function ArrayBufferReader(arrayBuffer) { 132 | var that = this; 133 | 134 | function init(callback, onerror) { 135 | that.size = arrayBuffer.byteLength; 136 | callback(); 137 | } 138 | 139 | function readUint8Array(index, length, callback, onerror) { 140 | callback(new Uint8Array(arrayBuffer.slice(index, index + length))); 141 | } 142 | 143 | that.size = 0; 144 | that.init = init; 145 | that.readUint8Array = readUint8Array; 146 | } 147 | ArrayBufferReader.prototype = new Reader(); 148 | ArrayBufferReader.prototype.constructor = ArrayBufferReader; 149 | 150 | function ArrayBufferWriter() { 151 | var array, that = this; 152 | 153 | function init(callback, onerror) { 154 | array = new Uint8Array(); 155 | callback(); 156 | } 157 | 158 | function writeUint8Array(arr, callback, onerror) { 159 | var tmpArray = new Uint8Array(array.length + arr.length); 160 | tmpArray.set(array); 161 | tmpArray.set(arr, array.length); 162 | array = tmpArray; 163 | callback(); 164 | } 165 | 166 | function getData(callback) { 167 | callback(array.buffer); 168 | } 169 | 170 | that.init = init; 171 | that.writeUint8Array = writeUint8Array; 172 | that.getData = getData; 173 | } 174 | ArrayBufferWriter.prototype = new Writer(); 175 | ArrayBufferWriter.prototype.constructor = ArrayBufferWriter; 176 | 177 | function FileWriter(fileEntry, contentType) { 178 | var writer, that = this; 179 | 180 | function init(callback, onerror) { 181 | fileEntry.createWriter(function(fileWriter) { 182 | writer = fileWriter; 183 | callback(); 184 | }, onerror); 185 | } 186 | 187 | function writeUint8Array(array, callback, onerror) { 188 | var blob = new Blob([ appendABViewSupported ? array : array.buffer ], { 189 | type : contentType 190 | }); 191 | writer.onwrite = function() { 192 | writer.onwrite = null; 193 | callback(); 194 | }; 195 | writer.onerror = onerror; 196 | writer.write(blob); 197 | } 198 | 199 | function getData(callback) { 200 | fileEntry.file(callback); 201 | } 202 | 203 | that.init = init; 204 | that.writeUint8Array = writeUint8Array; 205 | that.getData = getData; 206 | } 207 | FileWriter.prototype = new Writer(); 208 | FileWriter.prototype.constructor = FileWriter; 209 | 210 | zip.FileWriter = FileWriter; 211 | zip.HttpReader = HttpReader; 212 | zip.HttpRangeReader = HttpRangeReader; 213 | zip.ArrayBufferReader = ArrayBufferReader; 214 | zip.ArrayBufferWriter = ArrayBufferWriter; 215 | 216 | if (zip.fs) { 217 | ZipDirectoryEntry = zip.fs.ZipDirectoryEntry; 218 | ZipDirectoryEntry.prototype.addHttpContent = function(name, URL, useRangeHeader) { 219 | function addChild(parent, name, params, directory) { 220 | if (parent.directory) 221 | return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new zip.fs.ZipFileEntry(parent.fs, name, params, parent); 222 | else 223 | throw "Parent entry is not a directory."; 224 | } 225 | 226 | return addChild(this, name, { 227 | data : URL, 228 | Reader : useRangeHeader ? HttpRangeReader : HttpReader 229 | }); 230 | }; 231 | ZipDirectoryEntry.prototype.importHttpContent = function(URL, useRangeHeader, onend, onerror) { 232 | this.importZip(useRangeHeader ? new HttpRangeReader(URL) : new HttpReader(URL), onend, onerror); 233 | }; 234 | zip.fs.FS.prototype.importHttpContent = function(URL, useRangeHeader, onend, onerror) { 235 | this.entries = []; 236 | this.root = new ZipDirectoryEntry(this); 237 | this.root.importHttpContent(URL, useRangeHeader, onend, onerror); 238 | }; 239 | } 240 | 241 | })(); 242 | -------------------------------------------------------------------------------- /zip/zip-fs.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Gildas Lormeau. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the distribution. 13 | 14 | 3. The names of the authors may not be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, 18 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, 20 | INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 23 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | (function() { 30 | 31 | var CHUNK_SIZE = 512 * 1024; 32 | 33 | var TextWriter = zip.TextWriter, // 34 | BlobWriter = zip.BlobWriter, // 35 | Data64URIWriter = zip.Data64URIWriter, // 36 | Reader = zip.Reader, // 37 | TextReader = zip.TextReader, // 38 | BlobReader = zip.BlobReader, // 39 | Data64URIReader = zip.Data64URIReader, // 40 | createReader = zip.createReader, // 41 | createWriter = zip.createWriter; 42 | 43 | function ZipBlobReader(entry) { 44 | var that = this, blobReader; 45 | 46 | function init(callback) { 47 | this.size = entry.uncompressedSize; 48 | callback(); 49 | } 50 | 51 | function getData(callback) { 52 | if (that.data) 53 | callback(); 54 | else 55 | entry.getData(new BlobWriter(), function(data) { 56 | that.data = data; 57 | blobReader = new BlobReader(data); 58 | callback(); 59 | }, null, that.checkCrc32); 60 | } 61 | 62 | function readUint8Array(index, length, callback, onerror) { 63 | getData(function() { 64 | blobReader.readUint8Array(index, length, callback, onerror); 65 | }, onerror); 66 | } 67 | 68 | that.size = 0; 69 | that.init = init; 70 | that.readUint8Array = readUint8Array; 71 | } 72 | ZipBlobReader.prototype = new Reader(); 73 | ZipBlobReader.prototype.constructor = ZipBlobReader; 74 | ZipBlobReader.prototype.checkCrc32 = false; 75 | 76 | function getTotalSize(entry) { 77 | var size = 0; 78 | 79 | function process(entry) { 80 | size += entry.uncompressedSize || 0; 81 | entry.children.forEach(process); 82 | } 83 | 84 | process(entry); 85 | return size; 86 | } 87 | 88 | function initReaders(entry, onend, onerror) { 89 | var index = 0; 90 | 91 | function next() { 92 | index++; 93 | if (index < entry.children.length) 94 | process(entry.children[index]); 95 | else 96 | onend(); 97 | } 98 | 99 | function process(child) { 100 | if (child.directory) 101 | initReaders(child, next, onerror); 102 | else { 103 | child.reader = new child.Reader(child.data, onerror); 104 | child.reader.init(function() { 105 | child.uncompressedSize = child.reader.size; 106 | next(); 107 | }); 108 | } 109 | } 110 | 111 | if (entry.children.length) 112 | process(entry.children[index]); 113 | else 114 | onend(); 115 | } 116 | 117 | function detach(entry) { 118 | var children = entry.parent.children; 119 | children.forEach(function(child, index) { 120 | if (child.id == entry.id) 121 | children.splice(index, 1); 122 | }); 123 | } 124 | 125 | function exportZip(zipWriter, entry, onend, onprogress, totalSize) { 126 | var currentIndex = 0; 127 | 128 | function process(zipWriter, entry, onend, onprogress, totalSize) { 129 | var childIndex = 0; 130 | 131 | function exportChild() { 132 | var child = entry.children[childIndex]; 133 | if (child) 134 | zipWriter.add(child.getFullname(), child.reader, function() { 135 | currentIndex += child.uncompressedSize || 0; 136 | process(zipWriter, child, function() { 137 | childIndex++; 138 | exportChild(); 139 | }, onprogress, totalSize); 140 | }, function(index) { 141 | if (onprogress) 142 | onprogress(currentIndex + index, totalSize); 143 | }, { 144 | directory : child.directory, 145 | version : child.zipVersion 146 | }); 147 | else 148 | onend(); 149 | } 150 | 151 | exportChild(); 152 | } 153 | 154 | process(zipWriter, entry, onend, onprogress, totalSize); 155 | } 156 | 157 | function addFileEntry(zipEntry, fileEntry, onend, onerror) { 158 | function getChildren(fileEntry, callback) { 159 | if (fileEntry.isDirectory) 160 | fileEntry.createReader().readEntries(callback); 161 | if (fileEntry.isFile) 162 | callback([]); 163 | } 164 | 165 | function process(zipEntry, fileEntry, onend) { 166 | getChildren(fileEntry, function(children) { 167 | var childIndex = 0; 168 | 169 | function addChild(child) { 170 | function nextChild(childFileEntry) { 171 | process(childFileEntry, child, function() { 172 | childIndex++; 173 | processChild(); 174 | }); 175 | } 176 | 177 | if (child.isDirectory) 178 | nextChild(zipEntry.addDirectory(child.name)); 179 | if (child.isFile) 180 | child.file(function(file) { 181 | var childZipEntry = zipEntry.addBlob(child.name, file); 182 | childZipEntry.uncompressedSize = file.size; 183 | nextChild(childZipEntry); 184 | }, onerror); 185 | } 186 | 187 | function processChild() { 188 | var child = children[childIndex]; 189 | if (child) 190 | addChild(child); 191 | else 192 | onend(); 193 | } 194 | 195 | processChild(); 196 | }); 197 | } 198 | 199 | if (fileEntry.isDirectory) 200 | process(zipEntry, fileEntry, onend); 201 | else 202 | fileEntry.file(function(file) { 203 | zipEntry.addBlob(fileEntry.name, file); 204 | onend(); 205 | }, onerror); 206 | } 207 | 208 | function getFileEntry(fileEntry, entry, onend, onprogress, onerror, totalSize, checkCrc32) { 209 | var currentIndex = 0; 210 | 211 | function process(fileEntry, entry, onend, onprogress, onerror, totalSize) { 212 | var childIndex = 0; 213 | 214 | function addChild(child) { 215 | function nextChild(childFileEntry) { 216 | currentIndex += child.uncompressedSize || 0; 217 | process(childFileEntry, child, function() { 218 | childIndex++; 219 | processChild(); 220 | }, onprogress, onerror, totalSize); 221 | } 222 | 223 | if (child.directory) 224 | fileEntry.getDirectory(child.name, { 225 | create : true 226 | }, nextChild, onerror); 227 | else 228 | fileEntry.getFile(child.name, { 229 | create : true 230 | }, function(file) { 231 | child.getData(new zip.FileWriter(file, zip.getMimeType(child.name)), nextChild, function(index) { 232 | if (onprogress) 233 | onprogress(currentIndex + index, totalSize); 234 | }, checkCrc32); 235 | }, onerror); 236 | } 237 | 238 | function processChild() { 239 | var child = entry.children[childIndex]; 240 | if (child) 241 | addChild(child); 242 | else 243 | onend(); 244 | } 245 | 246 | processChild(); 247 | } 248 | 249 | if (entry.directory) 250 | process(fileEntry, entry, onend, onprogress, onerror, totalSize); 251 | else 252 | entry.getData(new zip.FileWriter(fileEntry, zip.getMimeType(entry.name)), onend, onprogress, checkCrc32); 253 | } 254 | 255 | function resetFS(fs) { 256 | fs.entries = []; 257 | fs.root = new ZipDirectoryEntry(fs); 258 | } 259 | 260 | function bufferedCopy(reader, writer, onend, onprogress, onerror) { 261 | var chunkIndex = 0; 262 | 263 | function stepCopy() { 264 | var index = chunkIndex * CHUNK_SIZE; 265 | if (onprogress) 266 | onprogress(index, reader.size); 267 | if (index < reader.size) 268 | reader.readUint8Array(index, Math.min(CHUNK_SIZE, reader.size - index), function(array) { 269 | writer.writeUint8Array(new Uint8Array(array), function() { 270 | chunkIndex++; 271 | stepCopy(); 272 | }); 273 | }, onerror); 274 | else 275 | writer.getData(onend); 276 | } 277 | 278 | stepCopy(); 279 | } 280 | 281 | function getEntryData(writer, onend, onprogress, onerror) { 282 | var that = this; 283 | if (!writer || (writer.constructor == that.Writer && that.data)) 284 | onend(that.data); 285 | else { 286 | if (!that.reader) 287 | that.reader = new that.Reader(that.data, onerror); 288 | that.reader.init(function() { 289 | writer.init(function() { 290 | bufferedCopy(that.reader, writer, onend, onprogress, onerror); 291 | }, onerror); 292 | }); 293 | } 294 | } 295 | 296 | function addChild(parent, name, params, directory) { 297 | if (parent.directory) 298 | return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new ZipFileEntry(parent.fs, name, params, parent); 299 | else 300 | throw "Parent entry is not a directory."; 301 | } 302 | 303 | function ZipEntry() { 304 | } 305 | 306 | ZipEntry.prototype = { 307 | init : function(fs, name, params, parent) { 308 | var that = this; 309 | if (fs.root && parent && parent.getChildByName(name)) 310 | throw "Entry filename already exists."; 311 | if (!params) 312 | params = {}; 313 | that.fs = fs; 314 | that.name = name; 315 | that.id = fs.entries.length; 316 | that.parent = parent; 317 | that.children = []; 318 | that.zipVersion = params.zipVersion || 0x14; 319 | that.uncompressedSize = 0; 320 | fs.entries.push(that); 321 | if (parent) 322 | that.parent.children.push(that); 323 | }, 324 | getFileEntry : function(fileEntry, onend, onprogress, onerror, checkCrc32) { 325 | var that = this; 326 | initReaders(that, function() { 327 | getFileEntry(fileEntry, that, onend, onprogress, onerror, getTotalSize(that), checkCrc32); 328 | }, onerror); 329 | }, 330 | moveTo : function(target) { 331 | var that = this; 332 | if (target.directory) { 333 | if (!target.isDescendantOf(that)) { 334 | if (that != target) { 335 | if (target.getChildByName(that.name)) 336 | throw "Entry filename already exists."; 337 | detach(that); 338 | that.parent = target; 339 | target.children.push(that); 340 | } 341 | } else 342 | throw "Entry is a ancestor of target entry."; 343 | } else 344 | throw "Target entry is not a directory."; 345 | }, 346 | getFullname : function() { 347 | var that = this, fullname = that.name, entry = that.parent; 348 | while (entry) { 349 | fullname = (entry.name ? entry.name + "/" : "") + fullname; 350 | entry = entry.parent; 351 | } 352 | return fullname; 353 | }, 354 | isDescendantOf : function(ancestor) { 355 | var entry = this.parent; 356 | while (entry && entry.id != ancestor.id) 357 | entry = entry.parent; 358 | return !!entry; 359 | } 360 | }; 361 | ZipEntry.prototype.constructor = ZipEntry; 362 | 363 | var ZipFileEntryProto; 364 | 365 | function ZipFileEntry(fs, name, params, parent) { 366 | var that = this; 367 | ZipEntry.prototype.init.call(that, fs, name, params, parent); 368 | that.Reader = params.Reader; 369 | that.Writer = params.Writer; 370 | that.data = params.data; 371 | that.getData = params.getData || getEntryData; 372 | } 373 | 374 | ZipFileEntry.prototype = ZipFileEntryProto = new ZipEntry(); 375 | ZipFileEntryProto.constructor = ZipFileEntry; 376 | ZipFileEntryProto.getText = function(onend, onprogress, checkCrc32, encoding) { 377 | this.getData(new TextWriter(encoding), onend, onprogress, checkCrc32); 378 | }; 379 | ZipFileEntryProto.getBlob = function(mimeType, onend, onprogress, checkCrc32) { 380 | this.getData(new BlobWriter(mimeType), onend, onprogress, checkCrc32); 381 | }; 382 | ZipFileEntryProto.getData64URI = function(mimeType, onend, onprogress, checkCrc32) { 383 | this.getData(new Data64URIWriter(mimeType), onend, onprogress, checkCrc32); 384 | }; 385 | 386 | var ZipDirectoryEntryProto; 387 | 388 | function ZipDirectoryEntry(fs, name, params, parent) { 389 | var that = this; 390 | ZipEntry.prototype.init.call(that, fs, name, params, parent); 391 | that.directory = true; 392 | } 393 | 394 | ZipDirectoryEntry.prototype = ZipDirectoryEntryProto = new ZipEntry(); 395 | ZipDirectoryEntryProto.constructor = ZipDirectoryEntry; 396 | ZipDirectoryEntryProto.addDirectory = function(name) { 397 | return addChild(this, name, null, true); 398 | }; 399 | ZipDirectoryEntryProto.addText = function(name, text) { 400 | return addChild(this, name, { 401 | data : text, 402 | Reader : TextReader, 403 | Writer : TextWriter 404 | }); 405 | }; 406 | ZipDirectoryEntryProto.addBlob = function(name, blob) { 407 | return addChild(this, name, { 408 | data : blob, 409 | Reader : BlobReader, 410 | Writer : BlobWriter 411 | }); 412 | }; 413 | ZipDirectoryEntryProto.addData64URI = function(name, dataURI) { 414 | return addChild(this, name, { 415 | data : dataURI, 416 | Reader : Data64URIReader, 417 | Writer : Data64URIWriter 418 | }); 419 | }; 420 | ZipDirectoryEntryProto.addFileEntry = function(fileEntry, onend, onerror) { 421 | addFileEntry(this, fileEntry, onend, onerror); 422 | }; 423 | ZipDirectoryEntryProto.addData = function(name, params) { 424 | return addChild(this, name, params); 425 | }; 426 | ZipDirectoryEntryProto.importBlob = function(blob, onend, onerror) { 427 | this.importZip(new BlobReader(blob), onend, onerror); 428 | }; 429 | ZipDirectoryEntryProto.importText = function(text, onend, onerror) { 430 | this.importZip(new TextReader(text), onend, onerror); 431 | }; 432 | ZipDirectoryEntryProto.importData64URI = function(dataURI, onend, onerror) { 433 | this.importZip(new Data64URIReader(dataURI), onend, onerror); 434 | }; 435 | ZipDirectoryEntryProto.exportBlob = function(onend, onprogress, onerror) { 436 | this.exportZip(new BlobWriter("application/zip"), onend, onprogress, onerror); 437 | }; 438 | ZipDirectoryEntryProto.exportText = function(onend, onprogress, onerror) { 439 | this.exportZip(new TextWriter(), onend, onprogress, onerror); 440 | }; 441 | ZipDirectoryEntryProto.exportFileEntry = function(fileEntry, onend, onprogress, onerror) { 442 | this.exportZip(new zip.FileWriter(fileEntry, "application/zip"), onend, onprogress, onerror); 443 | }; 444 | ZipDirectoryEntryProto.exportData64URI = function(onend, onprogress, onerror) { 445 | this.exportZip(new Data64URIWriter("application/zip"), onend, onprogress, onerror); 446 | }; 447 | ZipDirectoryEntryProto.importZip = function(reader, onend, onerror) { 448 | var that = this; 449 | createReader(reader, function(zipReader) { 450 | zipReader.getEntries(function(entries) { 451 | entries.forEach(function(entry) { 452 | var parent = that, path = entry.filename.split("/"), name = path.pop(); 453 | path.forEach(function(pathPart) { 454 | parent = parent.getChildByName(pathPart) || new ZipDirectoryEntry(that.fs, pathPart, null, parent); 455 | }); 456 | if (!entry.directory) 457 | addChild(parent, name, { 458 | data : entry, 459 | Reader : ZipBlobReader 460 | }); 461 | }); 462 | onend(); 463 | }); 464 | }, onerror); 465 | }; 466 | ZipDirectoryEntryProto.exportZip = function(writer, onend, onprogress, onerror) { 467 | var that = this; 468 | initReaders(that, function() { 469 | createWriter(writer, function(zipWriter) { 470 | exportZip(zipWriter, that, function() { 471 | zipWriter.close(onend); 472 | }, onprogress, getTotalSize(that)); 473 | }, onerror); 474 | }, onerror); 475 | }; 476 | ZipDirectoryEntryProto.getChildByName = function(name) { 477 | var childIndex, child, that = this; 478 | for (childIndex = 0; childIndex < that.children.length; childIndex++) { 479 | child = that.children[childIndex]; 480 | if (child.name == name) 481 | return child; 482 | } 483 | }; 484 | 485 | function FS() { 486 | resetFS(this); 487 | } 488 | FS.prototype = { 489 | remove : function(entry) { 490 | detach(entry); 491 | this.entries[entry.id] = null; 492 | }, 493 | find : function(fullname) { 494 | var index, path = fullname.split("/"), node = this.root; 495 | for (index = 0; node && index < path.length; index++) 496 | node = node.getChildByName(path[index]); 497 | return node; 498 | }, 499 | getById : function(id) { 500 | return this.entries[id]; 501 | }, 502 | importBlob : function(blob, onend, onerror) { 503 | resetFS(this); 504 | this.root.importBlob(blob, onend, onerror); 505 | }, 506 | importText : function(text, onend, onerror) { 507 | resetFS(this); 508 | this.root.importText(text, onend, onerror); 509 | }, 510 | importData64URI : function(dataURI, onend, onerror) { 511 | resetFS(this); 512 | this.root.importData64URI(dataURI, onend, onerror); 513 | }, 514 | exportBlob : function(onend, onprogress, onerror) { 515 | this.root.exportBlob(onend, onprogress, onerror); 516 | }, 517 | exportText : function(onend, onprogress, onerror) { 518 | this.root.exportText(onend, onprogress, onerror); 519 | }, 520 | exportFileEntry : function(fileEntry, onend, onprogress, onerror) { 521 | this.root.exportFileEntry(fileEntry, onend, onprogress, onerror); 522 | }, 523 | exportData64URI : function(onend, onprogress, onerror) { 524 | this.root.exportData64URI(onend, onprogress, onerror); 525 | } 526 | }; 527 | 528 | zip.fs = { 529 | FS : FS, 530 | ZipDirectoryEntry : ZipDirectoryEntry, 531 | ZipFileEntry : ZipFileEntry 532 | }; 533 | 534 | zip.getMimeType = function() { 535 | return "application/octet-stream"; 536 | }; 537 | 538 | })(); 539 | --------------------------------------------------------------------------------