├── .gitignore ├── LICENSE ├── README.md ├── about.html ├── application.xml ├── bg2css.html ├── css └── sample.css ├── default.png ├── divlist.html ├── help.html ├── help ├── 001.png ├── 003.gif ├── 004.gif ├── 005.gif ├── 02.png └── r.png ├── icons ├── AIRApp_128.png ├── AIRApp_16.png ├── AIRApp_32.png ├── AIRApp_48.png └── b.gif └── lib ├── air ├── AIRAliases.js ├── applicationupdater_ui.swf └── library.swf ├── js ├── AIRLocalizer.js ├── AIRMenuBuilder.js ├── divlist.js └── main.js └── menus ├── menu.js └── menu2.js /.gitignore: -------------------------------------------------------------------------------- 1 | bg2css.air 2 | bg2css_reverse_finally.icns 3 | bg2css.sublime-workspace 4 | bg2css.sublime-project 5 | .vscode -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 GhostZhang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bg2css 2 | 3 | CSS Sprites 样式生成工具 4 | 5 | ## 使用说明 6 | 7 | 1. 运行软件 8 | 2. 将要处理的图片拖入界面或 \command+o\ 9 | 3. 双击图片上的任意位置,会得到一个蓝色的区域,区域可移动位置,按住右下角可改变区域的大小 10 | 11 | ## 安装说明 12 | 13 | 1. 先安装[Adobe Air](https://airsdk.harman.com/runtime)运行环境 14 | 2. 下载安装最新版的[bg2css.air](https://github.com/ghostzhang/bg2css/releases) 15 | 16 | ## 版本信息 17 | 18 | bg2css v3.2.3 2020-12-22 19 | 20 | - (fix)帮助文档地址迁移到 github 21 | - (fix)版本更新改为手动 22 | - (fix)样式问题 23 | - (add)默认界面 24 | - (add)更新快捷键说明文档 25 | 26 | bg2css v3.2.2 2019-2-17 27 | 28 | - (fix)更新证书,请重新安装 29 | 30 | bg2css v3.2.1 2010-2-8 31 | 32 | - (add)复制当前大小 33 | - (add)复制提示优化 34 | - (add)从样式表导入 35 | - (add)多语言支持 36 | 37 | bg2css v3.2 2010-2-3 38 | 39 | - (fix)拖动全选 40 | - (fix)使用快捷键修改位置和大小时无边界判定 41 | - (add)修改层配色 42 | - (add)优化改变位置的快捷键 43 | - (add)优化改变大小的快捷键 44 | - (add)优化图片缩放的快捷键 45 | - (add)更新当前图片 46 | 47 | bg2css v3.1.2 2009-11-30 48 | 49 | - (add)“复制当前位置” 50 | - (fix)“操作区”位置挡到滚动条 51 | - (fix)复制坐标时没有“-”号 52 | 53 | bg2css v3.1.1 2009-8-1 54 | 55 | - (add)‘选中层时显示“当前层信息”’为默认选中 56 | - (fix)当前层激活状态不正确 57 | 58 | bg2css v3.1 2009-8-1 59 | 60 | - (fix)样式输出格式不统一 61 | - (fix)当图片太小是层大小判定错误 62 | - (fix)读取有边距的记录时层位置出错 63 | 64 | bg2css v3.0 2009-6-16 65 | 66 | - (add)单独定义层的输出设置 67 | - (add)当前信息层显示设置 68 | - (add)更新所有层信息窗 69 | - (fix)新建层时不激活 70 | - (fix)读取设置后图片不能缩放 71 | - (fix)操作界面布局 72 | 73 | bg2css v2.3 2009-6-2 74 | 75 | - (add)图片缩放增加快捷键 76 | - (add)新的程序图标 77 | - (fix)当前信息层会被层挡住 78 | 79 | bg2css v2.2 2009-5-27 80 | 81 | - (add)优化操作界面,操作区扩展到整个窗口 82 | - (add)程序菜单 83 | - (add)右键菜单 84 | - (fix)数字输入框内容不容易选中 85 | 86 | bg2css v2.1 2009-5-20 87 | 88 | - (add)窗口改变时保持当前层在窗口中 89 | - (fix)移动当前层信息框时当前层变灰 90 | - (fix)放大后载入新图层没有初始化 91 | 92 | bg2css v2.0 2009-5-12 93 | 94 | - (add)优化操作界面 95 | - (add)放大时定位到当前层位置 96 | - (add)图片放大不消锯齿 97 | - (add)图片放大 6 倍(用于原图过小的情况,大图片慎用) 98 | - (fix)图片放大后添加层再缩小信息出错 99 | 100 | bg2css v1.9.5 2009-5-2 101 | 102 | - (fix)保存时文件不能替换 103 | 104 | bg2css v1.9.4 2009-5-2 105 | 106 | - (add)自定义保存路径 107 | - (add)单独复制宽、高、X 坐标、Y 坐标 108 | - (add)复制当前样式时类名可选择 109 | - (fix)修改默认层大小 110 | - (fix)拖入文件时检查类型 111 | - (fix)"关于"里的链接在浏览器窗口打开 112 | 113 | bg2css v1.9.3 2009-4-14 114 | 115 | - (add)文件保存时覆盖提示 116 | - (fix)修改图片拖动响应区域 117 | 118 | bg2css v1.9.2 2009-4-13 119 | 120 | - (add)图片背景色可改 121 | - (add)快捷键删除层 122 | - (add)拖动更改图片 123 | 124 | bg2css v1.9.1 2009-4-12 125 | 126 | - (fix)支持中文路径 127 | 128 | bg2css v1.9.0 2009-4-12 129 | 130 | - (add)复制当前层 131 | - (fix)读取设置后再保存出错 132 | - (fix)修改了部分界面 133 | 134 | bg2css v1.8.2 2009-4-10 135 | 136 | - (add)公共样式部分可编辑 137 | - (fix)修改了部分界面 138 | 保存的设置文件增加一个项,请在之前保存的 xml 里的“imginfo”节点下手动增加一个“gbstyle”节点,值为“”. 139 | 140 | bg2css v1.8.1 2009-4-9 141 | 142 | - (add)一定范围的负边界 143 | - (add)复制选中层的样式 144 | - (fix)输出 0 时的显示 145 | 保存的设置文件增加一个项,请在之前保存的 xml 里的“imginfo”节点下手动增加一个“margin”节点,值为“0”. 146 | 147 | bg2css v1.8.0 2009-4-7 148 | 149 | - (add)复制样式 150 | - (add)层列表,以方便管理 151 | 152 | bg2css v1.7.0 2009-4-1 153 | 154 | - (add)保存层位置信息 155 | 156 | bg2css v1.6.0 2009-3-27 157 | 158 | - (add)边界验证 159 | - (fix)修改类名后放大失效 160 | 161 | bg2css v1.5.1 2009-3-26 162 | 163 | - (add)图片放大培数可改 164 | 165 | bg2css v1.5.0 2009-3-25 166 | 167 | - (add)图片放大预览 168 | - (fix)空值无验证 169 | 170 | bg2css v1.4.1 2009-3-21 171 | 172 | - (add)支持快捷键 173 | - (add)在线更新 174 | - (fix)添加层时有 bug:双负数 175 | - (fix)窗口滚动影响微调 176 | - (fix)值为 0 时输出为"-0px" 177 | 178 | bg2css v1.3 2009-3-20 179 | 180 | - (add)输出样式时可选是否输出宽高 181 | - (fix)生成样式时最后一个类删除后生成有问题 182 | - (fix)样式路径自定义 183 | 184 | bg2css v1.2 2009-3-19 185 | 186 | - (add)双击添加层 187 | - (add)层位置和大小微调 188 | 189 | bg2css v1.0 2009-3-17 190 | 191 | - (add)添加、删除层 192 | - (add)拖动层、修改层大小 193 | - (add)显示层相关信息 194 | - (add)生成样式 195 | - (add)当前层样式 196 | 197 | bg2css v1.1 2009-3-18 198 | 199 | - (add)修改类名 200 | - (add)修改层位置、大小 201 | - (add)重置层 202 | - (add)保存成样式文件 203 | -------------------------------------------------------------------------------- /about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 关于 CSS Sprites 样式生成工具 7 | 14 | 15 | 20 | 21 | 22 | 23 |

CSS Sprites 样式生成工具

24 |

简介

25 |

程序名称:CSS Sprites 样式生成工具(bg2css)

26 |

主要功能:方便使用CSS Sprites时对图片生成样式

27 |

© 2009 by GhostZhang

28 |

官方地址:https://www.cssforest.org/2019/02/17/CSS-Sprites-样式生成工具.html 30 |

31 |

帮助文档:https://github.com/ghostzhang/bg2css/wiki/bg2css-help 33 |

34 |

版本信息

35 |

36 | bg2css v3.2.3 2020-12-22
37 | (fix)帮助文档地址迁移到 github
38 | (fix)版本更新改为手动
39 | (fix)样式问题
40 | (add)默认界面
41 | (add)更新快捷键说明文档 42 |

43 | 44 | 45 | -------------------------------------------------------------------------------- /application.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | com.adobe.example.bg2css 18 | 19 | 20 | bg2css 21 | 22 | 23 | CSS Sprites 样式生成工具 v3.2.3 24 | 25 | 26 | 3.2.3 27 | 28 | 29 | CSS Sprites 样式生成工具 30 | 31 | 32 | GhostZhang 33 | 34 | 35 | 36 | 37 | bg2css.html 38 | 39 | 40 | CSS Sprites 样式生成工具 v3.2.3 41 | 42 | 43 | standard 44 | 45 | 46 | false 47 | 48 | 49 | true 50 | 51 | 52 | true 53 | 54 | 55 | true 56 | 57 | 58 | true 59 | 60 | 61 | 800 62 | 63 | 64 | 600 65 | 66 | 67 | 200 68 | 69 | 70 | 50 71 | 72 | 73 | 785 500 74 | 75 | 76 | 1280 1024 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 87 | 88 | icons/AIRApp_16.png 89 | icons/AIRApp_32.png 90 | icons/AIRApp_48.png 91 | icons/AIRApp_128.png 92 | 93 | 94 | 97 | 98 | 99 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /bg2css.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CSS Sprites 样式生成工具 v3.2.3 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |
20 | 21 |
23 |
图片缩放: 24 | 25 | 26 | 27 | 28 | | 更换背景色: 29 | 30 | 31 | 32 | | 33 | 边界留白: 34 | 36 | px 37 | 38 |
39 |
40 | 41 | 42 | 114 | 115 | 116 | 143 | 144 | 145 | 151 | 152 |
45
153 | 154 | 155 | -------------------------------------------------------------------------------- /css/sample.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | body{overflow:hidden;padding:6px;font-family:Arial,Helvetica,Tahoma,sans-serif;font-size:14px } 4 | li{margin-bottom:14px } 5 | input{font-size:12px;margin-top:10px;font-weight:bold;} 6 | fieldset{clear:both;margin-top:10px;padding-top:10px;border-left-style:none;border-right-style:none;border-bottom-style:none;border-top:2px solid #9eb1aa;} 7 | .hint{color:#FF0000;text-indent:15px;} 8 | #div_image_view{position:relative;height:99.5%;padding:0;overflow:auto;border:1px solid #000000;background-color:#555555;font-size:0;line-height:0;} 9 | #image_view{height:474px;} 10 | .div-drag{width:100%;height:100%;cursor:move;} 11 | .div-resize{width:8px;height:8px;background-color:#BF7F26;position:absolute;bottom:0;right:0;cursor:se-resize;} 12 | .div-dnr,.div-dnr-now{position:absolute;background-color:#BF7F26;opacity:0.6;} 13 | .div-dnr-now{background-color:#3399FF;} 14 | .div-dnr:hover{background-color:#1D5790;} 15 | #input_bg_path{width:15em;} 16 | .nonce-div-info,.save-css,.pre-css,.op-div-info{position:absolute;z-index:20000;padding:10px;border:1px solid #15A4B1;background-color:#FFFFFF;} 17 | .nonce-div-info button{width:auto;height:auto;} 18 | .list-button-op{margin-top:10px;padding-top:10px;} 19 | .list-button-op button{float:left;width:4em;height:3em;margin-right:10px;} 20 | .save-css legend,.pre-css legend{padding:2px;background-color:#FFFFFF;border:1px solid #15A4B1;} 21 | .save-css{top:50%;left:50%;width:80%;min-height:220px;margin:-45% 0 0 -40%;} 22 | .pre-css{top:50%;left:50%;width:80%;height:73%;margin:-45% 0 0 -40%;} 23 | #div_view_css{width:591px;height:80%;overflow:auto;padding:10px 3%;word-break:normal;word-wrap:break-word;} 24 | #input_bg_path,#textarea_gb_class{width:100%;} 25 | #textarea_gb_class{border-color:#C0C0C0;} 26 | #input_div_margin{width:3em;} 27 | #input_div_width,#input_div_height,#input_div_left,#input_div_top{width:5em;} 28 | #input_copy_pyl{width:3em;} 29 | #button_copy_top{position:absolute;top:0;left:30px;} 30 | #button_copy_bottom{position:absolute;bottom:0;left:30px;} 31 | #button_copy_left{position:absolute;top:30px;left:0;} 32 | #button_copy_right{position:absolute;top:30px;left:60px;} 33 | #input_div_name{width:113px;} 34 | #hint_txt{display:none;position:absolute;z-index:99999;top:50%;left:50%;width:260px;min-height:2em;margin-left:-130px;margin-top:-20px;padding:4px;border:2px solid #04b338;background-color:#FFFFFF;} 35 | -------------------------------------------------------------------------------- /default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/default.png -------------------------------------------------------------------------------- /divlist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 层信息 8 | 36 | 37 | 38 | 39 | 42 | 43 | 44 | 47 | 50 | 53 | 56 | 59 | 62 | 65 | 68 | 69 | 70 | 71 | 72 |
40 | 层信息表 41 |
45 | 层名 46 | 48 | 宽度 49 | 51 | 高度 52 | 54 | 水平位置 55 | 57 | 垂直位置 58 | 60 | 输出宽 61 | 63 | 输出高 64 | 66 | 操作 67 |
73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | CSS Sprites 样式生成工具 快捷键 13 | 38 | 39 | 40 | 41 |

CSS Sprites 样式生成工具 快捷键

42 | 43 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 58 | 60 | 62 | 64 | 65 | 66 | 68 | 70 | 72 | 74 | 75 | 76 | 78 | 80 | 82 | 84 | 85 | 86 | 88 | 90 | 92 | 94 | 95 | 96 | 98 | 100 | 102 | 104 | 105 | 106 | 108 | 110 | 112 | 114 | 115 | 116 | 118 | 120 | 122 | 124 | 125 | 126 | 128 | 130 | 132 | 134 | 135 | 136 | 138 | 140 | 142 | 144 | 145 | 146 |
44 | 菜单快捷键列表 45 |
名称快捷键(win)快捷键(mac)说明
打开图片 57 | Ctrl + O 59 | command + O 61 | 打开要操作的图片。 63 |
更新图片 67 | F5 69 | 无 71 | 更新当前图片文件。 73 |
读取定义文件 77 | Ctrl + Shift + O 79 | command + Shift + O 81 | 打开之前保存的定义文件。 83 |
保存当前定义 87 | Ctrl + S 89 | command + S 91 | 保存当前的定义到文件。 93 |
当前层信息 97 | Ctrl + N 99 | command + N 101 | 显示|隐藏当前层的信息面板。 103 |
所有层信息 107 | Ctrl + Shift + N 109 | 无 111 | 打当前层的信息窗口。 113 |
显示区定义 117 | Ctrl + M 119 | 无 121 | 显示|隐藏显示区的定义面板。 123 |
生成样式 127 | Ctrl + P 129 | command + P 131 | 显示|隐藏生成样式的定义面板。 133 |
样式预览 137 | Ctrl + Shift + P 139 | command + Shift + P 141 | 显示|隐藏样式预览面板。 143 |
147 | 148 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 163 | 165 | 167 | 169 | 170 | 171 | 173 | 175 | 177 | 178 | 179 | 181 | 183 | 185 | 186 | 187 | 189 | 191 | 193 | 194 | 195 |
149 | 图片操作快捷键列表 150 |
名称快捷键(win)快捷键(mac)说明
图片缩放 162 | Ctrl + 0 164 | cntrol + command + 0 166 | 图片100%显示。 168 |
Ctrl + 2 172 | cntrol + command + 2 174 | 图片200%显示。 176 |
Ctrl + 4 180 | cntrol + command + 4 182 | 图片400%显示。 184 |
Ctrl + 6 188 | cntrol + command + 6 190 | 图片600%显示。 192 |
196 | 197 | 198 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 213 | 215 | 217 | 219 | 220 | 221 | 223 | 225 | 227 | 229 | 230 | 231 | 233 | 235 | 237 | 238 | 239 | 241 | 243 | 245 | 246 | 247 | 249 | 251 | 253 | 254 | 255 | 257 | 259 | 261 | 263 | 264 | 265 | 267 | 269 | 271 | 272 | 273 | 275 | 277 | 279 | 280 | 281 | 283 | 285 | 287 | 288 | 289 |
199 | 当前层操作快捷键列表 200 |
名称快捷键(win)快捷键(mac)说明
删除 212 | Delete 214 | fn + delete 216 | 删除当前层 218 |
移动当前层 222 | Ctrl + 向上方向键 224 | cntrol + command + 向上方向键 226 | 向上移动当前层的位置 228 |
Ctrl + 向下方向键 232 | cntrol + command + 向下方向键 234 | 向下移动当前层的位置 236 |
Ctrl + 向左方向键 240 | cntrol + command + 向左方向键 242 | 向左移动当前层的位置 244 |
Ctrl + 向右方向键 248 | cntrol + command + 向右方向键 250 | 向右移动当前层的位置 252 |
修改当前层 256 | Ctrl + Shift + 向上方向键 258 | cntrol + command + Shift + 向上方向键 260 | 减少当前层的高度 262 |
Ctrl + Shift + 向下方向键 266 | cntrol + command + Shift + 向下方向键 268 | 增加当前层的高度 270 |
Ctrl + Shift + 向左方向键 274 | cntrol + command + Shift + 向左方向键 276 | 减少当前层的宽度 278 |
Ctrl + Shift + 向右方向键 282 | cntrol + command + Shift + 向右方向键 284 | 增加当前层的宽度 286 |
290 | 291 |

帮助文档:https://github.com/ghostzhang/bg2css/wiki/bg2css-help 293 |

294 | 295 | 296 | -------------------------------------------------------------------------------- /help/001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/help/001.png -------------------------------------------------------------------------------- /help/003.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/help/003.gif -------------------------------------------------------------------------------- /help/004.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/help/004.gif -------------------------------------------------------------------------------- /help/005.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/help/005.gif -------------------------------------------------------------------------------- /help/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/help/02.png -------------------------------------------------------------------------------- /help/r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/help/r.png -------------------------------------------------------------------------------- /icons/AIRApp_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/icons/AIRApp_128.png -------------------------------------------------------------------------------- /icons/AIRApp_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/icons/AIRApp_16.png -------------------------------------------------------------------------------- /icons/AIRApp_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/icons/AIRApp_32.png -------------------------------------------------------------------------------- /icons/AIRApp_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/icons/AIRApp_48.png -------------------------------------------------------------------------------- /icons/b.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/icons/b.gif -------------------------------------------------------------------------------- /lib/air/AIRAliases.js: -------------------------------------------------------------------------------- 1 | /* AIRAliases.js - Revision: 1.5 */ 2 | 3 | /* 4 | ADOBE SYSTEMS INCORPORATED 5 | Copyright 2007-2008 Adobe Systems Incorporated. All Rights Reserved. 6 | 7 | NOTICE: Adobe permits you to modify and distribute this file only in accordance with 8 | the terms of Adobe AIR SDK license agreement. You may have received this file from a 9 | source other than Adobe. Nonetheless, you may modify or 10 | distribute this file only in accordance with such agreement. 11 | */ 12 | 13 | 14 | var air; 15 | if (window.runtime) 16 | { 17 | if (!air) air = {}; 18 | // functions 19 | air.trace = window.runtime.trace; 20 | air.navigateToURL = window.runtime.flash.net.navigateToURL; 21 | air.sendToURL = window.runtime.flash.net.sendToURL; 22 | 23 | 24 | // file 25 | air.File = window.runtime.flash.filesystem.File; 26 | air.FileStream = window.runtime.flash.filesystem.FileStream; 27 | air.FileMode = window.runtime.flash.filesystem.FileMode; 28 | 29 | // events 30 | air.ActivityEvent = window.runtime.flash.events.ActivityEvent; 31 | air.AsyncErrorEvent = window.runtime.flash.events.AsyncErrorEvent; 32 | air.BrowserInvokeEvent = window.runtime.flash.events.BrowserInvokeEvent; 33 | air.DataEvent = window.runtime.flash.events.DataEvent; 34 | air.DRMAuthenticateEvent = window.runtime.flash.events.DRMAuthenticateEvent; 35 | air.DRMStatusEvent = window.runtime.flash.events.DRMStatusEvent; 36 | air.ErrorEvent = window.runtime.flash.events.ErrorEvent; 37 | air.Event = window.runtime.flash.events.Event; 38 | air.EventDispatcher = window.runtime.flash.events.EventDispatcher; 39 | air.FileListEvent = window.runtime.flash.events.FileListEvent; 40 | air.HTTPStatusEvent = window.runtime.flash.events.HTTPStatusEvent; 41 | air.IOErrorEvent = window.runtime.flash.events.IOErrorEvent; 42 | air.InvokeEvent = window.runtime.flash.events.InvokeEvent; 43 | air.NetStatusEvent = window.runtime.flash.events.NetStatusEvent; 44 | air.OutputProgressEvent = window.runtime.flash.events.OutputProgressEvent; 45 | air.ProgressEvent = window.runtime.flash.events.ProgressEvent; 46 | air.SecurityErrorEvent = window.runtime.flash.events.SecurityErrorEvent; 47 | air.StatusEvent = window.runtime.flash.events.StatusEvent; 48 | air.TimerEvent = window.runtime.flash.events.TimerEvent; 49 | air.SampleDataEvent = window.runtime.flash.events.SampleDataEvent; 50 | 51 | // native window 52 | air.NativeWindow = window.runtime.flash.display.NativeWindow; 53 | air.NativeWindowDisplayState = window.runtime.flash.display.NativeWindowDisplayState; 54 | air.NativeWindowInitOptions = window.runtime.flash.display.NativeWindowInitOptions; 55 | air.NativeWindowSystemChrome = window.runtime.flash.display.NativeWindowSystemChrome; 56 | air.NativeWindowResize = window.runtime.flash.display.NativeWindowResize; 57 | air.NativeWindowType = window.runtime.flash.display.NativeWindowType; 58 | 59 | air.NativeWindowBoundsEvent = window.runtime.flash.events.NativeWindowBoundsEvent; 60 | air.NativeWindowDisplayStateEvent = window.runtime.flash.events.NativeWindowDisplayStateEvent; 61 | 62 | // geom 63 | air.Point = window.runtime.flash.geom.Point; 64 | air.Rectangle = window.runtime.flash.geom.Rectangle; 65 | air.Matrix = window.runtime.flash.geom.Matrix; 66 | 67 | // 3D 68 | air.Matrix3D = window.runtime.flash.geom.Matrix3D; 69 | air.Vector3D = window.runtime.flash.geom.Vector3D; 70 | air.Orientation3D = window.runtime.flash.geom.Orientation3D; 71 | air.Utils3D = window.runtime.flash.geom.Utils3D; 72 | 73 | // Shader 74 | air.Shader = window.runtime.flash.display.Shader; 75 | air.ShaderFilter = window.runtime.flash.filters.ShaderFilter; 76 | air.ShaderPrecision = window.runtime.flash.display.ShaderPrecision; 77 | 78 | // net 79 | air.FileFilter = window.runtime.flash.net.FileFilter; 80 | 81 | air.LocalConnection = window.runtime.flash.net.LocalConnection; 82 | air.NetConnection = window.runtime.flash.net.NetConnection; 83 | 84 | air.URLLoader = window.runtime.flash.net.URLLoader; 85 | air.URLLoaderDataFormat = window.runtime.flash.net.URLLoaderDataFormat; 86 | air.URLRequest = window.runtime.flash.net.URLRequest; 87 | air.URLRequestDefaults = window.runtime.flash.net.URLRequestDefaults; 88 | air.URLRequestHeader = window.runtime.flash.net.URLRequestHeader; 89 | air.URLRequestMethod = window.runtime.flash.net.URLRequestMethod; 90 | air.URLStream = window.runtime.flash.net.URLStream; 91 | air.URLVariables = window.runtime.flash.net.URLVariables; 92 | air.Socket = window.runtime.flash.net.Socket; 93 | air.XMLSocket = window.runtime.flash.net.XMLSocket; 94 | 95 | air.Responder = window.runtime.flash.net.Responder; 96 | air.ObjectEncoding = window.runtime.flash.net.ObjectEncoding; 97 | 98 | air.NetStream = window.runtime.flash.net.NetStream; 99 | air.NetStreamInfo = window.runtime.flash.net.NetStreamInfo; 100 | air.NetStreamPlayOptions = window.runtime.flash.net.NetStreamPlayOptions; 101 | air.NetStreamPlayTransitions = window.runtime.flash.net.NetStreamPlayTransitions; 102 | air.SharedObject = window.runtime.flash.net.SharedObject; 103 | air.SharedObjectFlushStatus = window.runtime.flash.net.SharedObjectFlushStatus; 104 | 105 | // system 106 | air.Capabilities = window.runtime.flash.system.Capabilities; 107 | air.System = window.runtime.flash.system.System; 108 | air.Security = window.runtime.flash.system.Security; 109 | air.Updater = window.runtime.flash.desktop.Updater; 110 | 111 | // desktop 112 | air.Clipboard = window.runtime.flash.desktop.Clipboard; 113 | air.ClipboardFormats = window.runtime.flash.desktop.ClipboardFormats; 114 | air.ClipboardTransferMode = window.runtime.flash.desktop.ClipboardTransferMode; 115 | 116 | air.NativeDragManager = window.runtime.flash.desktop.NativeDragManager; 117 | air.NativeDragOptions = window.runtime.flash.desktop.NativeDragOptions; 118 | air.NativeDragActions = window.runtime.flash.desktop.NativeDragActions; 119 | 120 | air.Icon = window.runtime.flash.desktop.Icon; 121 | air.DockIcon = window.runtime.flash.desktop.DockIcon; 122 | air.InteractiveIcon = window.runtime.flash.desktop.InteractiveIcon; 123 | air.NotificationType = window.runtime.flash.desktop.NotificationType; 124 | air.SystemTrayIcon = window.runtime.flash.desktop.SystemTrayIcon; 125 | 126 | air.NativeApplication = window.runtime.flash.desktop.NativeApplication; 127 | 128 | // display 129 | air.NativeMenu = window.runtime.flash.display.NativeMenu; 130 | air.NativeMenuItem = window.runtime.flash.display.NativeMenuItem; 131 | air.Screen = window.runtime.flash.display.Screen; 132 | 133 | air.Loader = window.runtime.flash.display.Loader; 134 | air.Bitmap = window.runtime.flash.display.Bitmap; 135 | air.BitmapData = window.runtime.flash.display.BitmapData; 136 | 137 | // ui 138 | air.Keyboard = window.runtime.flash.ui.Keyboard; 139 | air.KeyLocation = window.runtime.flash.ui.KeyLocation; 140 | air.Mouse = window.runtime.flash.ui.Mouse; 141 | 142 | 143 | //security 144 | air.ReferencesValidationSetting = window.runtime.flash.security.ReferencesValidationSetting; 145 | air.RevocationCheckSettings = window.runtime.flash.security.RevocationCheckSettings; 146 | air.SignatureStatus = window.runtime.flash.security.SignatureStatus; 147 | air.SignerTrustSettings = window.runtime.flash.security.SignerTrustSettings; 148 | air.XMLSignatureValidator = window.runtime.flash.security.XMLSignatureValidator; 149 | 150 | 151 | // utils 152 | air.ByteArray = window.runtime.flash.utils.ByteArray; 153 | air.CompressionAlgorithm = window.runtime.flash.utils.CompressionAlgorithm; 154 | air.Endian = window.runtime.flash.utils.Endian; 155 | air.Timer = window.runtime.flash.utils.Timer; 156 | 157 | air.HTMLLoader = window.runtime.flash.html.HTMLLoader; 158 | air.HTMLPDFCapability = window.runtime.flash.html.HTMLPDFCapability; 159 | 160 | // media 161 | air.ID3Info = window.runtime.flash.media.ID3Info; 162 | air.Sound = window.runtime.flash.media.Sound; 163 | air.SoundChannel = window.runtime.flash.media.SoundChannel; 164 | air.SoundLoaderContext = window.runtime.flash.media.SoundLoaderContext; 165 | air.SoundMixer = window.runtime.flash.media.SoundMixer; 166 | air.SoundTransform = window.runtime.flash.media.SoundTransform; 167 | air.Microphone = window.runtime.flash.media.Microphone; 168 | air.Video = window.runtime.flash.media.Video; 169 | air.Camera = window.runtime.flash.media.Camera; 170 | air.SoundCodec = window.runtime.flash.media.SoundCodec; 171 | 172 | // data 173 | air.EncryptedLocalStore = window.runtime.flash.data.EncryptedLocalStore; 174 | air.SQLCollationType = window.runtime.flash.data.SQLCollationType; 175 | air.SQLColumnNameStyle = window.runtime.flash.data.SQLColumnNameStyle; 176 | air.SQLColumnSchema = window.runtime.flash.data.SQLColumnSchema; 177 | air.SQLConnection = window.runtime.flash.data.SQLConnection; 178 | air.SQLError = window.runtime.flash.errors.SQLError; 179 | air.SQLErrorEvent = window.runtime.flash.events.SQLErrorEvent; 180 | air.SQLErrorOperation = window.runtime.flash.errors.SQLErrorOperation; 181 | air.SQLEvent = window.runtime.flash.events.SQLEvent; 182 | air.SQLIndexSchema = window.runtime.flash.data.SQLIndexSchema; 183 | air.SQLMode = window.runtime.flash.data.SQLMode; 184 | air.SQLResult = window.runtime.flash.data.SQLResult; 185 | air.SQLSchema = window.runtime.flash.data.SQLSchema; 186 | air.SQLSchemaResult = window.runtime.flash.data.SQLSchemaResult; 187 | air.SQLStatement = window.runtime.flash.data.SQLStatement; 188 | air.SQLTableSchema = window.runtime.flash.data.SQLTableSchema; 189 | air.SQLTransactionLockType = window.runtime.flash.data.SQLTransactionLockType; 190 | air.SQLTriggerSchema = window.runtime.flash.data.SQLTriggerSchema; 191 | air.SQLUpdateEvent = window.runtime.flash.events.SQLUpdateEvent; 192 | air.SQLViewSchema = window.runtime.flash.data.SQLViewSchema; 193 | 194 | // service monitoring framework 195 | air.__defineGetter__("ServiceMonitor", function() { return window.runtime.air.net.ServiceMonitor; }) 196 | air.__defineGetter__("SocketMonitor", function() { return window.runtime.air.net.SocketMonitor; }) 197 | air.__defineGetter__("URLMonitor", function() { return window.runtime.air.net.URLMonitor; }) 198 | 199 | // update framework 200 | air.__defineGetter__("ApplicationUpdater", function() { return window.runtime.air.update.ApplicationUpdater; }); 201 | air.__defineGetter__("ApplicationUpdaterUI", function() { return window.runtime.air.update.ApplicationUpdaterUI; }); 202 | air.__defineGetter__("UpdateEvent", function() { return window.runtime.air.update.events.UpdateEvent; }); 203 | air.__defineGetter__("StatusUpdateEvent", function() { return window.runtime.air.update.events.StatusUpdateEvent; }); 204 | air.__defineGetter__("StatusUpdateErrorEvent", function() { return window.runtime.air.update.events.StatusUpdateErrorEvent; }); 205 | air.__defineGetter__("DownloadErrorEvent", function() { return window.runtime.air.update.events.DownloadErrorEvent; }); 206 | air.__defineGetter__("StatusFileUpdateEvent", function() { return window.runtime.air.update.events.StatusFileUpdateEvent; }); 207 | air.__defineGetter__("StatusFileUpdateErrorEvent", function() { return window.runtime.air.update.events.StatusFileUpdateErrorEvent; }); 208 | } -------------------------------------------------------------------------------- /lib/air/applicationupdater_ui.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/lib/air/applicationupdater_ui.swf -------------------------------------------------------------------------------- /lib/air/library.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostzhang/bg2css/c465e9d86aac9cd36891128a9c70342c287631e6/lib/air/library.swf -------------------------------------------------------------------------------- /lib/js/AIRLocalizer.js: -------------------------------------------------------------------------------- 1 | /* AIRLocalizer.js - Revision: 1.5 */ 2 | 3 | /* 4 | ADOBE SYSTEMS INCORPORATED 5 | Copyright 2007-2008 Adobe Systems Incorporated. All Rights Reserved. 6 | 7 | NOTICE: Adobe permits you to modify and distribute this file only in accordance with 8 | the terms of Adobe AIR SDK license agreement. You may have received this file from a 9 | source other than Adobe. Nonetheless, you may modify or 10 | distribute this file only in accordance with such agreement. 11 | */ 12 | 13 | 14 | // Using the function method to obfuscate inner globals to the main script, so that the 15 | // "window" remains untouched. 16 | (function(){ 17 | /** 18 | * This is automatically replaced while building 19 | * @version "1.5" 20 | * @private 21 | */ 22 | var version = "1.5"; 23 | 24 | 25 | /** 26 | * Just to make sure we have the right shortcuts included 27 | * @namespace window.air 28 | * @private 29 | */ 30 | var air = { 31 | File : window.runtime.flash.filesystem.File, 32 | FileStream : window.runtime.flash.filesystem.FileStream, 33 | FileMode : window.runtime.flash.filesystem.FileMode, 34 | Capabilities : window.runtime.flash.system.Capabilities 35 | }; 36 | 37 | /** 38 | * Utility functions 39 | * @namespace util 40 | * @private 41 | */ 42 | var util = { 43 | /** 44 | * Returns the content of a file 45 | * @param file air.File File that should be read 46 | * @return string 47 | */ 48 | stringFromFile : function stringFromFile(file){ 49 | var fileStream = new air.FileStream(); 50 | fileStream.open(file, air.FileMode.READ); 51 | var result = fileStream.readUTFBytes(file.size); 52 | fileStream.close(); 53 | return result; 54 | } 55 | }; 56 | 57 | /** 58 | * Used for sorting the locales array 59 | * @private 60 | */ 61 | 62 | function LocaleId(){ 63 | this.lang = ''; 64 | this.script = ''; 65 | this.region = ''; 66 | this.extended_langs = []; 67 | this.variants = []; 68 | this.extensions = {}; 69 | this.privates = []; 70 | this.privateLangs = false; 71 | }; 72 | 73 | 74 | LocaleId.prototype = { 75 | transformToParent: function(){ 76 | if(this.privates.length>0){ 77 | this.privates.splice(this.privates.length-1, 1); 78 | return true; 79 | } 80 | 81 | var lastExtensionName = null; 82 | for(var i in this.extensions){ 83 | if(this.extensions.hasOwnProperty(i)){ 84 | lastExtensionName = i; 85 | } 86 | } 87 | if(lastExtensionName){ 88 | var lastExtension = this.extensions[lastExtensionName]; 89 | if(lastExtension.length==1){ 90 | delete this.extensions[ lastExtensionName ]; 91 | return true; 92 | } 93 | lastExtension.splice(lastExtension.length-1, 1); 94 | return true; 95 | } 96 | 97 | if(this.variants.length>0){ 98 | this.variants.splice(this.variants.length-1, 1); 99 | return true; 100 | } 101 | 102 | if(this.script!=''){ 103 | //check if we can surpress the script 104 | if(LocaleId.getScriptByLang(this.lang)!=''){ 105 | this.script=''; 106 | return true; 107 | }else if(this.region==''){ 108 | //maybe the default region can surpress the script 109 | var region = LocaleId.getDefaultRegionForLangAndScript(this.lang, this.script); 110 | if(region!=''){ 111 | this.region = region; 112 | this.script = ''; 113 | return true; 114 | } 115 | } 116 | } 117 | 118 | if(this.region!=''){ 119 | if(!(this.script=='' && LocaleId.getScriptByLang(this.lang) == '')){ 120 | this.region=''; 121 | return true; 122 | } 123 | } 124 | 125 | 126 | if(this.extended_langs.length>0){ 127 | this.extended_langs.splice(this.extended_langs.length-1, 1); 128 | return true; 129 | } 130 | 131 | return false; 132 | }, 133 | 134 | isSiblingOf: function(other){ 135 | if(this.lang==other.lang&&this.script==other.script){ 136 | return true; 137 | } 138 | return false; 139 | }, 140 | 141 | equals: function(locale){ 142 | return this.toString() == locale.toString(); 143 | }, 144 | toString: function(){ 145 | var stack = [ this.lang ]; 146 | Array.prototype.push.apply(stack, this.extended_langs); 147 | if(this.script!='') stack.push(this.script); 148 | if(this.region!='') stack.push(this.region); 149 | Array.prototype.push.apply(stack, this.variants); 150 | for(var i in this.extensions){ 151 | if(this.extensions.hasOwnProperty(i)){ 152 | stack.push(i); 153 | Array.prototype.push.apply(stack, this.extensions[i]); 154 | } 155 | } 156 | if(this.privates.length>0){ 157 | stack.push('x'); 158 | Array.prototype.push.apply(stack, this.privates); 159 | } 160 | return stack.join('_'); 161 | }, 162 | canonicalize: function(){ 163 | for(var i in this.extensions){ 164 | if(this.extensions.hasOwnProperty(i)){ 165 | //also clear zero length extensions 166 | if(this.extensions[i].length==0) delete this.extensions[i]; 167 | else this.extensions[i] = this.extensions[i].sort(); 168 | } 169 | } 170 | this.extended_langs = this.extended_langs.sort(); 171 | this.variants = this.variants.sort(); 172 | this.privates = this.privates.sort(); 173 | if(this.script == ''){ 174 | this.script = LocaleId.getScriptByLang(this.lang); 175 | } 176 | //still no script, check the region 177 | if(this.script == '' && this.region!=''){ 178 | this.script = LocaleId.getScriptByLangAndRegion(this.lang, this.region); 179 | } 180 | 181 | if(this.region=='' && this.script!=''){ 182 | this.region = LocaleId.getDefaultRegionForLangAndScript(this.lang, this.script); 183 | } 184 | } 185 | } 186 | 187 | LocaleId.registry = { 188 | "scripts": ["cyrl", "latn", "ethi", "arab", "beng", "cyrl", "thaa", "tibt", "grek", "gujr", "hebr", "deva", "armn", "jpan", "geor", "khmr", "knda", "kore", "laoo", "mlym", "mymr", "orya", "guru", "sinh", "taml", "telu", "thai", "nkoo", "blis", "hans", "hant", "mong", "syrc"], 189 | "scriptById": {"cyrl": 5, "latn": 1, "ethi": 2, "arab": 3, "beng": 4, "thaa": 6, "tibt": 7, "grek": 8, "gujr": 9, "hebr": 10, "deva": 11, "armn": 12, "jpan": 13, "geor": 14, "khmr": 15, "knda": 16, "kore": 17, "laoo": 18, "mlym": 19, "mymr": 20, "orya": 21, "guru": 22, "sinh": 23, "taml": 24, "telu": 25, "thai": 26, "nkoo": 27, "blis": 28, "hans": 29, "hant": 30, "mong": 31, "syrc": 32} , 190 | "defaultRegionByLangAndScript": {"bg": {5: "bg"}, "ca": {1: "es"}, "zh": {30: "tw", 29: "cn"}, "cs": {1: "cz"}, "da": {1: "dk"}, "de": {1: "de"}, "el": {8: "gr"}, "en": {1: "us"}, "es": {1: "es"}, "fi": {1: "fi"}, "fr": {1: "fr"}, "he": {10: "il"}, "hu": {1: "hu"}, "is": {1: "is"}, "it": {1: "it"}, "ja": {13: "jp"}, "ko": {17: "kr"}, "nl": {1: "nl"}, "nb": {1: "no"}, "pl": {1: "pl"}, "pt": {1: "br"}, "ro": {1: "ro"}, "ru": {5: "ru"}, "hr": {1: "hr"}, "sk": {1: "sk"}, "sq": {1: "al"}, "sv": {1: "se"}, "th": {26: "th"}, "tr": {1: "tr"}, "ur": {3: "pk"}, "id": {1: "id"}, "uk": {5: "ua"}, "be": {5: "by"}, "sl": {1: "si"}, "et": {1: "ee"}, "lv": {1: "lv"}, "lt": {1: "lt"}, "fa": {3: "ir"}, "vi": {1: "vn"}, "hy": {12: "am"}, "az": {1: "az", 5: "az"}, "eu": {1: "es"}, "mk": {5: "mk"}, "af": {1: "za"}, "ka": {14: "ge"}, "fo": {1: "fo"}, "hi": {11: "in"}, "ms": {1: "my"}, "kk": {5: "kz"}, "ky": {5: "kg"}, "sw": {1: "ke"}, "uz": {1: "uz", 5: "uz"}, "tt": {5: "ru"}, "pa": {22: "in"}, "gu": {9: "in"}, "ta": {24: "in"}, "te": {25: "in"}, "kn": {16: "in"}, "mr": {11: "in"}, "sa": {11: "in"}, "mn": {5: "mn"}, "gl": {1: "es"}, "kok": {11: "in"}, "syr": {32: "sy"}, "dv": {6: "mv"}, "nn": {1: "no"}, "sr": {1: "cs", 5: "cs"}, "cy": {1: "gb"}, "mi": {1: "nz"}, "mt": {1: "mt"}, "quz": {1: "bo"}, "tn": {1: "za"}, "xh": {1: "za"}, "zu": {1: "za"}, "nso": {1: "za"}, "se": {1: "no"}, "smj": {1: "no"}, "sma": {1: "no"}, "sms": {1: "fi"}, "smn": {1: "fi"}, "bs": {1: "ba"}}, 191 | "scriptIdByLang": {"ab": 0, "af": 1, "am": 2, "ar": 3, "as": 4, "ay": 1, "be": 5, "bg": 5, "bn": 4, "bs": 1, "ca": 1, "ch": 1, "cs": 1, "cy": 1, "da": 1, "de": 1, "dv": 6, "dz": 7, "el": 8, "en": 1, "eo": 1, "es": 1, "et": 1, "eu": 1, "fa": 3, "fi": 1, "fj": 1, "fo": 1, "fr": 1, "frr": 1, "fy": 1, "ga": 1, "gl": 1, "gn": 1, "gu": 9, "gv": 1, "he": 10, "hi": 11, "hr": 1, "ht": 1, "hu": 1, "hy": 12, "id": 1, "in": 1, "is": 1, "it": 1, "iw": 10, "ja": 13, "ka": 14, "kk": 5, "kl": 1, "km": 15, "kn": 16, "ko": 17, "la": 1, "lb": 1, "ln": 1, "lo": 18, "lt": 1, "lv": 1, "mg": 1, "mh": 1, "mk": 5, "ml": 19, "mo": 1, "mr": 11, "ms": 1, "mt": 1, "my": 20, "na": 1, "nb": 1, "nd": 1, "ne": 11, "nl": 1, "nn": 1, "no": 1, "nr": 1, "ny": 1, "om": 1, "or": 21, "pa": 22, "pl": 1, "ps": 3, "pt": 1, "qu": 1, "rn": 1, "ro": 1, "ru": 5, "rw": 1, "sg": 1, "si": 23, "sk": 1, "sl": 1, "sm": 1, "so": 1, "sq": 1, "ss": 1, "st": 1, "sv": 1, "sw": 1, "ta": 24, "te": 25, "th": 26, "ti": 2, "tl": 1, "tn": 1, "to": 1, "tr": 1, "ts": 1, "uk": 5, "ur": 3, "ve": 1, "vi": 1, "wo": 1, "xh": 1, "yi": 10, "zu": 1, "cpe": 1, "dsb": 1, "frs": 1, "gsw": 1, "hsb": 1, "kok": 11, "mai": 11, "men": 1, "nds": 1, "niu": 1, "nqo": 27, "nso": 1, "son": 1, "tem": 1, "tkl": 1, "tmh": 1, "tpi": 1, "tvl": 1, "zbl": 28}, 192 | "scriptIdByLangAndRegion": {"zh": {"cn": 29, "sg": 29, "tw": 30, "hk": 30, "mo": 30}, "mn": {"cn": 31, "sg": 5}, "pa": {"pk": 3, "in": 22}, "ha": {"gh": 1, "ne": 1}}}; 193 | 194 | 195 | LocaleId.getScriptByLangAndRegion = function(lang, region){ 196 | var langRegions = LocaleId.registry.scriptIdByLangAndRegion[ lang ]; 197 | if(typeof langRegions=='undefined') return ''; 198 | var scriptId = langRegions[region]; 199 | if(typeof scriptId!='undefined'){ 200 | return LocaleId.registry.scripts[scriptId].toLowerCase(); 201 | } 202 | return ''; 203 | } 204 | 205 | LocaleId.getScriptByLang = function(lang){ 206 | var scriptId = LocaleId.registry.scriptIdByLang[ lang ]; 207 | if(typeof scriptId!='undefined'){ 208 | return LocaleId.registry.scripts[scriptId].toLowerCase(); 209 | } 210 | return ''; 211 | } 212 | 213 | LocaleId.getDefaultRegionForLangAndScript = function(lang, script){ 214 | var lang = LocaleId.registry.defaultRegionByLangAndScript[ lang ]; 215 | var scriptId = LocaleId.registry.scriptById[ script ]; 216 | if(typeof lang!='undefined' && typeof scriptId !='undefined' ){ 217 | return lang[scriptId] || ""; 218 | } 219 | return ''; 220 | } 221 | 222 | 223 | LocaleId.fromString = function(str){ 224 | //states 225 | { 226 | var PrimaryLanguage = 0, 227 | ExtendedLanguages = 1, 228 | Script = 2, 229 | Region = 3, 230 | Variants = 5, 231 | Extensions = 6, 232 | Privates = 7; 233 | } 234 | var localeId = new LocaleId(); 235 | 236 | var state = PrimaryLanguage; 237 | var subtags = str.replace(/-/g, '_').split('_'); 238 | 239 | var last_extension; 240 | 241 | for(var i=0, l=subtags.length; i='a' && firstChar<='z' && subtag_length>=5 ) 278 | || 279 | ( firstChar>='0' && firstChar<='9' && subtag_length>=4 ) 280 | ) 281 | ){ 282 | //variant 283 | localeId.variants.push(subtag); 284 | state = Variants; 285 | }else if ( state < Privates && subtag_length==1 ){ //singleton 286 | if(subtag == 'x'){ 287 | state = Privates; 288 | last_extension = localeId.privates; 289 | } else { 290 | state = Extensions; 291 | last_extension = localeId.extensions[subtag] || []; 292 | localeId.extensions[subtag] = last_extension; 293 | } 294 | }else if(state >= Extensions){ 295 | last_extension.push(subtag); 296 | } 297 | } 298 | } 299 | localeId.canonicalize(); 300 | return localeId; 301 | } 302 | 303 | var LocaleSorter = { 304 | /** 305 | * Promote only that locales from preferenceLocales that have parents in locales 306 | * @private 307 | * @param locales String[] List of locales to be sorted. 308 | * @param preferenceLocales String[] List of locales in the preference order 309 | * @param addAll Adds all the locales at the end, even though no locale is in the preferences list. Default is true 310 | * @return String[] 311 | */ 312 | sortLocalesUsingPreferences: function(_locales, _preferenceLocales, ultimateFallbackLocale, addAll){ 313 | var result = []; 314 | var haveLocale = {}; 315 | 316 | function prepare(list){ 317 | var resultList = []; 318 | for(var i=0,l=list.length;i=0;i--){ 527 | var attr = node.attributes[i]; 528 | if(attr.name.toLowerCase()==attributeInnerPrefix){ 529 | setInner = true; 530 | innerValue = attr.value; 531 | }else if(this.isLocalAttribute(attr)){ 532 | params.push([this.getLocalAttribute(attr), attr.value]); 533 | } 534 | } 535 | if(setInner){ 536 | var value = this.getHtmlString(innerValue); 537 | try{ 538 | node.innerHTML = value||innerValue; 539 | }catch(e){ 540 | node.textContent = value||innerValue; 541 | } 542 | } 543 | for(var i=params.length-1;i>=0;i--){ 544 | var param = params[i]; 545 | var value = this.getHtmlString(param[1]); 546 | node.setAttribute(param[0], value||param[1]); 547 | } 548 | }, 549 | 550 | /** 551 | * Replaces each node under 'node' 552 | * @param node DOMElement 553 | * @public 554 | */ 555 | run: function (node){ 556 | this.attributePrefix = this.parent.attributePrefix.toLowerCase(); 557 | this.attributePrefixLength = this.attributePrefix.length; 558 | var treeWalker = document.createTreeWalker( 559 | node||document, 560 | NodeFilter.SHOW_ELEMENT, 561 | { acceptNode: function(node) { return NodeFilter.FILTER_ACCEPT; } }, 562 | false 563 | ); 564 | while(treeWalker.nextNode()) this.walkNode(treeWalker.currentNode); 565 | }, 566 | 567 | /** 568 | * Separates the bundleName and resourceName and returns the string from locale chain 569 | * @param resourceName String Default bundle is "default" 570 | * @return String 571 | */ 572 | getHtmlString: function(resourceName){ 573 | var bundleName; 574 | var i = resourceName.indexOf('.'); 575 | if(i!=-1){ bundleName = resourceName.substr(0, i); resourceName=resourceName.substr(i+1); } 576 | else bundleName = "default" 577 | return this.parent.getStringFromChain(bundleName, resourceName); 578 | } 579 | }; 580 | 581 | 582 | 583 | /** 584 | * Creates a new object used in Localizer to store loaded bundles, locale chain and bundles path 585 | * @private 586 | * @constructor 587 | * @v 588 | */ 589 | function LocalizerPrivate(parent){ 590 | this.parent = parent; 591 | 592 | // dom walker needed to update nodes 593 | this.domWalker = new DOMWalker(this); 594 | 595 | 596 | // Locale chain is the internal order that the framework uses to search for locales 597 | this.localeChain = []; 598 | 599 | // When the developer sets the locale chain we should disable the automatic detection 600 | this.autoLocaleChain = true; 601 | 602 | // Loaded locales should be sorted for later use 603 | this.localeCache = {}; 604 | 605 | // Default bundle path used to solve the locales directories 606 | this.bundlePath = new air.File('app:/locale/'); 607 | 608 | // Store the system capabilities for later use 609 | this.userPreference = air.Capabilities.languages || [air.Capabilities.language]; 610 | 611 | // Event listeners 612 | this.eventListeners = {}; 613 | 614 | this.attributePrefix = 'local_'; 615 | 616 | } 617 | LocalizerPrivate.prototype = { 618 | 619 | /** 620 | * Creates a new locale object that caches bundles and files 621 | * registers the locale for later use 622 | * @private 623 | * @param locale The localeName to be created 624 | * @return LocaleHash 625 | */ 626 | createLocaleCache: function(locale){ 627 | var obj = { 628 | name : locale, 629 | bundles: {}, 630 | files: {} 631 | }; 632 | this.localeCache[locale] = obj; 633 | return obj; 634 | }, 635 | 636 | /** 637 | * Returns the locale cache object. In case it is not already loaded it is created. 638 | * @private 639 | * @param locale String The localeName to be returned 640 | * @return LocaleHash 641 | */ 642 | getLocaleCache: function(locale){ 643 | return this.localeCache[locale] || this.createLocaleCache(locale); 644 | }, 645 | 646 | 647 | /** 648 | * Removes all the cached locales that are not in the locale chain 649 | * @private 650 | */ 651 | cleanupCache: function (){ 652 | var isInChain = {}; 653 | for(var i in this.localeChain) isInChain[ this.localeChain[i] ] = true; 654 | 655 | for(var locale in this.localeCache ) { 656 | if( ! isInChain[locale] ){ 657 | this.localeCache [ locale ] = null; 658 | delete this.localeCache [locale]; 659 | } 660 | } 661 | }, 662 | 663 | /** 664 | * Removes all the cached locales 665 | * @private 666 | */ 667 | clearCache: function (){ 668 | for(var locale in this.localeCache ) { 669 | this.localeCache [ locale ] = null; 670 | delete this.localeCache [locale]; 671 | } 672 | }, 673 | /** 674 | * Creates the bundle object. Also caches it for later use 675 | * @private 676 | * @param locale String The locale name where it should search the bundle 677 | * @param bundlename String The bundle name for the returned bundle 678 | * @return ResourceBundle 679 | */ 680 | createBundle: function(locale, bundleName){ 681 | var localeCache = this.getLocaleCache(locale); 682 | var file = this.bundlePath.resolvePath(locale).resolvePath(bundleName+".properties"); 683 | var resourceBundle = new ResourceBundle(file); 684 | localeCache.bundles[bundleName] = resourceBundle; 685 | if(!resourceBundle.found){ 686 | setTimeout(function(obj){ 687 | obj.dispatchEvent(new LocalizerEvent(Localizer.BUNDLE_NOT_FOUND, { 688 | bundleName: bundleName, 689 | locale: locale 690 | })); 691 | }, 0, this); 692 | } 693 | return resourceBundle; 694 | }, 695 | 696 | /** 697 | * Loads a bundle and returns it. 698 | * @private 699 | * @param locale String The locale name where it should search the bundle 700 | * @param bundleName String The bundle name to be loaded 701 | * @param useCache Bool Setting this to false will force the function to reread the bundle. Default is true 702 | * @return ResourceBundle 703 | */ 704 | loadBundle: function(locale, bundleName, useCache){ 705 | var localeCache = this.getLocaleCache(locale); 706 | useCache=(typeof useCache=='undefined')?true:useCache; 707 | return (useCache&&localeCache.bundles[bundleName]) || this.createBundle(locale, bundleName); 708 | }, 709 | 710 | /** 711 | * Loads a bundle and returns its keys and values as an object. 712 | * @private 713 | * @param locale String The locale name where it should search the bundle 714 | * @param bundleName String The bundle name to be loaded 715 | * @return Object Returns null if the bundle is not found. 716 | */ 717 | getResourceBundle: function(locale, bundleName){ 718 | var bundle = this.loadBundle(locale, bundleName); 719 | if(bundle==null) 720 | return null; 721 | //make a copy of the bundle 722 | var result = {}; 723 | for (var key in bundle.keys){ 724 | result [ key ] = bundle.keys [key]; 725 | } 726 | return result; 727 | }, 728 | 729 | /** 730 | * Creates a new ResourceFile based on the fileName 731 | * @private 732 | * @param locale String The locale name where it should search the file 733 | * @param fileName String Filename that should be loaded 734 | * @return ResourceFile 735 | */ 736 | createFile: function(locale, fileName){ 737 | var localeCache = this.getLocaleCache(locale); 738 | var file = this.bundlePath.resolvePath(locale).resolvePath(fileName); 739 | var resourceFile = new ResourceFile(file); 740 | localeCache.files[fileName] = resourceFile; 741 | if(!resourceFile.found){ 742 | setTimeout(function(obj){ 743 | obj.dispatchEvent(new LocalizerEvent(Localizer.FILE_NOT_FOUND, { 744 | fileName: fileName, 745 | locale: locale 746 | })); 747 | }, 0, this); 748 | } 749 | return resourceFile; 750 | }, 751 | 752 | /** 753 | * Loads a file and returns it. 754 | * @private 755 | * @param locale String The locale name where it should search the file 756 | * @param bundleName String The file name to be loaded 757 | * @param useCache Bool Setting this to false will force the function to reread the file. Default is true 758 | * @return ResourceFile 759 | */ 760 | loadFile: function(locale, fileName, useCache){ 761 | var localeCache = this.getLocaleCache(locale); 762 | useCache=(typeof useCache=='undefined')?true:useCache; 763 | return (useCache&&localeCache.files[fileName]) || this.createFile(locale, fileName); 764 | }, 765 | 766 | /** 767 | * Automatically discovers the available locales using the listing directory of the bundle path, 768 | * returns an array of locales 769 | * @private 770 | * @return StringArray 771 | */ 772 | discoverAndReturnAvailableLocales: function (){ 773 | var folder = this.bundlePath; 774 | // check if the file exists and is a directory 775 | if(!(folder.exists&&folder.isDirectory)){ 776 | // just die sillently, because a higher level should take care of that 777 | return []; 778 | } 779 | 780 | var localeChain = [] 781 | var localeFolders = folder.getDirectoryListing(); 782 | for(var i=0, l=localeFolders.length; i0 ){ 871 | var oldChain = this.localeChain; 872 | this.localeChain = this.cloneChain(chain); 873 | 874 | // switch off auto locale chain detection 875 | this.autoLocaleChain = false; 876 | 877 | // send some events 878 | this.diffChainsAndFireEvent(this.localeChain, oldChain); 879 | } 880 | }, 881 | 882 | /** 883 | * Returns the current locale chain 884 | * @return String[] 885 | */ 886 | getLocaleChain: function(){ 887 | return this.cloneChain(this.localeChain); 888 | }, 889 | 890 | /** 891 | * Returns the source string, but replaces the "{i}" string with args[i] 892 | * @param source String 893 | * @param args String[] 894 | * @return String 895 | */ 896 | template: function(source, args){ 897 | var parser = /{([^}]*)}/g; 898 | var a = source.split(parser); 899 | var result = []; 900 | var d=0; 901 | for(var i=0,l=a.length;i=0;i--){ 935 | var evh = handlers[i]; 936 | if(evh.eventName==eventName&&evh.handler==handler){ 937 | handlers.splice(i, 1); 938 | } 939 | } 940 | }, 941 | 942 | dispatchEvent: function(ev){ 943 | var handlers = this.eventListeners[ev.name]; 944 | if(!handlers) return; 945 | for(var i=handlers.length-1;i>=0;i--){ 946 | handlers[i].handler.call(this.parent, ev); 947 | } 948 | }, 949 | 950 | 951 | /** 952 | * Loads the bundle and returns the resource value 953 | * @public 954 | * @param bundleName String 955 | * @param resourceName String 956 | * @param locale String 957 | * @return String 958 | */ 959 | getString: function(bundleName, resourceName, locale){ 960 | var bundle = this.loadBundle(locale, bundleName); 961 | var result = bundle.get(resourceName); 962 | if(result==null){ 963 | setTimeout(function(obj){ 964 | obj.dispatchEvent(new LocalizerEvent(Localizer.RESOURCE_NOT_FOUND, { 965 | bundleName: bundleName, 966 | resourceName: resourceName, 967 | locale: locale 968 | })); 969 | }, 0, this); 970 | } 971 | return result; 972 | }, 973 | 974 | /** 975 | * loads the file and returns the contents 976 | * @public 977 | * @param fileName String 978 | * @param locale String 979 | * @return String 980 | */ 981 | getFile: function(fileName, locale){ 982 | var file = this.loadFile(locale, fileName); 983 | return file.getContent(); 984 | }, 985 | 986 | /** 987 | * Uses the locale chain to get the first defined value 988 | * @public 989 | * @param bundleName String 990 | * @param resourcename String 991 | * @return String 992 | */ 993 | getStringFromChain: function(bundleName, resourceName){ 994 | var result; 995 | var chain = this.localeChain; 996 | if(chain){ 997 | for(var i=0, l=chain.length; i 1103 | // becomes 1104 | // Click here to login 1105 | 1106 | update: function update(/* DOMElement, optional */ parentNode /* = document */){ 1107 | this._private.update(parentNode); 1108 | }, 1109 | 1110 | // * If “locale” argument is provided it is used to return the value of the localization resource 1111 | // called “resourceName” located in the bundle called “bundleName” only for the locale “locale”. 1112 | // Otherwise, the locale chain returned by “getLocaleChain” is used to lookup the first locale 1113 | // that that provides the “resourceName”. For example if the locale chain is [fr_CA, fr] and a 1114 | // particular resource is not found in “fr_CA”, the framework will also search that resource in the “fr”. 1115 | // 1116 | // * It will automatically load the bundles if needed. 1117 | // 1118 | // * Returns null if the resource is not found and fires one of the following events: 1119 | // * RESOURCE_NOT_FOUND when the bundle does not contain the specified “resourceName”; 1120 | // * BUNDLE_NOT_FOUND when the bundle file is not found. 1121 | // 1122 | // * If “templateArgs” is provided the function will use it to replace bracketed numbers in the resource 1123 | // with the correspondent values from the “templateArgs” array (only where applicable, meaning 1124 | // that if templateArgs[n] is not defined, “{n}” will not be changed): 1125 | // * “{0}”, “{1}”, .... “{n}” will be replaced with templateArgs[0], templateArgs[1] ... templateArgs[n]. 1126 | // * in order to skip replacement for one number, just set that “templateArgs” item to undefined or null; 1127 | 1128 | getString: function getString(/* String */ bundleName, /*String */ resourceName, /* optional String[] */ templateArgs, /* optional, String */ locale ) /*: String*/{ 1129 | var result = null; 1130 | if(locale){ 1131 | result = this._private.getString(bundleName, resourceName, locale); 1132 | }else{ 1133 | result = this._private.getStringFromChain(bundleName, resourceName); 1134 | } 1135 | if(templateArgs&&result!=null){ 1136 | result = this._private.template(result, templateArgs); 1137 | } 1138 | return result; 1139 | }, 1140 | 1141 | // 1142 | // * Returns the keys found in a bundle 1143 | // 1144 | // @param locale String The locale name where it should search the bundle 1145 | // @param bundleName String The bundle name to be loaded 1146 | // 1147 | // * Returns null if the bundle is not found. 1148 | // 1149 | getResourceBundle: function(locale, bundleName){ 1150 | return this._private.getResourceBundle(locale, bundleName); 1151 | }, 1152 | 1153 | // * If “locale” argument is provided, it returns the contents of the file 1154 | // “{bundlesDirectory}/{locale}/{resourceFileName}”. Otherwise, the locale 1155 | // chain returned by “getLocaleChain” is used to lookup the first locale that 1156 | // that provides the “resourceFileName” file. For example if the locale chain is 1157 | // [fr_FR, fr] the file will be searched using that order: first will search 1158 | // “{bundlesDirectory}/fr_FR/{resourceFileName}” and only if it is not found the 1159 | // framework will continue to search for “{bundlesDirectory}/fr/{resourceFileName}”. 1160 | // 1161 | // * {bundlesPath} is the current bundle path set using “setBundlesDirectory”; 1162 | // 1163 | // * Returns null if the resource file is not found and fires: 1164 | // * FILE_NOT_FOUND event; 1165 | // 1166 | // * If “templateArgs” is provided the function will use it to replace bracketed numbers in the 1167 | // resource file with the correspondent values from the “templateArgs” array (only where applicable, 1168 | // meaning that if templateArgs[n] is not defined, “{n}” will not be changed): 1169 | // * “{0}”, “{1}”, .... “{n}” will be replaced with templateArgs[0], templateArgs[1] ... templateArgs[n]. 1170 | // * in order to skip replacement for one number, just set that “templateArgs” item to undefined; 1171 | 1172 | getFile: function getFile(/* String */ resourceFileName, /* optional String[] */ templateArgs, /* String */ locale ) /*: String*/ { 1173 | var result = null; 1174 | if(locale){ 1175 | result = this._private.getFile(resourceFileName, locale); 1176 | }else{ 1177 | result = this._private.getFileFromChain(resourceFileName); 1178 | } 1179 | if(templateArgs&&result!=null){ 1180 | result = this._private.template(result, templateArgs); 1181 | } 1182 | return result; 1183 | }, 1184 | 1185 | // * Sets the locale chain and updates the current locale used by all other functions. 1186 | // 1187 | // * Note: When “chain” argument is missing, is not an array or has zero length the function fails 1188 | // and throws “air.Localizer.IllegalArgumentsError” exception 1189 | // 1190 | // * Fires LOCALE_CHANGE event, the developer should update the DOM using update function. This event 1191 | // is fired synchronous whenever the locale chain has changed. 1192 | setLocaleChain: function setLocaleChain(/* optional, String[] */ chain){ 1193 | if(!(chain&&chain.hasOwnProperty&&chain.hasOwnProperty('length')&&chain.length>0)){ 1194 | throw new Localizer.IllegalArgumentsError("Locale chain should be an array."); 1195 | } 1196 | this._private.setLocaleChain(chain); 1197 | }, 1198 | 1199 | // * Returns the locale chain set by the previous call to “setLocaleChain”. 1200 | // 1201 | // * NOTE: If “setLocaleChain” hasn’t been called the function returns the automatically 1202 | // detected locale chain computed when the Localizer is instantiated (see also the property called “localizer”); 1203 | 1204 | getLocaleChain: function getLocaleChain()/* :String[] */ { 1205 | return this._private.getLocaleChain(); 1206 | }, 1207 | 1208 | // * Sets the prefix for local attributes used in the “update” function. 1209 | // 1210 | // * Default prefix is “local_”. 1211 | 1212 | setLocalAttributePrefix: function setLocalAttributePrefix(value){ 1213 | this._private.attributePrefix = value+''; 1214 | }, 1215 | 1216 | // typical add/remove Event Dispatcher 1217 | 1218 | addEventListener: function addEventListener(/* String */ eventName, /* callback function */ callback){ 1219 | this._private.addEventListener(eventName, callback); 1220 | }, 1221 | removeEventListener: function removeEventListener(/* String */ eventName, /* callback function */ callback){ 1222 | this._private.removeEventListener(eventName, callback); 1223 | } 1224 | 1225 | }; 1226 | 1227 | 1228 | // Define the getter function. This will temporararly set canCreateLocalizer to true 1229 | // and create a new Localizer. It writes the newly created localizer to the localizerInstance variable; 1230 | 1231 | var localizerInstance = null; 1232 | Localizer.__defineGetter__("localizer", function(){ 1233 | if(!localizerInstance){ 1234 | canCreateLocalizer = true; 1235 | localizerInstance = new Localizer(); 1236 | canCreateLocalizer = false; 1237 | } 1238 | return localizerInstance; 1239 | }); 1240 | 1241 | 1242 | // EVENTS 1243 | 1244 | // Fired by “setLocaleChain” when the current locale is changed (synchronous) 1245 | // Event object strcuture is : { localeChain /* : String [] */ } 1246 | Localizer.LOCALE_CHANGE = "change"; 1247 | 1248 | // Fired by “getString” and “update” functions when a resource is not found in the specified bundle (fired asynchronous) 1249 | // Event object structure is : { resourceName /* : String */, bundleName /* : String */ } 1250 | Localizer.RESOURCE_NOT_FOUND = "resourceNotFound"; 1251 | 1252 | // Fired by “getFile” when a resource file is not found (fired asynchronous) 1253 | // Event object structure is : { resourceFileName /* : String */ } 1254 | Localizer.FILE_NOT_FOUND = "fileNotFound"; 1255 | 1256 | // Fired by “getString” and “update” functions when a bundle file is not found (fired asynchronous) 1257 | // Event object structure is : { bundleName /* : String */ } 1258 | Localizer.BUNDLE_NOT_FOUND = "bundleNotFound"; 1259 | 1260 | // Version number 1261 | Localizer.version = version; 1262 | 1263 | (function(){ 1264 | 1265 | // ERROR 1266 | function BundlePathNotFoundError(path){ 1267 | this.name = 'air.Localizer.BundlePathNotFoundError'; 1268 | this.message = "Bundle directory not found "+path; 1269 | } 1270 | BundlePathNotFoundError.prototype = new Error; 1271 | Localizer.BundlePathNotFoundError = BundlePathNotFoundError; 1272 | 1273 | 1274 | function IllegalArgumentsError(msg){ 1275 | this.name = 'air.Localizer.IllegalArgumentsError'; 1276 | this.message = msg; 1277 | } 1278 | IllegalArgumentsError.prototype = new Error; 1279 | Localizer.IllegalArgumentsError = IllegalArgumentsError; 1280 | 1281 | }()); 1282 | 1283 | Localizer.LocaleId = LocaleId; 1284 | 1285 | Localizer.ultimateFallbackLocale = 'en'; 1286 | 1287 | 1288 | // * This function is for internal use only. 1289 | // 1290 | // * Sort a languages array using the order given by the system capabilities languages array. 1291 | // 1292 | // * Setting removeUnsupported to true removes system unsupported languages. When removeUnsupported is false it makes the system unsupported languages be the last ones preserving order from original array. 1293 | // 1294 | // * Default value for removeUnsupported is true. 1295 | // 1296 | // *NOTE: It uses the same approach that the ADOBE AIR application Installer uses: 1297 | // * it tries to find the perfect match for locale name; 1298 | // * otherwise it fallbacks to finding locales with same parents (eg. “en_US” will fallback to “en” ) 1299 | // * user preference will be promoted; 1300 | // 1301 | // * (system supported means they are in the Capabilities.languages array from the runtime) 1302 | // 1303 | // * eg: If Capabilities.languages = [ “fr_CA”, “en_UK”, “ja” ] and the “languages” argument 1304 | // is [ “en”, “fr_FR”, “zn_ZN” ] the returning array will be [ “fr_FR”, “en” ] 1305 | // 1306 | // * eg2: When the “languages” argument is [ fr, fr_CA, fr_FR, ro, en, en_US ]: 1307 | // * and the Capabilities.languages = [ fr_CA ] the result will be [ fr_CA, fr, fr_FR ] 1308 | // * and the Capabilities.languages = [ fr_CA, en ] the result will be [ fr_CA, fr, fr_FR, en, en_US ] 1309 | 1310 | Localizer.sortLanguagesByPreference = function sortLanguagesByPreference( /* String[] */ appLocales, /* String[] */ systemPreferences, /* String, optional */ ultimateFallbackLocale /* = null*/, /*Boolean, optional */ keepAllLocales /* = true */) /* : String[] */{ 1311 | if(!( appLocales && appLocales.hasOwnProperty('length') && systemPreferences&&systemPreferences.hasOwnProperty('length') )){ 1312 | throw new Localizer.IllegalArgumentsError("Expected at least two arguments: appLocales and systemPreferences."); 1313 | } 1314 | return LocaleSorter.sortLocalesUsingPreferences( appLocales, systemPreferences, ultimateFallbackLocale, keepAllLocales) 1315 | }; 1316 | 1317 | 1318 | 1319 | if(!window.air){ 1320 | window.air = {}; 1321 | } 1322 | 1323 | window.air.Localizer = Localizer; 1324 | 1325 | }()); -------------------------------------------------------------------------------- /lib/js/AIRMenuBuilder.js: -------------------------------------------------------------------------------- 1 | /* AIRMenuBuilder.js - Revision: 1.5 */ 2 | 3 | /* 4 | ADOBE SYSTEMS INCORPORATED 5 | Copyright 2007-2008 Adobe Systems Incorporated. All Rights Reserved. 6 | 7 | NOTICE: Adobe permits you to modify and distribute this file only in accordance with 8 | the terms of Adobe AIR SDK license agreement. You may have received this file from a 9 | source other than Adobe. Nonetheless, you may modify or 10 | distribute this file only in accordance with such agreement. 11 | */ 12 | 13 | (function AIRMenuBuilder () { 14 | 15 | function constructor ( ) { 16 | window ['air'] = window ['air'] || {}; 17 | window.air['ui'] = window.air['ui'] || {}; 18 | window.air.ui['Menu'] = new Menu(); 19 | registry = new FieldsRegistry(); 20 | currentOS = runtime.flash.system.Capabilities.os; 21 | } 22 | 23 | var currentOS = null; 24 | var registry = null; 25 | 26 | var File = runtime.flash.filesystem.File; 27 | var FileStream = runtime.flash.filesystem.FileStream; 28 | var FileMode = runtime.flash.filesystem.FileMode; 29 | var NativeMenu = runtime.flash.display.NativeMenu; 30 | var NativeMenuItem = runtime.flash.display.NativeMenuItem; 31 | var SELECT = runtime.flash.events.Event.SELECT; 32 | var KEYBOARD = runtime.flash.ui.Keyboard; 33 | var COMPLETE = runtime.flash.events.Event.COMPLETE; 34 | var IO_ERROR = runtime.flash.events.IOErrorEvent.IO_ERROR; 35 | var NativeApplication = runtime.flash.desktop.NativeApplication; 36 | var NativeWindow = runtime.flash.display.NativeWindow; 37 | var Loader = runtime.flash.display.Loader; 38 | var URLRequest = runtime.flash.net.URLRequest; 39 | var BitmapData = runtime.flash.display.BitmapData; 40 | 41 | /** 42 | * CLASS FieldsRegistry 43 | * @class 44 | * @private 45 | */ 46 | function FieldsRegistry () { 47 | 48 | this.proof = function (name, value) { 49 | if (!validateName(name)) { return null }; 50 | switch (name) { 51 | case FieldsRegistry.ENABLED: 52 | case FieldsRegistry.ALT_KEY: 53 | case FieldsRegistry.SHIFT_KEY: 54 | case FieldsRegistry.CMD_KEY: 55 | case FieldsRegistry.CTRL_KEY: 56 | case FieldsRegistry.TOGGLED: 57 | case FieldsRegistry.DEFAULT_KEY: 58 | return (typeof value == 'boolean')? 59 | value: (typeof value == 'string')? 60 | (value.toLowerCase() == 'false')? false : 61 | true : getDefault (name); 62 | case FieldsRegistry.KEY_EQUIVALENT: 63 | var d; 64 | return (typeof value == 'string')? 65 | (value.length == 1)? value : 66 | getDefault (name) : getDefault (name); 67 | case FieldsRegistry.LABEL: 68 | return (typeof value == 'string')? 69 | (value.length != 0)? value: 70 | getDefault (name) : getDefault (name); 71 | case FieldsRegistry.MNEMONIC_INDEX: 72 | var n; 73 | return (typeof value == 'number')? 74 | value: (typeof value == 'string')? 75 | (!isNaN ( n = parseInt(value) ))? n : 76 | getDefault (name) : getDefault (name); 77 | case FieldsRegistry.TYPE: 78 | return (typeof value == 'string') ? 79 | (validateType(value))? value : 80 | getDefault (name) : getDefault (name); 81 | case FieldsRegistry.ON_SELECT: 82 | var f; 83 | return (typeof value == 'function')? 84 | value : (typeof value == 'string')? 85 | (typeof (f = window[value]) == 'function')? 86 | f : getDefault (name) : getDefault (name); 87 | } 88 | } 89 | 90 | this.iterateFields = function (callback, scope) { 91 | var f, n, fr = FieldsRegistry; 92 | for (f in fr) { 93 | n = fr [f] !== fr.prototype? fr [f] : null; 94 | if (n && !validateType(n)) { 95 | callback.call ( scope || window, n ) 96 | }; 97 | } 98 | } 99 | 100 | var validateType = function (type) { 101 | return type == FieldsRegistry.REGULAR || 102 | type == FieldsRegistry.SEPARATOR || 103 | type == FieldsRegistry.CHECK; 104 | } 105 | 106 | var validateName = function (fieldName) { 107 | for (var f in FieldsRegistry) { 108 | if (FieldsRegistry[f] == fieldName) { return true }; 109 | } 110 | return false; 111 | } 112 | 113 | 114 | var getDefault = function (fieldName) { 115 | switch (fieldName) { 116 | case FieldsRegistry.ALT_KEY: 117 | case FieldsRegistry.SHIFT_KEY: 118 | case FieldsRegistry.TOGGLED: 119 | return false; 120 | case FieldsRegistry.ENABLED: 121 | case FieldsRegistry.DEFAULT_KEY: 122 | return true; 123 | case FieldsRegistry.KEY_EQUIVALENT: 124 | case FieldsRegistry.ON_SELECT: 125 | return null; 126 | case FieldsRegistry.LABEL: 127 | return ' '; 128 | case FieldsRegistry.MNEMONIC_INDEX: 129 | return -1; 130 | case FieldsRegistry.TYPE: 131 | return FieldsRegistry.REGULAR; 132 | case FieldsRegistry.CMD_KEY: 133 | case FieldsRegistry.CTRL_KEY: 134 | default: 135 | return null; 136 | } 137 | } 138 | 139 | } 140 | FieldsRegistry.ALT_KEY = 'altKey'; 141 | FieldsRegistry.CMD_KEY = 'cmdKey'; 142 | FieldsRegistry.CTRL_KEY = 'ctrlKey'; 143 | FieldsRegistry.ENABLED = 'enabled'; 144 | FieldsRegistry.KEY_EQUIVALENT = 'keyEquivalent'; 145 | FieldsRegistry.LABEL = 'label'; 146 | FieldsRegistry.MNEMONIC_INDEX = 'mnemonicIndex'; 147 | FieldsRegistry.SHIFT_KEY = 'shiftKey'; 148 | FieldsRegistry.TOGGLED = 'toggled'; 149 | FieldsRegistry.TYPE = 'type'; 150 | FieldsRegistry.ON_SELECT = 'onSelect'; 151 | FieldsRegistry.DEFAULT_KEY = 'defaultKeyEquivalentModifiers'; 152 | FieldsRegistry.SEPARATOR = 'separator'; 153 | FieldsRegistry.CHECK = 'check'; 154 | FieldsRegistry.REGULAR = 'regular'; 155 | 156 | /** 157 | * CLASS Menu 158 | * Description 159 | * Loads a user menu defined as XML or JSON, and sets it as one of the 160 | * supported menu types. 161 | * @class 162 | * @author ciacob 163 | */ 164 | function Menu() { 165 | 166 | var buildMenu = function (source, type) { 167 | var b = new Builder(); 168 | b.loadData (source, type); 169 | return b.build(); 170 | } 171 | 172 | var attachMenu = function (menu, type, target, icons) { 173 | var s = new Shell(); 174 | s.link(menu, type, target, icons); 175 | } 176 | 177 | /** 178 | * Load a menu defined in XML format. 179 | * @param source 180 | * An object containing XML menu(s) to be loaded for various OS-es. 181 | * @return 182 | * A NativeMenu object built from the given XML source. 183 | */ 184 | this.createFromXML = function ( source ) { 185 | return buildMenu ( source, Builder.XML ); 186 | } 187 | 188 | /** 189 | * Same as air.ui.Menu.fromXML, except it handles JSON data. 190 | */ 191 | this.createFromJSON = function ( source ) { 192 | return buildMenu ( source, Builder.JSON ); 193 | } 194 | 195 | /** 196 | * - on Windows: sets the given nativeMenu object as the NativeWindow's 197 | * menu; 198 | * - on Mac: inserts the items of the given nativeMenu object between 199 | * the 'Edit' and 'Window' default menus; 200 | * @param nativeMenu 201 | * A NativeMenu returned by one of the air.ui.Menu.from... 202 | * functions. 203 | * @param overwrite 204 | * A boolean that will change the behavior on Mac. If true, the 205 | * default menus will be replaced entirely by the given nativeMenu 206 | */ 207 | this.setAsMenu = function ( nativeMenu, overwrite ) { 208 | if (!arguments.length) { 209 | throw (new Error( 210 | "No argument given for the 'setAsMenu()' method." 211 | )); 212 | } 213 | var style = overwrite? Shell.MENU | Shell.OVERWRITE : Shell.MENU; 214 | attachMenu (nativeMenu, style); 215 | } 216 | 217 | /** 218 | * Displays the given menu as a contextual menu when the user right 219 | * clicks a certain DOM element. 220 | * @param nativeMenu 221 | * A NativeMenu returned by one of the air.ui.Menu.from... 222 | * functions. 223 | * @param domElement 224 | * The DOM Element to link with the given nativeMenu. The 225 | * contextual menu will only show when the user right clicks over 226 | * domElement. This attribute is optional. If missing, the context 227 | * menu will display on every right-click over the application. 228 | */ 229 | this.setAsContextMenu = function ( nativeMenu, domElement ) { 230 | if (!arguments.length) { 231 | throw (new Error( 232 | "No argument given for the 'setAsContextMenu()' method." 233 | )); 234 | } 235 | if (arguments.length < 2) { domElement = Shell.UNSPECIFIED }; 236 | attachMenu (nativeMenu, Shell.CONTEXT, domElement); 237 | } 238 | 239 | /** 240 | * Sets the given nativeMenu as the 241 | * ''NativeApplication.nativeApplication.icon.menu'' property. 242 | * @param nativeMenu 243 | * A NativeMenu returned by one of the air.ui.Menu.from... 244 | * functions. 245 | * @param icons 246 | * An array holding icon file paths or bitmap data objects. 247 | * If specified, these will be used as the application's 248 | * tray/dock icons. 249 | * @throws 250 | * If no bitmap data was set for the ''icon'' object and no default 251 | * icons are specified in the application descriptor. 252 | */ 253 | this.setAsIconMenu = function ( nativeMenu, icons ) { 254 | if (!arguments.length) { 255 | throw (new Error( 256 | "No argument given for the 'setAsIconMenu()' method." 257 | )); 258 | } 259 | attachMenu (nativeMenu, Shell.ICON, null, icons); 260 | } 261 | 262 | } 263 | 264 | /** 265 | * CLASS DataSource 266 | * @public 267 | * @abstract 268 | */ 269 | function DataSource() { 270 | var _this = this; 271 | 272 | var legalExtensions = ['xml', 'js']; 273 | 274 | var rSeed = null; 275 | 276 | var DATA_OBJECT = 1; 277 | var INLINE_STRING = 2; 278 | var FILE_PATH = 3; 279 | var FILE_OBJECT = 4; 280 | var ILLEGAL_TYPE = 5; 281 | 282 | function getFileContent (file) { 283 | var ret = ''; 284 | var fileStream = new FileStream(); 285 | fileStream.open(file, FileMode.READ); 286 | try { 287 | ret = fileStream.readUTFBytes(file.size); 288 | } catch(e) { 289 | throw( 290 | new Error(["Error\n", "ID: ", e.errorID, "\n", "Message: ", 291 | e.message, "\n"].join('')) 292 | ); 293 | } 294 | fileStream.close(); 295 | return ret; 296 | } 297 | 298 | function checkExtension (url, whiteList) { 299 | var match = url.match(/\.([^\.]*)$/); 300 | var extension = match? match[1] : null; 301 | for(var i=0; i 0); 467 | if (isError) { 468 | var errText = doc.getElementsByTagName(err)[0].innerText; 469 | var msg = errText.split(':'); 470 | msg.length -= 1; 471 | msg = msg.join(':\n'); 472 | throw (new Error ([ 473 | 'Could not parse data: malformed XML file.', msg 474 | ].join('\n'))); 475 | } 476 | that.document = doc; 477 | } 478 | } 479 | 480 | that.getRoot = function() { 481 | return that.document.documentElement; 482 | } 483 | 484 | that.getChildren = function (node) { 485 | var ret = []; 486 | if(node) { 487 | if(node.hasChildNodes && node.hasChildNodes()){ 488 | var children = node.childNodes; 489 | for(var i=0; i 0) { 693 | var prev = iterable[i-1]; 694 | prev['nextSibling'] = child; 695 | } 696 | } 697 | } 698 | } 699 | return ret; 700 | } 701 | 702 | that.getNextSibling = function (node) { 703 | if (node) { 704 | if(node !== that.getRoot()) { 705 | if (node['nextSibling']) { return node['nextSibling'] }; 706 | } 707 | } 708 | return null; 709 | } 710 | 711 | that.getParent = function (node) { 712 | if (node) { 713 | if(node !== that.getRoot()) { 714 | if (node['parent']) { return node['parent'] }; 715 | } 716 | } 717 | return null; 718 | } 719 | 720 | that.hasChildren = function (node) { 721 | if (node) { 722 | var iterable = (node === that.getRoot())? node: 723 | (node ['items'])? node ['items']: null; 724 | if (iterable) { 725 | return iterable.length && iterable.length > 0; 726 | } 727 | return false; 728 | } 729 | return false; 730 | } 731 | 732 | that.addChildAt = function (node, newChild, index) { 733 | if (node && newChild) { 734 | var children = that.getChildren (node) || (function() { 735 | node['items'] = []; 736 | return node['items']; 737 | })(); 738 | index = Math.min(Math.max(0, index), children.length); 739 | children.splice (index, 0, newChild); 740 | if (index > 0) { 741 | children [index-1]['nextSibling'] = children [index] 742 | }; 743 | if (index < children.length-1) { 744 | children[index]['nextSibling'] = children [index]+1 745 | }; 746 | node['items'] = children; 747 | } 748 | } 749 | 750 | that.removeChildAt = function (node, index) { 751 | if (node) { 752 | var children = that.getChildren (node) || (function() { 753 | node['items'] = []; 754 | return node['items']; 755 | })(); 756 | index = Math.min(Math.max(0, index), children.length); 757 | var removed = children [index]; 758 | children.splice (index, 1); 759 | if(index > 0 && index < children.length) { 760 | children [index-1]['nextSibling'] = children [index]; 761 | } 762 | node['items'] = children; 763 | return removed; 764 | } 765 | return null; 766 | } 767 | 768 | that.createNode = function (properties) { 769 | var node = {}; 770 | for (var p in properties) { 771 | that.setProperty (node, p, properties[p]) 772 | }; 773 | if (that.getProperty (node, 'id') == null) { 774 | that.setProperty (node, 'id', that.generateUID()); 775 | } 776 | return node; 777 | } 778 | 779 | that.getProperty = function (node, propName) { 780 | if (node) { return registry.proof(propName, node[propName]) }; 781 | return null; 782 | } 783 | 784 | that.setProperty = function (node, propName, propValue) { 785 | if (node) { 786 | node[propName] = registry.proof(propName, propValue); 787 | } 788 | } 789 | 790 | this.$JSONDataSource.apply (this, arguments); 791 | } 792 | 793 | /** 794 | * CLASS Builder 795 | * @private 796 | * @class 797 | */ 798 | function Builder() { 799 | 800 | var ds, root = null; 801 | 802 | function createDataSource (source, type) { 803 | var ret = null; 804 | if (type == Builder.XML) { ret = new XMLDataSource ( source ) }; 805 | if (type == Builder.JSON) { ret = new JSONDataSource( source )}; 806 | return ret; 807 | } 808 | 809 | function buildMenu() { 810 | var w = new Walker(ds, buildItem); 811 | w.walk (); 812 | } 813 | 814 | function buildItem (item) { 815 | 816 | // Get & parse info about the item to be built: 817 | var summary = ds.getSummary (item); 818 | var isFirstLevel = (!ds.getParent(item)); 819 | var isItemDisabled = (!summary[FieldsRegistry.ENABLED]); 820 | var hasChildren = ds.hasChildren(item); 821 | var isItemSeparator = (summary [FieldsRegistry.TYPE] == 822 | FieldsRegistry.SEPARATOR); 823 | var isItemAToggle = (summary [FieldsRegistry.TYPE] == 824 | FieldsRegistry.CHECK); 825 | 826 | // Build the NativeMenuItem to represent this item: 827 | var ret = parseLabelForMnemonic (summary [FieldsRegistry.LABEL]); 828 | var nmi = new NativeMenuItem ( ret[0], isItemSeparator ); 829 | 830 | 831 | // Attach features for this item: 832 | var parsedMnemonicIndex = ret[1]; 833 | if (parsedMnemonicIndex >= 0) { 834 | summary [FieldsRegistry.MNEMONIC_INDEX] = parsedMnemonicIndex; 835 | }; 836 | var mnemonicIndex = summary [FieldsRegistry.MNEMONIC_INDEX]; 837 | if (mnemonicIndex != -1) { nmi.mnemonicIndex = mnemonicIndex }; 838 | if (isItemAToggle) { 839 | var toggler = function (event) { 840 | var val = !ds.getProperty (item, 841 | FieldsRegistry.TOGGLED); 842 | ds.setProperty (item, FieldsRegistry.TOGGLED, val); 843 | nmi.checked = val; 844 | } 845 | nmi.addEventListener (SELECT, toggler); 846 | nmi.checked = summary [FieldsRegistry.TOGGLED]; 847 | } 848 | if (summary [FieldsRegistry.ON_SELECT]) { 849 | var f = function (event) { 850 | var target = event.target; 851 | summary [FieldsRegistry.ON_SELECT].call ( 852 | window, event, summary 853 | ); 854 | } 855 | nmi.addEventListener (SELECT, f); 856 | } 857 | attachKeyEquivalentHandler (nmi, summary); 858 | if ( isItemDisabled ) { nmi.enabled = false }; 859 | 860 | // Attach our item within the menu structure: 861 | item['_widget_'] = nmi; 862 | if (hasChildren) { nmi.submenu = new NativeMenu() }; 863 | var data = nmi.data || (nmi.data = {}); 864 | data['item'] = item; 865 | var parMnu = null; 866 | var parItem = ds.getParent(item); 867 | if (parItem) { 868 | var parWidget = parItem['_widget_']; 869 | parMnu = parWidget.submenu; 870 | if (!parMnu) { return }; 871 | } else { 872 | parMnu = root || ( root = new NativeMenu() ); 873 | } 874 | parMnu.addItem(nmi); 875 | } 876 | 877 | function qReplace (tStr, searchStr , replaceStr) { 878 | var index; 879 | while ((index = tStr.indexOf (searchStr)) >= 0) { 880 | var arr = tStr.split(''); 881 | arr.splice (index, searchStr.length, 882 | replaceStr); 883 | tStr = arr.join(''); 884 | } 885 | return tStr; 886 | } 887 | 888 | function parseLabelForMnemonic (label) { 889 | var l = label; 890 | if (l) { 891 | l = qReplace(l, '__', '[UNDERSCORE]'); 892 | l = qReplace(l, '_', '[MNEMONIC]'); 893 | l = qReplace(l, '[UNDERSCORE]', '_'); 894 | var mi = l.indexOf ('[MNEMONIC]'); 895 | l = qReplace(l, '[MNEMONIC]', ''); 896 | if (mi >= 0) { return [l, mi] }; 897 | } 898 | return [l, -1]; 899 | } 900 | 901 | function attachKeyEquivalentHandler (nativeItem, summary) { 902 | if (summary[FieldsRegistry.DEFAULT_KEY]) { 903 | // Linux implementation needs this check: 904 | var def = nativeItem.keyEquivalentModifiers && 905 | nativeItem.keyEquivalentModifiers[0]? 906 | nativeItem.keyEquivalentModifiers[0] : null; 907 | if (def && typeof def != "undefined") { 908 | if (summary[FieldsRegistry.CTRL_KEY] === false) { 909 | if (def == KEYBOARD.CONTROL) { def = null }; 910 | } 911 | if (summary[FieldsRegistry.CMD_KEY] === false) { 912 | if (def == KEYBOARD.COMMAND) { def = null }; 913 | } 914 | } 915 | } 916 | var key; 917 | if (key = summary[FieldsRegistry.KEY_EQUIVALENT]) { 918 | var mods = []; 919 | if (def) { mods.push(def) }; 920 | if (summary[FieldsRegistry.CTRL_KEY]) { 921 | mods.push (KEYBOARD.CONTROL); 922 | } 923 | if (summary[FieldsRegistry.CMD_KEY]) { 924 | mods.push (KEYBOARD.COMMAND); 925 | } 926 | if (summary[FieldsRegistry.ALT_KEY]) { 927 | mods.push (KEYBOARD.ALTERNATE); 928 | } 929 | key = (summary[FieldsRegistry.SHIFT_KEY])? 930 | key.toUpperCase() : key.toLowerCase(); 931 | nativeItem.keyEquivalent = key; 932 | nativeItem.keyEquivalentModifiers = mods; 933 | } 934 | } 935 | 936 | this.loadData = function (source, type) { 937 | if (source) { ds = createDataSource (source, type) } 938 | else { throw new Error([ 939 | "Cannot create menu. ", 940 | "Provided data source is null" 941 | ].join('')) } 942 | } 943 | 944 | this.build = function() { 945 | if(ds) {buildMenu()}; 946 | return root; 947 | } 948 | } 949 | Builder.XML = 0x10; 950 | Builder.JSON = 0x20; 951 | 952 | /** 953 | * CLASS NIConnector 954 | * @private 955 | * @class 956 | */ 957 | function NIConnector () { 958 | 959 | var that = this; 960 | 961 | var LAST = 0x1; 962 | var BEFORE_LAST = 0x2; 963 | 964 | var ni; 965 | var nativeMenu; 966 | var overwrite; 967 | var allSet; 968 | var isMac; 969 | 970 | function $NIConnector (oNi, oNewNativeMenu, bOverwriteExisting) { 971 | if (oNi && oNewNativeMenu) { 972 | allSet = true; 973 | ni = oNi; 974 | nativeMenu = oNewNativeMenu; 975 | overwrite = bOverwriteExisting; 976 | isMac = currentOS.indexOf('Mac') >= 0; 977 | if (typeof NIConnector.defaultMenu == "undefined") { 978 | var app = NativeApplication.nativeApplication; 979 | NIConnector.defaultMenu = app.menu; 980 | } 981 | } 982 | } 983 | 984 | 985 | function isDefaultApplicationMenu () { 986 | var app = NativeApplication.nativeApplication; 987 | return (app.menu == NIConnector.defaultMenu); 988 | } 989 | 990 | function purge () { 991 | while (ni.menu.numItems) { ni.menu.removeItemAt (0) } 992 | } 993 | 994 | function add ( style ) { 995 | if (!ni.menu) { 996 | replace(); 997 | return; 998 | } 999 | var addFunction = (style == LAST)? 1000 | ni.menu.addItem : function (item) { 1001 | ni.menu.addItemAt (item, ni.menu.numItems-1); 1002 | } 1003 | var item; 1004 | while (nativeMenu.numItems && (item = nativeMenu.removeItemAt(0))) { 1005 | if(isMac && !item.submenu) { continue }; 1006 | addFunction.call (that, item); 1007 | } 1008 | } 1009 | 1010 | function replace () { 1011 | ni.menu = nativeMenu; 1012 | } 1013 | 1014 | this.doConnect = function () { 1015 | if (allSet) { 1016 | if (overwrite) { 1017 | if (isMac) { 1018 | purge (); 1019 | add (LAST); 1020 | } 1021 | else { replace() }; 1022 | } 1023 | else { 1024 | if (isMac) { 1025 | if (isDefaultApplicationMenu()) { add (BEFORE_LAST) } 1026 | else { add (LAST) }; 1027 | } else { add (LAST) }; 1028 | } 1029 | } 1030 | } 1031 | 1032 | $NIConnector.apply (this, arguments); 1033 | } 1034 | NIConnector.defaultMenu; 1035 | 1036 | 1037 | /** 1038 | * CLASS Shell 1039 | * @private 1040 | * @class 1041 | */ 1042 | function Shell() { 1043 | 1044 | function $Shell(){} 1045 | 1046 | var that = this; 1047 | 1048 | var CONTEXT_MENU = 'contextmenu'; 1049 | var app = NativeApplication.nativeApplication; 1050 | 1051 | var uidSeed = 0; 1052 | var DEFAULT_ID = "DEFAULT_ID"; 1053 | 1054 | var isMac = currentOS.indexOf('Mac') >= 0; 1055 | 1056 | var isBitmapData = function(obj) { 1057 | return obj && 1058 | obj.constructor && 1059 | obj.constructor === (new BitmapData (1, 1)); 1060 | } 1061 | 1062 | var resolveDomEl = function (obj) { 1063 | var ret = null; 1064 | if (obj) { 1065 | if (typeof obj == 'object' && obj.nodeType == 1) { ret = obj }; 1066 | if (typeof obj == 'string') { 1067 | var el; 1068 | if (el = document.getElementById(obj)) { ret = el }; 1069 | } 1070 | } 1071 | return ret; 1072 | } 1073 | 1074 | var checkUserIcon = function (obj) { 1075 | var icon = app.icon; 1076 | return icon.bitmaps.length > 0; 1077 | } 1078 | 1079 | var getIcons = function (userIcons) { 1080 | var ret = []; 1081 | var entries = []; 1082 | if (userIcons && userIcons.length) { 1083 | entries = userIcons; 1084 | } else { 1085 | var p = new DOMParser(); 1086 | var descr = String(app.applicationDescriptor); 1087 | var descrDoc = p.parseFromString(descr, "text/xml"); 1088 | var appEl = descrDoc.getElementsByTagName('application')[0]; 1089 | var iconEl = appEl.getElementsByTagName('icon')[0]; 1090 | if (iconEl) { 1091 | var iconEntries = iconEl.getElementsByTagName('*'); 1092 | for (var i=0; i 0; 1188 | if (!haveDefaultIcons) { 1189 | if (!isMac) { 1190 | throw (new Error([ 1191 | "Cannot set the icon menu.", 1192 | "On operating systems that do not provide a default", 1193 | "tray icon, you must specify one before calling", 1194 | "setAsIconMenu().", 1195 | "Alternativelly, you can specify default icons in the", 1196 | "application's XML descriptor." 1197 | ].join('\n'))); 1198 | } 1199 | } 1200 | var doAttach = function(bitmaps){ 1201 | setBitmaps (bitmaps); 1202 | app.icon.menu = menu; 1203 | } 1204 | if (defaultIcons) { 1205 | loadDefaultBitmaps(defaultIcons, doAttach); 1206 | } 1207 | } 1208 | } 1209 | 1210 | this.link = function (oMenu, style, target, icons) { 1211 | if (Shell.MENU & style) { 1212 | var bOverwrite = style & Shell.OVERWRITE; 1213 | return linkMenu(oMenu, bOverwrite); 1214 | } 1215 | if (Shell.CONTEXT & style) {return linkContextMenu(oMenu, target)}; 1216 | if (Shell.ICON & style) { return linkIconMenu(oMenu, icons) }; 1217 | } 1218 | 1219 | $Shell.apply (this, arguments); 1220 | } 1221 | Shell.UNSPECIFIED = -1; 1222 | Shell.MENU = 1; 1223 | Shell.CONTEXT = 2; 1224 | Shell.ICON = 4; 1225 | Shell.OVERWRITE = 8; 1226 | 1227 | Shell.resolve = function (pathOrFile) { 1228 | var file = null; 1229 | try { 1230 | file = File(pathOrFile); 1231 | } catch(e) { 1232 | file = File.applicationDirectory.resolvePath (pathOrFile); 1233 | if (!file.exists) { 1234 | try { 1235 | file = new File (pathOrFile); 1236 | } catch(e) { 1237 | // must be a path, both 'relative' AND 'non-existing'. 1238 | } 1239 | } 1240 | } 1241 | return file; 1242 | } 1243 | 1244 | /** 1245 | * CLASS Walker 1246 | * @class 1247 | * @private 1248 | */ 1249 | function Walker() { 1250 | var t, c, currentItem, allSet, item; 1251 | 1252 | function $Walker (target, callback) { 1253 | if (target && target instanceof DataSource) { 1254 | t = target; 1255 | } 1256 | if (callback && typeof callback == "function") { 1257 | c = callback; 1258 | } 1259 | if (t && c) { allSet = true }; 1260 | } 1261 | 1262 | function getNearestAncestorSibling(node) { 1263 | while (node) { 1264 | node = t.getParent(node); 1265 | if(node) { 1266 | var s = t.getNextSibling(node); 1267 | if (s) { return s }; 1268 | } 1269 | } 1270 | return null; 1271 | } 1272 | 1273 | function getFirstChildOfRoot() { 1274 | return t.getChildren(t.getRoot())[0] || null; 1275 | } 1276 | 1277 | function doTraverse() { 1278 | if (allSet) { 1279 | while (item = getNext()) { c.call (window, item) }; 1280 | 1281 | } else { 1282 | throw (new Error([ 1283 | 'Cannot traverse data tree.', 1284 | 'Please check the arguments you provided to the Walker class.', 1285 | ].join('\n'))); 1286 | } 1287 | } 1288 | 1289 | function getNext() { 1290 | if (currentItem === null) { return null }; 1291 | 1292 | if (typeof currentItem == 'undefined') { 1293 | currentItem = getFirstChildOfRoot(); 1294 | } 1295 | 1296 | if (t.hasChildren(currentItem)) { 1297 | var parentNode = currentItem; 1298 | currentItem = t.getChildren(currentItem)[0]; 1299 | return parentNode; 1300 | } 1301 | 1302 | if(t.getNextSibling(currentItem)) { 1303 | var current = currentItem; 1304 | currentItem = t.getNextSibling(currentItem); 1305 | return current; 1306 | } 1307 | 1308 | var ci = currentItem; 1309 | currentItem = getNearestAncestorSibling(currentItem); 1310 | return ci; 1311 | } 1312 | 1313 | this.walk = function (callback) { 1314 | doTraverse(); 1315 | if (typeof callback == "function") { callback.call (this) }; 1316 | } 1317 | 1318 | $Walker.apply (this, arguments); 1319 | } 1320 | 1321 | constructor.apply (this, arguments); 1322 | })(); -------------------------------------------------------------------------------- /lib/js/divlist.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author ghostzhang 3 | */ 4 | function $(e){ 5 | return document.getElementById("" + e + ""); 6 | } 7 | 8 | function delDiv(divinfo){ 9 | var id = divinfo.parentNode.parentNode.id; 10 | window.opener.div_list_del(id); 11 | $(id).style.display = "none"; 12 | } 13 | 14 | function div_info(divinfo){ 15 | var id = divinfo.parentNode.parentNode.id; 16 | window.opener.reset_div_class(); 17 | window.opener.div_info(id, 0, 0, 0, 0); 18 | $(id).className = "div-dnr-now"; 19 | var temp_div = $("input_div_id").value; 20 | if (temp_div) { 21 | temp_div = $(temp_div); 22 | temp_div.className = "div-dnr"; 23 | } 24 | $("input_div_id").value = id; 25 | window.opener.image_x(1); 26 | } 27 | 28 | function resetDive(){ 29 | window.opener.resetDive(); 30 | } 31 | 32 | function delAll(){ 33 | window.opener.delAll(); 34 | $("div_list").style.display = "none"; 35 | } 36 | 37 | function addAtt(div_list){ 38 | for (var n = 0; n < div_list.length; n++) { 39 | if (div_list[n]) { 40 | var ch = document.createElement('input'); 41 | var bt = document.createElement('input'); 42 | 43 | ch.type = "radio"; 44 | ch.name = "radio_ch"; 45 | ch.onclick = function(){ 46 | div_info(this); 47 | } 48 | bt.type = "button"; 49 | bt.value = "X"; 50 | bt.onclick = function(){ 51 | delDiv(this) 52 | } 53 | 54 | $("choose_" + div_list[n][0] + "").appendChild(ch); 55 | $("del_" + div_list[n][0] + "").appendChild(bt); 56 | } 57 | } 58 | } 59 | 60 | function onload(){ 61 | var temp_div_list = window.opener.div_list(); 62 | var temp = ""; 63 | 64 | for (var n = 0; n < temp_div_list.length; n++) { 65 | if (temp_div_list[n]) { 66 | temp += ""; 67 | temp += "" + temp_div_list[n][1] + ""; 68 | temp += "" + temp_div_list[n][2] + "px"; 69 | temp += "" + temp_div_list[n][3] + "px"; 70 | temp += "" + temp_div_list[n][4] + "px"; 71 | temp += "" + temp_div_list[n][5] + "px"; 72 | 73 | if (temp_div_list[n][6]){ 74 | temp +='' + temp_div_list[n][6] + ""; 75 | }else{ 76 | temp +='' + temp_div_list[n][6] + ""; 77 | } 78 | 79 | if (temp_div_list[n][7]){ 80 | temp +='' + temp_div_list[n][7] + ""; 81 | }else{ 82 | temp +='' + temp_div_list[n][7] + ""; 83 | } 84 | temp += ''; 85 | temp += ''; 86 | temp += ""; 87 | } 88 | } 89 | $("div_list").innerHTML = temp; 90 | addAtt(temp_div_list); 91 | $('bt_reset').addEventListener('click', resetDive); 92 | $('bt_delall').addEventListener('click', delAll); 93 | } 94 | -------------------------------------------------------------------------------- /lib/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @author ghost 3 | */ 4 | var Browser_Name = navigator.appName; 5 | var x = 25, y = 25, x1 = 0, y1 = 0, xx = 0, yy = 0, xx1 = 0, yy1 = 0; 6 | var moveable = false; 7 | var index = 10000; 8 | var resizeable = false; 9 | var objId = ""; 10 | var objParentId = ""; 11 | var num = 1; 12 | var default_width = "30"; 13 | var default_height = "30"; 14 | 15 | var file = null; 16 | var file_path = null; 17 | var image = null; 18 | var image_path = new Array(); 19 | var image_url = ""; 20 | var image_width = null; 21 | var image_height = null; 22 | var file_xml = null; 23 | var file_path_xml = null; 24 | var div_margin = 0; 25 | var read_end = true; 26 | 27 | var array_style = new Array(); 28 | var array_div = new Array(); 29 | var num_array_style = 0; 30 | var del_array_div = new Array(); 31 | 32 | var menu_array = new Array(); 33 | var show_new = true; 34 | var show_nonce = true; 35 | 36 | function $(e) { 37 | return document.getElementById("" + e + ""); 38 | } 39 | 40 | function openInBrowser(url) { 41 | air.navigateToURL(new air.URLRequest(url)); 42 | } 43 | 44 | // 选择图片 45 | function doBrowseImg() { 46 | var filters = new runtime.Array(new air.FileFilter('Images(*.jpg;*.gif;*.png)', '*.jpg;*.gif;*.png;*.jpeg')); 47 | 48 | file.browseForOpen('Select an Image', filters); 49 | } 50 | 51 | function doSelectImg(e) { 52 | image_url = file.url; 53 | image.load(new air.URLRequest(image_url)); 54 | 55 | file_path = file.nativePath; 56 | } 57 | 58 | function doOver(e) { 59 | e.preventDefault(); 60 | } 61 | 62 | function doDrop(e) { 63 | var files = e.dataTransfer.getData('application/x-vnd.adobe.air.file-list'); 64 | 65 | if (checkFileType(files[0])) { 66 | image_url = files[0].url; 67 | image.load(new air.URLRequest(image_url)); 68 | file_path = files[0].nativePath; 69 | } 70 | else { 71 | return false; 72 | } 73 | doComplete(event); 74 | } 75 | 76 | function checkFileType(file) { 77 | var temp_file = file.name.split("."); 78 | var temp_type = "jpg,gif,png,jpeg,JPG,GIF,PNG,JPEG"; 79 | if (temp_type.search(temp_file[1]) >= 0) { 80 | return true; 81 | } 82 | else { 83 | return false; 84 | } 85 | } 86 | 87 | // 选择xml 88 | function doBrowseXml() { 89 | var filters = new runtime.Array(new air.FileFilter('XML(*.xml)', '*.xml')); 90 | 91 | file_xml.browseForOpen('Select an XML', filters); 92 | } 93 | 94 | function doSelectXml(e) { 95 | file_path_xml = file_xml.nativePath; 96 | doCompleteXml(); 97 | } 98 | 99 | function doComplete(event, imginfo) { 100 | var div = null; 101 | image_path.length = 0; 102 | $("div_view_css").innerText = ""; 103 | image_x(1); 104 | 105 | div = $("image_view"); 106 | if (arguments.length == 2) { 107 | image_width = div.style.width = imginfo[1] + "px"; 108 | image_height = div.style.height = imginfo[2] + "px"; 109 | image_path[0] = div.src = "file:///" + imginfo[0]; 110 | $("input_bg_path").value = file_path = imginfo[0]; 111 | } 112 | else { 113 | image_width = div.style.width = image.width + "px"; 114 | image_height = div.style.height = image.height + "px"; 115 | image_path[0] = div.src = "file:///" + file_path; 116 | $("input_bg_path").value = file_path; 117 | $("textarea_gb_class").value = ""; 118 | } 119 | 120 | div.style.backgroundRepeat = "no-repeat"; 121 | div.style.backgroundImage = "url(icon/b.gif)"; 122 | div.style.backgroundColor = "#000000"; 123 | 124 | $("bt_x1").disabled = ""; 125 | $("bt_x2").disabled = ""; 126 | $("bt_x4").disabled = ""; 127 | 128 | var temp_img_width = parseInt(image_width.replace("px", "")); 129 | var temp_img_height = parseInt(image_height.replace("px", "")); 130 | if (temp_img_width < 150 && temp_img_height < 150) { 131 | $("bt_x6").disabled = ""; 132 | } 133 | else { 134 | $("bt_x6").disabled = "true"; 135 | } 136 | if (temp_img_width > 0 && temp_img_width < default_width) { 137 | default_width = temp_img_width; 138 | } 139 | if (temp_img_height > 0 && temp_img_height < default_height) { 140 | default_height = temp_img_height; 141 | } 142 | $("bt_color_1").disabled = ""; 143 | $("bt_color_2").disabled = ""; 144 | $("bt_color_3").disabled = ""; 145 | $("checkbox_show_width").disabled = ""; 146 | $("checkbox_show_height").disabled = ""; 147 | } 148 | 149 | //修改层信息 150 | function doEdit() { 151 | var temp = $("input_div_id").value; 152 | if (temp) { 153 | $("button_div_edit").disabled = ""; 154 | $("button_copy_left").disabled = "true"; 155 | $("button_copy_top").disabled = "trun"; 156 | $("button_copy_right").disabled = "true"; 157 | $("button_copy_bottom").disabled = "true"; 158 | $("input_copy_pyl").disabled = "true"; 159 | $("button_div_copy_width").disabled = "true"; 160 | $("button_div_copy_height").disabled = "true"; 161 | $("button_div_copy_left").disabled = "true"; 162 | $("button_div_copy_top").disabled = "true"; 163 | $("checkbox_copy_div_class").disabled = "true"; 164 | $("checkbox_copy_div_width").disabled = "true"; 165 | $("checkbox_copy_div_height").disabled = "true"; 166 | $("checkbox_show_div_width").disabled = "true"; 167 | $("checkbox_show_div_height").disabled = "true"; 168 | $("button_div_copy").disabled = "true"; 169 | } 170 | } 171 | 172 | //修改层信息 173 | function editDiv() { 174 | var temp = $("input_div_id").value; 175 | 176 | if (temp != "") { 177 | checkinput(temp); 178 | update_info(temp); 179 | $("button_div_edit").disabled = "true"; 180 | $("button_copy_left").disabled = ""; 181 | $("button_copy_top").disabled = ""; 182 | $("button_copy_right").disabled = ""; 183 | $("button_copy_bottom").disabled = ""; 184 | $("input_copy_pyl").disabled = ""; 185 | $("button_div_copy_width").disabled = ""; 186 | $("button_div_copy_height").disabled = ""; 187 | $("button_div_copy_left").disabled = ""; 188 | $("button_div_copy_top").disabled = ""; 189 | $("checkbox_copy_div_class").disabled = ""; 190 | $("checkbox_copy_div_width").disabled = ""; 191 | $("checkbox_copy_div_height").disabled = ""; 192 | $("checkbox_show_div_width").disabled = ""; 193 | $("checkbox_show_div_height").disabled = ""; 194 | $("button_div_copy").disabled = ""; 195 | } 196 | } 197 | 198 | //删除层 199 | function delDiv(event, divid) { 200 | var temp = ""; 201 | if (arguments.length == 2) { 202 | temp = divid; 203 | } 204 | else { 205 | temp = $("input_div_id").value; 206 | } 207 | var temp_div_num = get_array_num(temp); 208 | if (temp_div_num >= 0) { 209 | $(temp).parentNode.removeChild($(temp)); 210 | 211 | $("input_div_id").value = ""; 212 | $("input_div_name").value = ""; 213 | $("input_div_width").value = ""; 214 | $("input_div_height").value = ""; 215 | $("input_div_left").value = ""; 216 | $("input_div_top").value = ""; 217 | 218 | array_div[temp_div_num] = ""; 219 | array_style[temp_div_num] = ""; 220 | $("button_div_edit").disabled = "true"; 221 | $("button_div_del").disabled = "true"; 222 | $("button_copy_left").disabled = "true"; 223 | $("button_copy_top").disabled = "true"; 224 | $("button_copy_right").disabled = "true"; 225 | $("button_copy_bottom").disabled = "true"; 226 | $("input_copy_pyl").disabled = "true"; 227 | $("checkbox_copy_div_class").disabled = "true"; 228 | $("checkbox_copy_div_width").disabled = "true"; 229 | $("checkbox_copy_div_height").disabled = "true"; 230 | $("checkbox_show_div_width").disabled = "true"; 231 | $("checkbox_show_div_height").disabled = "true"; 232 | $("button_div_copy").disabled = "true"; 233 | } 234 | } 235 | 236 | //重置层 237 | function resetDive() { 238 | var temp = $("input_div_id").value; 239 | var temp_style = array_style; 240 | var temp_image_view = $("image_view"); 241 | 242 | for (var n = 0; n < array_div.length; n++) { 243 | if (array_div[n] != "") { 244 | temp_style[n][2] = default_width; 245 | temp_style[n][3] = default_height; 246 | temp_style[n][4] = "10"; 247 | temp_style[n][5] = "10"; 248 | 249 | $(array_div[n]).style.width = temp_style[n][2] * num + "px"; 250 | $(array_div[n]).style.height = temp_style[n][3] * num + "px"; 251 | $(array_div[n]).style.left = temp_style[n][4] * num + "px"; 252 | $(array_div[n]).style.top = temp_style[n][5] * num + "px"; 253 | } 254 | } 255 | if (temp) { 256 | $("input_div_width").value = default_width; 257 | $("input_div_height").value = default_height; 258 | $("input_div_left").value = "10"; 259 | $("input_div_top").value = "10"; 260 | } 261 | } 262 | 263 | //增加层 264 | function addDiv(divinfo, addDiv) { 265 | var temp_background = $("image_view").style.backgroundImage; 266 | if (temp_background != "") { 267 | var rn = Math.round(Math.random() * 10000); 268 | var div = document.createElement('div'); 269 | var div_drag = document.createElement('div'); 270 | var div_resize = document.createElement('div'); 271 | var temp_image_view = $("image_view"); 272 | var e = addDiv ? addDiv : window.event; 273 | var temp_array = new Array(); 274 | 275 | //正常 276 | if (arguments.length == 2) { 277 | div.id = divinfo[0]; 278 | div.title = divinfo[1]; 279 | div.className = "div-dnr"; 280 | div.style.width = divinfo[2] + "px"; 281 | div.style.height = divinfo[3] + "px"; 282 | div.style.left = parseInt(divinfo[4]) + "px"; 283 | div.style.top = parseInt(divinfo[5]) + "px"; 284 | if (divinfo.length > 6) { 285 | temp_array[6] = divinfo[6]; 286 | temp_array[7] = divinfo[7]; 287 | } 288 | else { 289 | temp_array[6] = true; 290 | temp_array[7] = true; 291 | } 292 | } 293 | else { 294 | div.id = "div_" + rn; 295 | div.title = "div_" + rn; 296 | div.className = "div-dnr"; 297 | div.style.width = default_width * num + "px"; 298 | div.style.height = default_height * num + "px"; 299 | div.style.left = e.offsetX - parseInt(default_width * num / 2) + parseInt(div_margin * num) + "px"; 300 | div.style.top = e.offsetY - parseInt(default_height * num / 2) + parseInt(div_margin * num) + "px"; 301 | temp_array[6] = true; 302 | temp_array[7] = true; 303 | } 304 | 305 | div_drag.id = "drag_" + rn; 306 | div_drag.className = "div-drag"; 307 | div_drag.onmousedown = function () { 308 | startDrag(this, event) 309 | }; 310 | div_drag.onmousemove = function () { 311 | drag(event) 312 | }; 313 | div_drag.onmouseup = function () { 314 | stopDrag(event) 315 | }; 316 | 317 | div_resize.id = "resize_" + rn; 318 | div_resize.className = "div-resize"; 319 | div_resize.onmousedown = function () { 320 | startResize(this, event) 321 | }; 322 | div_resize.onmousemove = function () { 323 | Resizing(event) 324 | }; 325 | div_resize.onmouseup = function () { 326 | stopResize(event) 327 | }; 328 | 329 | div.appendChild(div_drag); 330 | div.appendChild(div_resize); 331 | $("div_image_view").appendChild(div); 332 | 333 | checkxy(div.id); 334 | 335 | var temp = $(div.id); 336 | var temp_id = div.id; 337 | temp_array[0] = "" + temp_id + ""; 338 | temp_array[1] = "" + temp.title + ""; 339 | temp_array[2] = "" + parseInt(temp.style.width.replace("px", "") / num) + ""; 340 | temp_array[3] = "" + parseInt(temp.style.height.replace("px", "") / num) + ""; 341 | temp_array[4] = "" + parseInt(temp.style.left.replace("px", "") / num) + ""; 342 | temp_array[5] = "" + parseInt(temp.style.top.replace("px", "") / num) + ""; 343 | 344 | array_div[num_array_style] = temp_array[0]; 345 | array_style[num_array_style++] = temp_array; 346 | 347 | $("bt_view_css").disabled = ""; 348 | if (arguments.length == 1) { 349 | $("input_div_id").value = temp_id; 350 | reset_div_className(); 351 | div_info(temp_id, 0, 0, 0, 0); 352 | $(temp_id).style.zIndex = ++index; 353 | if (show_new) { 354 | showNonceDiv("true"); 355 | } 356 | } 357 | } 358 | } 359 | 360 | //设置当前层信息显示方式 361 | function setShowDiv() { 362 | var temp = arguments[0].target.data.item.name; 363 | var op = arguments[0].target.data.item.toggled; 364 | 365 | switch (temp) { 366 | case "show_new": 367 | if (!op) { 368 | show_new = false; 369 | } 370 | else { 371 | show_new = true; 372 | } 373 | break; 374 | case "show_nonce": 375 | if (!op) { 376 | show_nonce = false; 377 | } 378 | else { 379 | show_nonce = true; 380 | } 381 | break; 382 | } 383 | } 384 | 385 | //重置层的类名 386 | function reset_div_className() { 387 | var temp_lenght = array_style.length; 388 | for (var n = 0; n < temp_lenght; n++) { 389 | if ($(array_style[n][1])) { 390 | $(array_style[n][1]).className = "div-dnr"; 391 | } 392 | } 393 | } 394 | 395 | //取得层位置 396 | function get_array_num(e) { 397 | var temp_lenght = array_div.length; 398 | for (var n = 0; n < temp_lenght; n++) { 399 | if (array_div[n] == e) { 400 | return n; 401 | } 402 | } 403 | } 404 | 405 | //修改留白 406 | function doEditDivMargin() { 407 | var temp = $("image_view").style.width; 408 | if (temp != 0) { 409 | $("button_div_margin_edit").disabled = ""; 410 | } 411 | } 412 | 413 | //修改留白 414 | function editDivMargin() { 415 | var temp_margin = $("input_div_margin").value; 416 | if (temp_margin != div_margin) { 417 | div_margin = temp_margin; 418 | } 419 | else 420 | if (temp_margin == "") { 421 | div_margin = 0; 422 | $("input_div_margin").value = 0; 423 | } 424 | $("div_image").style.padding = div_margin * num; 425 | updataDivMagin(); 426 | $("button_div_margin_edit").disabled = "true"; 427 | } 428 | 429 | //检查输入 430 | function checkinput(e) { 431 | var temp = $("" + e + ""); 432 | var temp_num = get_array_num(e); 433 | var temp_array = new Array(); 434 | 435 | temp_array[1] = $("input_div_name").value; 436 | temp_array[2] = $("input_div_width").value; 437 | temp_array[3] = $("input_div_height").value; 438 | temp_array[4] = $("input_div_left").value; 439 | temp_array[5] = $("input_div_top").value; 440 | 441 | if (temp_array[1] == "") { 442 | $("input_div_name").value = array_style[temp_num][1]; 443 | } 444 | if (temp_array[2] == "") { 445 | $("input_div_width").value = array_style[temp_num][2]; 446 | } 447 | if (temp_array[3] == "") { 448 | $("input_div_height").value = array_style[temp_num][3]; 449 | } 450 | if (temp_array[4] == "") { 451 | $("input_div_left").value = array_style[temp_num][4]; 452 | } 453 | if (temp_array[5] == "") { 454 | $("input_div_top").value = array_style[temp_num][5]; 455 | } 456 | } 457 | 458 | //检查坐标 459 | function checkxy(e) { 460 | var temp = $("" + e + ""); 461 | var temp_div_width = parseInt(temp.style.width); 462 | var temp_div_height = parseInt(temp.style.height); 463 | var temp_div_left = parseInt(temp.style.left); 464 | var temp_div_top = parseInt(temp.style.top); 465 | 466 | if (temp.id.substr(0, 4) == "div_") { 467 | var temp_div_right = parseInt($("image_view").style.width) - temp_div_width + parseInt(div_margin * 2 * num); 468 | var temp_div_bottom = parseInt($("image_view").style.height) - temp_div_height + parseInt(div_margin * 2 * num); 469 | } 470 | else { 471 | var temp_div_right = parseInt($("div_image_view").offsetWidth) - parseInt(temp_div_width); 472 | var temp_div_bottom = parseInt($("div_image_view").offsetHeight) - parseInt(temp_div_height + 22); 473 | } 474 | 475 | if (read_end && temp_div_left < 0) { 476 | temp.style.left = 0; 477 | } 478 | 479 | if (temp_div_left > temp_div_right) { 480 | temp.style.left = Math.round(temp_div_right); 481 | } 482 | 483 | if (read_end && temp_div_top < 0) { 484 | temp.style.top = 0; 485 | } 486 | 487 | if (temp_div_top > temp_div_bottom) { 488 | temp.style.top = Math.round(temp_div_bottom); 489 | } 490 | } 491 | 492 | //检查大小 493 | function checkwh(e) { 494 | var temp = $("" + e + ""); 495 | var temp_div_width = parseInt(temp.style.width); 496 | var temp_div_height = parseInt(temp.style.height); 497 | var temp_div_left = parseInt(temp.style.left); 498 | var temp_div_top = parseInt(temp.style.top); 499 | var temp_div_right = temp_div_left + temp_div_width; 500 | var temp_div_bottom = temp_div_top + temp_div_height; 501 | var temp_div_width = parseInt($("image_view").style.width) + parseInt(div_margin * 2 * num); 502 | var temp_div_height = parseInt($("image_view").style.height) + parseInt(div_margin * 2 * num); 503 | var temp_width = temp_div_width - temp_div_left; 504 | var temp_height = temp_div_height - temp_div_top; 505 | 506 | if (temp_div_right > temp_div_width) { 507 | temp.style.width = temp_width; 508 | } 509 | if (temp_div_bottom > temp_div_height) { 510 | temp.style.height = temp_height; 511 | } 512 | } 513 | 514 | //更新层信息 515 | function update_info(e) { 516 | var temp = $("" + e + ""); 517 | if (temp.id.substr(0, 4) == "div_") { 518 | var temp_num = get_array_num(e); 519 | var temp_array = new Array(); 520 | 521 | temp_array[0] = "" + e + ""; 522 | temp_array[1] = $("input_div_name").value; 523 | temp_array[2] = $("input_div_width").value; 524 | temp_array[3] = $("input_div_height").value; 525 | temp_array[4] = $("input_div_left").value; 526 | temp_array[5] = $("input_div_top").value; 527 | temp_array[6] = $("checkbox_show_div_width").checked; 528 | temp_array[7] = $("checkbox_show_div_height").checked; 529 | array_style[temp_num] = temp_array; 530 | 531 | temp.title = temp_array[1]; 532 | temp.style.width = Math.round(temp_array[2]) * num + "px"; 533 | temp.style.height = Math.round(temp_array[3]) * num + "px"; 534 | temp.style.left = Math.round(temp_array[4]) * num + div_margin * num + "px"; 535 | temp.style.top = Math.round(temp_array[5]) * num + div_margin * num + "px"; 536 | } 537 | } 538 | 539 | function checkNum(e) { 540 | if (e > 0) { 541 | return "-" + e + "px"; 542 | } 543 | else 544 | if (e < 0) { 545 | e = e - e * 2; 546 | return e + "px"; 547 | } 548 | else { 549 | return e; 550 | } 551 | } 552 | 553 | function checkType(fullpath) { 554 | var temp_path = fullpath.split("/"); 555 | var temp_file = temp_path[temp_path.length - 1].split("."); 556 | if (temp_file[1]) { 557 | var type = temp_file[1]; 558 | 559 | if (type != "xml") { 560 | temp_file[1] = "xml"; 561 | var temp = temp_file.join("."); 562 | temp_path[temp_path.length - 1] = temp; 563 | temp = temp_path.join("/"); 564 | return temp; 565 | } 566 | else { 567 | return fullpath; 568 | } 569 | } 570 | else { 571 | var temp = fullpath + ".xml"; 572 | return temp; 573 | } 574 | } 575 | 576 | function div_info(e, t1, t2, t3, t4) { 577 | var temp = $("" + e + ""); 578 | if (temp.id.substr(0, 4) == "div_") { 579 | $("input_div_id").value = temp.id; 580 | $("input_div_name").value = temp.title; 581 | 582 | if (num > 1) { 583 | $("input_div_width").value = Math.round(parseInt(temp.style.width) / num) + parseInt(t1); 584 | $("input_div_height").value = Math.round(parseInt(temp.style.height) / num) + parseInt(t2); 585 | $("input_div_left").value = Math.round(parseInt(temp.style.left) / num) - div_margin + parseInt(t3); 586 | $("input_div_top").value = Math.round(parseInt(temp.style.top) / num) - div_margin + parseInt(t4); 587 | } 588 | else { 589 | $("input_div_width").value = parseInt(temp.style.width) + parseInt(t1); 590 | $("input_div_height").value = parseInt(temp.style.height) + parseInt(t2); 591 | $("input_div_left").value = parseInt(temp.style.left) - div_margin + parseInt(t3); 592 | $("input_div_top").value = parseInt(temp.style.top) - div_margin + parseInt(t4); 593 | } 594 | $("checkbox_show_div_width").checked = show_divwh("width"); 595 | $("checkbox_show_div_height").checked = show_divwh("height"); 596 | 597 | temp.className = "div-dnr-now"; 598 | $("button_div_edit").disabled = "true"; 599 | $("button_div_del").disabled = ""; 600 | $("button_copy_left").disabled = ""; 601 | $("button_copy_top").disabled = ""; 602 | $("button_copy_right").disabled = ""; 603 | $("button_copy_bottom").disabled = ""; 604 | $("input_copy_pyl").disabled = ""; 605 | $("button_div_copy_width").disabled = ""; 606 | $("button_div_copy_height").disabled = ""; 607 | $("button_div_copy_left").disabled = ""; 608 | $("button_div_copy_top").disabled = ""; 609 | $("checkbox_copy_div_class").disabled = ""; 610 | $("checkbox_copy_div_width").disabled = ""; 611 | $("checkbox_copy_div_height").disabled = ""; 612 | $("checkbox_show_div_width").disabled = ""; 613 | $("checkbox_show_div_height").disabled = ""; 614 | $("button_div_copy").disabled = ""; 615 | } 616 | } 617 | 618 | //输出样式 619 | function view_css() { 620 | var temp = ""; 621 | var temp_css = ""; 622 | var temp_background = $("image_view").style.backgroundImage; 623 | var temp_background_value = $("input_bg_path").value; 624 | var temp_gbstyle = $("textarea_gb_class").value; 625 | var div = $("div_view_css"); 626 | var temp_lenght = array_div.length; 627 | var checkbox_show_width = $("checkbox_show_width").checked; 628 | var checkbox_show_height = $("checkbox_show_height").checked; 629 | var radio_show_allwh = $("radio_show_allwh").checked; 630 | 631 | if (temp_background_value == "") { 632 | temp_background_value = "background:url(" + temp_background + ") no-repeat 0 0;"; 633 | } 634 | else { 635 | temp_background_value = "background:url(" + temp_background_value + ") no-repeat 0 0;"; 636 | } 637 | 638 | for (var n = 0; n < temp_lenght; n++) { 639 | if (array_div[n] != "") { 640 | temp += "." + array_style[n][1] + ","; 641 | } 642 | } 643 | if (temp != "") { 644 | temp = temp.replace(/,$/g, ""); 645 | if (temp_gbstyle != "") { 646 | temp += "{\n" + temp_background_value + "\n" + temp_gbstyle + "\n}\n"; 647 | } 648 | else { 649 | temp += "{" + temp_background_value + "}\n"; 650 | } 651 | temp_css = temp; 652 | for (var n = 0; n < array_div.length; n++) { 653 | if (radio_show_allwh) { 654 | if (array_div[n] != "") { 655 | temp = "." + array_style[n][1] + "{"; 656 | 657 | if (checkbox_show_width) { 658 | temp += "width:" + array_style[n][2] + "px;"; 659 | } 660 | if (checkbox_show_height) { 661 | temp += "height:" + array_style[n][3] + "px;"; 662 | } 663 | 664 | temp += "background-position:" + checkNum(array_style[n][4]); 665 | temp += " " + checkNum(array_style[n][5]); 666 | temp += ";}\n"; 667 | temp_css = temp_css + temp; 668 | } 669 | } 670 | else { 671 | if (array_div[n] != "") { 672 | temp = "." + array_style[n][1] + "{"; 673 | 674 | if (array_style[n][6]) { 675 | temp += "width:" + array_style[n][2] + "px;"; 676 | } 677 | if (array_style[n][7]) { 678 | temp += "height:" + array_style[n][3] + "px;"; 679 | } 680 | 681 | temp += "background-position:" + checkNum(array_style[n][4]); 682 | temp += " " + checkNum(array_style[n][5]); 683 | temp += ";}\n"; 684 | temp_css = temp_css + temp; 685 | } 686 | } 687 | } 688 | div.innerText = temp_css; 689 | $("bt_copy_css").disabled = ""; 690 | } 691 | else { 692 | div.innerText = ""; 693 | $("bt_copy_css").disabled = "true"; 694 | } 695 | showhide("pre_css_div"); 696 | } 697 | 698 | //显示当前层宽高是否输出 699 | function show_divwh(op) { 700 | var temp = $("input_div_id").value; 701 | 702 | if (temp) { 703 | var n = get_array_num(temp); 704 | if (op == "width") { 705 | return array_style[n][6]; 706 | } 707 | if (op == "height") { 708 | return array_style[n][7]; 709 | } 710 | } 711 | } 712 | 713 | //设置当前层宽高是否输出 714 | function set_divwh() { 715 | var temp = $("input_div_id").value; 716 | var nonce = $(this.id).checked; 717 | 718 | if (temp) { 719 | var n = get_array_num(temp); 720 | switch (this.id) { 721 | case "checkbox_show_div_width": 722 | if (nonce) { 723 | array_style[n][6] = true; 724 | } 725 | else { 726 | array_style[n][6] = false; 727 | } 728 | break; 729 | case "checkbox_show_div_height": 730 | if (nonce) { 731 | array_style[n][7] = true; 732 | } 733 | else { 734 | array_style[n][7] = false; 735 | } 736 | break; 737 | } 738 | } 739 | } 740 | 741 | function doSave() { 742 | var docsDir = air.File.documentsDirectory; 743 | try { 744 | docsDir.browseForSave("Save As"); 745 | docsDir.addEventListener(air.Event.SELECT, doSaveSet); 746 | } 747 | catch (error) { 748 | air.trace("Failed:", error.message) 749 | } 750 | } 751 | 752 | function doSaveSet(event) { 753 | view_css(); 754 | var newFile = event.target; 755 | newFile.url = "" + checkType(event.target.url) + ""; 756 | 757 | var stream = new air.FileStream(); 758 | stream.open(newFile, air.FileMode.WRITE); 759 | 760 | var temp_gbstyle = $("textarea_gb_class").value; 761 | var cr = air.File.lineEnding; 762 | temp_gbstyle.replace("\n", cr); 763 | image_width.replace("px", ""); 764 | image_height.replace("px", ""); 765 | var note = '' + cr + 766 | '' + 767 | cr + 768 | '3' + 769 | cr + 770 | '' + 771 | cr + 772 | '' + 773 | file_path + 774 | '' + 775 | cr + 776 | '' + 777 | image_width + 778 | '' + 779 | cr + 780 | '' + 781 | image_height + 782 | '' + 783 | cr + 784 | '' + 785 | div_margin + 786 | '' + 787 | cr + 788 | '' + 789 | temp_gbstyle + 790 | '' + 791 | cr + 792 | ''; 793 | 794 | var temp_style = array_style; 795 | 796 | for (var n = 0; n < array_div.length; n++) { 797 | if (array_div[n] != "") { 798 | note += ' ' + cr + '' + array_style[n][0] + '' + cr + '' + array_style[n][1] + '' + cr + '' + array_style[n][2] + '' + cr + '' + array_style[n][3] + '' + cr + '' + array_style[n][4] + '' + cr + '' + array_style[n][5] + '' + cr + '' + array_style[n][6] + '' + cr + '' + array_style[n][7] + '' + cr + ''; 799 | } 800 | } 801 | 802 | note += cr + ''; 803 | 804 | stream.writeUTFBytes(note); 805 | stream.close(); 806 | 807 | } 808 | 809 | //开始拖动 810 | function startDrag(obj, evt) { 811 | e = evt ? evt : window.event; 812 | if (true) { 813 | window.captureEvents(Event.MOUSEMOVE | Event.MOUSEUP); 814 | 815 | var win = obj.parentNode;//取得父窗体 816 | objId = obj.id; 817 | objParentId = win.id; 818 | 819 | if (objParentId.substr(0, 4) == "div_") { 820 | var temp_id = $("input_div_id").value; 821 | if (temp_id) { 822 | $(temp_id).className = "div-dnr"; 823 | } 824 | 825 | div_info(objParentId, 0, 0, 0, 0); 826 | win.style.zIndex = ++index;//设置父窗体的Z轴值 827 | } 828 | 829 | x = parseInt(e.clientX);//取得当前鼠标的X坐标 830 | y = parseInt(e.clientY);//取得当前鼠标的Y坐标 831 | x1 = parseInt(win.style.left);//将父窗体的距浏览器左边界的距离转换为NUMBER 832 | y1 = parseInt(win.style.top);//将父窗体的距浏览器上边界的距离转换为NUMBER 833 | moveable = true; 834 | if (show_nonce) { 835 | showNonceDiv("true"); 836 | } 837 | } 838 | } 839 | 840 | function drag(evt) { 841 | e = evt ? evt : window.event; 842 | if (moveable) { 843 | var win = $("" + objParentId + ""); 844 | win.style.left = parseInt(x1 + e.clientX - x); 845 | win.style.top = parseInt(y1 + e.clientY - y); 846 | checkxy(objParentId); 847 | div_info(objParentId, 0, 0, 0, 0); 848 | } 849 | } 850 | 851 | //停止拖动 852 | function stopDrag(event) { 853 | var obj = $("" + objId + ""); 854 | if (moveable) { 855 | e.preventDefault(); 856 | document.addEventListener("mouseup", stopDrag, true); 857 | document.addEventListener("mousemove", drag, true); 858 | 859 | update_info(objParentId); 860 | 861 | moveable = false; 862 | objId = ""; 863 | objParentId = ""; 864 | } 865 | } 866 | 867 | //开始缩放 868 | function startResize(obj, evt) { 869 | var e = evt; 870 | 871 | e.preventDefault(); 872 | document.addEventListener("mouseup", stopResize, true); 873 | document.addEventListener("mousemove", Resizing, true); 874 | 875 | var win = obj.parentNode; 876 | objId = obj.id; 877 | objParentId = win.id; 878 | win.style.zIndex = ++index; 879 | x = parseInt(e.screenX); 880 | y = parseInt(e.screenY); 881 | x1 = parseInt(win.style.width); 882 | y1 = parseInt(win.style.height); 883 | resizeable = true; 884 | } 885 | 886 | function Resizing(evt) { 887 | var e = evt ? evt : window.event; 888 | 889 | if (resizeable) { 890 | var win = $("" + objParentId + ""); 891 | win.style.width = parseInt(x1 + e.screenX - x) + "px"; 892 | win.style.height = parseInt(y1 + e.screenY - y) + "px"; 893 | checkwh(objParentId); 894 | div_info(objParentId, 0, 0, 0, 0); 895 | } 896 | } 897 | 898 | //停止缩放 899 | function stopResize(evt) { 900 | var obj = $("" + objId + ""); 901 | if (resizeable) { 902 | document.removeEventListener("mouseup", stopResize, true); 903 | document.removeEventListener("mousemove", Resizing, true); 904 | 905 | update_info(objParentId); 906 | resizeable = false; 907 | objId = ""; 908 | objParentId = ""; 909 | } 910 | } 911 | 912 | //更改图片底色 913 | function image_color(n) { 914 | var img = $("image_view"); 915 | img.style.backgroundColor = "#" + n; 916 | } 917 | 918 | //图片缩放 919 | function image_x(n) { 920 | var img_div = $("div_image_view"); 921 | var img = $("image_view"); 922 | 923 | if (n != "" && n > 0) { 924 | num = parseInt(n); 925 | 926 | if (num > 1) { 927 | if (image_path[num]) { 928 | img.src = image_path[num]; 929 | } 930 | else { 931 | if (image.width * num < 8192 && image.height * num < 8192) { 932 | var bmp = new air.BitmapData(image.width * num, image.height * num, true, 0x00000000); 933 | var temp = air.File.createTempFile(); 934 | var desktop = null; 935 | var matrix = new air.Matrix(); 936 | var stream = new air.FileStream(); 937 | var div = null; 938 | var elem = null; 939 | 940 | matrix.scale(num, num); 941 | bmp.draw(image.content, matrix); 942 | 943 | png = runtime.com.adobe.images.PNGEncoder.encode(bmp); 944 | 945 | stream.open(temp, air.FileMode.WRITE); 946 | stream.writeBytes(png, 0, 0); 947 | stream.close(); 948 | image_path[num] = img.src = temp.url; 949 | } 950 | else { 951 | img.src = image_path[0]; 952 | } 953 | } 954 | } 955 | else { 956 | img.src = image_path[0]; 957 | } 958 | img.style.width = parseInt(image_width) * num + "px"; 959 | img.style.height = parseInt(image_height) * num + "px"; 960 | 961 | 962 | 963 | $("div_image").style.padding = div_margin * num; 964 | 965 | var temp = 0; 966 | var temp_lenght = array_div.length; 967 | 968 | for (var n = 0; n < temp_lenght; n++) { 969 | if (array_div[n] != "") { 970 | temp++; 971 | } 972 | } 973 | if (temp > 0) { 974 | for (var n = 0; n < temp_lenght; n++) { 975 | if (array_div[n] != "") { 976 | $(array_style[n][0]).style.width = array_style[n][2] * num + "px"; 977 | $(array_style[n][0]).style.height = array_style[n][3] * num + "px"; 978 | $(array_style[n][0]).style.left = parseInt(array_style[n][4]) * num + div_margin * num + "px"; 979 | $(array_style[n][0]).style.top = parseInt(array_style[n][5]) * num + div_margin * num + "px"; 980 | } 981 | } 982 | resetDivXY(); 983 | } 984 | 985 | } 986 | else { 987 | num = 1; 988 | } 989 | } 990 | 991 | //当前层在窗口内显示 992 | function resetDivXY() { 993 | var img_div = $("div_image_view"); 994 | var nonce_div = $("input_div_id").value; 995 | if (nonce_div != "") { 996 | nonce_div = $("" + nonce_div + ""); 997 | if (nonce_div.offsetLeft > img_div.clientWidth) { 998 | img_div.scrollLeft = parseInt(nonce_div.offsetLeft) - parseInt(img_div.clientWidth / 2) + parseInt(nonce_div.clientWidth / 2); 999 | } 1000 | else { 1001 | img_div.scrollLeft = parseInt(nonce_div.offsetLeft) - parseInt(img_div.clientWidth / 2) + parseInt(nonce_div.clientWidth / 2); 1002 | } 1003 | if (nonce_div.offsetTop > img_div.clientHeight) { 1004 | img_div.scrollTop = parseInt(nonce_div.offsetTop) - parseInt(img_div.clientHeight / 2) + parseInt(nonce_div.clientHeight / 2); 1005 | } 1006 | else { 1007 | img_div.scrollTop = parseInt(nonce_div.offsetTop) - parseInt(img_div.clientHeight / 2) + parseInt(nonce_div.clientHeight / 2); 1008 | } 1009 | } 1010 | } 1011 | 1012 | function updataDivMagin() { 1013 | var temp_margin = $("input_div_margin").value; 1014 | var temp = 0; 1015 | var temp_lenght = array_div.length; 1016 | 1017 | for (var n = 0; n < temp_lenght; n++) { 1018 | if (array_div[n] != "") { 1019 | temp++; 1020 | } 1021 | } 1022 | if (temp > 0) { 1023 | for (var n = 0; n < array_div.length; n++) { 1024 | if (array_div[n] != "") { 1025 | $(array_style[n][0]).style.left = parseInt(array_style[n][4]) * num + div_margin * num + "px"; 1026 | $(array_style[n][0]).style.top = parseInt(array_style[n][5]) * num + div_margin * num + "px"; 1027 | checkxy(array_style[n][0]); 1028 | } 1029 | } 1030 | } 1031 | } 1032 | 1033 | //显示隐藏层 1034 | function showhide(e, op) { 1035 | var temp_div = $("" + e + ""); 1036 | if (temp_div) { 1037 | var display = "blcok"; 1038 | if (op != "true") { 1039 | display = temp_div.style.display; 1040 | } 1041 | switch (display) { 1042 | case "block": 1043 | temp_div.style.display = "none"; 1044 | break; 1045 | default: 1046 | temp_div.style.display = "block"; 1047 | break; 1048 | } 1049 | } 1050 | } 1051 | 1052 | //显示隐藏当前层 1053 | function showNonceDiv(op) { 1054 | checkxy('nonce_div'); 1055 | showhide('nonce_div', op); 1056 | } 1057 | 1058 | //显示隐藏生成样式层 1059 | function showSaveDiv() { 1060 | showhide('save_css_div'); 1061 | } 1062 | 1063 | //显示隐藏操作层 1064 | function showOpDiv() { 1065 | showhide('op_div'); 1066 | } 1067 | 1068 | //打开窗口 1069 | function menuOpenWin() { 1070 | var op = arguments[0].target.data.item.name; 1071 | 1072 | switch (op) { 1073 | case "allDiv": 1074 | doWindow('divlist.html', 'width=600,height=600,top=100,scrollbars=yes'); 1075 | break; 1076 | case "about": 1077 | doWindow('about.html', 'width=460,height=360,scrollbars=yes'); 1078 | break; 1079 | case "help": 1080 | doWindow('help.html', 'width=700,height=600,top=100,scrollbars=yes'); 1081 | break; 1082 | default: 1083 | break; 1084 | } 1085 | } 1086 | 1087 | //初始化页面 1088 | function doLoad() { 1089 | //菜单 1090 | var menu = air.ui.Menu.createFromJSON("lib/menus/menu.js"); 1091 | air.ui.Menu.setAsMenu(menu); 1092 | var menu1 = air.ui.Menu.createFromJSON("lib/menus/menu2.js"); 1093 | air.ui.Menu.setAsContextMenu(menu1, "div_image_view"); 1094 | 1095 | $('button_div_del').addEventListener('click', delDiv); 1096 | $('button_div_edit').addEventListener('click', editDiv); 1097 | $('button_div_margin_edit').addEventListener('click', editDivMargin); 1098 | $('input_div_margin').addEventListener('focus', doEditDivMargin); 1099 | 1100 | $('bt_copy_css').addEventListener('click', doCopyCss); 1101 | $('button_div_copy_width').addEventListener('click', doCopyDivCss); 1102 | $('button_div_copy_height').addEventListener('click', doCopyDivCss); 1103 | $('button_div_copy_left').addEventListener('click', doCopyDivCss); 1104 | $('button_div_copy_top').addEventListener('click', doCopyDivCss); 1105 | $('button_div_copy').addEventListener('click', doCopyDivCss); 1106 | $('button_div_copy_wh').addEventListener('click', doCopyDivCss); 1107 | $('button_div_copy_xy').addEventListener('click', doCopyDivCss); 1108 | $('button_copy_left').addEventListener('click', doCopyDiv); 1109 | $('button_copy_top').addEventListener('click', doCopyDiv); 1110 | $('button_copy_right').addEventListener('click', doCopyDiv); 1111 | $('button_copy_bottom').addEventListener('click', doCopyDiv); 1112 | 1113 | $('checkbox_copy_div_class').checked = ""; 1114 | $('checkbox_copy_div_width').checked = ""; 1115 | $('checkbox_copy_div_height').checked = ""; 1116 | $('checkbox_show_div_width').addEventListener('click', set_divwh); 1117 | $('checkbox_show_div_height').addEventListener('click', set_divwh); 1118 | 1119 | image = new air.Loader(); 1120 | image.contentLoaderInfo.addEventListener(air.Event.COMPLETE, doComplete); 1121 | 1122 | file = air.File.applicationDirectory; 1123 | file.addEventListener(air.Event.SELECT, doSelectImg); 1124 | 1125 | file_xml = air.File.applicationDirectory; 1126 | file_xml.addEventListener(air.Event.SELECT, doSelectXml); 1127 | 1128 | $('bt_view_css').addEventListener('click', view_css); 1129 | 1130 | $('input_div_name').addEventListener('focus', doEdit); 1131 | $('input_div_width').addEventListener('focus', doEdit); 1132 | $('input_div_height').addEventListener('focus', doEdit); 1133 | $('input_div_left').addEventListener('focus', doEdit); 1134 | $('input_div_top').addEventListener('focus', doEdit); 1135 | 1136 | $('image_view').addEventListener('dblclick', addDiv); 1137 | } 1138 | 1139 | //快捷键 1140 | function keyDown(e) { 1141 | var e = event ? event : window.event.getEvent(); 1142 | var key = runtime.flash.ui.Keyboard; 1143 | var temp_img = $("image_view").src; 1144 | var temp_div = $("input_div_id").value; 1145 | var key_ctrl = e.ctrlKey; 1146 | var key_alt = e.altKey; 1147 | var key_shift = e.shiftKey; 1148 | 1149 | if (temp_img != "") { 1150 | if (key_ctrl) { 1151 | switch (event.keyCode) { 1152 | case key.NUMBER_0: 1153 | case key.NUMPAD_1: 1154 | image_x(1); 1155 | break; 1156 | case key.NUMBER_2: 1157 | case key.NUMPAD_2: 1158 | image_x(2); 1159 | break; 1160 | case key.NUMBER_4: 1161 | case key.NUMPAD_4: 1162 | image_x(4); 1163 | break; 1164 | case key.NUMBER_6: 1165 | case key.NUMPAD_6: 1166 | image_x(6); 1167 | break; 1168 | } 1169 | } 1170 | } 1171 | if (event.keyCode == 116) { 1172 | refreshPic(); 1173 | } 1174 | if (temp_div != "") { 1175 | //alert("ASCII代码是:"+event.keyCode); 1176 | if (event.keyCode == key.DELETE || event.keyCode == 15 && event.keyCode == 8) { 1177 | delDiv(event, temp_div); 1178 | } 1179 | if (key_shift && key_ctrl) { 1180 | switch (event.keyCode) { 1181 | case 38: 1182 | div_info(temp_div, 0, -1, 0, 0); 1183 | update_info(temp_div); 1184 | checkwh(temp_div); 1185 | break; 1186 | case 40: 1187 | div_info(temp_div, 0, 1, 0, 0); 1188 | update_info(temp_div); 1189 | checkwh(temp_div); 1190 | break; 1191 | case 37: 1192 | div_info(temp_div, -1, 0, 0, 0); 1193 | update_info(temp_div); 1194 | checkwh(temp_div); 1195 | break; 1196 | case 39: 1197 | div_info(temp_div, 1, 0, 0, 0); 1198 | update_info(temp_div); 1199 | checkwh(temp_div); 1200 | break; 1201 | } 1202 | } 1203 | else 1204 | if (!key_shift && key_ctrl) { 1205 | switch (event.keyCode) { 1206 | case 38: 1207 | div_info(temp_div, 0, 0, 0, -1); 1208 | update_info(temp_div); 1209 | checkxy(temp_div); 1210 | break; 1211 | case 40: 1212 | div_info(temp_div, 0, 0, 0, 1); 1213 | update_info(temp_div); 1214 | checkxy(temp_div); 1215 | break; 1216 | case 37: 1217 | div_info(temp_div, 0, 0, -1, 0); 1218 | update_info(temp_div); 1219 | checkxy(temp_div); 1220 | break; 1221 | case 39: 1222 | div_info(temp_div, 0, 0, 1, 0); 1223 | update_info(temp_div); 1224 | checkxy(temp_div); 1225 | break; 1226 | } 1227 | } 1228 | } 1229 | } 1230 | 1231 | /* 1232 | * 打开新窗口 1233 | */ 1234 | function doWindow(page, info) { 1235 | /* 1236 | var init = new air.NativeWindowInitOptions(); 1237 | var bounds = null; 1238 | var win = null; 1239 | var page = air.File.applicationDirectory.resolvePath( page ); 1240 | bounds = new air.Rectangle( ( air.Capabilities.screenResolutionX - 325 ) / 2, ( air.Capabilities.screenResolutionY - 145 ) / 2, 325, 145 ); 1241 | init.minimizable = false; 1242 | init.maximizable = false; 1243 | init.resizable = false; 1244 | 1245 | win = air.HTMLLoader.createRootWindow( true, init, false, bounds ); 1246 | win.load( new air.URLRequest( page.url ) ); 1247 | */ 1248 | var login = window.open(page, null, info); 1249 | } 1250 | 1251 | function doCopyDiv() { 1252 | var id = this.id; 1253 | var rn = Math.round(Math.random() * 10000); 1254 | var temp = $("input_div_id").value; 1255 | var n = get_array_num(temp); 1256 | var temp_id = temp_name = "div_" + rn; 1257 | var temp_width = parseInt(array_style[n][2]) * num; 1258 | var temp_height = parseInt(array_style[n][3]) * num; 1259 | var temp_left = parseInt(array_style[n][4]) * num + div_margin * num; 1260 | var temp_top = parseInt(array_style[n][5]) * num + div_margin * num; 1261 | var temp_array = new Array(); 1262 | var pyl = $("input_copy_pyl").value; 1263 | 1264 | if (pyl == "") { 1265 | pyl = default_width * num; 1266 | } 1267 | else { 1268 | pyl = pyl * num; 1269 | } 1270 | switch (id) { 1271 | case "button_copy_left": 1272 | temp_left = temp_left - pyl; 1273 | break; 1274 | case "button_copy_top": 1275 | temp_top = temp_top - pyl; 1276 | break; 1277 | case "button_copy_right": 1278 | temp_left = temp_left + pyl; 1279 | break; 1280 | case "button_copy_bottom": 1281 | temp_top = temp_top + pyl; 1282 | break; 1283 | } 1284 | 1285 | temp_array = [temp_id, temp_name, temp_width, temp_height, temp_left, temp_top]; 1286 | addDiv(temp_array, addDiv); 1287 | $(temp).className = "div-dnr"; 1288 | div_info(temp_id, 0, 0, 0, 0); 1289 | update_info(temp_id); 1290 | } 1291 | 1292 | //复制当前层样式 1293 | function doCopyDivCss(event) { 1294 | var temp_id = this.id; 1295 | var temp = $("input_div_id").value; 1296 | var n = get_array_num(temp); 1297 | var checkbox_show_class = $("checkbox_copy_div_class").checked; 1298 | var checkbox_show_width = $("checkbox_copy_div_width").checked; 1299 | var checkbox_show_height = $("checkbox_copy_div_height").checked; 1300 | var copy = ""; 1301 | 1302 | if (temp != "") { 1303 | checkinput(temp); 1304 | switch (temp_id) { 1305 | case "button_div_copy_width": 1306 | copy = "width:" + array_style[n][2] + "px;"; 1307 | break; 1308 | case "button_div_copy_height": 1309 | copy = "height:" + array_style[n][3] + "px;"; 1310 | break; 1311 | case "button_div_copy_left": 1312 | copy = (0 - array_style[n][4]) + "px"; 1313 | break; 1314 | case "button_div_copy_top": 1315 | copy = (0 - array_style[n][5]) + "px"; 1316 | break; 1317 | case "button_div_copy": 1318 | if (checkbox_show_class) { 1319 | copy = "." + array_style[n][1] + "{"; 1320 | } 1321 | if (checkbox_show_width) { 1322 | copy += "width:" + array_style[n][2] + "px;"; 1323 | } 1324 | if (checkbox_show_height) { 1325 | copy += "height:" + array_style[n][3] + "px;"; 1326 | } 1327 | copy += "background-position:" + checkNum(array_style[n][4]) + " " + checkNum(array_style[n][5]) + ";"; 1328 | if (checkbox_show_class) { 1329 | copy += "}\n"; 1330 | } 1331 | break; 1332 | case "button_div_copy_wh": 1333 | copy += "width:" + array_style[n][2] + "px;height:" + array_style[n][3] + "px;"; 1334 | break; 1335 | case "button_div_copy_xy": 1336 | copy += checkNum(array_style[n][4]) + " " + checkNum(array_style[n][5]); 1337 | break; 1338 | } 1339 | } 1340 | 1341 | air.Clipboard.generalClipboard.clear(); 1342 | air.Clipboard.generalClipboard.setData(air.ClipboardFormats.TEXT_FORMAT, copy); 1343 | doTimer("样式 " + copy + " 已复制到剪贴板!"); 1344 | } 1345 | 1346 | //复制所有样式 1347 | function doCopyCss(v) { 1348 | var copy = $("div_view_css").innerText; 1349 | air.Clipboard.generalClipboard.clear(); 1350 | air.Clipboard.generalClipboard.setData(air.ClipboardFormats.TEXT_FORMAT, copy); 1351 | doTimer("样式复制成功!"); 1352 | } 1353 | 1354 | //刷新图片 1355 | function refreshPic() { 1356 | if ($("image_view").src != "") { 1357 | image.load(new air.URLRequest(image_url)); 1358 | file_path = image_url.replace("file:///", ""); 1359 | doComplete(event); 1360 | } 1361 | } 1362 | 1363 | function doTimer(txt) { 1364 | $("hint_txt").style.display = "block"; 1365 | $("hint_txt").innerText = txt; 1366 | setTimeout(function () { $("hint_txt").style.display = "none" }, 1500); 1367 | } 1368 | 1369 | //读取设置 1370 | function doCompleteXml() { 1371 | xml = new XMLHttpRequest(); 1372 | 1373 | xml.onreadystatechange = function () { 1374 | read_end = false; 1375 | var version = null; 1376 | var imginfo = null; 1377 | var divinfo = null; 1378 | var temp_path = null; 1379 | var temp_id = null; 1380 | var temp_name = null; 1381 | var temp_width = null; 1382 | var temp_height = null; 1383 | var temp_left = null; 1384 | var temp_top = null; 1385 | var temp_set_width = null; 1386 | var temp_set_height = null; 1387 | var temp_array = new Array(); 1388 | var temp_array_div = new Array(); 1389 | image_path.length = 0; 1390 | 1391 | if (xml.readyState == 4) { 1392 | imginfo = xml.responseXML.documentElement.getElementsByTagName('imginfo'); 1393 | divinfo = xml.responseXML.documentElement.getElementsByTagName('divinfo'); 1394 | version = xml.responseXML.documentElement.getElementsByTagName('version'); 1395 | 1396 | image_path[0] = temp_path = imginfo[0].getElementsByTagName('path')[0].textContent; 1397 | temp_width = imginfo[0].getElementsByTagName('width')[0].textContent; 1398 | temp_height = imginfo[0].getElementsByTagName('height')[0].textContent; 1399 | $("input_div_margin").value = div_margin = imginfo[0].getElementsByTagName('margin')[0].textContent; 1400 | $("textarea_gb_class").value = imginfo[0].getElementsByTagName('gbstyle')[0].textContent; 1401 | 1402 | temp_array_div = [temp_path, temp_width, temp_height] 1403 | doComplete(event, temp_array_div); 1404 | if (version == "3") { 1405 | for (var c = 0; c < divinfo.length; c++) { 1406 | temp_id = divinfo[c].getElementsByTagName('id')[0].textContent; 1407 | temp_name = divinfo[c].getElementsByTagName('name')[0].textContent; 1408 | temp_width = divinfo[c].getElementsByTagName('width')[0].textContent; 1409 | temp_height = divinfo[c].getElementsByTagName('height')[0].textContent; 1410 | temp_left = divinfo[c].getElementsByTagName('left')[0].textContent; 1411 | temp_top = divinfo[c].getElementsByTagName('top')[0].textContent; 1412 | temp_set_width = divinfo[c].getElementsByTagName('setWidth')[0].textContent; 1413 | temp_set_height = divinfo[c].getElementsByTagName('setHeight')[0].textContent; 1414 | 1415 | temp_array[c] = [temp_id, temp_name, temp_width, temp_height, temp_left, temp_top, temp_set_width, temp_set_height]; 1416 | } 1417 | } 1418 | else { 1419 | for (var c = 0; c < divinfo.length; c++) { 1420 | temp_id = divinfo[c].getElementsByTagName('id')[0].textContent; 1421 | temp_name = divinfo[c].getElementsByTagName('name')[0].textContent; 1422 | temp_width = divinfo[c].getElementsByTagName('width')[0].textContent; 1423 | temp_height = divinfo[c].getElementsByTagName('height')[0].textContent; 1424 | temp_left = divinfo[c].getElementsByTagName('left')[0].textContent; 1425 | temp_top = divinfo[c].getElementsByTagName('top')[0].textContent; 1426 | 1427 | temp_array[c] = [temp_id, temp_name, temp_width, temp_height, temp_left, temp_top]; 1428 | } 1429 | } 1430 | $("div_view_css").innerText = ""; 1431 | temp_path = "file:///" + temp_path; 1432 | image.load(new air.URLRequest(temp_path)); 1433 | setDiv(temp_array); 1434 | } 1435 | read_end = true; 1436 | } 1437 | xml.open('GET', file_xml.url, true); 1438 | xml.send(null); 1439 | } 1440 | 1441 | function setDiv(e) { 1442 | for (var c = 0; c < array_div.length; c++) { 1443 | if (array_div[c] != "") { 1444 | delDiv(event, array_div[c]); 1445 | } 1446 | } 1447 | 1448 | array_div.length = 0; 1449 | array_style.length = 0; 1450 | num_array_style = 0; 1451 | image_x(1); 1452 | 1453 | for (var c = 0; c < e.length; c++) { 1454 | array_div[c] = e[c][0]; 1455 | addDiv(e[c], addDiv); 1456 | } 1457 | updataDivMagin(); 1458 | } 1459 | 1460 | function delAll() { 1461 | for (var c = 0; c < array_div.length; c++) { 1462 | if (array_div[c] != "") { 1463 | delDiv(event, array_div[c]); 1464 | } 1465 | } 1466 | 1467 | array_div.length = 0; 1468 | array_style.length = 0; 1469 | num_array_style = 0; 1470 | } 1471 | 1472 | /* 1473 | 用于其它页面调用 1474 | */ 1475 | function div_list() { 1476 | var temp = new Array(); 1477 | var temp_lenght = array_div.length; 1478 | for (var n = 0; n < temp_lenght; n++) { 1479 | if (array_div[n] != "") { 1480 | temp[n] = array_style[n]; 1481 | } 1482 | } 1483 | 1484 | return temp; 1485 | } 1486 | 1487 | function div_list_del(e) { 1488 | delDiv(event, e); 1489 | } 1490 | 1491 | function reset_div_class() { 1492 | var temp_div = $("input_div_id").value; 1493 | if (temp_div) { 1494 | temp_div = $(temp_div); 1495 | temp_div.className = "div-dnr"; 1496 | } 1497 | } 1498 | 1499 | function checkUpdates() { 1500 | openInBrowser("https://github.com/ghostzhang/bg2css/releases") 1501 | } -------------------------------------------------------------------------------- /lib/menus/menu.js: -------------------------------------------------------------------------------- 1 | [{ 2 | label: "文件", 3 | items: [{ 4 | label: "选择图片", 5 | keyEquivalent: "O", 6 | onSelect: doBrowseImg 7 | }, { 8 | label: "读取定义文件", 9 | keyEquivalent: "O", 10 | shiftKey: true, 11 | onSelect: doBrowseXml 12 | }, { 13 | type: "separator" 14 | }, { 15 | label: "保存当前定义", 16 | keyEquivalent: "S", 17 | onSelect: doSave 18 | }] 19 | }, { 20 | label: "图层", 21 | items: [{ 22 | label: "显示|隐藏“当前层信息”", 23 | keyEquivalent: "N", 24 | onSelect: showNonceDiv 25 | }, { 26 | label: "显示|隐藏“所有层信息”", 27 | keyEquivalent: "N", 28 | shiftKey: true, 29 | name: "allDiv", 30 | onSelect: menuOpenWin 31 | }] 32 | }, { 33 | label: "操作", 34 | items: [{ 35 | label: "刷新图片", 36 | toggled: "true", 37 | onSelect: refreshPic 38 | }, { 39 | type: "separator" 40 | },{ 41 | label: "新建层时显示“当前层信息”", 42 | type: "check", 43 | name: "show_new", 44 | toggled: "true", 45 | onSelect: setShowDiv 46 | }, { 47 | label: "选中层时显示“当前层信息”", 48 | type: "check", 49 | name: "show_nonce", 50 | toggled: "true", 51 | onSelect: setShowDiv 52 | }, { 53 | type: "separator" 54 | }, { 55 | label: "显示|隐藏“区定义”", 56 | keyEquivalent: "M", 57 | onSelect: showOpDiv 58 | }, { 59 | type: "separator" 60 | }, { 61 | label: "生成样式", 62 | keyEquivalent: "P", 63 | onSelect: showSaveDiv 64 | }, { 65 | label: "样式预览", 66 | shiftKey: true, 67 | keyEquivalent: "P", 68 | onSelect: view_css 69 | }] 70 | }, { 71 | label: "帮助", 72 | items: [{ 73 | label: "关于...", 74 | name: "about", 75 | onSelect: menuOpenWin 76 | }, { 77 | label: "快捷键...", 78 | name: "help", 79 | onSelect: menuOpenWin 80 | }, { 81 | type: "separator" 82 | }, { 83 | label: "检查更新...", 84 | onSelect: checkUpdates 85 | }] 86 | }] 87 | -------------------------------------------------------------------------------- /lib/menus/menu2.js: -------------------------------------------------------------------------------- 1 | [{ 2 | label: "显示|隐藏“当前层信息”", 3 | toggled: "false", 4 | keyEquivalent: "N", 5 | onSelect: showNonceDiv 6 | }, { 7 | label: "显示|隐藏“所有层信息", 8 | keyEquivalent: "N", 9 | shiftKey: true, 10 | name: "allDiv", 11 | onSelect: menuOpenWin 12 | }, { 13 | type: "separator" 14 | }, { 15 | label: "显示|隐藏“区定义”", 16 | keyEquivalent: "M", 17 | onSelect: showOpDiv 18 | }, { 19 | label: "生成样式", 20 | keyEquivalent: "P", 21 | onSelect: showSaveDiv 22 | }] 23 | --------------------------------------------------------------------------------