├── Content ├── CustomPreset.css ├── Data.json ├── Fonts.css ├── Images │ ├── 128.png │ ├── 16.png │ ├── 24.png │ ├── 32.png │ ├── 60-lines.png │ ├── 64.png │ ├── Background.png │ ├── galaxy.svg │ ├── ipad.svg │ ├── iphone.svg │ ├── nexus.svg │ ├── notebook.svg │ └── notebookback.png ├── Style.css ├── font │ ├── OpenSans-Regular.woff2 │ ├── Vollkorn-Regular.ttf │ ├── Vollkorn-Regular.woff2 │ └── fontello.woff2 └── fontello.css ├── CustomPreset.html ├── README.md ├── Scripts ├── Option.js ├── OptionInfo.js ├── Popup.js ├── Resizer.js ├── Sortable.js └── background.js ├── manifest.json └── popup.html /Content/CustomPreset.css: -------------------------------------------------------------------------------- 1 | html 2 | { 3 | 4 | } 5 | body 6 | { 7 | height: 100vh; 8 | width: 100%; 9 | min-width: 900px; 10 | background: url('Images/60-lines.png'); 11 | margin: 0; 12 | display: flex; 13 | justify-content: center; 14 | align-items: center; 15 | user-select: none; 16 | } 17 | .wrapper 18 | { 19 | position: relative; 20 | background:url(Images/Background.png) no-repeat center center; 21 | background-size: contain; 22 | width: 70%; 23 | height: 549.413px; 24 | display: flex; 25 | justify-content: center; 26 | align-items: center; 27 | } 28 | 29 | .textBox { 30 | -webkit-appearance: none; 31 | box-sizing: border-box; 32 | height: 30px; 33 | width: 200px; 34 | background-color: #fff; 35 | outline: none; 36 | border: 1px solid #fff; 37 | color: #000; 38 | border-radius: 2px; 39 | font-size: 100%; 40 | transition: all 0.2s ease; 41 | padding: 0 5px; 42 | border-radius: 1px; 43 | 44 | } 45 | 46 | .textBox-error 47 | { 48 | background-color: #edd7d7; 49 | border-color:red; 50 | } 51 | table tr td 52 | { 53 | padding: 5px; 54 | } 55 | table th, 56 | table tr td:first-of-type 57 | { 58 | color:#000; 59 | font-family: 'OpenSans'; 60 | font-size: small; 61 | } 62 | table tr td 63 | { 64 | color:#000; 65 | } 66 | .sepButton-active 67 | { 68 | pointer-events: auto !important; 69 | background: rebeccapurple !important; 70 | } 71 | .sepButton { 72 | pointer-events: none; 73 | /*background: #0ab3a3;*/ 74 | background: #ccc; 75 | display: flex; 76 | justify-content: center; 77 | align-items: center; 78 | color: #fff; 79 | -webkit-box-shadow: 0 5px 5px rgba(0,0,0,0.14); 80 | box-shadow: 0 5px 5px rgba(0,0,0,0.3); 81 | font-size: small; 82 | line-height: 20px; 83 | text-align: center; 84 | vertical-align: middle; 85 | white-space: nowrap; 86 | cursor: pointer; 87 | border-radius: 0.1em; 88 | font-family: 'OpenSans'; 89 | position: relative; 90 | overflow: hidden; 91 | width: 200px; 92 | height: 30px; 93 | margin-bottom: 10px; 94 | } 95 | .sepButton:hover 96 | { 97 | opacity: 0.9; 98 | } 99 | .sepButton:active 100 | { 101 | box-shadow: 0 2px 5px rgba(0,0,0,0.3); 102 | 103 | } 104 | #display { 105 | position: absolute; 106 | left:12.43%; 107 | right: 12.4%; 108 | top:7.4%; 109 | bottom: 11.0%; 110 | } 111 | #display>div { 112 | position: absolute; 113 | pointer-events: none; 114 | background: rebeccapurple; 115 | z-index: 10; 116 | } 117 | #display table { 118 | background-size:cover; 119 | pointer-events: none; 120 | position: absolute; 121 | table-layout: fixed; 122 | border-collapse: collapse; 123 | box-sizing: border-box; 124 | z-index: 20; 125 | } 126 | #display td { 127 | text-align: center; 128 | 129 | } 130 | #display td::before{ 131 | content:"\00d7"; 132 | display: flex; 133 | justify-content: center; 134 | align-items: center; 135 | } 136 | 137 | input:read-only 138 | { 139 | background-color: #f5f5f5; 140 | border-color: #ccc; 141 | } 142 | -------------------------------------------------------------------------------- /Content/Data.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets":[{ 3 | "id": "1", 4 | "width": 100, 5 | "height": 100, 6 | "left":0, 7 | "top": 0, 8 | "sortorder":0, 9 | "isempty":false 10 | }, 11 | { 12 | "id": "2", 13 | "width": 75, 14 | "height": 100, 15 | "left": 0, 16 | "top": 0, 17 | "sortorder":1, 18 | "isempty":false 19 | }, 20 | { 21 | "id": "3", 22 | "width": 75, 23 | "height": 100, 24 | "left": 25, 25 | "top": 0, 26 | "sortorder":2, 27 | "isempty":false 28 | }, 29 | { 30 | "id": "4", 31 | "width": 50, 32 | "height": 100, 33 | "left": 0, 34 | "top": 0, 35 | "sortorder":3, 36 | "isempty":false 37 | }, 38 | { 39 | "id": "5", 40 | "width": 50, 41 | "height": 100, 42 | "left": 25, 43 | "top": 0, 44 | "sortorder":4, 45 | "isempty":false 46 | }, 47 | { 48 | "id": "6", 49 | "width": 50, 50 | "height": 100, 51 | "left": 50, 52 | "top": 0, 53 | "sortorder":5, 54 | "isempty":false 55 | }, 56 | { 57 | "id": "7", 58 | "width": 25, 59 | "height": 100, 60 | "left": 37.5, 61 | "top": 0, 62 | "sortorder":6, 63 | "isempty":false 64 | }, 65 | { 66 | "id": "8", 67 | "width": 25, 68 | "height": 100, 69 | "left": 75, 70 | "top": 0, 71 | "sortorder":7, 72 | "isempty":false 73 | }, 74 | { 75 | "id": "9", 76 | "width": 100, 77 | "height": 75, 78 | "left": 0, 79 | "top": 0, 80 | "sortorder":8, 81 | "isempty":false 82 | }, 83 | { 84 | "id": "10", 85 | "width": 100, 86 | "height": 75, 87 | "left": 0, 88 | "top": 25, 89 | "sortorder":9, 90 | "isempty":false 91 | }, 92 | { 93 | "id": "11", 94 | "width": 100, 95 | "height": 50, 96 | "left": 0, 97 | "top": 0, 98 | "sortorder":10, 99 | "isempty":false 100 | }, 101 | { 102 | "id": "12", 103 | "width": 100, 104 | "height": 50, 105 | "left": 0, 106 | "top": 25, 107 | "sortorder":11, 108 | "isempty":false 109 | }, 110 | { 111 | "id": "13", 112 | "width": 100, 113 | "height": 50, 114 | "left": 0, 115 | "top": 50, 116 | "sortorder":12, 117 | "isempty":false 118 | }, 119 | { 120 | "id": "14", 121 | "width": 100, 122 | "height": 25, 123 | "left": 0, 124 | "top": 0, 125 | "sortorder":13, 126 | "isempty":false 127 | }, 128 | { 129 | "id": "15", 130 | "width": 100, 131 | "height": 25, 132 | "left": 0, 133 | "top": 37.5, 134 | "sortorder":14, 135 | "isempty":false 136 | }, 137 | { 138 | "id": "16", 139 | "width": 100, 140 | "height": 25, 141 | "left": 0, 142 | "top": 75, 143 | "sortorder":15, 144 | "isempty":false 145 | }, 146 | { 147 | "id": "17", 148 | "width": 0, 149 | "height": 0, 150 | "left": 0, 151 | "top": 0, 152 | "sortorder":16, 153 | "isempty":true 154 | }, 155 | { 156 | "id": "18", 157 | "width": 50, 158 | "height": 50, 159 | "left": 0, 160 | "top": 50, 161 | "sortorder":17, 162 | "isempty":true 163 | }, 164 | { 165 | "id": "19", 166 | "width": 0, 167 | "height":0, 168 | "left": 0, 169 | "top": 0, 170 | "sortorder":18, 171 | "isempty":true 172 | }, 173 | { 174 | "id": "20", 175 | "width":0, 176 | "height":0, 177 | "left": 0, 178 | "top":0, 179 | "sortorder":19, 180 | "isempty":true 181 | } 182 | ] 183 | } 184 | -------------------------------------------------------------------------------- /Content/Fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'OpenSans'; 3 | src: url('font/OpenSans-Regular.woff2') format('woff2'); 4 | font-weight: normal; 5 | font-style: normal; 6 | } 7 | 8 | @font-face { 9 | font-family: 'Vollkorn'; 10 | src: url('font/Vollkorn-Regular.woff2') format('woff2'); 11 | font-weight: normal; 12 | font-style: normal; 13 | } 14 | -------------------------------------------------------------------------------- /Content/Images/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ray-lothian/Layout-Resizer/5d7626640818e44ef00ea6ef6fb261c9fab43544/Content/Images/128.png -------------------------------------------------------------------------------- /Content/Images/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ray-lothian/Layout-Resizer/5d7626640818e44ef00ea6ef6fb261c9fab43544/Content/Images/16.png -------------------------------------------------------------------------------- /Content/Images/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ray-lothian/Layout-Resizer/5d7626640818e44ef00ea6ef6fb261c9fab43544/Content/Images/24.png -------------------------------------------------------------------------------- /Content/Images/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ray-lothian/Layout-Resizer/5d7626640818e44ef00ea6ef6fb261c9fab43544/Content/Images/32.png -------------------------------------------------------------------------------- /Content/Images/60-lines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ray-lothian/Layout-Resizer/5d7626640818e44ef00ea6ef6fb261c9fab43544/Content/Images/60-lines.png -------------------------------------------------------------------------------- /Content/Images/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ray-lothian/Layout-Resizer/5d7626640818e44ef00ea6ef6fb261c9fab43544/Content/Images/64.png -------------------------------------------------------------------------------- /Content/Images/Background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ray-lothian/Layout-Resizer/5d7626640818e44ef00ea6ef6fb261c9fab43544/Content/Images/Background.png -------------------------------------------------------------------------------- /Content/Images/galaxy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 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 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Content/Images/ipad.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 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 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Content/Images/iphone.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 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 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Content/Images/nexus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 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 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Content/Images/notebook.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 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 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Content/Images/notebookback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ray-lothian/Layout-Resizer/5d7626640818e44ef00ea6ef6fb261c9fab43544/Content/Images/notebookback.png -------------------------------------------------------------------------------- /Content/Style.css: -------------------------------------------------------------------------------- 1 | /*:root{ 2 | --counter :10s; 3 | } */ 4 | 5 | ::-webkit-scrollbar { 6 | display: none; 7 | } 8 | html,body 9 | { 10 | margin: 0; 11 | padding: 0; 12 | } 13 | body 14 | { 15 | width: 550px; 16 | 17 | background: #fdfdfd; 18 | font-family: 'OpenSans'; 19 | 20 | box-sizing: border-box; 21 | color: #111; 22 | overflow-y: scroll; 23 | user-select: none; 24 | } 25 | header 26 | { 27 | display: flex; 28 | justify-content: space-between; 29 | font-weight: bold; 30 | align-items: center; 31 | font-size: small; 32 | padding: 12px 0; 33 | position: fixed; 34 | top: 0; 35 | left: 0; 36 | right: 0; 37 | background-color:rebeccapurple; 38 | z-index: 1; 39 | color:#fff; 40 | } 41 | header > span >a 42 | { 43 | text-decoration: underline; 44 | } 45 | header > i, header> div >i 46 | { 47 | font-size: x-large; 48 | cursor: pointer; 49 | 50 | } 51 | main 52 | { 53 | margin-top: 57px; 54 | display :flex; 55 | flex-flow: row wrap; 56 | border-collapse: collapse; 57 | } 58 | 59 | main > div 60 | { 61 | box-sizing:border-box; 62 | width:110px; 63 | height: 100px; 64 | border:1px solid #f5f5f5; 65 | display: flex; 66 | justify-content: center; 67 | align-items: center; 68 | position: relative; 69 | cursor: pointer; 70 | transition: all 0.2s ease; 71 | 72 | } 73 | main > div > span 74 | { 75 | position: absolute; 76 | bottom:3px; 77 | font-size: 90%; 78 | } 79 | main > div > i 80 | { 81 | position: absolute; 82 | top: 3px; 83 | font-size: large; 84 | font-style:normal; 85 | color:#333; 86 | display: none; 87 | font-weight: bold; 88 | pointer-events: auto !important; 89 | } 90 | main > div >div 91 | { 92 | width:64px; 93 | height: 64px; 94 | background:url(../Content/Images/notebookback.png) center center no-repeat; 95 | } 96 | main > div >canvas 97 | { 98 | position: absolute; 99 | } 100 | .preset > * 101 | { 102 | pointer-events: none; 103 | } 104 | .preset:hover 105 | { 106 | box-shadow: inset 0 0 0 2px #aaa; 107 | } 108 | 109 | .presetDisableHover:hover 110 | { 111 | box-shadow: none; 112 | } 113 | 114 | @keyframes blink-smooth { 115 | 50% { 116 | color: transparent; 117 | opacity:0.1; 118 | } 119 | } 120 | .icon-plus{ 121 | font-size: 140%; 122 | margin-left: 10px; 123 | } 124 | .icon-pencil 125 | { 126 | margin-right: 10px; 127 | } 128 | 129 | .dialogWrapper 130 | { 131 | background-color: rgba(255,255,255,0.7); 132 | position: fixed; 133 | top: 0; 134 | left: 0; 135 | right: 0; 136 | bottom: 0; 137 | z-index: 1000; 138 | justify-content: center; 139 | align-items: center; 140 | display: none; 141 | } 142 | .dialog 143 | { 144 | padding: 20px; 145 | width: 80%; 146 | box-shadow: 0 2px 25px #aaa; 147 | background-color: white; 148 | 149 | } 150 | .dialog >p 151 | { 152 | text-align: center; 153 | } 154 | 155 | .sepButton { 156 | /*background: #0ab3a3;*/ 157 | background: rebeccapurple; 158 | display: inline-block; 159 | padding: 0.6em; 160 | width: 100px; 161 | color: #fff; 162 | font-size: small; 163 | line-height: 20px; 164 | text-align: center; 165 | vertical-align: middle; 166 | white-space: nowrap; 167 | cursor: pointer; 168 | border-radius: 0.3em; 169 | } 170 | 171 | .sepButton-light 172 | { 173 | background:#eee; 174 | color:#000; 175 | box-shadow: 0 2px 12px #444; 176 | } 177 | .sepButton-light:hover 178 | { 179 | background-color: #f5f5f5 !important; 180 | opacity: 1 !important; 181 | } 182 | 183 | .sepButton:hover { 184 | opacity: 0.8; 185 | } 186 | 187 | .editMode i 188 | { 189 | display:inline-block; 190 | } 191 | .editMode-cancel::before 192 | { 193 | content: 'Cancel' !important; 194 | margin-right: 40px !important; 195 | font-size: small !important; 196 | font-weight: bold !important; 197 | font-family: OpenSans !important; 198 | } 199 | 200 | .hotkey { 201 | position: absolute; 202 | top: 0.5em; 203 | right: 0.5em; 204 | font-size: 0.7em; 205 | } 206 | -------------------------------------------------------------------------------- /Content/font/OpenSans-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ray-lothian/Layout-Resizer/5d7626640818e44ef00ea6ef6fb261c9fab43544/Content/font/OpenSans-Regular.woff2 -------------------------------------------------------------------------------- /Content/font/Vollkorn-Regular.ttf: -------------------------------------------------------------------------------- 1 | GDEFJ�h�GPOS�lҴ�(GSUB6*3J� OS/2�b��`cmap��9��"cvt �� �$fpgmY�7 �sgaspg 2 | �Xglyf$�@ ���head����6hhea?�T$hmtx�J+[��loca�3�*���maxp�x name�N��p1post��g>Ĥ�prepm��| @�Bt��_<� �ȪT8Ȱ�������� ��G 3 | ���������u 4 | s��������)��/P�CFA @��� 5 | ���� " �5����2�2�2�2�2�2�2�&# 6 | �(�(2(+�(�(�(�(�(V$�)S#.$@��D$9��*��@$  !#,#t$T$T$(((((((<#D+"(�$�(O$_3G#G#G#3  '>0>-�3��������>x9�#�#�9�#H9H9H9H9H99�#�9c9x9|9�5�:R�919�(�9�9�#�#�#�#�#�#�#G9^8�#�9DI�9�9�9�9�9��~vvw: 7 | ���Kh��W��$q$m$�$�$��x�|Z�<W<�<�<�<<<\<�<<�(�(�<�<�(�(,6.4�6K####6F5,`#K!�>�>m!k/lj!6<�<6<<$=�*�)R<�<Y(�KA2U-�<�#�2�7(25r(q#B.k(,$�/�-3#[6I*,+C�-�("DvXLBZ�Z�<�6�~�#�<g$�$�8q+�$�$�$�&�* 8 | m=$�<�2�(�$��"�����Չ����������������������dž�@HIKMRSTUZ[\]^`gijklmrstuw���˩x !"#$&-/01349:;�͙��������CPBQNWXYVbcaopnz{~}�<  /9~�17�����    " & 0 : D s �"'���������� 0:�17�����    & 0 9 D q �"'��������������������������=�����j���`�d�L�!ޯ�;�� 8T���z����������������������@HIKMRSTUZ[\]^`gijklmrstuw�����x !"#$&-/01349:;<?������������|������~����y����������ABCDEFGJNOPQVWXYL_abcde�fnopqvh2 10 | %'()*+�,5678=.>������������<  /9~�17�����    " & 0 : D s �"'���������� 0:�17�����    & 0 9 D q �"'��������������������������=�����j���`�d�L�!ޯ�;�� 8T���z����������������������@HIKMRSTUZ[\]^`gijklmrstuw�����x !"#$&-/01349:;<?������������|������~����y����������ABCDEFGJNOPQVWXYL_abcde�fnopqvh2 11 | %'()*+�,5678=.>������������,K� PX��Y����D� _^-�, EiD�`-�,�*!-�, F�%FRX#Y � �Id� F had�%F hadRX#e�Y/ �SXi �TX!�@Yi �TX!�@eYY:-�, F�%FRX#�Y F jad�%F jadRX#�Y/�-�,K �&PXQX��D�@DY!! E��PX��D!YY-�, EiD�` E}iD�`-�,�*-�,K �&SX�@�Y�� �&SX#!�����#Y �&SX#!�����#Y �&SX#!����#Y �&SX#!�@���#Y �&SX�%E��PX#!��#!�%E#!#!Y!YD-� ,KSXED!!Y-�+�+�+�>2'+��qX6"+�{dN6"+�q\H6"+�aO>,+�+� E}iDK�`RX��Y��(-19Z ��� � � 5�� +5=EQ]kw����������������!!35#32+732+'32#'#732#'#7353#'#'##73#7##73#'##53353#'3#5##53373#"=3325'3#3#3#73#3#3#'3#3#3#'3#3##74&'554&54&?3##5#254#254##53'3#73#'254#254#3'3'3#5`��llJV<&!:TMH' J)&'-��[�               12 |  13 | 14 |    15 | 16 | 2���� H��I/�+/�иI�&и&/���+�H��:/�EX�@/�@>Y�EX�/�>Y�EX�#/�#>Y�++�#���@�2�01%32>53.5465#"&54>74.'&#""&'6&'>3228.$#Z$; 17 | 1"AA9QW (   !(X/"0  � '!%""5&(0   18 |  821=%(#(= )4$��2����&x~��2����&y���2����&z���2���s&{���2����&|���2����&}�&����HVc%3267#"&'&'#"&54>76754&#""&'6&'>32676326=32767674.#"�95 -!19!U42G  19 | 'SBC4N-)#3!  "*R3(()';)I��L(*  (�#%,4 "(&�A5#&-'*!;521?% 532!*="5A 20 | �([7�/(J= 21 | ����*>��?/�4/�?�и/�>��и>�и/�>�и/�4�&��EX�#/�#>Y�EX�/� >Y�EX�/�>Y�/��#�9�01"&'>54.#4672>767>32'32>54.#"E` 22 |  &($ $,Xc$A\�#2,!(+# ' 7;�  �� jt5\E(Q ,K<0B(.I4(����$C�+�EX� /� >Y�EX�/�>Y� ���� �01%#".54>32#.#"327�P9&K;$5M3^9 8,29$5#C,N+,;X;-VD)-8:>\V&F6 :(���<%#.52654&#.57&'.54>32#.#"327�(#/(/'-1% 23 | #%;$5M3^9 8,29$5#C,N+)0$&  9 ;X;-VD)-8:>\V&F6 :(���8Mm�+��;��EX�/�>Y�EX�/� >Y�EX�!/�!>Y�EX�1/�1>Y��@��1�J�01254.#4672>7".54767#"&54>675&'&#"32>! &($ * !!  $,Xc$A\� #2,!'+#�z  ��     24 |  jt4]E(��+� 25 | ,K<0B(.+����2E(�EX�/�>Y�9#+��A�01&'4677#"&54>32&'&'.74'&'&#"32>�2?LGq&!7A#?U2tb+BR' &) 26 |  27 | !2-"H9*%G 28 | !? 3�UIhCsj>U5  29 | 0&!  ��1) '>-[X0P(����%/��0/�)/�0�и/�(��и/�(�и/�)� ��и/�EX�/�>Y�EX�/�>Y�(+�����,�0173267#".54>32#"'34&#"�!!8,!@#X75P55M01D, 3"Ug�0,$�$:$-&&@W10VB&!8K+k$BR'��(����&xm��(����&y��(����&z��(����&|�$����7K�/�"/�EX�(/�( >Y�EX�/�>Y����"���(�4�013".+"47>5.#47354>32#4&#"�f5' 30 | !D#%$ 31 | (+B$;K''' $*)"� 32 |  33 | �!( #2 (8U9 34 | :)6IC)���CVf��&R+�J.+�\?+�b+�EX�/�>Y�EX�/�>Y�EX�+/�+>Y�M��D�ATD]� ��и�W���_�0123.'##"'&'32#"&54767&'.54767'.54>"'32>54."32654.�#� !.D,$!  902E+%B[6]Q# 35 |  -C  2>!4% $A' 60!* $� !8#=. 36 |  37 |    +"G;%EB& !=("=-�34(�'?B65/##��0�P��Q/�/���Q�.и./���?и�CиC/�EX�K/�K>Y�EX�Y�EX�#/�#>Y�EX� /� >Y�K��01%3.#"4726=4.#"3.#"472654.#4672>7>7>32�8A$!"( 'CB' &($ %-4(4# %2�#/ (?.k2% %2�  �   &>.$�� � /M� +� ��� �и/�EX�,/�,>Y�EX�/�>Y� +014632#"&3.#"46726=4.#4672>7Y$!#!p :=( &($ ~""#"�2%  38 |  39 | %2�  ������ �&x��$��%�&y�������A�&z�������,�'|�h$�� �#�+�EX� /� >Y0173.#"46726=4.#4672>7� :=( &($ 2%  40 |  41 | %2�   ���*M�%+�%���%�и/�EX� /� >Y�EX�/�>Y�"(+014.#4672>7.'>54632#"&o &($ 0; &$!#!E  �l3VE3 42 | ":8=&d""#" ���/�+�EX� /� >Y�EX�/�>Y014.#4672>7.'>5o &($ 0; &E  �l3VE3 43 | ":8=&#�� �NL�+��;��A/�EX�/�>Y�EX� /� >Y�EX�5/�5>Y014.#4672>77>54#&5;27".'&'3.#"467265n &($ C" X8%W &,$;! 1; :=(?  �`>&  44 |  "O 45 | 46 | .6! BJ#i2%  47 |  48 | %2#���#"�+�/�EX� /� >Y014.#4672>73.#"467265n &($  :=(?  ��2%  49 |  50 | %2$��Q��6��/�xиx/�g��и/�g� 51 | и 52 | /�g�и/�x�[�A�[]A�[]Ap[]�H��и/�[�<�A�<]A�<]Ap<]�)��EX�/�>Y�EX�/�>Y�EX�#/�#>Y�EX�m/�m>Y�EX�V/�V>Y�EX�7/�7>Y�EX�P/�P>Y�EX�1/�1>Y�EX�s/�s>Y�#�B��a�01>76767>326767>32.#"47>=4.#".#"47>=4.#".#"47>=4.'46- $%! 53 | $.*F%-3'8@("( @?("( (CE(� 54 |  55 |    &. 56 |    &>.�! #2�#/ (?.k! #2�#/ (?.p2# #2�  $��1�O��P/�/���P�.и./���?и�BиB/�EX�Y�EX�J/�J>Y�EX�#/�#>Y�EX� /� >Y�J���4и4/01%3.#"4726=4.#"3.#"4726=4.'467>7>7>32�8A$!"( 'CB'%%! %-4(4# %2�#/ (?.k2% %2�      &>.��$��1s&{ $(���� !Y�"/�/�"�и/������EX�/�>Y�EX�/�>Y���� �01732654.#"4>32#".�H=<:%1:9e!X��(����&&x���(����&&y��(����&&z��(���s&&{��(����&&|�(����#-75�EX�/�>Y�EX�/�>Y�$���5�0174>327#"'&'"&'7&'&2654'&''7&'&#",!�<: �#K�:9�3W@$/ 58 | 7X53X?$ C L*,�cO.%�0�E/� ^#� �=P��Q/�J/�Q�и/���*и�,и,/��/и//�J�9���@��EX�'/�'>Y�EX�6/�6>Y�EX�/�>Y�EX� /� >Y��E��6�M�01"'&'.+"47>54.'467>7767>3232>54&#"  D#%$ 59 | (%%!  60 | 61 | $,Xc$A\� #2,@0+# o# #2�     hm8`G(6*� ,KY�EX�/�>Y�EX� /� >Y�EX�%/�% >Y��=��1�G�01"/3.#"472654.#4672>767>32'32>54.#" GD( &($  $,Xc$A\w#2,!(+ 62 |  r" %2�  �  jt5\E(A,K<0B((� �3E��F/�/�и/�� и /�F�и/��$���6и�=��EX�/�>Y�EX�/�>Y�EX�2/�2>Y��:���B�01>=4767#".54>32.+"4675.#"32>% 63 | #'$C3#@Z7Ea 64 | 65 | ( "" BI  0BS#,'!� !� 66 | 67 |   68 | 6P63\E)$1-�j2# o)� d^/@')$����AI�+��(��EX�2/�2>Y�EX� 69 | /� 70 | >Y�2�%и2�>�01.+"47>=4.'467>76767>32#.#"� 71 | !D#%$ 72 | (%%!  <'!  *j!( #2�   #)  #. C0'(����@��A/�//�и/�A�9и9/� ��/���9�!и!/�9�&и&/�&/�/�EX�>/�>>Y�EX�/�>Y�>� 73 | ���,��>,9�4 74 | 901#.#"#".'>4&'>332654.'.54>32c(%/((7!1C'.'!>4)- *!)8#!2:-D�6 ' "( 4%  #! ?>$ "+ /$��.�Z.#467354>32#".'>'>332654.54>54.#".#"47>5t 2B(?L#$7%,2,)6# $,'-3-" ," %.(�  75 | (:V8&0+!"&6)2'  76 | :A8/&%!.#'!( 7)��#2��Al%R� 77 | +� 78 | �и���EX�/�>Y�+�� 79 | и�и��015>733267#"&5.'467\(� I/ @ <8 ��  x 80 | �3- Y�EX� /� >Y�EX�/�>Y�EX�&/�&>Y�@�014.'467>7".5475#".=4.'467>732>5s'J  "#  81 | 3F#7&#" (2(J    ��     3)D3�    �L?*A,��#��$�'x�4��#��$�&y4��#��$�&z$4�����&|�4�� �;6�EX�%/�%>Y�EX�/�>Y�EX�/�>Y013267"&'.'.'.5326767676&'&O24  �   $  82 |   83 | *? C 84 |  ! & � '��:HNE5     >L( 9.4-A3����D��EX�/�>Y�EX�/�>Y�EX�/�>Y�EX�1/�1>Y�EX�7/�7>Y�EX�B/�B>Y�EX�/�>Y�EX�%/�%>Y017>.'&5327"&'.'&'"&'.'.'.532672�%'6   05#  e &( � D& -!!3* � 85 | �$V]0'&�$0 .%��*[\-��[�[ 86 |   87 | ;E:4W����_G�EX�*/�*>Y�EX�:/�:>Y�EX� /� >Y�EX�Z/�Z>Y01%&'&'3&+"467>?&'&'.'&5;2776&'.532673&+"467>. ) N E 6;#  (!(& J 88 | j#f=.(  "a# 89 | +>(    i% 90 |    ��M@�EX�>/�>>Y�EX�/�>Y�EX�/�>Y� ��"�01>.'&5;27#"&'&673267>767&'.'.'&5;76367�  h �,''# 91 | "4 &#  :@$ 92 | 93 |  94 |  * * 95 |   &��DT--  96 | +!$,TL%. &9= ��0�/�&<yU��-�,�&<| 3����C_�EX�/�>Y�EX� /� >Y�EX�%/�%>Y�EX�-/�->Y���и �8��9�01;2>732>72#".+".5>767#""&'>C,2`0*.262#   $*9BU 0571 \$  � @FJE,$ #%$   CJNF)!!J����6CX�EX�/�>Y�EX�./�.>Y�EX�/�>Y�7"+�"�и/�"� и /0163"&/#"#467>&/".#"467>?3'.'&'?�  ! !  97 | ,AHE;)5,  ]�L  98 | ���$     fE;- 99 |   'v� !������&@x��%�EX�/�>Y�EX�./�.>Y01������&@yJ�������&@z_������J&@{W������W&@|,�������&@}�>����v�!#467>=".#"467>76&'.52;67#.+3265>3"&'.+32>7"&47673��91) ( 95 �0-,�N.%>0H3<)  *$+ 100 |   &/:%  J�� !�  $�".!+  101 |   102 | +#�'#  )*).$��*&; !� % / 103 | #O#<  09319��9�*9Iy�,!+�C+�4+�,�<��EX�(/�(>Y�EX�/�>Y�=++����(�%���1и%�H�012632+"47>54&'.532654.#32>54.#"�$H#+M;"NC'G6 :[@C'NE(9[$JE'>K%0>$ ,4� !8,AZ 104 | '@.)H5 %�2# ���%JB.:! /�$-'4 #��[�,C�(+�EX�/�>Y�EX�#/�#>Y����#��012#.#"3267#".54>q?g8 '6!?Z9#A_<0d* 9q?g8 '6!?Z9#A_<0d* 9Y�EX�/�>Y����$���,и$�6�01;2632+"47>54&'.32>54.#": 106 | ""!B B�mE)ASTOA%IA(�#=#"467354&'.32>54.#"3"&+6 107 | ""!B B�mE)ASTOA%IA$#R(�#Y�EX�Y�&+�S� ��<�,��CиC/� �L�01#.+32>5>3"&'.+;2>7".+"47>54&'.5;26�%>0H**   )*#.:%  +4y%IA(.1$g��)+).$�� p "�$ / 108 | #O# %�2# ��9���'x��M��9���'y3�M��9���'z1�M��9��W'|���M9����HO�<+��&��EX�E/�E>Y�EX�6/�6>Y�&+�E� ��?�01#.+32>5>3"&'.+.+"47>54&'&5;26�%>0E1*   )1 109 | !D#&& 110 | ((,-)f��)+).$�� p "�!( #2�2##����Dm�E/�/���E�"и"/��-и-/�"�9��/�EX�'/�'>Y�EX�/�>Y�'�4���>�01%4.'.53267#".54>32#.#"3267>5"HF +�UJyW/;b|BH{--<"@^==[=/�"'   111 | '"-" +3]�QTT+#K- 4C%.Lc6DxY4 112 | &9����H��I/�H/�I�и/���&иH�(иH�9��EX�./�.>Y�EX�!/�!>Y�EX� /� >Y�EX�C/�C>Y�'+��и/��и/01#"&#"47>54&'&53267!54&'&53267&#"47>5;-_-#(<=B((7B ;(1(7B ;((<=B(E�2##2�2##2��2##2�Z2##29��+�/�+�EX� 113 | /� 114 | >Y�EX�/�>Y014&'&53267&#"47>5�(7B ;((<=B(%2##2�Z2##2��9��@�&UxD���9��E�&Uy�����5����&U%z�����:��mW&U#|����/�/� +�EX�/�>Y�EX�/�>Y017&'>54&'&53267� (M@,(B!!F&}FlXI#2=J02##29����LY�+��<��EX�/�>Y�EX� 115 | /� 116 | >Y�EX�B/�B>Y�EX�6/�6>Y014&'&532677>.'.5327".'&'&#"47>5�(7B ;(�8>)!&�"&(444&T%AO+!(<=B(%2##2¼#  117 |   118 |  !�*14 ;- 119 | \d.%�2##29���6=�1+�EX�)/�)>Y�EX�/�>Y���и/01%2>7".+"47>54&'.532673B*7'  +4y%IA(!9 ;#- 0# 120 | #O# %�2#  "�h$(����PG�EX�/�>Y�EX�/�>Y�EX�9/�9>Y�EX�#/�#>Y01273267".+"467>4' # .#"467>76&#.5�%'��)$$ 121 |   E $�� =:  **���)  '��%0   122 |   123 |  +!W� ���(3    8-d6) 124 |  9����@��A/�8/���A�*и*/���*�,и,/�*�5��EX�7/�7>Y�EX�/�>Y�EX�/�>Y�EX�/�>Y�EX�/�>Y�EX�"/�">Y013267"#3.#"4672>5'.'.53274.#.36 �a6;((�� 125 |  !6)���*9"   "9*�  ��K)6!��9���J&^{z�#����']�(/�/�(�и/�� 126 | �����EX�/�>Y�EX�/�>Y����#�014>32#".732>54.#"#3YyEHyX21XyIJzW/g ?\<1M6&B[6,L7TL\22[MJ^65^f?v[7+Jd9CvX2'Gc��#����&`x����#����&`yt���#����&`z}���#���J&`{k���#���W&`|C�#����#1?4>3272#"'&'"&'7'.32>54'&'&'&#"#3YyEH<4 127 | @ ,21XyIJ=$BK+/�.<1M6��j 8 -6,L7TL\2 F 128 | U -MJ^6T ^/�+Jd9C;2'�f?;/'�'Gc9��#�@a�A/�:/�A�и/���:�(��EX�/�>Y�EX� 129 | /� 130 | >Y�5-+����?�01.+"47>54&'&532632#"&'&6732>54.#"� 131 |  132 | !D#&& 133 | (('II+7P49U9#4)*@-~�!( #2�2# 7J*&O@)$>0*E28��'�F4&'&53267632632#"&'&6732>54.#"&#"47>5�(7B ;( 07P49U9# 4)*@- (<=B(%2##2 3D&$H:% !7,%>-��2##2#�H��(<a�=/�3/�=�и/�3� 134 | ���)��/�EX�/�>Y�EX�#/�#>Y�.���8�014>327.'#".732>54.#"#3YyEHyX21X="$@H39&!,# &4#JzW/g ?\<1M6&B[6,L7TL\22[MJ^ 135 | )  136 | %&"5^f?v[7+Jd9CvX2'Gc9����BS��T/�O/���T�9и9/�%��E��EX�@/�@>Y�EX�/�>Y�EX�/�>Y�EX�+/�+>Y�EX�3/�3>Y�"J+�@�=��CиC/�R�012632".'&'&''.+"467>54&#.5332>54&#"�*S*9R50,K #D2&R%.! ) & D! ((Ft 137 | )G5KZ�-=$F0, %0#?@  R0.,$!�2#    138 | #2�2% 139 |  $��%8'?OD����=}�>/�2/�>�9и9/���2���9�%и%/�EX�/�>Y�EX�/�>Y�����-��-9�59012#.#"#".'>5>332>54.54>8P !-4.EPE.6J,#5--  !7**.EQE.0C�L+7 40,8,'3H7&E4&L&<+%-8)%3L='A/��/�2c�+�EX� /� >Y�EX�/�>Y�EX�/�>Y�EX�%/�%>Y����и�01#""&'>5;2>7#.+.#"47>5�3'-   *�LK%C9  7?0 C G} *#P#DR6?�!  !9����IP�% +�2+�EX�/�>Y�EX�;/�;>Y�EX�/�>Y�*�01#".54.'.532673267>=4.'.53267I R3F^9 A>'A2<  140 | 64 +C5)=Z:>   141 |  142 |  !��*J6 *9(�$/   0$��9����&mx����9����&my����9����&mz����9���W&m|P�����7G�EX�1/�1>Y�EX�/�>Y�EX�/�>Y�EX�/�>Y0167676&'.53267#.'.'.5327�+)&'# $"/(9#/_3;95E @9 143 | bc[bYV`f7>   <2����I��{4%,  )����M��EX�/�>Y�EX�/�>Y�EX�/�>Y�EX�/�>Y�EX�)/�)>Y�EX�./�.>Y�EX�7/�7>Y�EX�9/�9>Y�EX�@/�@>Y�EX�C/�C>Y01;2>7>3>.'.53267#.'&'#&'.'.B!   $$ 144 | 145 | �76a  *74  �45� +Y. � (!.hk5 A��G41L&3! 146 |  147 |   5*�@��E<9����(- 148 | ��g�aG�EX�Z/�Z>Y�EX� /� >Y�EX�Y�EX�+/�+>Y017>.'.53267.#"467>&'&'.#"467>?'&'.'.53267 *'J69 !k:8 EC*+W&288:%�:> CF@>s +   149 |   *"�\^#,    ' FF�82  150 |  -3�\^(.     &��]�J@�+�EX�)/�)>Y�EX�=/�=>Y�EX�/�>Y01'&+"#467>=.'.5;26767676&'.5;267nB!$&! 151 | � 152 | 6E" ' "(4.'�(. 153 |    *#�     '4=42//8-1&   &����]�&uy_�:��8�4_�EX�/�>Y�EX�/�>Y�EX�/�>Y�EX�"/�">Y���и�)��*�012;2732>7.+".56767#""&'>f>G#�,6]]W[�.='! %A> �!;0`]ZX�!/! " 154 | 155 | � 156 | ���� 2)!R( 157 | ���� 2) W���� �/�/�EX� /� >Y01&'.'>�  158 | #< 3 "6Q" 159 | +W����/� /�/� /01>7>&� 160 | % !F 2T&&c.K��-� /�/�EX�/� >Y�EX�/� >Y01>7>3&/.'.K&U"J- 161 | $$ ).+ +P)%V-     h�s� 162 | +�+01&5>3232672#".#"r 163 | 6!!  0!"#& 5&  8(  ��� !� +��и/� ��01"&5463272#"&546� � # l#���� +�+014632#".732654&#"�<,$<-#7f(6 164 | !)6 ! *WI�w 165 | � 166 | +��и/01#"467� -!_v@w ��k�EX� /� >Y01%#.52654&#.57D0(/'-1% 167 | 2B0$&  O$��O�Vk�EX�@/�@>Y�EX�/�>Y�EX�J/�J>Y�EX�,/�, >Y�=+�=�<и&и%и,�8�014.'".+"47>5.#467354>32'4&#"3>7.#"467>5�)#&$&@!" 168 | ( 2B"?Z8/H 1+-E:� H 169 |  =!!=(A ��0% #2   170 | (0S=# ( 171 | 172 | )-GIG 173 | ��2#    174 | #2$��L�Jb� /�EX�/�>Y�EX�D/�D>Y�EX�-/�- >Y��� �и � ��ܸ�'и&�01&'&#"3"&#"47>5.#47354>327673.#"467265�599f5'/E#C(+B*CT*"   :=(<+AMG 175 |  176 | � ) 177 | #2 (;V7 ��2%  178 |  179 | %2$��Qk�EX�@/�@>Y�EX�,/�, >Y�EX�I/�I>Y�EX�/�>Y�=+��и=�&и,�8�014.'".+"47>5.#467354>32'4&#"3>7.'>5�)#&$&@!" 180 | ( 2B"?Z8/H 1+-E:� H 181 | 0; &A ��0% #2   182 | (0S=# ( 183 | 184 | )-GIG 185 | �o3VE3 186 | ":8=&$����Vo�1/�EX�/�>Y�EX�L/�L>Y�>;+�  187 | +�(*+�1���;�Vи и;�<иL�D�015&'&#"3".+"47>5.#47354>326733267#"&5.'467�598f5' 188 | !D#%$ 189 | (+B)CT*" � I/ @ <8 �h+AM3 190 |  191 | �!( #2 ;V7  � 192 | �3- Y�EX�/�>Y�EX�p/�p>Y�wz+�b`+��L+�  +�CE+�'{+�U���p�h�0154&#"3".+"47>5.#".+"47>5.#47354>3267>326733267#"&5.'467#547&'&#"�;598f5' 193 | !D#%$ 194 | (1#38 195 | !D#%$ 196 | (+B%@V2+(&"T*" � I/ @ <8 �*9K�a00AM3 197 |  198 | �!( #2 �!( #2  2T<"   � 199 | �3- Y�EX�/�>Y��01"&'.'>2#"&546� 200 |     201 | $"�/pxz9Fxle3 ��#"x����*6T� 202 | +�+��.���4и4/�/�EX�1/�1>Y�+�1�+�012#.54>54&#""&'>4&'>2#"&546#;+-7-  203 | !1 &*! 204 | H;&#� 01HDL4 * D+!3*$$'+572"&54632� 205 |     206 | $"�.nuw8Evjb2 207 | S#"Z���&2%�EX�-/�->Y�EX�/�>Y01"&54>54&'>332672"&54632�GZ-7-  208 | (/( &*! 209 | H9&#�@>0FCJ3 ) C*1A55$#;D#0 R$ #<���"� +�/�EX�/� >Y01"&'.'>u  210 |  � ,^B5g2 <��Y� /�/� �и/���и/����/�/�EX�/� >Y�EX�/� >Y01"&'.'>7"&'.'>t 211 |   �  �([94h1 +`@4i1 <�D��/�/�����012#"&54>"32654&�AE#2>D#/-&�E4."F6,!&'/8$&,2<^��,�/�EX�*/�*>Y01>7.'.'.'>7.'>7>76  $B& L%#  + ? >$<'�G# &!9! H#2*" 212 | .$B'<���f $� +�EX�/�>Y��0172#"&546y$"f#"<�G�a�+�/�/017"'>54'467>�"' !/(a ;960#B, 213 | % ��<����n��<�� f&�'�@�pP�EX�/�>Y�EX�/�>Y�EX�/�>Y���� ����01<�� 9� +��и/� �и/�+� +0172#"&5462#"&546}$"$"�#"*#"<�G�� 7� +��и/� �и/�/� /�+012#"&546"'>54'467>�$"1"' !/(�#"�� ;960#B, 214 | % ��(�h�b��5���(�j3c�o6�<���/�+�EX�/�>Y�EX�/� >Y01&54672^"&$  /(� ;7Q* , 215 | % <�G�(.54676.54676^(!*s( (� 216 | $,Z&8%  217 | $,U&6" ��(���������(�3��o��6S�� �/�/01.'47>�   218 | -V%)J� %'$ '(' -S"J4W�� � /�/017&'>7'.'63Y.  $J()MW 219 |  A$"*)#A! )S6S��'� /�/�/�/01.'47>7.'467>�  1-N(*G� 0&+" #:� %%" 'J" -K%%D" D?&N#'$" &BKW��)%&'>7'.'63.'>7.'63 .  $J()M� & >""AW 220 |  A$"*)#A! )S&@#&()"@ (P#����+� /�/�/016'.54>� #2!3$ Xa,D�5mw�LN�{r8u��Ayy}#����+�/�/� /01&'>54.'>L0D,aX$3!2#�E}yyA��u8r{�NL�wm5F���� +�/�/�/�/01;27&+"F[(3 .d�  "�,����� +�/�/�/�/01&+"467>54.'467;27�d. 3([���"  #��$�<-�(+�� и /�(�5и5/� /�/01.54654.'467>54&54> 3# 221 | 2''1 "3?$ '% "<� A)01/( 222 | *11g/'" 223 | -6= &J#,% 224 |  225 | #($P'72*!��"�:-�&+��и/�&�0и0/�/�/01.5>54&54>7.54?>54&'400<" %' $?34$ 1''2 226 | #3�*27'P$(# 227 |  228 | %,#J& =6- 229 | E,/g11* 230 | (/10)A >�p�G�+��и/�� и /�EX�/� >Y�EX� /� >Y012"&'>  �_5yB��B{6c>�p�2"&'2"&'>    � `3760�067498!��N�%�EX�/�>Y�EX�/� >Y01.'L  �/��C��/�EX�/� 231 | >Y01.'[ �"��U� X�EX�/� >Y�EX�/� >Y�EX�/� >Y�EX�/�>Y�EX� /� >Y01>32' %��;!��I�%�EX�/�>Y�EX�/� >Y01.'I �<�q��� %�+��и/�� и /01"&+"#47�&9�18" \ !<�g+ �+��и/01"467gMPK +#' <��# #"467�d.bsL#  232 | <��"  4>7����H�" $� �'4 �/�1�01#".54>32;27"'&'#"&'; 233 | 3P9=_C/E$' >!*'3'=)D2'D2   234 |  �� 235 | k��.=!8*%5#=���Zq%�EX�6/�6 >Y�EX�/�>Y01%#".'64'>332654.'.54>767&'.54>32#.#"'67>54.'&''=+." 236 |   "). 4+,;%  237 | )9$2?   .&3E,'l !=1 238 | / 24 9,  #C!.9 +& !.3<&6. 137*>%/ 239 | +1<( ;1 D  &%%' -&%%*���&3�$/�EX�/�>Y�EX�/�>Y�� �013.'"'"&'6'&'"4673&'>7� 240 | %'   241 | .+ �yWX. ������ff#WX)�2��WA�3/� /�EX�Y�EX�/�>Y�<�F���N�01!.76767#>76'&'676'4673&'&'>73.'"'67>7� 242 | %'.+ � � 243 | %'  .+  3,*2 *. :-/0.:#/#4)+5! . :,0.-;#<��� +�+012#".546�(83) =�%/=',9<��J � +�+012#"&546r$ J&(��1�'9�EX�/� 244 | >Y�EX�/�>Y����� 245 | �01"32>54.'2#".54>#6$4I/$4!1H1\H,*F^34`I+.K^�3C'%NA)3C%"NB,3!@^<Y�EX�/�>Y017&/#"467>=4.'&5;267�!6A& ! ?(!     #2�! $1A����Ci�/+�EX�/�>Y�EX�/�>Y�EX�$/�$>Y�EX�/� 247 | >Y����и�4�01232>72#.+"#.5>7>54.#""&'>4&'>6- *!#� 0a4).*+W)% *, 248 |  249 | %,3� 2$&',! &9  (O$*'(8I "#"  2�U��:J�!+�EX�/� 250 | >Y�+��и/��-���8и8/012676#"&'46732>54&#".5>7#""&'>5>J!V3%F7!%Ec>2J ?3=1 HI  251 | Y�EX�/�>Y�EX� /� >Y�EX� /� >Y����%и'�01!"&=#".5>7>7232'�  M~@ &,00-( W  ��� � 3=E#"E?6�_ *O��<�U�)5F�-+�EX�/� 253 | >Y�( +��и/����и/01;265>3+"#"&'4732>54.'.5�-R  -;3 254 | @iK)/HW(&= 76*+CR' �?# 255 | e&9M5:Y< 256 | *<%+@-#���~3d�4/�-/�4�и/�#��и/�-���#�!и!/�/�EX�/�>Y�2 +��(�0167>32#"&54>732>54.#"�GlH$#Ve":L+lkGm�;�).+ +2_2T? ^Y2Q: zp�\) ��=P/(10>%2�P��+3�+�/�+��и/��)и)/012>3.5467>7#""&'>53/2% &N)' 257 | #3C(� 258 |  ''� B�O/PKK*  259 |  X0PgzE&F*7���}';Jd�:+�0$+�H+�B+�EX�/�>Y� E+�*E9��5��> 590167&'&54>32#".54>&'32>54'67654&#"�5"+A*Ua$#16K,,G3%�"? $,"d4#%-,+$!&24(CB/% 260 | 6=$&=+)7#8/.$*&-!. (7�+46*+'7(�V�� 5O�6/�%/�6� и /�%���%�#и#/� �/��/�*+�4+01%67#".54>32.5>'67654.#"32u#**K7!#QXX%OuN%5 *08q 2F+6S9��BmXD0  HZmY013.#"46726=4&#&5;267"�56<�   261 |  �(fE�5@�'+�EX�/� >Y� +��и/��и/01232672#"&#"#.5>7>54&#""&'64'>�& -P  E$%> :#   262 | 8� #'4' 1 3 6%",78#�D�:276#"&'>732>54&#".'>7#""&'>53> 1'0F+-1 263 | %& ,-  *5>  �  L*"3!!:+ 264 |  )&5 265 | 5B 8.�"��+��и/�� и�и/��и� и /� /�EX�/� 266 | >Y� +��и/� �и�и/���01%6=#"#467354&5>33"&+#46 CB� �':W! �#" !T;'� �D�� %�  267 | +� 268 | �и/� 269 | �и/01"&+"467�*7fBwD  !(��A�"&'7&'>37#&'t �qt �� 270 | (o<�%kl+*;  �jm �� )t@�gf--?=�� %"&+"46?2#"&546"&54632�*7fBwD�  !� �k,��iG�+�+��и/�� и /��и/��и/01%"&+"#467%"&+"#467�0�69"�/�68"�  �  $Q� 271 | /�$/� /�/���$�!�013"&"##4>=#"467354&5>3"&+"#467+�&&# 5/C� �*4�9<"j �-' -2#�x  /���4 � /�/01%.'&67�3ZX\6 Y 272 | ��! 'B?A$   ��-���4 �/� /01 >7.7��� 273 | Y 6\XZ3 ��  $A?B' !#�$�SM�EX�*/�*>Y�EX�B/�B>Y�EX�/�>Y�EX� 274 | /� 275 | >Y�1�01.5475#"/.'>54.'467>732>=4.'467>7"�  276 | 3F#  277 |  278 | #" (2('J  "#  3 3-;   98�    �L?*A,f    ��     6��J�.2��EX�!/�! >Y�EX�'/�' >Y�EX�/�>Y�EX�/�>Y�+�*+�� и� и /��и/��и/��и�и/��и/�*�и*�%и�/и�0�013#.'7"#&'7"#4737#"46737373!37�&mk/*6*@. )+, q&*'l0+�/ +g��&�&��� ����  � ��� ��*�O� 279 | +� 280 | �й�017&'>323267#".#"?)J#6563 *H 334=�7)6(+�� �/� 281 | /01.'7>'8l+ �  467 !�B�< 282 | �KNKC9��3C�/�/��4���<�01%"'&'.'7&'&54767'>7676327'"32654.)"1 :  6-!$$ - 5  283 | B9%5A$15@#1K 284 | 2 285 | =!$' 7 - 286 | 287 | . 5 &/"@ 7 Y�EX�#/�#>Y�� 288 | ��ܸ#����P��Jܹ<�01#""!#""3267#".'&'#4673&=#467367>32#.#"�d.1#'d.1!_<0d* 9Y�EX�/�>Y��*���+��8�01%"&'5&'.54>76752#&'&'27�(' %;$5&& K0 C,�$)N+/).z ;X;-VD�P&8:��:.V&F6jD����FR\��W5+�;N+�[+�W�и� и /�W�иW�и5�#и#/�5�%и%/�5�AиA/�5�CиC/�5�G�� /�C/�EX�/�>Y�EX�%/�%>Y�EX�/�>Y�EX�/�>Y�EX�A/�A>Y����Hи�W�01&'.'>5>3&'.54>76752#.'&'"&'67>54&'&'5�--  !(E.0!  &( (E.6%! ,.# p""&L&<+ 3L='A/ 291 | < 292 | L+7�3H7&E4 /$b� %-8��0,��]�`�� #+� �и#�)��EX�S/�S>Y�EX�?/�?>Y�EX�/�>Y� +�+� �$и�(и�+и�.�013#3#'&+"#467>=#46?5'#473'.'.5;26767676&'.5;267�z�� �B!$&! 293 | ��� 294 | cv 295 | 6E" ' "(4.z $*+(. 296 |    *#8  297 | (%�     '4=42//8-1&   &L���TQ�D/�EX�(/�(>Y�EX�/�>Y�D�иD�>��и(�4��D�A�01%"'.#"&'>54'#"4673'.54>32'.#"3&+67>32326�4 !&'C" -%'N 298 | /F-6C! 66&4 299 | v!,() ,%d3  "138! @,$E6 ?&E<<0$40 2[4 Z���+?M��!+� )+�1K+�C;+�EX�/�>Y�EX�,/�,>Y�EX�/�>Y�EX�/�>Y�+�F6+��$��,�@�01.'2#".54>"32>54&2#".54>"32>54&�) k%7%);&';'*? ,(  -�x$7%(:&';'*> ,.) / 300 | � ��+7"=.,7!<.*(6G*6F�+6"<.,6 <.*>06F)6EZ����#+?Ocq6�EX�P/�P>Y�EX�6/�6>Y�EX� 301 | /� 302 | >Y012#".54>"32>54&.'2#".54>"32>54&2#".54>"32>54&�%7%);&';&)> .(  /��) k%7%);&';'*? ,(  -�x$7%(:&';'*> ,.) /7+7"=.,7!<.*(6G*6F�� 303 | � ��+7"=.,7!<.*(6G*6F�+6"<.,6 <.*>06F)6E<kW�".'&5467#"'>7"467�  304 |  595@Y) 305 | ! %bf_"'%  +' 306 |  A& 307 | >)6����^sz�t/�$/�t�и/�o��и/�$�8��/�EX�S/�S>Y�EX� /� >Y�EX�/�>Y�)5+��_�01%"&'&'#".54>767'.54>32#.#"67676&'.532672767&'.'&/<  (*& !"(*/;Y�EX�/�>Y�EX�/�>Y�EX�/�>Y�EX�E/�E>Y�EX�N/�N>Y�'1+�;+�E����\���b�012276732>54.#"3267#".54>32#"&=#"&54>65&'&#"32>7676� 314 |  *&%KoJUU*+X�ZS�5EUb4f�c17i�bT~T**AP%' =%8D2D|0+$ $#� 315 | #�%,$HiE6aJ+:f�RN�m@6< 2"@s�]Z�uD0Rm>Q�a74.J!3=^q;cG(c  [gWD!C2/>#���;'Q+�#+�@H+�(6+�+01732>54.#"4>32#".2#.#"3267#".54>N.Pm??mP..Pm??lQ.+5\|HG}\55\}GH}\4^.?# 316 |  ) '  1#? O:$G7"9N�?mP-.Pl??mP..Pm?H|\55\|HG}\55[}'5( .>"#A3 317 | &)8S83S; <6��'\f�V/014>32#".732>54.#"3".'&#&+"547>=4&#&=32'">54&#<3D'(E22E('D3!)8!"9))9"!8)� 318 |    319 |   &  ]'"9�'E33E'(D22D(!8))8!!9))9$   320 | *$ d  WQ$��v�9K�/�9/� /�EX�&/�&>Y�EX�/� >Y������9�7�0154>32#4&#"3".+"47>5.#47s-: 7 % g6' 321 | !D#%$ 322 | (*�$Y�EX�J/�J>Y�EX�6/�6>Y�e+����!�#��^�?���[�0154>327>32#4&#"3".+"47>5.#".+"47>5.#47!547&'&#"t%@V2+(: 7 % f5' 326 | !D#%$ 327 | (1#38 328 | !D#%$ 329 | (+� *9K�2T<"  330 | 6&9,":-C 331 |  332 | �!( #2�!( #2$4'DP/8����X@�EX�/�>Y�EX�//�/>Y�EX�/�>Y�/�=�01&+"467>54>3223267#"&'>5>332>54.'.56767&#.#"�<  333 | 'G`98")&,+$'86N19O& "  & & 1L4,," 5"7&   334 | .&Kc< 335 | 2C@>4F))H5#I#7%%2!;.  Y�EX�/�>Y014.#467>7.#"467>5�,%3R% D!!I! 337 | A& 338 |  ��#+ 339 |  340 |    341 |  342 | +#$����nz��/�o/�B/�EX�5/�5>Y�EX�/�>Y�EX�h/�h>Y�EX�P/�P >Y�vH+�P���� ��o�#��B�?�014&#"3"&#"47>5.#".+"47>5.#47354>327>3267673.#"467265547&'&#"�=599f5'/E#C(1#38 343 | !D#%$ 344 | (+B%@V2+(#"T*"  :=(�� *9K500AMG 345 |  346 | � ) 347 | #2 �!( #2 2T<"   ��2%  348 |  349 | %2A(0%DP3$����y���/��/�/�EX�"/�">Y�EX�/� >Y�EX�f/�f>Y�EX�R/�R>Y�EX�2/�2>Y��+�����>����[���w�0154>327>32'4&#"3>7.#"467>=4.'".+"47>5.#".+"47>5.#47%47&'&#"3t%@V2+($ Z8/H 1+-E:� H 350 |  =!!=()#&$&@!" 351 | (1#38 352 | !D#%$ 353 | (+�*9K��2T<" # ( 354 | 355 | )-GIG 356 | ��2#    357 | #2� ��0% #2 �!( #2 (,'DP3��"� +� /�/014Ǔ>7.#"47>5f.%D  ?#&7G)  358 |  �� )  &$\�82632#"&'&6732654.#".'>7#""&'>'�0< ?#4*3H+09  /#/=    CK F�E&/ $;( 359 | 360 | *- 361 | $J%H&����036�1/�EX�/�>Y�1�и1�"��и"�'�01%32#"&/##467>=#&5>7256/  =  5 %79;9Rl� 362 |   HMO& ���*��n�4"�/�EX�/�>Y��+�01232656#"&#"#.5>?>54&#""'64'6�3'.& 4 {   8-S,&[#&#=� (*D#6$7 *^<*#1,/+ ������&�&�Z�e*�/�EX�D/�D>Y�+2+�2�M�01����@�&�&�P���/�EX�I/�I>Y�7�01��$���&�&�x��0�EX�Y/�Y>Y�HA+�+�H�c�01f�[ 363 | #&467!#��my�) !���<�g+�2g�� F:�/�#/�EX�>/�> >Y�++�#���>�0�0132>53.5467#"&54>74&'&#""&'6&'>32�(  Z3 364 |  '54 8K* 365 |   366 | H'$-   &&  367 |     +),( - &(e{� ,�/�EX�/� >Y����� �0132654&#"4>32#"&�-(#%3$##\-?$SV-?'OY*ISF9HPEI)C0cO)C0a$����[gx�/�/�\/�/�EX�P/�P>Y�EX�4/�4>Y�EX�/� >Y�c+�����"��\�=���Y�0154>327>32#4&#"3".+"47>5.#".+"47>5.#47!547&'&#"t%@V2+(!K''' $*)"f5' 368 | !D#%$ 369 | (1#38 370 | !D#%$ 371 | (+� *9K�2T<"  372 | :)6ICC 373 |  374 | �!( #2�!( #2$0&DP/((((���� �F��������H�8DP\h�  \ � 375 | : � 4 @ � � � � � � J�R�~�X�(�N����6��� $���H�2��� �.�,8DP\�>�H�lx���� 376 | � �!�"J"�#Z#�#�$$$$�%`&&�&�'*'R'z'�'�(((^(�(�)b)�*�+V,R,�-&-X-�-�.F.~.�.�/*/4/n/�/�000N0�0�0�0�0�1J1�1�1�202j2�3@3�3�3�3�4>4f4�4�4�4�5>5�6H6�7767�7�8|8�9p9�:^:�;X;�<<�<�=P=~=�=�>:>�>�>�?|@.@f@�AA�B C C�D�EDE�F6GHH�I4I�JzKKfLRMVM�M�NRN�N�N�O O8O@O�PP�P�!����� &3.Cq � 377 | �� W s "��� ��  � � 4�   7  Q \q &� &� 378 | �  8� 8� D  4M � �Copyright (c) 2010, Friedrich Althausen (http://friedrichalthausen.de). All rights reserved. 379 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 380 | This license is available with a FAQ at: http://scripts.sil.org/OFLVollkornRegularFA: Vollkorn-Regular: 2010Vollkorn RegularVersion 2.001Vollkorn-RegularVollkorn is a trademark of Friedrich AlthausenFriedrich AlthausenFriedrich AlthausenVollkorn - the free and healthy typeface for bread and butter use, designed by Friedrich Althausen. 381 | Vollkorn came into being as my first type designing attempt. I published the Regular in 2005 under a Creative-Commons-License. Until the counter finally collapsed two years later it had been downloaded thousands of times and used for web and print matters. It intends to be a quiet, modest and well working text face for bread and butter use. Unlike its examples in the book faces from the renaissance until today, it has dark and meaty serifs and a bouncing and healthy look. It might be used as body type as well as for headlines or titles. "Vollkorn" (pronounced "Follkorn") is German for "wholemeal" which refers to the old term "Brotschrift". It stood for the small fonts for every day use in hand setting times. 382 | Since 19 May 2010 Vollkorn is published under the OFL. 383 | Original Designers address: Friedrich Althausen, friedrichalthausen.de, Weimar, Germanyhttp://friedrichalthausen.dehttp://friedrichalthausen.deSIL Open Font License, Version 1.1http://scripts.sil.org/OFLVollkorn RegularCopyright (c) 2010, Friedrich Althausen (http://friedrichalthausen.de). All rights reserved. 384 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 385 | This license is available with a FAQ at: http://scripts.sil.org/OFLVollkorn RegularRegularFA: Vollkorn-Regular: 2010Vollkorn RegularVersion 2.001Vollkorn-RegularVollkorn is a trademark of Friedrich AlthausenFriedrich AlthausenFriedrich AlthausenVollkorn - the free and healthy typeface for bread and butter use, designed by Friedrich Althausen. 386 | Vollkorn came into being as my first type designing attempt. I published the Regular in 2005 under a Creative-Commons-License. Until the counter finally collapsed two years later it had been downloaded thousands of times and used for web and print matters. It intends to be a quiet, modest and well working text face for bread and butter use. Unlike its examples in the book faces from the renaissance until today, it has dark and meaty serifs and a bouncing and healthy look. It might be used as body type as well as for headlines or titles. "Vollkorn" (pronounced "Follkorn") is German for "wholemeal" which refers to the old term "Brotschrift". It stood for the small fonts for every day use in hand setting times. 387 | Since 19 May 2010 Vollkorn is published under the OFL. 388 | Original Designers address: Friedrich Althausen, friedrichalthausen.de, Weimar, Germanyhttp://friedrichalthausen.dehttp://friedrichalthausen.deSIL Open Font License, Version 1.1http://scripts.sil.org/OFLVollkornRegular��)�Djikmln�EFoG�HqprsIJKLutvw�MNOPQxRzy{}|�S�TUV�WX~��YZ[\��]$����bc�%&d'�(�e��)*+,����-./01f2����g�3�45678���h9:;<�=C��������"�� 389 | � ����������� >@^`_� ?�B������� 390 | ������ �!�aA� ���� #�� ������.nulldotlessjmacronf_jf_tf_f_t 391 | apostrophe 392 | shortslashperiodcenteredEuroarrowf.caltf_f.caltEszettone.altf_f_lf_f_ione.numr 393 | three.numr four.dnomtwo.dnomuni00ADf_funi00A0`�� "������(08@HV^l��������t{p� 394 | y�D 395 | M# 396 | 5r 397 | ,latn��kern(2T�����8Ld���H\L�:DNXblv�������������������� 398 | ",6@JXfp����������� 399 | &4>|��6t���� :@FLRX^djpv��P"4�������  400 |  . L R p z � � � � � � � 401 |  402 | d 403 | � 404 | � 405 | � l r | � � � 0 v �  $ * D V x � � � � � � �J���&,2x~��������Dl��r��l��r��l��r��l��r��l��r��l��r��l��r��l��r��l��r��;��l��r��;��l��r��l��;��l��r��l��1nx(<(���(' 406 | )+ 407 | H�KZLd]<k(ldrZsdtPw<��(�F�d�d�x�Z�d�d�d�2�d�Z�Z�(�d�(�d�d�d�d�d�F�dl��r��l��r��l��l��r��l(rr(l��r��l��l��r��'��l��r��l��r��l��r��l��r��;��l��r��l��r��l��r��l��r��l��r��l��r��;��l��r��;��l��r��l��r��;��l��r���l��r�����l��r��l����3��l��r��l��r��l��r��l��r��l��r��l��r��l��r�����l��r�����l��r��l��r�����l��r�����l��r�����l��r��3��l��r�js�����������������������������������3��l��r�js�����������������������������������3��l��r�js�����������������������������������3��l��r�js�����������������������������������3��l��r�js�����������������������������������3��l��r�js�����������������������������������3��l��r�js�����������������������������������r��r��r����'��5�����r��:��:��l��r��s��������l��r��r��r��r��r��r��r��r��r��'��:��l��r��s��������l��-�������� 408 | ������������2(���� ��-��1��3��4��5��6��;��?��G��]��j��k���������������(������������������������������������4��������������������(���� ��'��)��*��+��-��1��3��4��5��6��;��?��G�`VW2X2_�������������������������������t�������������������������������4���������'��-��.��0��1��3��4��5��K��M��N��O��P��_��f��j���������'��-��.��0��1��3��4��5��K��M��N��O��P��_��f��j����������t������l��r��l��r��������������l��r��s���(���������l��r��s���(������������l��r��s���(���������l��r��l��r��l��r��s���(���������l��r��s���(�����������������������.��;��G��l��r��s��t�������������������P��������.��;��G��l��r��s��t�������������������P��������.��;��G��l��r��s��t�������������������P�����������.��;��G��l��r��s��t�������������������P������Z(����������(��(��-��1��3��4��6��;��?��G����������������������~���������������l��r�������@l��r��s���(�����������.��;��G��l��r��s��t�������������������P��������.��;��G��l��r��s��t�������������������P��������.��;��G��l��r��s��t�������������������P��������.��;��G��l��r��s��t�������������������P��������.��;��G��l��r��s��t�������������������P������;��l��r������������� 409 | r��l��r��������������l��r��������l��r��������������������l��r�������������� 410 | l��r��������������������������������;��l��r�������(H�������H������������.��;��G��l��r��s��t�������������������P��������.��;��G��l��r��s��t�������������������P��������.��;��G��l��r��s��t�������������������P������l��r����.��;��G��l��r��s��t�������������������P���������l����.��;��G��l��r��s��t�������������������P���������lrr��l��r����d��-l��r��l��r����.��;��G��l��r��s��t�������������������P��������.��;��G��l��r��s��t�������������������P������1nx(<(���(' 411 | )+ 412 | H�KZLd]<k(ldrZsdtPw<��(�F�d�d�x�Z�d�d�d�2�d�Z�Z�(�d�(�d�d�d�d�d�F�d�(Zp��~��Pn��,J����4R�� & D � � 413 | 414 | 415 | � 416 | � 417 | �  , J � � � � 9��:��<��=��>�� ����!��"��.�� ������&��,��-��/��������������������������������������������������������������������������9��:��<��=��>�� ����&��,��-��/��������������������������������������������������������9��:��<��=��>������������������������������������������������������������ �� 418 | �� �� ������&��,��-��/��@��A��B��C��D��E��F��������������������������@��A��B��C��D��E��F��������������������������������������������������u��v����������������������������������������������� @��A��B��C��D��E��F��������������������@��A��B��C��D��E��F�� ������&��,��-��/��u��v�����������������������������������������������������@���� �� �� ����������������#��$��%��&��'��(��)��*��+��,��/��0��7��8��9��:��<��=��>��@��A��B��C��D��E��F��������������������������������������������������������������������������������H���� �� 419 | �� �� ��������������#��$��%��&��(��,��/��0��7��8��9��:��<��=��>��@��A��B��C��D��E��F��I��J��K��S��`��a��b��c��d��e��f��i��������������������������������������������������������������������������������F�������� �� 420 | �� �� ������������������#��$��%��&��'��(��)��*��+��,��-��/��0��5��6��7��8��9��:��<��=��>��@��A��B��C��D��E��F�����������������������������������������������������������������������������������������������������������������������������@��A��B��C��D��E��F��������������������������������������������������������������������������������������������������������������������������������������������������C�������� �� 421 | �� �� ����������������#��$��%��&��'��)��*��+��,��/��0��5��7��8��9��:��<��=��>��@��A��B��C��D��E��F��������������������������������������������������������������������������������@��A��B��C��D��E��F������������������������������������������������������������������������������������������������������������������@��A��B��C��D��E��F������������������������������������������������������������������������������������ @��A��B��C��D��E��F��������������������������������������������������������@��A��B��C��D��E��F�������������������������������������������������� ('((()(*(+(.(@��A��B��C��D��E��F��@��A��B��C��D��E��F��@��A��B��C��D��E��F��@��A��B��C��D��E��F������������������� 422 | $4������`d��~����������(����������*d ��������������������������������������������������0X���������^z������X��FnZ<�,N<Pd��������d����jxn���� !#FIK=RS@[]B`fEhlLrsQuvS��U��m��n��v������������������������������( !0234;RS[\ghjlrst�������������������������������9:<=>�����������9:<=>9:<=>uvuv@ABCDEFuv����������������@F &,/@ABCDEF�� &'()*+,-.��#$%'()*+0��� 423 | #$%IJ�� IJS`abcdefiKK`fiimq ���������� &&,,//@Fuv��������������������������������������9:<> &&'+,-�������������� &&,,//����uv &&,-@F�������������������� 424 |  &&,,//���������������������������� @F����������������&&,-9:<>@FIJuv����������������������������������������IJSS`fii &&,,//KK`fiimq���� !"&&'+,-..589:<>������  '+.. !"..9:<>#%00�� '+..9:<>@F�������������������������� 425 |  !"..58HHIJKKMRSSTY[\^_`fghiijj���������� 426 | #%IJ��9:<>KK`fiimquv��������������������������@Fmq 427 | $Vlatn��aaltcalt dlig&liga, $.�"Nt���  &����"��f 428 |  �"�3��3>D&2������q 429 | !"%')*+.23578>HKLMNOPQRTUVWXYZ[\]^_ghjlmnopqrstuvw������������������������������������������������ 430 | -------------------------------------------------------------------------------- /Content/font/Vollkorn-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ray-lothian/Layout-Resizer/5d7626640818e44ef00ea6ef6fb261c9fab43544/Content/font/Vollkorn-Regular.woff2 -------------------------------------------------------------------------------- /Content/font/fontello.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ray-lothian/Layout-Resizer/5d7626640818e44ef00ea6ef6fb261c9fab43544/Content/font/fontello.woff2 -------------------------------------------------------------------------------- /Content/fontello.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'fontello'; 3 | src: url('font/fontello.woff2?54338848') format('woff2'); 4 | font-weight: normal; 5 | font-style: normal; 6 | } 7 | /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ 8 | /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ 9 | /* 10 | @media screen and (-webkit-min-device-pixel-ratio:0) { 11 | @font-face { 12 | font-family: 'fontello'; 13 | src: url('../font/fontello.svg?54338848#fontello') format('svg'); 14 | } 15 | } 16 | */ 17 | 18 | [class^="icon-"]:before, [class*=" icon-"]:before { 19 | font-family: "fontello"; 20 | font-style: normal; 21 | font-weight: normal; 22 | speak: none; 23 | 24 | display: inline-block; 25 | text-decoration: inherit; 26 | width: 1em; 27 | margin-right: .2em; 28 | text-align: center; 29 | /* opacity: .8; */ 30 | 31 | /* For safety - reset parent styles, that can break glyph codes*/ 32 | font-variant: normal; 33 | text-transform: none; 34 | 35 | /* fix buttons height, for twitter bootstrap */ 36 | line-height: 1em; 37 | 38 | /* Animation center compensation - margins should be symmetric */ 39 | /* remove if not needed */ 40 | margin-left: .2em; 41 | 42 | /* you can be more comfortable with increased icons size */ 43 | /* font-size: 120%; */ 44 | 45 | /* Font smoothing. That was taken from TWBS */ 46 | -webkit-font-smoothing: antialiased; 47 | -moz-osx-font-smoothing: grayscale; 48 | 49 | /* Uncomment for 3D effect */ 50 | /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ 51 | } 52 | 53 | .icon-trash:before { content: '\e800'; } /* '' */ 54 | .icon-pencil:before { content: '\e801'; } /* '' */ 55 | .icon-plus:before { content: '\e802'; } /* '' */ 56 | .icon-arrows-ccw:before { content: '\e803'; } /* '' */ 57 | -------------------------------------------------------------------------------- /CustomPreset.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Custom Preset 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 29 | 30 | 31 | 32 | 33 | 34 | 37 | 38 | 39 | 40 | 43 | 44 | 45 | 46 | 49 | 50 | 51 | 52 | 55 | 56 | 57 | 58 | 61 | 62 | 63 |
Mode: 26 | 27 | 28 |
Top: 35 | 36 |
Left: 41 | 42 |
Width: 47 | 48 |
Height: 53 | 54 |
59 | Save Preset 60 |
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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | For usage instruction please visit: 2 | * [https://github.com/ray-lothian/Layout-Resizer](https://github.com/ray-lothian/Layout-Resizer) 3 | 4 | To install visit: 5 | * Chrome: [https://chrome.google.com/webstore/detail/window-layout-resizer/gpogedegpcfmbpfbjilofgfmjglebnhi](https://chrome.google.com/webstore/detail/window-layout-resizer/gpogedegpcfmbpfbjilofgfmjglebnhi) 6 | * Firefox: [https://addons.mozilla.org/en-US/firefox/addon/window-layout-resizer/](https://addons.mozilla.org/en-US/firefox/addon/window-layout-resizer/) 7 | -------------------------------------------------------------------------------- /Scripts/Option.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var data; 3 | var shadowData; 4 | var ui = { 5 | events: { 6 | 7 | }, 8 | on: (id, callback) => ui.events[id] = callback, 9 | emit: (id, value) => ui.events[id] && ui.events[id](value) 10 | }; 11 | 12 | { 13 | let width, height; 14 | const split = { 15 | width: width / 10, 16 | height: height / 10 17 | }; 18 | const display = document.getElementById('display'); 19 | 20 | { // position the display element inside the svg 21 | let left, top; 22 | 23 | const resize = () => { 24 | var w = document.getElementById('wrapper'); 25 | w.style.height = w.clientWidth * 0.5747 + 'px'; 26 | const rect = display.getBoundingClientRect(); 27 | const body = document.body.getBoundingClientRect(); 28 | left = rect.left; 29 | top = rect.top; 30 | width = rect.width; 31 | height = rect.height; 32 | 33 | Object.assign(display.style, { 34 | 35 | }); 36 | // 37 | split.width = width / 10; 38 | split.height = height / 10; 39 | }; 40 | resize(); 41 | window.addEventListener('resize', resize); 42 | } 43 | 44 | const box = document.getElementById('box'); 45 | const pos = { 46 | x: 0, 47 | y: 0, 48 | }; 49 | 50 | let lastCall = 0; 51 | function observe(e) { 52 | // limit the rate 53 | const now = Date.now(); 54 | if (now - lastCall < 50) { 55 | console.log('skipped'); 56 | return; 57 | } 58 | lastCall = now; 59 | 60 | // definitions 61 | const rect = { 62 | left: Math.max(0, Math.min(pos.x, e.offsetX)), 63 | top: Math.max(0, Math.min(pos.y, e.offsetY)), 64 | }; 65 | // fit to table 66 | rect.left = Math.floor(rect.left / split.width) * split.width; 67 | rect.top = Math.floor(rect.top / split.height) * split.height; 68 | 69 | rect.width = split.width * (Math.floor(Math.max(pos.x, e.offsetX) / split.width) + 1) - rect.left; 70 | rect.width = Math.min(rect.width, width - rect.left); 71 | rect.height = split.height * (Math.floor(Math.max(pos.y, e.offsetY) / split.height) + 1) - rect.top; 72 | rect.height = Math.min(rect.height, height - rect.top); 73 | 74 | Object.assign(box.style, { 75 | left: rect.left / width * 100 + '%', 76 | width: rect.width / width * 100 + '%', 77 | top: rect.top / height * 100 + '%', 78 | height: rect.height / height * 100 + '%' 79 | }); 80 | 81 | ui.emit('change', box.style); 82 | } 83 | 84 | display.addEventListener('mousedown', e => { 85 | document.getElementById('savePreset').classList.add('sepButton-active'); 86 | pos.x = e.offsetX; 87 | pos.y = e.offsetY; 88 | observe(e); 89 | display.addEventListener('mousemove', observe); 90 | }); 91 | document.addEventListener('mouseup', () => display.removeEventListener('mousemove', observe)); 92 | } 93 | 94 | 95 | document.addEventListener('DOMContentLoaded', () => { 96 | const request = new XMLHttpRequest(); 97 | request.open('GET', '../Content/Data.json'); 98 | request.onload = () => { 99 | shadowData = JSON.parse(request.responseText).presets; 100 | 101 | chrome.storage.local.get(['presets'], results => { 102 | if (results.presets !== undefined) { 103 | data = results.presets; 104 | data.sort(Compare); 105 | } else { 106 | data = shadowData; 107 | } 108 | }); 109 | }; 110 | request.send(); 111 | }); 112 | 113 | function Compare(a, b) { 114 | if (parseInt(a.sortorder) > parseInt(b.sortorder)) { 115 | return 1; 116 | } 117 | if (parseInt(a.sortorder) < parseInt(b.sortorder)) { 118 | return -1; 119 | } 120 | return 0; 121 | } 122 | -------------------------------------------------------------------------------- /Scripts/OptionInfo.js: -------------------------------------------------------------------------------- 1 | /* globals ui */ 2 | 'use strict'; 3 | 4 | { 5 | const left = document.getElementById('txtLeft'); 6 | const top = document.getElementById('txtTop'); 7 | const width = document.getElementById('txtWidth'); 8 | const height = document.getElementById('txtHeight'); 9 | 10 | const save = document.getElementById('savePreset'); 11 | 12 | const modes = document.getElementById('mode'); 13 | let mode = modes.querySelector(':checked').value; 14 | modes.addEventListener('change', ({target}) => { 15 | mode = target.value; 16 | ui.emit('change', { 17 | left: left.dataset.value, 18 | top: top.dataset.value, 19 | width: width.dataset.value, 20 | height: height.dataset.value 21 | }); 22 | }); 23 | 24 | function insert(e, value, max) { 25 | e.dataset.value = value; 26 | e.value = mode === 'percent' ? value : (parseInt(value) * max / 100).toFixed(0) + 'px'; 27 | } 28 | 29 | ui.on('change', rect => { 30 | insert(left, rect.left, screen.availWidth); 31 | insert(width, rect.width, screen.availWidth); 32 | insert(top, rect.top, screen.availHeight); 33 | insert(height, rect.height, screen.availHeight); 34 | 35 | save.disabled = rect.width === '0%' || rect.height === '0%'; 36 | 37 | }); 38 | // save 39 | save.addEventListener('click', () => { 40 | chrome.storage.local.get(['presets'], results => { 41 | if (results.presets !== undefined) { 42 | data = results.presets; 43 | data.sort(Compare); 44 | } 45 | 46 | const widthValue = width.dataset.value.replace('%',''); 47 | const heightValue = height.dataset.value.replace('%',''); 48 | const leftValue = left.dataset.value.replace('%',''); 49 | const topValue = top.dataset.value.replace('%',''); 50 | let idValue; 51 | 52 | let isAnyEmptyPreset = false; 53 | for (let i = 0; i < data.length; i++) { 54 | if (data[i].isempty === true) { 55 | idValue = data[i].id; 56 | isAnyEmptyPreset = true; 57 | break; 58 | } 59 | } 60 | if (isAnyEmptyPreset === false) { 61 | chrome.runtime.sendMessage({ 62 | method: 'notify', 63 | message: `You have reached the maximum number of allowed configurations! 64 | 65 | Delete at least one configuration and try again.` 66 | }); 67 | return; 68 | } else { 69 | data.map(preset => { 70 | if (preset.id === idValue) { 71 | preset.width = widthValue; 72 | preset.height = heightValue; 73 | preset.left = leftValue; 74 | preset.top = topValue; 75 | preset.isempty = false; 76 | } 77 | }); 78 | chrome.storage.local.set({ 79 | 'presets': data 80 | }, () => { 81 | chrome.runtime.sendMessage({ 82 | method: 'notify', 83 | message: 'The operation was successful.' 84 | }, () => location.reload()); 85 | }); 86 | } 87 | }); 88 | 89 | }); 90 | } 91 | -------------------------------------------------------------------------------- /Scripts/Popup.js: -------------------------------------------------------------------------------- 1 | /* global loadPresets, browser, Sortable, resizeWindow, comparePresets */ 2 | 3 | const main = document.getElementsByTagName('main')[0]; 4 | const resetPreset = document.getElementById('resetPreset'); 5 | 6 | let data; 7 | let shortcuts; 8 | let workArea; 9 | 10 | window.addEventListener('load', () => chrome.system.display.getInfo({}, info => { 11 | chrome.windows.getCurrent(win => { 12 | const o = info.filter(o => { 13 | return win.left >= o.workArea.left && 14 | win.top >= o.workArea.top && 15 | win.width <= o.workArea.width && 16 | win.height <= o.workArea.height; 17 | }).shift() || info[0]; 18 | workArea = o.workArea; 19 | loadPresets(initialize); 20 | }); 21 | })); 22 | 23 | function initialize(loadedData) { 24 | data = loadedData; 25 | 26 | function initWithBrowserCommands(browserCommands) { 27 | shortcuts = browserCommands.filter(cmd => cmd.name.match(/resize\d/)); 28 | 29 | for (let i = 0; i < data.length; i++) { 30 | createPreset(data[i], i); 31 | } 32 | 33 | Sortable.create(main, { 34 | animation: 250, 35 | onStart: function() { 36 | const presets = document.getElementsByClassName('preset'); 37 | for (let i = 0; i < presets.length; i++) { 38 | presets[i].classList.add('presetDisableHover'); 39 | } 40 | }, 41 | onEnd: function() { 42 | const presets = document.getElementsByClassName('preset'); 43 | for (let i = 0; i < presets.length; i++) { 44 | presets[i].classList.remove('presetDisableHover'); 45 | presets[i].setAttribute('data-sortorder', i); 46 | data.find(p => p.id === presets[i].getAttribute('data-id')).sortorder = i; 47 | } 48 | chrome.storage.local.set({ 49 | 'presets': data 50 | }, () => { 51 | 52 | }); 53 | } 54 | }); 55 | } 56 | 57 | try { 58 | browser.commands.getAll().then(initWithBrowserCommands); 59 | } 60 | catch (err) { 61 | chrome.commands.getAll((initWithBrowserCommands)); 62 | } 63 | } 64 | 65 | function createPreset(preset, index) { 66 | if (preset.isempty === false) { 67 | const shortcut = index < shortcuts.length ? shortcuts[index] : null; 68 | 69 | const presetElem = document.createElement('div'); 70 | presetElem.className = 'preset'; 71 | presetElem.setAttribute('data-sortorder', preset.sortorder); 72 | presetElem.setAttribute('data-id', preset.id); 73 | presetElem.setAttribute('data-width', preset.width); 74 | presetElem.setAttribute('data-height', preset.height); 75 | presetElem.setAttribute('data-left', preset.left); 76 | presetElem.setAttribute('data-top', preset.top); 77 | const btnRemove = document.createElement('i'); 78 | btnRemove.className = 'icon-trash'; 79 | btnRemove.setAttribute('data-removeElem', preset.id); 80 | const sizeElem = document.createElement('span'); 81 | sizeElem.textContent = 82 | Math.round(preset.width / 100 * workArea.width) + ' * ' + 83 | Math.round(preset.height / 100 * workArea.height); 84 | const img = document.createElement('div'); 85 | const canvas = document.createElement('canvas'); 86 | canvas.setAttribute('id', 'c' + preset.id); 87 | canvas.setAttribute('width', '64'); 88 | canvas.setAttribute('height', '64'); 89 | presetElem.appendChild(btnRemove); 90 | presetElem.appendChild(sizeElem); 91 | presetElem.appendChild(img); 92 | presetElem.appendChild(canvas); 93 | if (shortcut != null) { 94 | const key = shortcut.shortcut.replace('MacCtrl', 'Ctrl'); 95 | const hotkeyInfo = document.createElement('span'); 96 | hotkeyInfo.className = 'hotkey'; 97 | hotkeyInfo.textContent = key; 98 | presetElem.appendChild(hotkeyInfo); 99 | } 100 | main.appendChild(presetElem); 101 | drawRec( 102 | canvas.id, 103 | Math.round(preset.left / 100 * 45.6), Math.round(preset.top / 100 * 30), 104 | Math.round(preset.width / 100 * 45.6), Math.round(preset.height / 100 * 30) 105 | ); 106 | } 107 | else { 108 | const presetElem = document.createElement('div'); 109 | presetElem.className = 'preset'; 110 | presetElem.setAttribute('data-sortorder', preset.sortorder); 111 | presetElem.setAttribute('data-id', preset.id); 112 | main.appendChild(presetElem); 113 | } 114 | } 115 | 116 | function drawRec(canvasId, x, y, w, h) { 117 | const canvas = document.getElementById(canvasId); 118 | const ctx = canvas.getContext('2d'); 119 | ctx.fillStyle = '#663399'; 120 | ctx.rect(x + 9, y + 15, w, h); 121 | ctx.fill(); 122 | } 123 | 124 | 125 | let selectedElem; 126 | document.addEventListener('click', e => { 127 | const dialog = document.getElementsByClassName('dialogWrapper')[0]; 128 | const dialogReset = document.getElementsByClassName('dialogWrapper')[1]; 129 | 130 | if (e.target.className == 'icon-trash') { 131 | dialog.style.display = 'flex'; 132 | selectedElem = e.target.parentElement.getAttribute('data-id'); 133 | } 134 | let presets; 135 | const btnEdit = document.getElementById('btnEdit'); 136 | switch (e.target.id) { 137 | case 'btnEdit': 138 | presets = document.getElementsByClassName('preset'); 139 | if (e.target.state == undefined) { 140 | for (let i = 0; i < presets.length; i++) { 141 | presets[i].classList.add('editMode'); 142 | } 143 | e.target.classList.add('editMode-cancel'); 144 | e.target.state = 'IsInEditMode'; 145 | } 146 | else { 147 | for (let i = 0; i < presets.length; i++) { 148 | presets[i].classList.remove('editMode'); 149 | } 150 | e.target.classList.remove('editMode-cancel'); 151 | e.target.state = undefined; 152 | } 153 | break; 154 | case 'btnNewPreset': 155 | chrome.tabs.create({ 156 | 'url': '../CustomPreset.html' 157 | }); 158 | break; 159 | case 'btnCancel': 160 | dialog.style.display = 'none'; 161 | break; 162 | case 'btnResetCancel': 163 | dialogReset.style.display = 'none'; 164 | break; 165 | case 'btnOk': 166 | dialog.style.display = 'none'; 167 | emptyMain(); 168 | removePreset(selectedElem); 169 | presets = document.getElementsByClassName('preset'); 170 | for (let i = 0; i < presets.length; i++) { 171 | presets[i].classList.remove('editMode'); 172 | } 173 | if (btnEdit.state != undefined) { 174 | btnEdit.classList.remove('editMode-cancel'); 175 | btnEdit.state = undefined; 176 | } 177 | data.sort(comparePresets); 178 | for (let i = 0; i < data.length; i++) { 179 | createPreset(data[i], i); 180 | } 181 | break; 182 | case 'btnResetOk': 183 | chrome.storage.local.remove('presets', () => chrome.runtime.sendMessage({ 184 | method: 'notify', 185 | message: 'Layouts are reset to the default values' 186 | })); 187 | fetch('../Content/Data.json').then(r => r.json()).then(j => { 188 | data = j.presets; 189 | emptyMain(); 190 | initialize(); 191 | }); 192 | dialogReset.style.display = 'none'; 193 | break; 194 | default: 195 | } 196 | 197 | if (e.target.className == 'preset') { 198 | const x = parseInt(e.target.getAttribute('data-left')); 199 | const y = parseInt(e.target.getAttribute('data-top')); 200 | const w = parseInt(e.target.getAttribute('data-width')); 201 | const h = parseInt(e.target.getAttribute('data-height')); 202 | resizeWindow(x, y, w, h); 203 | } 204 | }); 205 | 206 | function emptyMain() { 207 | while (main.firstChild) { 208 | main.removeChild(main.firstChild); 209 | } 210 | } 211 | 212 | function removePreset(dataID) { 213 | data.map(obj =>{ 214 | if (obj.id === dataID) { 215 | obj.isempty = true; 216 | } 217 | }); 218 | chrome.storage.local.set({ 219 | 'presets': data 220 | }, () => { 221 | 222 | }); 223 | } 224 | resetPreset.addEventListener('click', () => { 225 | const dialogForReset = document.getElementsByClassName('dialogWrapper')[1]; 226 | dialogForReset.style.display = 'flex'; 227 | }); 228 | -------------------------------------------------------------------------------- /Scripts/Resizer.js: -------------------------------------------------------------------------------- 1 | /* global workArea, data */ 2 | 3 | 'use strict'; 4 | 5 | function loadPresets(callback) { 6 | chrome.storage.local.get(['presets'], results => { 7 | if (results.presets !== undefined) { 8 | data = results.presets; 9 | data.sort(comparePresets); 10 | callback(data); 11 | } 12 | else { 13 | const requestURL = '../Content/Data.json'; 14 | const request = new XMLHttpRequest(); 15 | request.open('GET', requestURL); 16 | request.send(); 17 | 18 | request.onload = () => { 19 | if (request.status === 200) { 20 | data = JSON.parse(request.responseText).presets; 21 | chrome.storage.local.set({ 22 | 'presets': data 23 | }, () => { 24 | callback(data); 25 | }); 26 | } 27 | }; 28 | } 29 | }); 30 | } 31 | 32 | // Firefox polyfill 33 | chrome.system = chrome.system || { 34 | display: { 35 | getInfo(flags, callback) { 36 | Promise.all([ 37 | new Promise(resolve => setTimeout(() => resolve(screen), 200)), 38 | new Promise(resolve => chrome.runtime.getBackgroundPage(bg => { 39 | resolve(bg.screen); 40 | })) 41 | ]).then(([a, b]) => { 42 | callback([a, b].map(a => { 43 | const obj = {}; 44 | Object.assign(obj, { 45 | width: a.availWidth, 46 | height: a.availHeight, 47 | top: a.availTop, 48 | left: a.availLeft 49 | }); 50 | return { 51 | bounds: obj, 52 | workArea: obj 53 | }; 54 | })); 55 | }); 56 | } 57 | } 58 | }; 59 | 60 | function resizeWindow(x, y, w, h) { 61 | chrome.windows.getCurrent(wind => { 62 | if (w && h) { 63 | const updateInfo = { 64 | left: workArea.left + Math.round(x / 100 * workArea.width), 65 | top: workArea.top + Math.round(y / 100 * workArea.height), 66 | width: Math.round(w / 100 * workArea.width), 67 | height: Math.round(h / 100 * workArea.height) 68 | }; 69 | chrome.windows.update(wind.id, updateInfo, () => window.close()); 70 | } 71 | }); 72 | } 73 | 74 | function comparePresets(a, b) { 75 | if (parseInt(a.sortorder) > parseInt(b.sortorder)) { 76 | return 1; 77 | } 78 | if (parseInt(a.sortorder) < parseInt(b.sortorder)) { 79 | return -1; 80 | } 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /Scripts/Sortable.js: -------------------------------------------------------------------------------- 1 | /**! 2 | * Sortable 3 | * @author RubaXa 4 | * @license MIT 5 | */ 6 | 7 | (function sortableModule(factory) { 8 | "use strict"; 9 | 10 | if (typeof define === "function" && define.amd) { 11 | define(factory); 12 | } 13 | else if (typeof module != "undefined" && typeof module.exports != "undefined") { 14 | module.exports = factory(); 15 | } 16 | else { 17 | /* jshint sub:true */ 18 | window["Sortable"] = factory(); 19 | } 20 | })(function sortableFactory() { 21 | "use strict"; 22 | 23 | if (typeof window == "undefined" || !window.document) { 24 | return function sortableError() { 25 | throw new Error("Sortable.js requires a window with a document"); 26 | }; 27 | } 28 | 29 | var dragEl, 30 | parentEl, 31 | ghostEl, 32 | cloneEl, 33 | rootEl, 34 | nextEl, 35 | lastDownEl, 36 | 37 | scrollEl, 38 | scrollParentEl, 39 | scrollCustomFn, 40 | 41 | lastEl, 42 | lastCSS, 43 | lastParentCSS, 44 | 45 | oldIndex, 46 | newIndex, 47 | 48 | activeGroup, 49 | putSortable, 50 | 51 | autoScroll = {}, 52 | 53 | tapEvt, 54 | touchEvt, 55 | 56 | moved, 57 | 58 | /** @const */ 59 | R_SPACE = /\s+/g, 60 | R_FLOAT = /left|right|inline/, 61 | 62 | expando = 'Sortable' + (new Date).getTime(), 63 | 64 | win = window, 65 | document = win.document, 66 | parseInt = win.parseInt, 67 | 68 | $ = win.jQuery || win.Zepto, 69 | Polymer = win.Polymer, 70 | 71 | captureMode = false, 72 | 73 | supportDraggable = !!('draggable' in document.createElement('div')), 74 | supportCssPointerEvents = (function (el) { 75 | // false when IE11 76 | if (!!navigator.userAgent.match(/Trident.*rv[ :]?11\./)) { 77 | return false; 78 | } 79 | el = document.createElement('x'); 80 | el.style.cssText = 'pointer-events:auto'; 81 | return el.style.pointerEvents === 'auto'; 82 | })(), 83 | 84 | _silent = false, 85 | 86 | abs = Math.abs, 87 | min = Math.min, 88 | 89 | savedInputChecked = [], 90 | touchDragOverListeners = [], 91 | 92 | _autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) { 93 | // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521 94 | if (rootEl && options.scroll) { 95 | var _this = rootEl[expando], 96 | el, 97 | rect, 98 | sens = options.scrollSensitivity, 99 | speed = options.scrollSpeed, 100 | 101 | x = evt.clientX, 102 | y = evt.clientY, 103 | 104 | winWidth = window.innerWidth, 105 | winHeight = window.innerHeight, 106 | 107 | vx, 108 | vy, 109 | 110 | scrollOffsetX, 111 | scrollOffsetY 112 | ; 113 | 114 | // Delect scrollEl 115 | if (scrollParentEl !== rootEl) { 116 | scrollEl = options.scroll; 117 | scrollParentEl = rootEl; 118 | scrollCustomFn = options.scrollFn; 119 | 120 | if (scrollEl === true) { 121 | scrollEl = rootEl; 122 | 123 | do { 124 | if ((scrollEl.offsetWidth < scrollEl.scrollWidth) || 125 | (scrollEl.offsetHeight < scrollEl.scrollHeight) 126 | ) { 127 | break; 128 | } 129 | /* jshint boss:true */ 130 | } while (scrollEl = scrollEl.parentNode); 131 | } 132 | } 133 | 134 | if (scrollEl) { 135 | el = scrollEl; 136 | rect = scrollEl.getBoundingClientRect(); 137 | vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens); 138 | vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens); 139 | } 140 | 141 | 142 | if (!(vx || vy)) { 143 | vx = (winWidth - x <= sens) - (x <= sens); 144 | vy = (winHeight - y <= sens) - (y <= sens); 145 | 146 | /* jshint expr:true */ 147 | (vx || vy) && (el = win); 148 | } 149 | 150 | 151 | if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) { 152 | autoScroll.el = el; 153 | autoScroll.vx = vx; 154 | autoScroll.vy = vy; 155 | 156 | clearInterval(autoScroll.pid); 157 | 158 | if (el) { 159 | autoScroll.pid = setInterval(function () { 160 | scrollOffsetY = vy ? vy * speed : 0; 161 | scrollOffsetX = vx ? vx * speed : 0; 162 | 163 | if ('function' === typeof(scrollCustomFn)) { 164 | return scrollCustomFn.call(_this, scrollOffsetX, scrollOffsetY, evt); 165 | } 166 | 167 | if (el === win) { 168 | win.scrollTo(win.pageXOffset + scrollOffsetX, win.pageYOffset + scrollOffsetY); 169 | } else { 170 | el.scrollTop += scrollOffsetY; 171 | el.scrollLeft += scrollOffsetX; 172 | } 173 | }, 24); 174 | } 175 | } 176 | } 177 | }, 30), 178 | 179 | _prepareGroup = function (options) { 180 | function toFn(value, pull) { 181 | if (value === void 0 || value === true) { 182 | value = group.name; 183 | } 184 | 185 | if (typeof value === 'function') { 186 | return value; 187 | } else { 188 | return function (to, from) { 189 | var fromGroup = from.options.group.name; 190 | 191 | return pull 192 | ? value 193 | : value && (value.join 194 | ? value.indexOf(fromGroup) > -1 195 | : (fromGroup == value) 196 | ); 197 | }; 198 | } 199 | } 200 | 201 | var group = {}; 202 | var originalGroup = options.group; 203 | 204 | if (!originalGroup || typeof originalGroup != 'object') { 205 | originalGroup = {name: originalGroup}; 206 | } 207 | 208 | group.name = originalGroup.name; 209 | group.checkPull = toFn(originalGroup.pull, true); 210 | group.checkPut = toFn(originalGroup.put); 211 | group.revertClone = originalGroup.revertClone; 212 | 213 | options.group = group; 214 | } 215 | ; 216 | 217 | 218 | /** 219 | * @class Sortable 220 | * @param {HTMLElement} el 221 | * @param {Object} [options] 222 | */ 223 | function Sortable(el, options) { 224 | if (!(el && el.nodeType && el.nodeType === 1)) { 225 | throw 'Sortable: `el` must be HTMLElement, and not ' + {}.toString.call(el); 226 | } 227 | 228 | this.el = el; // root element 229 | this.options = options = _extend({}, options); 230 | 231 | 232 | // Export instance 233 | el[expando] = this; 234 | 235 | // Default options 236 | var defaults = { 237 | group: Math.random(), 238 | sort: true, 239 | disabled: false, 240 | store: null, 241 | handle: null, 242 | scroll: true, 243 | scrollSensitivity: 30, 244 | scrollSpeed: 10, 245 | draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*', 246 | ghostClass: 'sortable-ghost', 247 | chosenClass: 'sortable-chosen', 248 | dragClass: 'sortable-drag', 249 | ignore: 'a, img', 250 | filter: null, 251 | preventOnFilter: true, 252 | animation: 0, 253 | setData: function (dataTransfer, dragEl) { 254 | dataTransfer.setData('Text', dragEl.textContent); 255 | }, 256 | dropBubble: false, 257 | dragoverBubble: false, 258 | dataIdAttr: 'data-id', 259 | delay: 0, 260 | forceFallback: false, 261 | fallbackClass: 'sortable-fallback', 262 | fallbackOnBody: false, 263 | fallbackTolerance: 0, 264 | fallbackOffset: {x: 0, y: 0} 265 | }; 266 | 267 | 268 | // Set default options 269 | for (var name in defaults) { 270 | !(name in options) && (options[name] = defaults[name]); 271 | } 272 | 273 | _prepareGroup(options); 274 | 275 | // Bind all private methods 276 | for (var fn in this) { 277 | if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { 278 | this[fn] = this[fn].bind(this); 279 | } 280 | } 281 | 282 | // Setup drag mode 283 | this.nativeDraggable = options.forceFallback ? false : supportDraggable; 284 | 285 | // Bind events 286 | _on(el, 'mousedown', this._onTapStart); 287 | _on(el, 'touchstart', this._onTapStart); 288 | _on(el, 'pointerdown', this._onTapStart); 289 | 290 | if (this.nativeDraggable) { 291 | _on(el, 'dragover', this); 292 | _on(el, 'dragenter', this); 293 | } 294 | 295 | touchDragOverListeners.push(this._onDragOver); 296 | 297 | // Restore sorting 298 | options.store && this.sort(options.store.get(this)); 299 | } 300 | 301 | 302 | Sortable.prototype = /** @lends Sortable.prototype */ { 303 | constructor: Sortable, 304 | 305 | _onTapStart: function (/** Event|TouchEvent */evt) { 306 | var _this = this, 307 | el = this.el, 308 | options = this.options, 309 | preventOnFilter = options.preventOnFilter, 310 | type = evt.type, 311 | touch = evt.touches && evt.touches[0], 312 | target = (touch || evt).target, 313 | originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0]) || target, 314 | filter = options.filter, 315 | startIndex; 316 | 317 | _saveInputCheckedState(el); 318 | 319 | 320 | // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group. 321 | if (dragEl) { 322 | return; 323 | } 324 | 325 | if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) { 326 | return; // only left button or enabled 327 | } 328 | 329 | 330 | target = _closest(target, options.draggable, el); 331 | 332 | if (!target) { 333 | return; 334 | } 335 | 336 | if (lastDownEl === target) { 337 | // Ignoring duplicate `down` 338 | return; 339 | } 340 | 341 | // Get the index of the dragged element within its parent 342 | startIndex = _index(target, options.draggable); 343 | 344 | // Check filter 345 | if (typeof filter === 'function') { 346 | if (filter.call(this, evt, target, this)) { 347 | _dispatchEvent(_this, originalTarget, 'filter', target, el, startIndex); 348 | preventOnFilter && evt.preventDefault(); 349 | return; // cancel dnd 350 | } 351 | } 352 | else if (filter) { 353 | filter = filter.split(',').some(function (criteria) { 354 | criteria = _closest(originalTarget, criteria.trim(), el); 355 | 356 | if (criteria) { 357 | _dispatchEvent(_this, criteria, 'filter', target, el, startIndex); 358 | return true; 359 | } 360 | }); 361 | 362 | if (filter) { 363 | preventOnFilter && evt.preventDefault(); 364 | return; // cancel dnd 365 | } 366 | } 367 | 368 | if (options.handle && !_closest(originalTarget, options.handle, el)) { 369 | return; 370 | } 371 | 372 | // Prepare `dragstart` 373 | this._prepareDragStart(evt, touch, target, startIndex); 374 | }, 375 | 376 | _prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex) { 377 | var _this = this, 378 | el = _this.el, 379 | options = _this.options, 380 | ownerDocument = el.ownerDocument, 381 | dragStartFn; 382 | 383 | if (target && !dragEl && (target.parentNode === el)) { 384 | tapEvt = evt; 385 | 386 | rootEl = el; 387 | dragEl = target; 388 | parentEl = dragEl.parentNode; 389 | nextEl = dragEl.nextSibling; 390 | lastDownEl = target; 391 | activeGroup = options.group; 392 | oldIndex = startIndex; 393 | 394 | this._lastX = (touch || evt).clientX; 395 | this._lastY = (touch || evt).clientY; 396 | 397 | dragEl.style['will-change'] = 'transform'; 398 | 399 | dragStartFn = function () { 400 | // Delayed drag has been triggered 401 | // we can re-enable the events: touchmove/mousemove 402 | _this._disableDelayedDrag(); 403 | 404 | // Make the element draggable 405 | dragEl.draggable = _this.nativeDraggable; 406 | 407 | // Chosen item 408 | _toggleClass(dragEl, options.chosenClass, true); 409 | 410 | // Bind the events: dragstart/dragend 411 | _this._triggerDragStart(evt, touch); 412 | 413 | // Drag start event 414 | _dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, oldIndex); 415 | }; 416 | 417 | // Disable "draggable" 418 | options.ignore.split(',').forEach(function (criteria) { 419 | _find(dragEl, criteria.trim(), _disableDraggable); 420 | }); 421 | 422 | _on(ownerDocument, 'mouseup', _this._onDrop); 423 | _on(ownerDocument, 'touchend', _this._onDrop); 424 | _on(ownerDocument, 'touchcancel', _this._onDrop); 425 | _on(ownerDocument, 'pointercancel', _this._onDrop); 426 | _on(ownerDocument, 'selectstart', _this); 427 | 428 | if (options.delay) { 429 | // If the user moves the pointer or let go the click or touch 430 | // before the delay has been reached: 431 | // disable the delayed drag 432 | _on(ownerDocument, 'mouseup', _this._disableDelayedDrag); 433 | _on(ownerDocument, 'touchend', _this._disableDelayedDrag); 434 | _on(ownerDocument, 'touchcancel', _this._disableDelayedDrag); 435 | _on(ownerDocument, 'mousemove', _this._disableDelayedDrag); 436 | _on(ownerDocument, 'touchmove', _this._disableDelayedDrag); 437 | _on(ownerDocument, 'pointermove', _this._disableDelayedDrag); 438 | 439 | _this._dragStartTimer = setTimeout(dragStartFn, options.delay); 440 | } else { 441 | dragStartFn(); 442 | } 443 | 444 | 445 | } 446 | }, 447 | 448 | _disableDelayedDrag: function () { 449 | var ownerDocument = this.el.ownerDocument; 450 | 451 | clearTimeout(this._dragStartTimer); 452 | _off(ownerDocument, 'mouseup', this._disableDelayedDrag); 453 | _off(ownerDocument, 'touchend', this._disableDelayedDrag); 454 | _off(ownerDocument, 'touchcancel', this._disableDelayedDrag); 455 | _off(ownerDocument, 'mousemove', this._disableDelayedDrag); 456 | _off(ownerDocument, 'touchmove', this._disableDelayedDrag); 457 | _off(ownerDocument, 'pointermove', this._disableDelayedDrag); 458 | }, 459 | 460 | _triggerDragStart: function (/** Event */evt, /** Touch */touch) { 461 | touch = touch || (evt.pointerType == 'touch' ? evt : null); 462 | 463 | if (touch) { 464 | // Touch device support 465 | tapEvt = { 466 | target: dragEl, 467 | clientX: touch.clientX, 468 | clientY: touch.clientY 469 | }; 470 | 471 | this._onDragStart(tapEvt, 'touch'); 472 | } 473 | else if (!this.nativeDraggable) { 474 | this._onDragStart(tapEvt, true); 475 | } 476 | else { 477 | _on(dragEl, 'dragend', this); 478 | _on(rootEl, 'dragstart', this._onDragStart); 479 | } 480 | 481 | try { 482 | if (document.selection) { 483 | // Timeout neccessary for IE9 484 | setTimeout(function () { 485 | document.selection.empty(); 486 | }); 487 | } else { 488 | window.getSelection().removeAllRanges(); 489 | } 490 | } catch (err) { 491 | } 492 | }, 493 | 494 | _dragStarted: function () { 495 | if (rootEl && dragEl) { 496 | var options = this.options; 497 | 498 | // Apply effect 499 | _toggleClass(dragEl, options.ghostClass, true); 500 | _toggleClass(dragEl, options.dragClass, false); 501 | 502 | Sortable.active = this; 503 | 504 | // Drag start event 505 | _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, oldIndex); 506 | } else { 507 | this._nulling(); 508 | } 509 | }, 510 | 511 | _emulateDragOver: function () { 512 | if (touchEvt) { 513 | if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) { 514 | return; 515 | } 516 | 517 | this._lastX = touchEvt.clientX; 518 | this._lastY = touchEvt.clientY; 519 | 520 | if (!supportCssPointerEvents) { 521 | _css(ghostEl, 'display', 'none'); 522 | } 523 | 524 | var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY), 525 | parent = target, 526 | i = touchDragOverListeners.length; 527 | 528 | if (parent) { 529 | do { 530 | if (parent[expando]) { 531 | while (i--) { 532 | touchDragOverListeners[i]({ 533 | clientX: touchEvt.clientX, 534 | clientY: touchEvt.clientY, 535 | target: target, 536 | rootEl: parent 537 | }); 538 | } 539 | 540 | break; 541 | } 542 | 543 | target = parent; // store last element 544 | } 545 | /* jshint boss:true */ 546 | while (parent = parent.parentNode); 547 | } 548 | 549 | if (!supportCssPointerEvents) { 550 | _css(ghostEl, 'display', ''); 551 | } 552 | } 553 | }, 554 | 555 | 556 | _onTouchMove: function (/**TouchEvent*/evt) { 557 | if (tapEvt) { 558 | var options = this.options, 559 | fallbackTolerance = options.fallbackTolerance, 560 | fallbackOffset = options.fallbackOffset, 561 | touch = evt.touches ? evt.touches[0] : evt, 562 | dx = (touch.clientX - tapEvt.clientX) + fallbackOffset.x, 563 | dy = (touch.clientY - tapEvt.clientY) + fallbackOffset.y, 564 | translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)'; 565 | 566 | // only set the status to dragging, when we are actually dragging 567 | if (!Sortable.active) { 568 | if (fallbackTolerance && 569 | min(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY)) < fallbackTolerance 570 | ) { 571 | return; 572 | } 573 | 574 | this._dragStarted(); 575 | } 576 | 577 | // as well as creating the ghost element on the document body 578 | this._appendGhost(); 579 | 580 | moved = true; 581 | touchEvt = touch; 582 | 583 | _css(ghostEl, 'webkitTransform', translate3d); 584 | _css(ghostEl, 'mozTransform', translate3d); 585 | _css(ghostEl, 'msTransform', translate3d); 586 | _css(ghostEl, 'transform', translate3d); 587 | 588 | evt.preventDefault(); 589 | } 590 | }, 591 | 592 | _appendGhost: function () { 593 | if (!ghostEl) { 594 | var rect = dragEl.getBoundingClientRect(), 595 | css = _css(dragEl), 596 | options = this.options, 597 | ghostRect; 598 | 599 | ghostEl = dragEl.cloneNode(true); 600 | 601 | _toggleClass(ghostEl, options.ghostClass, false); 602 | _toggleClass(ghostEl, options.fallbackClass, true); 603 | _toggleClass(ghostEl, options.dragClass, true); 604 | 605 | _css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10)); 606 | _css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10)); 607 | _css(ghostEl, 'width', rect.width); 608 | _css(ghostEl, 'height', rect.height); 609 | _css(ghostEl, 'opacity', '0.8'); 610 | _css(ghostEl, 'position', 'fixed'); 611 | _css(ghostEl, 'zIndex', '100000'); 612 | _css(ghostEl, 'pointerEvents', 'none'); 613 | 614 | options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl); 615 | 616 | // Fixing dimensions. 617 | ghostRect = ghostEl.getBoundingClientRect(); 618 | _css(ghostEl, 'width', rect.width * 2 - ghostRect.width); 619 | _css(ghostEl, 'height', rect.height * 2 - ghostRect.height); 620 | } 621 | }, 622 | 623 | _onDragStart: function (/**Event*/evt, /**boolean*/useFallback) { 624 | var dataTransfer = evt.dataTransfer, 625 | options = this.options; 626 | 627 | this._offUpEvents(); 628 | 629 | if (activeGroup.checkPull(this, this, dragEl, evt)) { 630 | cloneEl = _clone(dragEl); 631 | 632 | cloneEl.draggable = false; 633 | cloneEl.style['will-change'] = ''; 634 | 635 | _css(cloneEl, 'display', 'none'); 636 | _toggleClass(cloneEl, this.options.chosenClass, false); 637 | 638 | rootEl.insertBefore(cloneEl, dragEl); 639 | _dispatchEvent(this, rootEl, 'clone', dragEl); 640 | } 641 | 642 | _toggleClass(dragEl, options.dragClass, true); 643 | 644 | if (useFallback) { 645 | if (useFallback === 'touch') { 646 | // Bind touch events 647 | _on(document, 'touchmove', this._onTouchMove); 648 | _on(document, 'touchend', this._onDrop); 649 | _on(document, 'touchcancel', this._onDrop); 650 | _on(document, 'pointermove', this._onTouchMove); 651 | _on(document, 'pointerup', this._onDrop); 652 | } else { 653 | // Old brwoser 654 | _on(document, 'mousemove', this._onTouchMove); 655 | _on(document, 'mouseup', this._onDrop); 656 | } 657 | 658 | this._loopId = setInterval(this._emulateDragOver, 50); 659 | } 660 | else { 661 | if (dataTransfer) { 662 | dataTransfer.effectAllowed = 'move'; 663 | options.setData && options.setData.call(this, dataTransfer, dragEl); 664 | } 665 | 666 | _on(document, 'drop', this); 667 | setTimeout(this._dragStarted, 0); 668 | } 669 | }, 670 | 671 | _onDragOver: function (/**Event*/evt) { 672 | var el = this.el, 673 | target, 674 | dragRect, 675 | targetRect, 676 | revert, 677 | options = this.options, 678 | group = options.group, 679 | activeSortable = Sortable.active, 680 | isOwner = (activeGroup === group), 681 | isMovingBetweenSortable = false, 682 | canSort = options.sort; 683 | 684 | if (evt.preventDefault !== void 0) { 685 | evt.preventDefault(); 686 | !options.dragoverBubble && evt.stopPropagation(); 687 | } 688 | 689 | if (dragEl.animated) { 690 | return; 691 | } 692 | 693 | moved = true; 694 | 695 | if (activeSortable && !options.disabled && 696 | (isOwner 697 | ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list 698 | : ( 699 | putSortable === this || 700 | ( 701 | (activeSortable.lastPullMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && 702 | group.checkPut(this, activeSortable, dragEl, evt) 703 | ) 704 | ) 705 | ) && 706 | (evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback 707 | ) { 708 | // Smart auto-scrolling 709 | _autoScroll(evt, options, this.el); 710 | 711 | if (_silent) { 712 | return; 713 | } 714 | 715 | target = _closest(evt.target, options.draggable, el); 716 | dragRect = dragEl.getBoundingClientRect(); 717 | 718 | if (putSortable !== this) { 719 | putSortable = this; 720 | isMovingBetweenSortable = true; 721 | } 722 | 723 | if (revert) { 724 | _cloneHide(activeSortable, true); 725 | parentEl = rootEl; // actualization 726 | 727 | if (cloneEl || nextEl) { 728 | rootEl.insertBefore(dragEl, cloneEl || nextEl); 729 | } 730 | else if (!canSort) { 731 | rootEl.appendChild(dragEl); 732 | } 733 | 734 | return; 735 | } 736 | 737 | 738 | if ((el.children.length === 0) || (el.children[0] === ghostEl) || 739 | (el === evt.target) && (_ghostIsLast(el, evt)) 740 | ) { 741 | //assign target only if condition is true 742 | if (el.children.length !== 0 && el.children[0] !== ghostEl && el === evt.target) { 743 | target = el.lastElementChild; 744 | } 745 | 746 | if (target) { 747 | if (target.animated) { 748 | return; 749 | } 750 | 751 | targetRect = target.getBoundingClientRect(); 752 | } 753 | 754 | _cloneHide(activeSortable, isOwner); 755 | 756 | if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) { 757 | if (!dragEl.contains(el)) { 758 | el.appendChild(dragEl); 759 | parentEl = el; // actualization 760 | } 761 | 762 | this._animate(dragRect, dragEl); 763 | target && this._animate(targetRect, target); 764 | } 765 | } 766 | else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) { 767 | if (lastEl !== target) { 768 | lastEl = target; 769 | lastCSS = _css(target); 770 | lastParentCSS = _css(target.parentNode); 771 | } 772 | 773 | targetRect = target.getBoundingClientRect(); 774 | 775 | var width = targetRect.right - targetRect.left, 776 | height = targetRect.bottom - targetRect.top, 777 | floating = R_FLOAT.test(lastCSS.cssFloat + lastCSS.display) 778 | || (lastParentCSS.display == 'flex' && lastParentCSS['flex-direction'].indexOf('row') === 0), 779 | isWide = (target.offsetWidth > dragEl.offsetWidth), 780 | isLong = (target.offsetHeight > dragEl.offsetHeight), 781 | halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5, 782 | nextSibling = target.nextElementSibling, 783 | after = false 784 | ; 785 | 786 | if (floating) { 787 | var elTop = dragEl.offsetTop, 788 | tgTop = target.offsetTop; 789 | 790 | if (elTop === tgTop) { 791 | after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide; 792 | } 793 | else if (target.previousElementSibling === dragEl || dragEl.previousElementSibling === target) { 794 | after = (evt.clientY - targetRect.top) / height > 0.5; 795 | } else { 796 | after = tgTop > elTop; 797 | } 798 | } else if (!isMovingBetweenSortable) { 799 | after = (nextSibling !== dragEl) && !isLong || halfway && isLong; 800 | } 801 | 802 | var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after); 803 | 804 | if (moveVector !== false) { 805 | if (moveVector === 1 || moveVector === -1) { 806 | after = (moveVector === 1); 807 | } 808 | 809 | _silent = true; 810 | setTimeout(_unsilent, 30); 811 | 812 | _cloneHide(activeSortable, isOwner); 813 | 814 | if (!dragEl.contains(el)) { 815 | if (after && !nextSibling) { 816 | el.appendChild(dragEl); 817 | } else { 818 | target.parentNode.insertBefore(dragEl, after ? nextSibling : target); 819 | } 820 | } 821 | 822 | parentEl = dragEl.parentNode; // actualization 823 | 824 | this._animate(dragRect, dragEl); 825 | this._animate(targetRect, target); 826 | } 827 | } 828 | } 829 | }, 830 | 831 | _animate: function (prevRect, target) { 832 | var ms = this.options.animation; 833 | 834 | if (ms) { 835 | var currentRect = target.getBoundingClientRect(); 836 | 837 | if (prevRect.nodeType === 1) { 838 | prevRect = prevRect.getBoundingClientRect(); 839 | } 840 | 841 | _css(target, 'transition', 'none'); 842 | _css(target, 'transform', 'translate3d(' 843 | + (prevRect.left - currentRect.left) + 'px,' 844 | + (prevRect.top - currentRect.top) + 'px,0)' 845 | ); 846 | 847 | target.offsetWidth; // repaint 848 | 849 | _css(target, 'transition', 'all ' + ms + 'ms'); 850 | _css(target, 'transform', 'translate3d(0,0,0)'); 851 | 852 | clearTimeout(target.animated); 853 | target.animated = setTimeout(function () { 854 | _css(target, 'transition', ''); 855 | _css(target, 'transform', ''); 856 | target.animated = false; 857 | }, ms); 858 | } 859 | }, 860 | 861 | _offUpEvents: function () { 862 | var ownerDocument = this.el.ownerDocument; 863 | 864 | _off(document, 'touchmove', this._onTouchMove); 865 | _off(document, 'pointermove', this._onTouchMove); 866 | _off(ownerDocument, 'mouseup', this._onDrop); 867 | _off(ownerDocument, 'touchend', this._onDrop); 868 | _off(ownerDocument, 'pointerup', this._onDrop); 869 | _off(ownerDocument, 'touchcancel', this._onDrop); 870 | _off(ownerDocument, 'pointercancel', this._onDrop); 871 | _off(ownerDocument, 'selectstart', this); 872 | }, 873 | 874 | _onDrop: function (/**Event*/evt) { 875 | var el = this.el, 876 | options = this.options; 877 | 878 | clearInterval(this._loopId); 879 | clearInterval(autoScroll.pid); 880 | clearTimeout(this._dragStartTimer); 881 | 882 | // Unbind events 883 | _off(document, 'mousemove', this._onTouchMove); 884 | 885 | if (this.nativeDraggable) { 886 | _off(document, 'drop', this); 887 | _off(el, 'dragstart', this._onDragStart); 888 | } 889 | 890 | this._offUpEvents(); 891 | 892 | if (evt) { 893 | if (moved) { 894 | evt.preventDefault(); 895 | !options.dropBubble && evt.stopPropagation(); 896 | } 897 | 898 | ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl); 899 | 900 | if (rootEl === parentEl || Sortable.active.lastPullMode !== 'clone') { 901 | // Remove clone 902 | cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl); 903 | } 904 | 905 | if (dragEl) { 906 | if (this.nativeDraggable) { 907 | _off(dragEl, 'dragend', this); 908 | } 909 | 910 | _disableDraggable(dragEl); 911 | dragEl.style['will-change'] = ''; 912 | 913 | // Remove class's 914 | _toggleClass(dragEl, this.options.ghostClass, false); 915 | _toggleClass(dragEl, this.options.chosenClass, false); 916 | 917 | // Drag stop event 918 | _dispatchEvent(this, rootEl, 'unchoose', dragEl, rootEl, oldIndex); 919 | 920 | if (rootEl !== parentEl) { 921 | newIndex = _index(dragEl, options.draggable); 922 | 923 | if (newIndex >= 0) { 924 | // Add event 925 | _dispatchEvent(null, parentEl, 'add', dragEl, rootEl, oldIndex, newIndex); 926 | 927 | // Remove event 928 | _dispatchEvent(this, rootEl, 'remove', dragEl, rootEl, oldIndex, newIndex); 929 | 930 | // drag from one list and drop into another 931 | _dispatchEvent(null, parentEl, 'sort', dragEl, rootEl, oldIndex, newIndex); 932 | _dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex); 933 | } 934 | } 935 | else { 936 | if (dragEl.nextSibling !== nextEl) { 937 | // Get the index of the dragged element within its parent 938 | newIndex = _index(dragEl, options.draggable); 939 | 940 | if (newIndex >= 0) { 941 | // drag & drop within the same list 942 | _dispatchEvent(this, rootEl, 'update', dragEl, rootEl, oldIndex, newIndex); 943 | _dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex); 944 | } 945 | } 946 | } 947 | 948 | if (Sortable.active) { 949 | /* jshint eqnull:true */ 950 | if (newIndex == null || newIndex === -1) { 951 | newIndex = oldIndex; 952 | } 953 | 954 | _dispatchEvent(this, rootEl, 'end', dragEl, rootEl, oldIndex, newIndex); 955 | 956 | // Save sorting 957 | this.save(); 958 | } 959 | } 960 | 961 | } 962 | 963 | this._nulling(); 964 | }, 965 | 966 | _nulling: function() { 967 | rootEl = 968 | dragEl = 969 | parentEl = 970 | ghostEl = 971 | nextEl = 972 | cloneEl = 973 | lastDownEl = 974 | 975 | scrollEl = 976 | scrollParentEl = 977 | 978 | tapEvt = 979 | touchEvt = 980 | 981 | moved = 982 | newIndex = 983 | 984 | lastEl = 985 | lastCSS = 986 | 987 | putSortable = 988 | activeGroup = 989 | Sortable.active = null; 990 | 991 | savedInputChecked.forEach(function (el) { 992 | el.checked = true; 993 | }); 994 | savedInputChecked.length = 0; 995 | }, 996 | 997 | handleEvent: function (/**Event*/evt) { 998 | switch (evt.type) { 999 | case 'drop': 1000 | case 'dragend': 1001 | this._onDrop(evt); 1002 | break; 1003 | 1004 | case 'dragover': 1005 | case 'dragenter': 1006 | if (dragEl) { 1007 | this._onDragOver(evt); 1008 | _globalDragOver(evt); 1009 | } 1010 | break; 1011 | 1012 | case 'selectstart': 1013 | evt.preventDefault(); 1014 | break; 1015 | } 1016 | }, 1017 | 1018 | 1019 | /** 1020 | * Serializes the item into an array of string. 1021 | * @returns {String[]} 1022 | */ 1023 | toArray: function () { 1024 | var order = [], 1025 | el, 1026 | children = this.el.children, 1027 | i = 0, 1028 | n = children.length, 1029 | options = this.options; 1030 | 1031 | for (; i < n; i++) { 1032 | el = children[i]; 1033 | if (_closest(el, options.draggable, this.el)) { 1034 | order.push(el.getAttribute(options.dataIdAttr) || _generateId(el)); 1035 | } 1036 | } 1037 | 1038 | return order; 1039 | }, 1040 | 1041 | 1042 | /** 1043 | * Sorts the elements according to the array. 1044 | * @param {String[]} order order of the items 1045 | */ 1046 | sort: function (order) { 1047 | var items = {}, rootEl = this.el; 1048 | 1049 | this.toArray().forEach(function (id, i) { 1050 | var el = rootEl.children[i]; 1051 | 1052 | if (_closest(el, this.options.draggable, rootEl)) { 1053 | items[id] = el; 1054 | } 1055 | }, this); 1056 | 1057 | order.forEach(function (id) { 1058 | if (items[id]) { 1059 | rootEl.removeChild(items[id]); 1060 | rootEl.appendChild(items[id]); 1061 | } 1062 | }); 1063 | }, 1064 | 1065 | 1066 | /** 1067 | * Save the current sorting 1068 | */ 1069 | save: function () { 1070 | var store = this.options.store; 1071 | store && store.set(this); 1072 | }, 1073 | 1074 | 1075 | /** 1076 | * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. 1077 | * @param {HTMLElement} el 1078 | * @param {String} [selector] default: `options.draggable` 1079 | * @returns {HTMLElement|null} 1080 | */ 1081 | closest: function (el, selector) { 1082 | return _closest(el, selector || this.options.draggable, this.el); 1083 | }, 1084 | 1085 | 1086 | /** 1087 | * Set/get option 1088 | * @param {string} name 1089 | * @param {*} [value] 1090 | * @returns {*} 1091 | */ 1092 | option: function (name, value) { 1093 | var options = this.options; 1094 | 1095 | if (value === void 0) { 1096 | return options[name]; 1097 | } else { 1098 | options[name] = value; 1099 | 1100 | if (name === 'group') { 1101 | _prepareGroup(options); 1102 | } 1103 | } 1104 | }, 1105 | 1106 | 1107 | /** 1108 | * Destroy 1109 | */ 1110 | destroy: function () { 1111 | var el = this.el; 1112 | 1113 | el[expando] = null; 1114 | 1115 | _off(el, 'mousedown', this._onTapStart); 1116 | _off(el, 'touchstart', this._onTapStart); 1117 | _off(el, 'pointerdown', this._onTapStart); 1118 | 1119 | if (this.nativeDraggable) { 1120 | _off(el, 'dragover', this); 1121 | _off(el, 'dragenter', this); 1122 | } 1123 | 1124 | // Remove draggable attributes 1125 | Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) { 1126 | el.removeAttribute('draggable'); 1127 | }); 1128 | 1129 | touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1); 1130 | 1131 | this._onDrop(); 1132 | 1133 | this.el = el = null; 1134 | } 1135 | }; 1136 | 1137 | 1138 | function _cloneHide(sortable, state) { 1139 | if (sortable.lastPullMode !== 'clone') { 1140 | state = true; 1141 | } 1142 | 1143 | if (cloneEl && (cloneEl.state !== state)) { 1144 | _css(cloneEl, 'display', state ? 'none' : ''); 1145 | 1146 | if (!state) { 1147 | if (cloneEl.state) { 1148 | if (sortable.options.group.revertClone) { 1149 | rootEl.insertBefore(cloneEl, nextEl); 1150 | sortable._animate(dragEl, cloneEl); 1151 | } else { 1152 | rootEl.insertBefore(cloneEl, dragEl); 1153 | } 1154 | } 1155 | } 1156 | 1157 | cloneEl.state = state; 1158 | } 1159 | } 1160 | 1161 | 1162 | function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) { 1163 | if (el) { 1164 | ctx = ctx || document; 1165 | 1166 | do { 1167 | if ((selector === '>*' && el.parentNode === ctx) || _matches(el, selector)) { 1168 | return el; 1169 | } 1170 | /* jshint boss:true */ 1171 | } while (el = _getParentOrHost(el)); 1172 | } 1173 | 1174 | return null; 1175 | } 1176 | 1177 | 1178 | function _getParentOrHost(el) { 1179 | var parent = el.host; 1180 | 1181 | return (parent && parent.nodeType) ? parent : el.parentNode; 1182 | } 1183 | 1184 | 1185 | function _globalDragOver(/**Event*/evt) { 1186 | if (evt.dataTransfer) { 1187 | evt.dataTransfer.dropEffect = 'move'; 1188 | } 1189 | evt.preventDefault(); 1190 | } 1191 | 1192 | 1193 | function _on(el, event, fn) { 1194 | el.addEventListener(event, fn, captureMode); 1195 | } 1196 | 1197 | 1198 | function _off(el, event, fn) { 1199 | el.removeEventListener(event, fn, captureMode); 1200 | } 1201 | 1202 | 1203 | function _toggleClass(el, name, state) { 1204 | if (el) { 1205 | if (el.classList) { 1206 | el.classList[state ? 'add' : 'remove'](name); 1207 | } 1208 | else { 1209 | var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' '); 1210 | el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' '); 1211 | } 1212 | } 1213 | } 1214 | 1215 | 1216 | function _css(el, prop, val) { 1217 | var style = el && el.style; 1218 | 1219 | if (style) { 1220 | if (val === void 0) { 1221 | if (document.defaultView && document.defaultView.getComputedStyle) { 1222 | val = document.defaultView.getComputedStyle(el, ''); 1223 | } 1224 | else if (el.currentStyle) { 1225 | val = el.currentStyle; 1226 | } 1227 | 1228 | return prop === void 0 ? val : val[prop]; 1229 | } 1230 | else { 1231 | if (!(prop in style)) { 1232 | prop = '-webkit-' + prop; 1233 | } 1234 | 1235 | style[prop] = val + (typeof val === 'string' ? '' : 'px'); 1236 | } 1237 | } 1238 | } 1239 | 1240 | 1241 | function _find(ctx, tagName, iterator) { 1242 | if (ctx) { 1243 | var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length; 1244 | 1245 | if (iterator) { 1246 | for (; i < n; i++) { 1247 | iterator(list[i], i); 1248 | } 1249 | } 1250 | 1251 | return list; 1252 | } 1253 | 1254 | return []; 1255 | } 1256 | 1257 | 1258 | 1259 | function _dispatchEvent(sortable, rootEl, name, targetEl, fromEl, startIndex, newIndex) { 1260 | sortable = (sortable || rootEl[expando]); 1261 | 1262 | var evt = document.createEvent('Event'), 1263 | options = sortable.options, 1264 | onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1); 1265 | 1266 | evt.initEvent(name, true, true); 1267 | 1268 | evt.to = rootEl; 1269 | evt.from = fromEl || rootEl; 1270 | evt.item = targetEl || rootEl; 1271 | evt.clone = cloneEl; 1272 | 1273 | evt.oldIndex = startIndex; 1274 | evt.newIndex = newIndex; 1275 | 1276 | rootEl.dispatchEvent(evt); 1277 | 1278 | if (options[onName]) { 1279 | options[onName].call(sortable, evt); 1280 | } 1281 | } 1282 | 1283 | 1284 | function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt, willInsertAfter) { 1285 | var evt, 1286 | sortable = fromEl[expando], 1287 | onMoveFn = sortable.options.onMove, 1288 | retVal; 1289 | 1290 | evt = document.createEvent('Event'); 1291 | evt.initEvent('move', true, true); 1292 | 1293 | evt.to = toEl; 1294 | evt.from = fromEl; 1295 | evt.dragged = dragEl; 1296 | evt.draggedRect = dragRect; 1297 | evt.related = targetEl || toEl; 1298 | evt.relatedRect = targetRect || toEl.getBoundingClientRect(); 1299 | evt.willInsertAfter = willInsertAfter; 1300 | 1301 | fromEl.dispatchEvent(evt); 1302 | 1303 | if (onMoveFn) { 1304 | retVal = onMoveFn.call(sortable, evt, originalEvt); 1305 | } 1306 | 1307 | return retVal; 1308 | } 1309 | 1310 | 1311 | function _disableDraggable(el) { 1312 | el.draggable = false; 1313 | } 1314 | 1315 | 1316 | function _unsilent() { 1317 | _silent = false; 1318 | } 1319 | 1320 | 1321 | /** @returns {HTMLElement|false} */ 1322 | function _ghostIsLast(el, evt) { 1323 | var lastEl = el.lastElementChild, 1324 | rect = lastEl.getBoundingClientRect(); 1325 | 1326 | // 5 — min delta 1327 | // abs — нельзя добавлять, а то глюки при наведении сверху 1328 | return (evt.clientY - (rect.top + rect.height) > 5) || 1329 | (evt.clientX - (rect.left + rect.width) > 5); 1330 | } 1331 | 1332 | 1333 | /** 1334 | * Generate id 1335 | * @param {HTMLElement} el 1336 | * @returns {String} 1337 | * @private 1338 | */ 1339 | function _generateId(el) { 1340 | var str = el.tagName + el.className + el.src + el.href + el.textContent, 1341 | i = str.length, 1342 | sum = 0; 1343 | 1344 | while (i--) { 1345 | sum += str.charCodeAt(i); 1346 | } 1347 | 1348 | return sum.toString(36); 1349 | } 1350 | 1351 | /** 1352 | * Returns the index of an element within its parent for a selected set of 1353 | * elements 1354 | * @param {HTMLElement} el 1355 | * @param {selector} selector 1356 | * @return {number} 1357 | */ 1358 | function _index(el, selector) { 1359 | var index = 0; 1360 | 1361 | if (!el || !el.parentNode) { 1362 | return -1; 1363 | } 1364 | 1365 | while (el && (el = el.previousElementSibling)) { 1366 | if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && (selector === '>*' || _matches(el, selector))) { 1367 | index++; 1368 | } 1369 | } 1370 | 1371 | return index; 1372 | } 1373 | 1374 | function _matches(/**HTMLElement*/el, /**String*/selector) { 1375 | if (el) { 1376 | selector = selector.split('.'); 1377 | 1378 | var tag = selector.shift().toUpperCase(), 1379 | re = new RegExp('\\s(' + selector.join('|') + ')(?=\\s)', 'g'); 1380 | 1381 | return ( 1382 | (tag === '' || el.nodeName.toUpperCase() == tag) && 1383 | (!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length) 1384 | ); 1385 | } 1386 | 1387 | return false; 1388 | } 1389 | 1390 | function _throttle(callback, ms) { 1391 | var args, _this; 1392 | 1393 | return function () { 1394 | if (args === void 0) { 1395 | args = arguments; 1396 | _this = this; 1397 | 1398 | setTimeout(function () { 1399 | if (args.length === 1) { 1400 | callback.call(_this, args[0]); 1401 | } else { 1402 | callback.apply(_this, args); 1403 | } 1404 | 1405 | args = void 0; 1406 | }, ms); 1407 | } 1408 | }; 1409 | } 1410 | 1411 | function _extend(dst, src) { 1412 | if (dst && src) { 1413 | for (var key in src) { 1414 | if (src.hasOwnProperty(key)) { 1415 | dst[key] = src[key]; 1416 | } 1417 | } 1418 | } 1419 | 1420 | return dst; 1421 | } 1422 | 1423 | function _clone(el) { 1424 | return $ 1425 | ? $(el).clone(true)[0] 1426 | : (Polymer && Polymer.dom 1427 | ? Polymer.dom(el).cloneNode(true) 1428 | : el.cloneNode(true) 1429 | ); 1430 | } 1431 | 1432 | function _saveInputCheckedState(root) { 1433 | var inputs = root.getElementsByTagName('input'); 1434 | var idx = inputs.length; 1435 | 1436 | while (idx--) { 1437 | var el = inputs[idx]; 1438 | el.checked && savedInputChecked.push(el); 1439 | } 1440 | } 1441 | 1442 | // Fixed #973: 1443 | _on(document, 'touchmove', function (evt) { 1444 | if (Sortable.active) { 1445 | evt.preventDefault(); 1446 | } 1447 | }); 1448 | 1449 | try { 1450 | window.addEventListener('test', null, Object.defineProperty({}, 'passive', { 1451 | get: function () { 1452 | captureMode = { 1453 | capture: false, 1454 | passive: false 1455 | }; 1456 | } 1457 | })); 1458 | } catch (err) {} 1459 | 1460 | // Export utils 1461 | Sortable.utils = { 1462 | on: _on, 1463 | off: _off, 1464 | css: _css, 1465 | find: _find, 1466 | is: function (el, selector) { 1467 | return !!_closest(el, selector, el); 1468 | }, 1469 | extend: _extend, 1470 | throttle: _throttle, 1471 | closest: _closest, 1472 | toggleClass: _toggleClass, 1473 | clone: _clone, 1474 | index: _index 1475 | }; 1476 | 1477 | 1478 | /** 1479 | * Create sortable instance 1480 | * @param {HTMLElement} el 1481 | * @param {Object} [options] 1482 | */ 1483 | Sortable.create = function (el, options) { 1484 | return new Sortable(el, options); 1485 | }; 1486 | 1487 | 1488 | // Export 1489 | Sortable.version = '1.6.1'; 1490 | return Sortable; 1491 | }); 1492 | -------------------------------------------------------------------------------- /Scripts/background.js: -------------------------------------------------------------------------------- 1 | /* global loadPresets */ 2 | 'use strict'; 3 | 4 | chrome.runtime.onMessage.addListener(request => { 5 | if (request.method === 'notify') { 6 | const notificationOptions = { 7 | type: 'basic', 8 | title: 'Success Operation', 9 | iconUrl: 'Content/Images/24.png', 10 | message: request.message 11 | }; 12 | chrome.notifications.create(notificationOptions); 13 | } 14 | }); 15 | 16 | /* FAQs & Feedback */ 17 | { 18 | const {management, runtime: {onInstalled, setUninstallURL, getManifest}, storage, tabs} = chrome; 19 | if (navigator.webdriver !== true) { 20 | const page = getManifest().homepage_url; 21 | const {name, version} = getManifest(); 22 | onInstalled.addListener(({reason, previousVersion}) => { 23 | management.getSelf(({installType}) => installType === 'normal' && storage.local.get({ 24 | 'faqs': true, 25 | 'last-update': 0 26 | }, prefs => { 27 | if (reason === 'install' || (prefs.faqs && reason === 'update')) { 28 | const doUpdate = (Date.now() - prefs['last-update']) / 1000 / 60 / 60 / 24 > 45; 29 | if (doUpdate && previousVersion !== version) { 30 | tabs.create({ 31 | url: page + '?version=' + version + (previousVersion ? '&p=' + previousVersion : '') + '&type=' + reason, 32 | active: reason === 'install' 33 | }); 34 | storage.local.set({'last-update': Date.now()}); 35 | } 36 | } 37 | })); 38 | }); 39 | setUninstallURL(page + '?rd=feedback&name=' + encodeURIComponent(name) + '&version=' + version); 40 | } 41 | } 42 | 43 | /** 44 | * Event listener for keyboard commands 45 | * 46 | * This event listener binds to keyboard shortcuts defined in `manifest.json`. 47 | * It triggers the preset with the index concerting to the last digit of 48 | * the keyboard shortcut preset's name. That is, the shortcut `resize0` would 49 | * trigger the first preset. 50 | */ 51 | function shortcutHandler(name) { 52 | const triggered = parseInt(name.slice(-1), 10); 53 | 54 | loadPresets(presets => { 55 | const preset = presets[triggered]; 56 | const x = parseInt(preset.left); 57 | const y = parseInt(preset.top); 58 | const w = parseInt(preset.width); 59 | const h = parseInt(preset.height); 60 | resizeWindow(x, y, w, h); 61 | }); 62 | }; 63 | 64 | try { 65 | browser.commands.onCommand.addListener(shortcutHandler); 66 | } 67 | catch (err) { 68 | chrome.commands.onCommand.addListener(shortcutHandler); 69 | } 70 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "Window Layout Resizer", 4 | "description": "Resize the current window into different customizable layouts (Multiple monitors are supported).", 5 | "version": "0.1.5", 6 | "icons": { 7 | "16": "Content/Images/16.png", 8 | "24": "Content/Images/24.png", 9 | "32": "Content/Images/32.png", 10 | "64": "Content/Images/64.png", 11 | "128": "Content/Images/128.png" 12 | }, 13 | "browser_action": { 14 | "default_popup": "popup.html" 15 | }, 16 | "background":{ 17 | "scripts":[ 18 | "Scripts/Resizer.js", 19 | "Scripts/background.js" 20 | ], 21 | "persistent":false 22 | }, 23 | "permissions": [ 24 | "storage", 25 | "system.display", 26 | "notifications" 27 | ], 28 | "homepage_url": "https://add0n.com/layout-resizer.html", 29 | "commands": { 30 | "resize0": { 31 | "description": "Resize to template #1" 32 | }, 33 | "resize1": { 34 | "description": "Resize to template #2" 35 | }, 36 | "resize2": { 37 | "description": "Resize to template #3" 38 | }, 39 | "resize3": { 40 | "description": "Resize to template #4" 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Window Layout Resizer 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Are you sure?

17 |

18 | OK 19 | Cancel 20 |

21 |
22 |
23 |
24 | 25 | Window Layout Resizer 26 |
27 | 28 | 29 |
30 |
31 | 32 |
33 |
34 |
35 |
36 |

ِDo you want reset presets?

37 |

38 | OK 39 | Cancel 40 |

41 |
42 |
43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | --------------------------------------------------------------------------------