Lib_Js_Mage - Version 1.6.0.0

Version Notes

1.6.0.0

Download this release

Release Info

Developer Magento Core Team
Extension Lib_Js_Mage
Version 1.6.0.0
Comparing to
See all releases


Version 1.6.0.0

Files changed (57) hide show
  1. js/blank.html +0 -0
  2. js/flash/AC_RunActiveContent.js +292 -0
  3. js/index.php +144 -0
  4. js/lib/FABridge.js +613 -0
  5. js/lib/boxover.js +372 -0
  6. js/lib/ccard.js +28 -0
  7. js/lib/dropdown.js +36 -0
  8. js/lib/ds-sleight.js +38 -0
  9. js/lib/flex.js +427 -0
  10. js/mage/adminhtml/accordion.js +139 -0
  11. js/mage/adminhtml/browser.js +395 -0
  12. js/mage/adminhtml/events.js +137 -0
  13. js/mage/adminhtml/flexuploader.js +372 -0
  14. js/mage/adminhtml/form.js +470 -0
  15. js/mage/adminhtml/giftmessage.js +280 -0
  16. js/mage/adminhtml/giftoptions/tooltip.js +211 -0
  17. js/mage/adminhtml/grid.js +850 -0
  18. js/mage/adminhtml/hash.js +162 -0
  19. js/mage/adminhtml/image.js +91 -0
  20. js/mage/adminhtml/loader.js +282 -0
  21. js/mage/adminhtml/magento-all.js +25 -0
  22. js/mage/adminhtml/product.js +1052 -0
  23. js/mage/adminhtml/product/composite/configure.js +765 -0
  24. js/mage/adminhtml/rules.js +383 -0
  25. js/mage/adminhtml/sales.js +1055 -0
  26. js/mage/adminhtml/sales/packaging.js +813 -0
  27. js/mage/adminhtml/scrollbar.js +397 -0
  28. js/mage/adminhtml/tabs.js +248 -0
  29. js/mage/adminhtml/tools.js +735 -0
  30. js/mage/adminhtml/uploader.js +258 -0
  31. js/mage/adminhtml/variables.js +164 -0
  32. js/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentovariable/editor_plugin.js +67 -0
  33. js/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentovariable/img/icon.gif +0 -0
  34. js/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js +90 -0
  35. js/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/img/icon.gif +0 -0
  36. js/mage/adminhtml/wysiwyg/tiny_mce/setup.js +351 -0
  37. js/mage/adminhtml/wysiwyg/tiny_mce/themes/advanced/skins/default/content.css +55 -0
  38. js/mage/adminhtml/wysiwyg/tiny_mce/themes/advanced/skins/default/dialog.css +87 -0
  39. js/mage/adminhtml/wysiwyg/widget.js +396 -0
  40. js/mage/centinel.js +112 -0
  41. js/mage/cookies.js +78 -0
  42. js/mage/directpost.js +414 -0
  43. js/mage/translate.js +50 -0
  44. js/mage/translate_inline.css +36 -0
  45. js/mage/translate_inline.js +196 -0
  46. js/spacer.gif +0 -0
  47. js/varien/accordion.js +112 -0
  48. js/varien/configurable.js +319 -0
  49. js/varien/form.js +328 -0
  50. js/varien/iehover-fix.js +64 -0
  51. js/varien/js.js +682 -0
  52. js/varien/menu.js +132 -0
  53. js/varien/payment.js +68 -0
  54. js/varien/product.js +722 -0
  55. js/varien/telephone.js +131 -0
  56. js/varien/weee.js +36 -0
  57. package.xml +18 -0
js/blank.html ADDED
File without changes
js/flash/AC_RunActiveContent.js ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //v1.7
2
+ // Flash Player Version Detection
3
+ // Detect Client Browser type
4
+ // Copyright 2005-2007 Adobe Systems Incorporated. All rights reserved.
5
+ var isIE = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;
6
+ var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;
7
+ var isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false;
8
+
9
+ function ControlVersion()
10
+ {
11
+ var version;
12
+ var axo;
13
+ var e;
14
+
15
+ // NOTE : new ActiveXObject(strFoo) throws an exception if strFoo isn't in the registry
16
+
17
+ try {
18
+ // version will be set for 7.X or greater players
19
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
20
+ version = axo.GetVariable("$version");
21
+ } catch (e) {
22
+ }
23
+
24
+ if (!version)
25
+ {
26
+ try {
27
+ // version will be set for 6.X players only
28
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
29
+
30
+ // installed player is some revision of 6.0
31
+ // GetVariable("$version") crashes for versions 6.0.22 through 6.0.29,
32
+ // so we have to be careful.
33
+
34
+ // default to the first public version
35
+ version = "WIN 6,0,21,0";
36
+
37
+ // throws if AllowScripAccess does not exist (introduced in 6.0r47)
38
+ axo.AllowScriptAccess = "always";
39
+
40
+ // safe to call for 6.0r47 or greater
41
+ version = axo.GetVariable("$version");
42
+
43
+ } catch (e) {
44
+ }
45
+ }
46
+
47
+ if (!version)
48
+ {
49
+ try {
50
+ // version will be set for 4.X or 5.X player
51
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");
52
+ version = axo.GetVariable("$version");
53
+ } catch (e) {
54
+ }
55
+ }
56
+
57
+ if (!version)
58
+ {
59
+ try {
60
+ // version will be set for 3.X player
61
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");
62
+ version = "WIN 3,0,18,0";
63
+ } catch (e) {
64
+ }
65
+ }
66
+
67
+ if (!version)
68
+ {
69
+ try {
70
+ // version will be set for 2.X player
71
+ axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
72
+ version = "WIN 2,0,0,11";
73
+ } catch (e) {
74
+ version = -1;
75
+ }
76
+ }
77
+
78
+ return version;
79
+ }
80
+
81
+ // JavaScript helper required to detect Flash Player PlugIn version information
82
+ function GetSwfVer(){
83
+ // NS/Opera version >= 3 check for Flash plugin in plugin array
84
+ var flashVer = -1;
85
+
86
+ if (navigator.plugins != null && navigator.plugins.length > 0) {
87
+ if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) {
88
+ var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
89
+ var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
90
+ var descArray = flashDescription.split(" ");
91
+ var tempArrayMajor = descArray[2].split(".");
92
+ var versionMajor = tempArrayMajor[0];
93
+ var versionMinor = tempArrayMajor[1];
94
+ var versionRevision = descArray[3];
95
+ if (versionRevision == "") {
96
+ versionRevision = descArray[4];
97
+ }
98
+ if (versionRevision[0] == "d") {
99
+ versionRevision = versionRevision.substring(1);
100
+ } else if (versionRevision[0] == "r") {
101
+ versionRevision = versionRevision.substring(1);
102
+ if (versionRevision.indexOf("d") > 0) {
103
+ versionRevision = versionRevision.substring(0, versionRevision.indexOf("d"));
104
+ }
105
+ }
106
+ var flashVer = versionMajor + "." + versionMinor + "." + versionRevision;
107
+ }
108
+ }
109
+ // MSN/WebTV 2.6 supports Flash 4
110
+ else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4;
111
+ // WebTV 2.5 supports Flash 3
112
+ else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3;
113
+ // older WebTV supports Flash 2
114
+ else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2;
115
+ else if ( isIE && isWin && !isOpera ) {
116
+ flashVer = ControlVersion();
117
+ }
118
+ return flashVer;
119
+ }
120
+
121
+ // When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available
122
+ function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision)
123
+ {
124
+ versionStr = GetSwfVer();
125
+ if (versionStr == -1 ) {
126
+ return false;
127
+ } else if (versionStr != 0) {
128
+ if(isIE && isWin && !isOpera) {
129
+ // Given "WIN 2,0,0,11"
130
+ tempArray = versionStr.split(" "); // ["WIN", "2,0,0,11"]
131
+ tempString = tempArray[1]; // "2,0,0,11"
132
+ versionArray = tempString.split(","); // ['2', '0', '0', '11']
133
+ } else {
134
+ versionArray = versionStr.split(".");
135
+ }
136
+ var versionMajor = versionArray[0];
137
+ var versionMinor = versionArray[1];
138
+ var versionRevision = versionArray[2];
139
+
140
+ // is the major.revision >= requested major.revision AND the minor version >= requested minor
141
+ if (versionMajor > parseFloat(reqMajorVer)) {
142
+ return true;
143
+ } else if (versionMajor == parseFloat(reqMajorVer)) {
144
+ if (versionMinor > parseFloat(reqMinorVer))
145
+ return true;
146
+ else if (versionMinor == parseFloat(reqMinorVer)) {
147
+ if (versionRevision >= parseFloat(reqRevision))
148
+ return true;
149
+ }
150
+ }
151
+ return false;
152
+ }
153
+ }
154
+
155
+ function AC_AddExtension(src, ext)
156
+ {
157
+ if (src.indexOf('?') != -1)
158
+ return src.replace(/\?/, ext+'?');
159
+ else
160
+ return src + ext;
161
+ }
162
+
163
+ function AC_Generateobj(objAttrs, params, embedAttrs)
164
+ {
165
+ var str = '';
166
+ if (isIE && isWin && !isOpera)
167
+ {
168
+ str += '<object ';
169
+ for (var i in objAttrs)
170
+ {
171
+ str += i + '="' + objAttrs[i] + '" ';
172
+ }
173
+ str += '>';
174
+ for (var i in params)
175
+ {
176
+ str += '<param name="' + i + '" value="' + params[i] + '" /> ';
177
+ }
178
+ str += '</object>';
179
+ }
180
+ else
181
+ {
182
+ str += '<embed ';
183
+ for (var i in embedAttrs)
184
+ {
185
+ str += i + '="' + embedAttrs[i] + '" ';
186
+ }
187
+ str += '> </embed>';
188
+ }
189
+
190
+ document.write(str);
191
+ }
192
+
193
+ function AC_FL_RunContent(){
194
+ var ret =
195
+ AC_GetArgs
196
+ ( arguments, ".swf", "movie", "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
197
+ , "application/x-shockwave-flash"
198
+ );
199
+ AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs);
200
+ }
201
+
202
+ function AC_SW_RunContent(){
203
+ var ret =
204
+ AC_GetArgs
205
+ ( arguments, ".dcr", "src", "clsid:166B1BCA-3F9C-11CF-8075-444553540000"
206
+ , null
207
+ );
208
+ AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs);
209
+ }
210
+
211
+ function AC_GetArgs(args, ext, srcParamName, classid, mimeType){
212
+ var ret = new Object();
213
+ ret.embedAttrs = new Object();
214
+ ret.params = new Object();
215
+ ret.objAttrs = new Object();
216
+ for (var i=0; i < args.length; i=i+2){
217
+ var currArg = args[i].toLowerCase();
218
+
219
+ switch (currArg){
220
+ case "classid":
221
+ break;
222
+ case "pluginspage":
223
+ ret.embedAttrs[args[i]] = args[i+1];
224
+ break;
225
+ case "src":
226
+ case "movie":
227
+ args[i+1] = AC_AddExtension(args[i+1], ext);
228
+ ret.embedAttrs["src"] = args[i+1];
229
+ ret.params[srcParamName] = args[i+1];
230
+ break;
231
+ case "onafterupdate":
232
+ case "onbeforeupdate":
233
+ case "onblur":
234
+ case "oncellchange":
235
+ case "onclick":
236
+ case "ondblclick":
237
+ case "ondrag":
238
+ case "ondragend":
239
+ case "ondragenter":
240
+ case "ondragleave":
241
+ case "ondragover":
242
+ case "ondrop":
243
+ case "onfinish":
244
+ case "onfocus":
245
+ case "onhelp":
246
+ case "onmousedown":
247
+ case "onmouseup":
248
+ case "onmouseover":
249
+ case "onmousemove":
250
+ case "onmouseout":
251
+ case "onkeypress":
252
+ case "onkeydown":
253
+ case "onkeyup":
254
+ case "onload":
255
+ case "onlosecapture":
256
+ case "onpropertychange":
257
+ case "onreadystatechange":
258
+ case "onrowsdelete":
259
+ case "onrowenter":
260
+ case "onrowexit":
261
+ case "onrowsinserted":
262
+ case "onstart":
263
+ case "onscroll":
264
+ case "onbeforeeditfocus":
265
+ case "onactivate":
266
+ case "onbeforedeactivate":
267
+ case "ondeactivate":
268
+ case "type":
269
+ case "codebase":
270
+ case "id":
271
+ ret.objAttrs[args[i]] = args[i+1];
272
+ break;
273
+ case "width":
274
+ case "height":
275
+ case "align":
276
+ case "vspace":
277
+ case "hspace":
278
+ case "class":
279
+ case "title":
280
+ case "accesskey":
281
+ case "name":
282
+ case "tabindex":
283
+ ret.embedAttrs[args[i]] = ret.objAttrs[args[i]] = args[i+1];
284
+ break;
285
+ default:
286
+ ret.embedAttrs[args[i]] = ret.params[args[i]] = args[i+1];
287
+ }
288
+ }
289
+ ret.objAttrs["classid"] = classid;
290
+ if (mimeType) ret.embedAttrs["type"] = mimeType;
291
+ return ret;
292
+ }
js/index.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * DISCLAIMER
16
+ *
17
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
18
+ * versions in the future. If you wish to customize Magento for your
19
+ * needs please refer to http://www.magentocommerce.com for more information.
20
+ *
21
+ * @category Mage
22
+ * @package Mage_Core
23
+ * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
24
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
25
+ */
26
+
27
+ /**
28
+ * Proxy script to combine and compress one or few files for JS and CSS
29
+ *
30
+ * Restricts access only to files under current script's folder
31
+ *
32
+ * @category Mage
33
+ * @package Mage_Core
34
+ * @author Magento Core Team <core@magentocommerce.com>
35
+ */
36
+
37
+ // no files specified return 404
38
+ if (empty($_GET['f'])) {
39
+ header('HTTP/1.0 404 Not Found');
40
+ echo "SYNTAX: index.php/x.js?f=dir1/file1.js,dir2/file2.js";
41
+ exit;
42
+ }
43
+
44
+ // allow web server set content type automatically
45
+ $contentType = false;
46
+
47
+ // set custom content type if specified
48
+ if (isset($_GET['c'])) {
49
+ $contentType = $_GET['c']==='auto' ? true : $_GET['c'];
50
+ }
51
+
52
+ // get files content
53
+ $files = is_array($_GET['f']) ? $_GET['f'] : explode(',', $_GET['f']);
54
+
55
+ // set allowed content-type
56
+ $contentTypeAllowed = array(
57
+ 'text/javascript',
58
+ 'text/css',
59
+ // 'image/gif',
60
+ // 'image/png',
61
+ // 'image/jpeg',
62
+ );
63
+ // set allowed file extensions
64
+ $fileExtAllowed = array(
65
+ 'js',
66
+ 'css',
67
+ // 'gif',
68
+ // 'png',
69
+ // 'js'
70
+ );
71
+
72
+ $out = '';
73
+ $lastModified = 0;
74
+ foreach ($files as $f) {
75
+ $fileRealPath = realpath($f);
76
+ // check file path (security)
77
+ if (strpos($fileRealPath, realpath(dirname(__FILE__))) !== 0) {
78
+ continue;
79
+ }
80
+
81
+ $fileExt = strtolower(pathinfo($fileRealPath, PATHINFO_EXTENSION));
82
+
83
+ // check file extension
84
+ if (empty($fileExt) || !in_array($fileExt, $fileExtAllowed)) {
85
+ continue;
86
+ }
87
+
88
+ // try automatically get content type if requested
89
+ if ($contentType === true) {
90
+ $contentTypes = array(
91
+ 'js' => 'text/javascript',
92
+ 'css' => 'text/css',
93
+ // 'gif' => 'image/gif',
94
+ // 'png' => 'image/png',
95
+ // 'jpg' => 'image/jpeg',
96
+ );
97
+ if (empty($contentTypes[$fileExt])) { // security
98
+ continue;
99
+ }
100
+ $contentType = !empty($contentTypes[$fileExt]) ? $contentTypes[$fileExt] : false;
101
+ }
102
+
103
+ // append file contents
104
+ // we must have blank line at the end of all files but if somebody forget to add it
105
+ // we need add it here
106
+ $out .= file_get_contents($fileRealPath) . "\n";
107
+ $lastModified = max($lastModified, filemtime($fileRealPath));
108
+ }
109
+
110
+ //checking if client have older copy then we have on server
111
+ if (function_exists('date_default_timezone_set')) {
112
+ date_default_timezone_set('UTC');
113
+ }
114
+ if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified) {
115
+ header("HTTP/1.1 304 Not Modified");
116
+ exit;
117
+ }
118
+
119
+ // last modified is the max mtime for loaded files
120
+ header('Cache-Control: must-revalidate');
121
+ header('Last-modified: ' . gmdate('r', $lastModified));
122
+
123
+ // optional custom content type, can be emulated by index.php/x.js or x.css
124
+ if (is_string($contentType) && in_array($contentType, $contentTypeAllowed)) {
125
+ header('Content-type: '.$contentType);
126
+ }
127
+
128
+ // remove spaces, default on
129
+ if (!(isset($_GET['s']) && !$_GET['s'])) {
130
+ $out = preg_replace('#[ \t]+#', ' ', $out);
131
+ }
132
+
133
+ // use gzip or deflate, use this if not enabled in .htaccess, default on
134
+ //if (!(isset($_GET['z']) && !$_GET['z'])) {
135
+ // ini_set('zlib.output_compression', 1);
136
+ //}
137
+
138
+ // add Expires header if not disabled, default 1 year
139
+ if (!(isset($_GET['e']) && $_GET['e']==='no')) {
140
+ $time = time()+(isset($_GET['e']) ? $_GET['e'] : 365)*86400;
141
+ header('Expires: '.gmdate('r', $time));
142
+ }
143
+
144
+ echo $out;
js/lib/FABridge.js ADDED
@@ -0,0 +1,613 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Copyright 2006 Adobe Systems Incorporated
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
5
+ to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6
+ and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7
+
8
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9
+
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
13
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
14
+ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15
+
16
+ */
17
+
18
+
19
+ /*
20
+ * The Bridge class, responsible for navigating AS instances
21
+ */
22
+ function FABridge(target,bridgeName)
23
+ {
24
+ this.target = target;
25
+ this.remoteTypeCache = {};
26
+ this.remoteInstanceCache = {};
27
+ this.remoteFunctionCache = {};
28
+ this.localFunctionCache = {};
29
+ this.bridgeID = FABridge.nextBridgeID++;
30
+ this.name = bridgeName;
31
+ this.nextLocalFuncID = 0;
32
+ FABridge.instances[this.name] = this;
33
+ FABridge.idMap[this.bridgeID] = this;
34
+
35
+ return this;
36
+ }
37
+
38
+ // type codes for packed values
39
+ FABridge.TYPE_ASINSTANCE = 1;
40
+ FABridge.TYPE_ASFUNCTION = 2;
41
+
42
+ FABridge.TYPE_JSFUNCTION = 3;
43
+ FABridge.TYPE_ANONYMOUS = 4;
44
+
45
+ FABridge.initCallbacks = {};
46
+ FABridge.userTypes = {};
47
+
48
+ FABridge.addToUserTypes = function()
49
+ {
50
+ for (var i = 0; i < arguments.length; i++)
51
+ {
52
+ FABridge.userTypes[arguments[i]] = {
53
+ 'typeName': arguments[i],
54
+ 'enriched': false
55
+ };
56
+ }
57
+ }
58
+
59
+ FABridge.argsToArray = function(args)
60
+ {
61
+ var result = [];
62
+ for (var i = 0; i < args.length; i++)
63
+ {
64
+ result[i] = args[i];
65
+ }
66
+ return result;
67
+ }
68
+
69
+ function instanceFactory(objID)
70
+ {
71
+ this.fb_instance_id = objID;
72
+ return this;
73
+ }
74
+
75
+ function FABridge__invokeJSFunction(args)
76
+ {
77
+ var funcID = args[0];
78
+ var throughArgs = args.concat();//FABridge.argsToArray(arguments);
79
+ throughArgs.shift();
80
+
81
+ var bridge = FABridge.extractBridgeFromID(funcID);
82
+ return bridge.invokeLocalFunction(funcID, throughArgs);
83
+ }
84
+
85
+ FABridge.addInitializationCallback = function(bridgeName, callback)
86
+ {
87
+ var inst = FABridge.instances[bridgeName];
88
+ if (inst != undefined)
89
+ {
90
+ callback.call(inst);
91
+ return;
92
+ }
93
+
94
+ var callbackList = FABridge.initCallbacks[bridgeName];
95
+ if(callbackList == null)
96
+ {
97
+ FABridge.initCallbacks[bridgeName] = callbackList = [];
98
+ }
99
+
100
+ callbackList.push(callback);
101
+ }
102
+
103
+ // updated for changes to SWFObject2
104
+ function FABridge__bridgeInitialized(bridgeName) {
105
+ var objects = document.getElementsByTagName("object");
106
+ var ol = objects.length;
107
+ var activeObjects = [];
108
+ if (ol > 0) {
109
+ for (var i = 0; i < ol; i++) {
110
+ if (typeof objects[i].SetVariable != "undefined") {
111
+ activeObjects[activeObjects.length] = objects[i];
112
+ }
113
+ }
114
+ }
115
+ var embeds = document.getElementsByTagName("embed");
116
+ var el = embeds.length;
117
+ var activeEmbeds = [];
118
+ if (el > 0) {
119
+ for (var j = 0; j < el; j++) {
120
+ if (typeof embeds[j].SetVariable != "undefined") {
121
+ activeEmbeds[activeEmbeds.length] = embeds[j];
122
+ }
123
+ }
124
+ }
125
+ var aol = activeObjects.length;
126
+ var ael = activeEmbeds.length;
127
+ var searchStr = "bridgeName="+ bridgeName;
128
+ if ((aol == 1 && !ael) || (aol == 1 && ael == 1)) {
129
+ FABridge.attachBridge(activeObjects[0], bridgeName);
130
+ }
131
+ else if (ael == 1 && !aol) {
132
+ FABridge.attachBridge(activeEmbeds[0], bridgeName);
133
+ }
134
+ else {
135
+ var flash_found = false;
136
+ if (aol > 1) {
137
+ for (var k = 0; k < aol; k++) {
138
+ var params = activeObjects[k].childNodes;
139
+ for (var l = 0; l < params.length; l++) {
140
+ var param = params[l];
141
+ if (param.nodeType == 1 && param.tagName.toLowerCase() == "param" && param["name"].toLowerCase() == "flashvars" && param["value"].indexOf(searchStr) >= 0) {
142
+ FABridge.attachBridge(activeObjects[k], bridgeName);
143
+ flash_found = true;
144
+ break;
145
+ }
146
+ }
147
+ if (flash_found) {
148
+ break;
149
+ }
150
+ }
151
+ }
152
+ if (!flash_found && ael > 1) {
153
+ for (var m = 0; m < ael; m++) {
154
+ var flashVars = activeEmbeds[m].attributes.getNamedItem("flashVars").nodeValue;
155
+ if (flashVars.indexOf(searchStr) >= 0) {
156
+ FABridge.attachBridge(activeEmbeds[m], bridgeName);
157
+ break;
158
+ }
159
+ }
160
+ }
161
+ }
162
+ return true;
163
+ }
164
+
165
+ // used to track multiple bridge instances, since callbacks from AS are global across the page.
166
+
167
+ FABridge.nextBridgeID = 0;
168
+ FABridge.instances = {};
169
+ FABridge.idMap = {};
170
+ FABridge.refCount = 0;
171
+
172
+ FABridge.extractBridgeFromID = function(id)
173
+ {
174
+ var bridgeID = (id >> 16);
175
+ return FABridge.idMap[bridgeID];
176
+ }
177
+
178
+ FABridge.attachBridge = function(instance, bridgeName)
179
+ {
180
+
181
+ // reuse bridge if it exists
182
+ // var newBridgeInstance = new FABridge(instance, bridgeName);
183
+
184
+ // reuse bridge if it exists
185
+ // FABridge[bridgeName] = newBridgeInstance;
186
+
187
+ if (typeof FABridge[bridgeName] == 'undefined') {
188
+ FABridge[bridgeName] = new FABridge(instance, bridgeName);
189
+ }
190
+
191
+ /* FABridge[bridgeName] = function() {
192
+ return newBridgeInstance.root();
193
+ }
194
+ */
195
+ var callbacks = FABridge.initCallbacks[bridgeName];
196
+ if (callbacks == null)
197
+ {
198
+ return;
199
+ }
200
+ for (var i = 0; i < callbacks.length; i++)
201
+ {
202
+ // callbacks[i].call(newBridgeInstance);
203
+ callbacks[i].call(FABridge[bridgeName]);
204
+ }
205
+
206
+ // reuse bridge if it exists
207
+ // delete FABridge.initCallbacks[bridgeName]
208
+ }
209
+
210
+ // some methods can't be proxied. You can use the explicit get,set, and call methods if necessary.
211
+
212
+ FABridge.blockedMethods =
213
+ {
214
+ toString: true,
215
+ get: true,
216
+ set: true,
217
+ call: true
218
+ };
219
+
220
+ FABridge.prototype =
221
+ {
222
+
223
+
224
+ // bootstrapping
225
+
226
+ root: function()
227
+ {
228
+ return this.deserialize(this.target.getRoot());
229
+ },
230
+ //clears all of the AS objects in the cache maps
231
+ releaseASObjects: function()
232
+ {
233
+ return this.target.releaseASObjects();
234
+ },
235
+ //clears a specific object in AS from the type maps
236
+ releaseNamedASObject: function(value)
237
+ {
238
+ if(typeof(value) != "object")
239
+ {
240
+ return false;
241
+ }
242
+ else
243
+ {
244
+ var ret = this.target.releaseNamedASObject(value.fb_instance_id);
245
+ return ret;
246
+ }
247
+ },
248
+ //create a new AS Object
249
+ create: function(className)
250
+ {
251
+ return this.deserialize(this.target.create(className));
252
+ },
253
+
254
+
255
+ // utilities
256
+
257
+ makeID: function(token)
258
+ {
259
+ return (this.bridgeID << 16) + token;
260
+ },
261
+
262
+
263
+ // low level access to the flash object
264
+
265
+ //get a named property from an AS object
266
+ getPropertyFromAS: function(objRef, propName)
267
+ {
268
+ if (FABridge.refCount > 0)
269
+ {
270
+ throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");
271
+ }
272
+ else
273
+ {
274
+ FABridge.refCount++;
275
+ retVal = this.target.getPropFromAS(objRef, propName);
276
+ retVal = this.handleError(retVal);
277
+ FABridge.refCount--;
278
+ return retVal;
279
+ }
280
+ },
281
+ //set a named property on an AS object
282
+ setPropertyInAS: function(objRef,propName, value)
283
+ {
284
+ if (FABridge.refCount > 0)
285
+ {
286
+ throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");
287
+ }
288
+ else
289
+ {
290
+ FABridge.refCount++;
291
+ retVal = this.target.setPropInAS(objRef,propName, this.serialize(value));
292
+ retVal = this.handleError(retVal);
293
+ FABridge.refCount--;
294
+ return retVal;
295
+ }
296
+ },
297
+
298
+ //call an AS function
299
+ callASFunction: function(funcID, args)
300
+ {
301
+ if (FABridge.refCount > 0)
302
+ {
303
+ throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");
304
+ }
305
+ else
306
+ {
307
+ FABridge.refCount++;
308
+ retVal = this.target.invokeASFunction(funcID, this.serialize(args));
309
+ retVal = this.handleError(retVal);
310
+ FABridge.refCount--;
311
+ return retVal;
312
+ }
313
+ },
314
+ //call a method on an AS object
315
+ callASMethod: function(objID, funcName, args)
316
+ {
317
+ if (FABridge.refCount > 0)
318
+ {
319
+ throw new Error("You are trying to call recursively into the Flash Player which is not allowed. In most cases the JavaScript setTimeout function, can be used as a workaround.");
320
+ }
321
+ else
322
+ {
323
+ FABridge.refCount++;
324
+ args = this.serialize(args);
325
+ retVal = this.target.invokeASMethod(objID, funcName, args);
326
+ retVal = this.handleError(retVal);
327
+ FABridge.refCount--;
328
+ return retVal;
329
+ }
330
+ },
331
+
332
+ // responders to remote calls from flash
333
+
334
+ //callback from flash that executes a local JS function
335
+ //used mostly when setting js functions as callbacks on events
336
+ invokeLocalFunction: function(funcID, args)
337
+ {
338
+ var result;
339
+ var func = this.localFunctionCache[funcID];
340
+
341
+ if(func != undefined)
342
+ {
343
+ result = this.serialize(func.apply(null, this.deserialize(args)));
344
+ }
345
+
346
+ return result;
347
+ },
348
+
349
+ // Object Types and Proxies
350
+
351
+ // accepts an object reference, returns a type object matching the obj reference.
352
+ getTypeFromName: function(objTypeName)
353
+ {
354
+ return this.remoteTypeCache[objTypeName];
355
+ },
356
+ //create an AS proxy for the given object ID and type
357
+ createProxy: function(objID, typeName)
358
+ {
359
+ var objType = this.getTypeFromName(typeName);
360
+ instanceFactory.prototype = objType;
361
+ var instance = new instanceFactory(objID);
362
+ this.remoteInstanceCache[objID] = instance;
363
+ return instance;
364
+ },
365
+ //return the proxy associated with the given object ID
366
+ getProxy: function(objID)
367
+ {
368
+ return this.remoteInstanceCache[objID];
369
+ },
370
+
371
+ // accepts a type structure, returns a constructed type
372
+ addTypeDataToCache: function(typeData)
373
+ {
374
+ newType = new ASProxy(this, typeData.name);
375
+ var accessors = typeData.accessors;
376
+ for (var i = 0; i < accessors.length; i++)
377
+ {
378
+ this.addPropertyToType(newType, accessors[i]);
379
+ }
380
+
381
+ var methods = typeData.methods;
382
+ for (var i = 0; i < methods.length; i++)
383
+ {
384
+ if (FABridge.blockedMethods[methods[i]] == undefined)
385
+ {
386
+ this.addMethodToType(newType, methods[i]);
387
+ }
388
+ }
389
+
390
+
391
+ this.remoteTypeCache[newType.typeName] = newType;
392
+ return newType;
393
+ },
394
+
395
+ //add a property to a typename; used to define the properties that can be called on an AS proxied object
396
+ addPropertyToType: function(ty, propName)
397
+ {
398
+ var c = propName.charAt(0);
399
+ var setterName;
400
+ var getterName;
401
+ if(c >= "a" && c <= "z")
402
+ {
403
+ getterName = "get" + c.toUpperCase() + propName.substr(1);
404
+ setterName = "set" + c.toUpperCase() + propName.substr(1);
405
+ }
406
+ else
407
+ {
408
+ getterName = "get" + propName;
409
+ setterName = "set" + propName;
410
+ }
411
+ ty[setterName] = function(val)
412
+ {
413
+ this.bridge.setPropertyInAS(this.fb_instance_id, propName, val);
414
+ }
415
+ ty[getterName] = function()
416
+ {
417
+ return this.bridge.deserialize(this.bridge.getPropertyFromAS(this.fb_instance_id, propName));
418
+ }
419
+ },
420
+
421
+ //add a method to a typename; used to define the methods that can be callefd on an AS proxied object
422
+ addMethodToType: function(ty, methodName)
423
+ {
424
+ ty[methodName] = function()
425
+ {
426
+ return this.bridge.deserialize(this.bridge.callASMethod(this.fb_instance_id, methodName, FABridge.argsToArray(arguments)));
427
+ }
428
+ },
429
+
430
+ // Function Proxies
431
+
432
+ //returns the AS proxy for the specified function ID
433
+ getFunctionProxy: function(funcID)
434
+ {
435
+ var bridge = this;
436
+ if (this.remoteFunctionCache[funcID] == null)
437
+ {
438
+ this.remoteFunctionCache[funcID] = function()
439
+ {
440
+ bridge.callASFunction(funcID, FABridge.argsToArray(arguments));
441
+ }
442
+ }
443
+ return this.remoteFunctionCache[funcID];
444
+ },
445
+
446
+ //reutrns the ID of the given function; if it doesnt exist it is created and added to the local cache
447
+ getFunctionID: function(func)
448
+ {
449
+ if (func.__bridge_id__ == undefined)
450
+ {
451
+ func.__bridge_id__ = this.makeID(this.nextLocalFuncID++);
452
+ this.localFunctionCache[func.__bridge_id__] = func;
453
+ }
454
+ return func.__bridge_id__;
455
+ },
456
+
457
+ // serialization / deserialization
458
+
459
+ serialize: function(value)
460
+ {
461
+ var result = {};
462
+
463
+ var t = typeof(value);
464
+ //primitives are kept as such
465
+ if (t == "number" || t == "string" || t == "boolean" || t == null || t == undefined)
466
+ {
467
+ result = value;
468
+ }
469
+ else if (value instanceof Array)
470
+ {
471
+ //arrays are serializesd recursively
472
+ result = [];
473
+ for (var i = 0; i < value.length; i++)
474
+ {
475
+ result[i] = this.serialize(value[i]);
476
+ }
477
+ }
478
+ else if (t == "function")
479
+ {
480
+ //js functions are assigned an ID and stored in the local cache
481
+ result.type = FABridge.TYPE_JSFUNCTION;
482
+ result.value = this.getFunctionID(value);
483
+ }
484
+ else if (value instanceof ASProxy)
485
+ {
486
+ result.type = FABridge.TYPE_ASINSTANCE;
487
+ result.value = value.fb_instance_id;
488
+ }
489
+ else
490
+ {
491
+ result.type = FABridge.TYPE_ANONYMOUS;
492
+ result.value = value;
493
+ }
494
+
495
+ return result;
496
+ },
497
+
498
+ //on deserialization we always check the return for the specific error code that is used to marshall NPE's into JS errors
499
+ // the unpacking is done by returning the value on each pachet for objects/arrays
500
+ deserialize: function(packedValue)
501
+ {
502
+
503
+ var result;
504
+
505
+ var t = typeof(packedValue);
506
+ if (t == "number" || t == "string" || t == "boolean" || packedValue == null || packedValue == undefined)
507
+ {
508
+ result = this.handleError(packedValue);
509
+ }
510
+ else if (packedValue instanceof Array)
511
+ {
512
+ result = [];
513
+ for (var i = 0; i < packedValue.length; i++)
514
+ {
515
+ result[i] = this.deserialize(packedValue[i]);
516
+ }
517
+ }
518
+ else if (t == "object")
519
+ {
520
+ for(var i = 0; i < packedValue.newTypes.length; i++)
521
+ {
522
+ this.addTypeDataToCache(packedValue.newTypes[i]);
523
+ }
524
+ for (var aRefID in packedValue.newRefs)
525
+ {
526
+ this.createProxy(aRefID, packedValue.newRefs[aRefID]);
527
+ }
528
+ if (packedValue.type == FABridge.TYPE_PRIMITIVE)
529
+ {
530
+ result = packedValue.value;
531
+ }
532
+ else if (packedValue.type == FABridge.TYPE_ASFUNCTION)
533
+ {
534
+ result = this.getFunctionProxy(packedValue.value);
535
+ }
536
+ else if (packedValue.type == FABridge.TYPE_ASINSTANCE)
537
+ {
538
+ result = this.getProxy(packedValue.value);
539
+ }
540
+ else if (packedValue.type == FABridge.TYPE_ANONYMOUS)
541
+ {
542
+ result = packedValue.value;
543
+ }
544
+ }
545
+ return result;
546
+ },
547
+ //increases the reference count for the given object
548
+ addRef: function(obj)
549
+ {
550
+ this.target.incRef(obj.fb_instance_id);
551
+ },
552
+ //decrease the reference count for the given object and release it if needed
553
+ release:function(obj)
554
+ {
555
+ this.target.releaseRef(obj.fb_instance_id);
556
+ },
557
+
558
+ // check the given value for the components of the hard-coded error code : __FLASHERROR
559
+ // used to marshall NPE's into flash
560
+
561
+ handleError: function(value)
562
+ {
563
+ if (typeof(value)=="string" && value.indexOf("__FLASHERROR")==0)
564
+ {
565
+ var myErrorMessage = value.split("||");
566
+ if(FABridge.refCount > 0 )
567
+ {
568
+ FABridge.refCount--;
569
+ }
570
+ throw new Error(myErrorMessage[1]);
571
+ return value;
572
+ }
573
+ else
574
+ {
575
+ return value;
576
+ }
577
+ }
578
+ };
579
+
580
+ // The root ASProxy class that facades a flash object
581
+
582
+ ASProxy = function(bridge, typeName)
583
+ {
584
+ this.bridge = bridge;
585
+ this.typeName = typeName;
586
+ return this;
587
+ };
588
+ //methods available on each ASProxy object
589
+ ASProxy.prototype =
590
+ {
591
+ get: function(propName)
592
+ {
593
+ return this.bridge.deserialize(this.bridge.getPropertyFromAS(this.fb_instance_id, propName));
594
+ },
595
+
596
+ set: function(propName, value)
597
+ {
598
+ this.bridge.setPropertyInAS(this.fb_instance_id, propName, value);
599
+ },
600
+
601
+ call: function(funcName, args)
602
+ {
603
+ this.bridge.callASMethod(this.fb_instance_id, funcName, args);
604
+ },
605
+
606
+ addRef: function() {
607
+ this.bridge.addRef(this);
608
+ },
609
+
610
+ release: function() {
611
+ this.bridge.release(this);
612
+ }
613
+ };
js/lib/boxover.js ADDED
@@ -0,0 +1,372 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* --- BoxOver ---
2
+ /* --- v 2.1 17th June 2006
3
+ By Oliver Bryant with help of Matthew Tagg
4
+ http://boxover.swazz.org */
5
+
6
+ if (typeof document.attachEvent!='undefined') {
7
+ window.attachEvent('onload',init);
8
+ document.attachEvent('onmousemove',moveMouse);
9
+ document.attachEvent('onclick',checkMove); }
10
+ else {
11
+ window.addEventListener('load',init,false);
12
+ document.addEventListener('mousemove',moveMouse,false);
13
+ document.addEventListener('click',checkMove,false);
14
+ }
15
+
16
+ var oDv=document.createElement("div");
17
+ var dvHdr=document.createElement("div");
18
+ var dvBdy=document.createElement("div");
19
+ var windowlock,boxMove,fixposx,fixposy,lockX,lockY,fixx,fixy,ox,oy,boxLeft,boxRight,boxTop,boxBottom,evt,mouseX,mouseY,boxOpen,totalScrollTop,totalScrollLeft;
20
+ boxOpen=false;
21
+ ox=10;
22
+ oy=10;
23
+ lockX=0;
24
+ lockY=0;
25
+
26
+ function init() {
27
+ oDv.appendChild(dvHdr);
28
+ oDv.appendChild(dvBdy);
29
+ oDv.style.position="absolute";
30
+ oDv.style.visibility='hidden';
31
+ document.body.appendChild(oDv);
32
+ }
33
+
34
+ function defHdrStyle() {
35
+ dvHdr.innerHTML='<img style="vertical-align:middle" src="info.gif">&nbsp;&nbsp;'+dvHdr.innerHTML;
36
+ dvHdr.style.fontWeight='bold';
37
+ dvHdr.style.width='150px';
38
+ dvHdr.style.fontFamily='arial';
39
+ dvHdr.style.border='1px solid #A5CFE9';
40
+ dvHdr.style.padding='3';
41
+ dvHdr.style.fontSize='11';
42
+ dvHdr.style.color='#4B7A98';
43
+ dvHdr.style.background='#D5EBF9';
44
+ dvHdr.style.filter='alpha(opacity=85)'; // IE
45
+ dvHdr.style.opacity='0.85'; // FF
46
+ }
47
+
48
+ function defBdyStyle() {
49
+ dvBdy.style.borderBottom='1px solid #A5CFE9';
50
+ dvBdy.style.borderLeft='1px solid #A5CFE9';
51
+ dvBdy.style.borderRight='1px solid #A5CFE9';
52
+ dvBdy.style.width='150px';
53
+ dvBdy.style.fontFamily='arial';
54
+ dvBdy.style.fontSize='11';
55
+ dvBdy.style.padding='3';
56
+ dvBdy.style.color='#1B4966';
57
+ dvBdy.style.background='#FFFFFF';
58
+ dvBdy.style.filter='alpha(opacity=85)'; // IE
59
+ dvBdy.style.opacity='0.85'; // FF
60
+ }
61
+
62
+ function checkElemBO(txt) {
63
+ if (!txt || typeof(txt) != 'string') return false;
64
+ if ((txt.indexOf('header')>-1)&&(txt.indexOf('body')>-1)&&(txt.indexOf('[')>-1)&&(txt.indexOf('[')>-1))
65
+ return true;
66
+ else
67
+ return false;
68
+ }
69
+
70
+ function scanBO(curNode) {
71
+ if (checkElemBO(curNode.title)) {
72
+ curNode.boHDR=getParam('header',curNode.title);
73
+ curNode.boBDY=getParam('body',curNode.title);
74
+ curNode.boCSSBDY=getParam('cssbody',curNode.title);
75
+ curNode.boCSSHDR=getParam('cssheader',curNode.title);
76
+ curNode.IEbugfix=(getParam('hideselects',curNode.title)=='on')?true:false;
77
+ curNode.fixX=parseInt(getParam('fixedrelx',curNode.title));
78
+ curNode.fixY=parseInt(getParam('fixedrely',curNode.title));
79
+ curNode.absX=parseInt(getParam('fixedabsx',curNode.title));
80
+ curNode.absY=parseInt(getParam('fixedabsy',curNode.title));
81
+ curNode.offY=(getParam('offsety',curNode.title)!='')?parseInt(getParam('offsety',curNode.title)):10;
82
+ curNode.offX=(getParam('offsetx',curNode.title)!='')?parseInt(getParam('offsetx',curNode.title)):10;
83
+ curNode.fade=(getParam('fade',curNode.title)=='on')?true:false;
84
+ curNode.fadespeed=(getParam('fadespeed',curNode.title)!='')?getParam('fadespeed',curNode.title):0.04;
85
+ curNode.delay=(getParam('delay',curNode.title)!='')?parseInt(getParam('delay',curNode.title)):0;
86
+ if (getParam('requireclick',curNode.title)=='on') {
87
+ curNode.requireclick=true;
88
+ document.all?curNode.attachEvent('onclick',showHideBox):curNode.addEventListener('click',showHideBox,false);
89
+ document.all?curNode.attachEvent('onmouseover',hideBox):curNode.addEventListener('mouseover',hideBox,false);
90
+ }
91
+ else {// Note : if requireclick is on the stop clicks are ignored
92
+ if (getParam('doubleclickstop',curNode.title)!='off') {
93
+ document.all?curNode.attachEvent('ondblclick',pauseBox):curNode.addEventListener('dblclick',pauseBox,false);
94
+ }
95
+ if (getParam('singleclickstop',curNode.title)=='on') {
96
+ document.all?curNode.attachEvent('onclick',pauseBox):curNode.addEventListener('click',pauseBox,false);
97
+ }
98
+ }
99
+ curNode.windowLock=getParam('windowlock',curNode.title).toLowerCase()=='off'?false:true;
100
+ curNode.title='';
101
+ curNode.hasbox=1;
102
+ }
103
+ else
104
+ curNode.hasbox=2;
105
+ }
106
+
107
+
108
+ function getParam(param,list) {
109
+ var reg = new RegExp('([^a-zA-Z]' + param + '|^' + param + ')\\s*=\\s*\\[\\s*(((\\[\\[)|(\\]\\])|([^\\]\\[]))*)\\s*\\]');
110
+ var res = reg.exec(list);
111
+ var returnvar;
112
+ if(res)
113
+ return res[2].replace('[[','[').replace(']]',']');
114
+ else
115
+ return '';
116
+ }
117
+
118
+ function Left(elem){
119
+ var x=0;
120
+ if (elem.calcLeft)
121
+ return elem.calcLeft;
122
+ var oElem=elem;
123
+ while(elem){
124
+ if ((elem.currentStyle)&& (!isNaN(parseInt(elem.currentStyle.borderLeftWidth)))&&(x!=0))
125
+ x+=parseInt(elem.currentStyle.borderLeftWidth);
126
+ x+=elem.offsetLeft;
127
+ elem=elem.offsetParent;
128
+ }
129
+ oElem.calcLeft=x;
130
+ return x;
131
+ }
132
+
133
+ function Top(elem){
134
+ var x=0;
135
+ if (elem.calcTop)
136
+ return elem.calcTop;
137
+ var oElem=elem;
138
+ while(elem){
139
+ if ((elem.currentStyle)&& (!isNaN(parseInt(elem.currentStyle.borderTopWidth)))&&(x!=0))
140
+ x+=parseInt(elem.currentStyle.borderTopWidth);
141
+ x+=elem.offsetTop;
142
+ elem=elem.offsetParent;
143
+ }
144
+ oElem.calcTop=x;
145
+ return x;
146
+
147
+ }
148
+
149
+ var ah,ab;
150
+ function applyStyles() {
151
+ if(ab)
152
+ oDv.removeChild(dvBdy);
153
+ if (ah)
154
+ oDv.removeChild(dvHdr);
155
+ dvHdr=document.createElement("div");
156
+ dvBdy=document.createElement("div");
157
+ CBE.boCSSBDY?dvBdy.className=CBE.boCSSBDY:defBdyStyle();
158
+ CBE.boCSSHDR?dvHdr.className=CBE.boCSSHDR:defHdrStyle();
159
+ dvHdr.innerHTML=CBE.boHDR;
160
+ dvBdy.innerHTML=CBE.boBDY;
161
+ ah=false;
162
+ ab=false;
163
+ if (CBE.boHDR!='') {
164
+ oDv.appendChild(dvHdr);
165
+ ah=true;
166
+ }
167
+ if (CBE.boBDY!=''){
168
+ oDv.appendChild(dvBdy);
169
+ ab=true;
170
+ }
171
+ }
172
+
173
+ var CSE,iterElem,LSE,CBE,LBE, totalScrollLeft, totalScrollTop, width, height ;
174
+ var ini=false;
175
+
176
+ // Customised function for inner window dimension
177
+ function SHW() {
178
+ if (document.body && (document.body.clientWidth !=0)) {
179
+ width=document.body.clientWidth;
180
+ height=document.body.clientHeight;
181
+ }
182
+ if (document.documentElement && (document.documentElement.clientWidth!=0) && (document.body.clientWidth + 20 >= document.documentElement.clientWidth)) {
183
+ width=document.documentElement.clientWidth;
184
+ height=document.documentElement.clientHeight;
185
+ }
186
+ return [width,height];
187
+ }
188
+
189
+
190
+ var ID=null;
191
+ function moveMouse(e) {
192
+ //boxMove=true;
193
+ e?evt=e:evt=event;
194
+
195
+ CSE=evt.target?evt.target:evt.srcElement;
196
+
197
+ if (!CSE.hasbox) {
198
+ // Note we need to scan up DOM here, some elements like TR don't get triggered as srcElement
199
+ iElem=CSE;
200
+ while ((iElem.parentNode) && (!iElem.hasbox)) {
201
+ scanBO(iElem);
202
+ iElem=iElem.parentNode;
203
+ }
204
+ }
205
+
206
+ if ((CSE!=LSE)&&(!isChild(CSE,dvHdr))&&(!isChild(CSE,dvBdy))){
207
+ if (!CSE.boxItem) {
208
+ iterElem=CSE;
209
+ while ((iterElem.hasbox==2)&&(iterElem.parentNode))
210
+ iterElem=iterElem.parentNode;
211
+ CSE.boxItem=iterElem;
212
+ }
213
+ iterElem=CSE.boxItem;
214
+ if (CSE.boxItem&&(CSE.boxItem.hasbox==1)) {
215
+ LBE=CBE;
216
+ CBE=iterElem;
217
+ if (CBE!=LBE) {
218
+ applyStyles();
219
+ if (!CBE.requireclick)
220
+ if (CBE.fade) {
221
+ if (ID!=null)
222
+ clearTimeout(ID);
223
+ ID=setTimeout("fadeIn("+CBE.fadespeed+")",CBE.delay);
224
+ }
225
+ else {
226
+ if (ID!=null)
227
+ clearTimeout(ID);
228
+ COL=1;
229
+ ID=setTimeout("oDv.style.visibility='visible';ID=null;",CBE.delay);
230
+ }
231
+ if (CBE.IEbugfix) {hideSelects();}
232
+ fixposx=!isNaN(CBE.fixX)?Left(CBE)+CBE.fixX:CBE.absX;
233
+ fixposy=!isNaN(CBE.fixY)?Top(CBE)+CBE.fixY:CBE.absY;
234
+ lockX=0;
235
+ lockY=0;
236
+ boxMove=true;
237
+ ox=CBE.offX?CBE.offX:10;
238
+ oy=CBE.offY?CBE.offY:10;
239
+ }
240
+ }
241
+ else if (!isChild(CSE,dvHdr) && !isChild(CSE,dvBdy) && (boxMove)) {
242
+ // The conditional here fixes flickering between tables cells.
243
+ if ((!isChild(CBE,CSE)) || (CSE.tagName!='TABLE')) {
244
+ CBE=null;
245
+ if (ID!=null)
246
+ clearTimeout(ID);
247
+ fadeOut();
248
+ showSelects();
249
+ }
250
+ }
251
+ LSE=CSE;
252
+ }
253
+ else if (((isChild(CSE,dvHdr) || isChild(CSE,dvBdy))&&(boxMove))) {
254
+ totalScrollLeft=0;
255
+ totalScrollTop=0;
256
+
257
+ iterElem=CSE;
258
+ while(iterElem) {
259
+ if(!isNaN(parseInt(iterElem.scrollTop)))
260
+ totalScrollTop+=parseInt(iterElem.scrollTop);
261
+ if(!isNaN(parseInt(iterElem.scrollLeft)))
262
+ totalScrollLeft+=parseInt(iterElem.scrollLeft);
263
+ iterElem=iterElem.parentNode;
264
+ }
265
+ if (CBE!=null) {
266
+ boxLeft=Left(CBE)-totalScrollLeft;
267
+ boxRight=parseInt(Left(CBE)+CBE.offsetWidth)-totalScrollLeft;
268
+ boxTop=Top(CBE)-totalScrollTop;
269
+ boxBottom=parseInt(Top(CBE)+CBE.offsetHeight)-totalScrollTop;
270
+ doCheck();
271
+ }
272
+ }
273
+
274
+ if (boxMove&&CBE) {
275
+ // This added to alleviate bug in IE6 w.r.t DOCTYPE
276
+ bodyScrollTop=document.documentElement&&document.documentElement.scrollTop?document.documentElement.scrollTop:document.body.scrollTop;
277
+ bodyScrollLet=document.documentElement&&document.documentElement.scrollLeft?document.documentElement.scrollLeft:document.body.scrollLeft;
278
+ mouseX=evt.pageX?evt.pageX-bodyScrollLet:evt.clientX-document.body.clientLeft;
279
+ mouseY=evt.pageY?evt.pageY-bodyScrollTop:evt.clientY-document.body.clientTop;
280
+ if ((CBE)&&(CBE.windowLock)) {
281
+ mouseY < -oy?lockY=-mouseY-oy:lockY=0;
282
+ mouseX < -ox?lockX=-mouseX-ox:lockX=0;
283
+ mouseY > (SHW()[1]-oDv.offsetHeight-oy)?lockY=-mouseY+SHW()[1]-oDv.offsetHeight-oy:lockY=lockY;
284
+ mouseX > (SHW()[0]-dvBdy.offsetWidth-ox)?lockX=-mouseX-ox+SHW()[0]-dvBdy.offsetWidth:lockX=lockX;
285
+ }
286
+ oDv.style.left=((fixposx)||(fixposx==0))?fixposx:bodyScrollLet+mouseX+ox+lockX+"px";
287
+ oDv.style.top=((fixposy)||(fixposy==0))?fixposy:bodyScrollTop+mouseY+oy+lockY+"px";
288
+
289
+ }
290
+ }
291
+
292
+ function doCheck() {
293
+ if ( (mouseX < boxLeft) || (mouseX >boxRight) || (mouseY < boxTop) || (mouseY > boxBottom)) {
294
+ if (!CBE.requireclick)
295
+ fadeOut();
296
+ if (CBE.IEbugfix) {showSelects();}
297
+ CBE=null;
298
+ }
299
+ }
300
+
301
+ function pauseBox(e) {
302
+ e?evt=e:evt=event;
303
+ boxMove=false;
304
+ evt.cancelBubble=true;
305
+ }
306
+
307
+ function showHideBox(e) {
308
+ oDv.style.visibility=(oDv.style.visibility!='visible')?'visible':'hidden';
309
+ }
310
+
311
+ function hideBox(e) {
312
+ oDv.style.visibility='hidden';
313
+ }
314
+
315
+ var COL=0;
316
+ var stopfade=false;
317
+ function fadeIn(fs) {
318
+ ID=null;
319
+ COL=0;
320
+ oDv.style.visibility='visible';
321
+ fadeIn2(fs);
322
+ }
323
+
324
+ function fadeIn2(fs) {
325
+ COL=COL+fs;
326
+ COL=(COL>1)?1:COL;
327
+ oDv.style.filter='alpha(opacity='+parseInt(100*COL)+')';
328
+ oDv.style.opacity=COL;
329
+ if (COL<1)
330
+ setTimeout("fadeIn2("+fs+")",20);
331
+ }
332
+
333
+
334
+ function fadeOut() {
335
+ oDv.style.visibility='hidden';
336
+
337
+ }
338
+
339
+ function isChild(s,d) {
340
+ while(s) {
341
+ if (s==d)
342
+ return true;
343
+ s=s.parentNode;
344
+ }
345
+ return false;
346
+ }
347
+
348
+ var cSrc;
349
+ function checkMove(e) {
350
+ e?evt=e:evt=event;
351
+ cSrc=evt.target?evt.target:evt.srcElement;
352
+ if ((!boxMove)&&(!isChild(cSrc,oDv))) {
353
+ fadeOut();
354
+ if (CBE&&CBE.IEbugfix) {showSelects();}
355
+ boxMove=true;
356
+ CBE=null;
357
+ }
358
+ }
359
+
360
+ function showSelects(){
361
+ var elements = document.getElementsByTagName("select");
362
+ for (i=0;i< elements.length;i++){
363
+ elements[i].style.visibility='visible';
364
+ }
365
+ }
366
+
367
+ function hideSelects(){
368
+ var elements = document.getElementsByTagName("select");
369
+ for (i=0;i< elements.length;i++){
370
+ elements[i].style.visibility='hidden';
371
+ }
372
+ }
js/lib/ccard.js ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Credit Card Validation Javascript
2
+ // copyright 12th May 2003, by Stephen Chapman, Felgall Pty Ltd
3
+
4
+ // You have permission to copy and use this javascript provided that
5
+ // the content of the script is not changed in any way.
6
+
7
+ function validateCreditCard(s) {
8
+ // remove non-numerics
9
+ var v = "0123456789";
10
+ var w = "";
11
+ for (i=0; i < s.length; i++) {
12
+ x = s.charAt(i);
13
+ if (v.indexOf(x,0) != -1)
14
+ w += x;
15
+ }
16
+ // validate number
17
+ j = w.length / 2;
18
+ k = Math.floor(j);
19
+ m = Math.ceil(j) - k;
20
+ c = 0;
21
+ for (i=0; i<k; i++) {
22
+ a = w.charAt(i*2+m) * 2;
23
+ c += a > 9 ? Math.floor(a/10 + a%10) : a;
24
+ }
25
+ for (i=0; i<k+m; i++) c += w.charAt(i*2+1-m) * 1;
26
+ return (c%10 == 0);
27
+ }
28
+
js/lib/dropdown.js ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ dropdown = function() {
26
+ var ele = document.getElementById("nav").getElementsByTagName("LI");
27
+ for (var i=0; i<ele.length; i++) {
28
+ ele[i].onmouseover=function() {
29
+ this.className+=" over";
30
+ }
31
+ ele[i].onmouseout=function() {
32
+ this.className=this.className.replace(new RegExp(" over\\b"), "");
33
+ }
34
+ }
35
+ }
36
+ if (window.attachEvent) window.attachEvent("onload", dropdown);
js/lib/ds-sleight.js ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Universal transparent-PNG enabler for MSIE/Win 5.5+
2
+ // http://dsandler.org
3
+ // From original code: http://www.youngpup.net/?request=/snippets/sleight.xml
4
+ // and background-image code: http://www.allinthehead.com/retro/69
5
+ // also:
6
+ // * use sizingMethod=crop to avoid scaling PNGs (who would do such a thing?)
7
+ // * only do this once, to make it compatible with CSS rollovers
8
+
9
+ if (navigator.platform == "Win32" && navigator.appName == "Microsoft Internet Explorer" && window.attachEvent) {
10
+ window.attachEvent("onload", enableAlphaImages);
11
+ }
12
+
13
+ function enableAlphaImages(){
14
+ var rslt = navigator.appVersion.match(/MSIE (\d+\.\d+)/, '');
15
+ var itsAllGood = (rslt != null && Number(rslt[1]) >= 5.5);
16
+ if (itsAllGood) {
17
+ for (var i=0; i<document.all.length; i++){
18
+ var obj = document.all[i];
19
+ var bg = obj.currentStyle.backgroundImage;
20
+ var img = document.images[i];
21
+ if (bg && bg.match(/\.png/i) != null) {
22
+ var img = bg.substring(5,bg.length-2);
23
+ var offset = obj.style["background-position"];
24
+ obj.style.filter =
25
+ "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+img+"', sizingMethod='crop')";
26
+ obj.style.backgroundImage = "url('"+BLANK_IMG+"')";
27
+ obj.style["background-position"] = offset; // reapply
28
+ } else if (img && img.src.match(/\.png$/i) != null) {
29
+ var src = img.src;
30
+ img.style.width = img.width + "px";
31
+ img.style.height = img.height + "px";
32
+ img.style.filter =
33
+ "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+src+"', sizingMethod='crop')"
34
+ img.src = BLANK_IMG;
35
+ }
36
+ }
37
+ }
38
+ }
js/lib/flex.js ADDED
@@ -0,0 +1,427 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ /**
27
+ * Flex maintance object
28
+ *
29
+ *
30
+ */
31
+ Flex = {};
32
+ Flex.currentID = 0;
33
+ Flex.uniqId = function() {
34
+ return 'flexMovieUID'+( ++Flex.currentID );
35
+ };
36
+
37
+ /**
38
+ * Check flash player version for required version
39
+ *
40
+ * @param Number major
41
+ * @param Number minor
42
+ * @param Number revision
43
+ * @return Boolean
44
+ */
45
+ Flex.checkFlashPlayerVersion = function(major, minor, revision) {
46
+ var version = Flex.getFlashPlayerVersion();
47
+
48
+ if (version === false) {
49
+ return false;
50
+ }
51
+
52
+ var requestedVersion = Flex.transformVersionToFloat([major, minor, revision], 5);
53
+ var currentVersion = Flex.transformVersionToFloat(version, 5);
54
+
55
+ return requestedVersion <= currentVersion;
56
+ };
57
+
58
+ /**
59
+ * Get flash player version in internet explorer
60
+ * by creating of test ActiveXObjects
61
+ *
62
+ * @return String|Boolean
63
+ */
64
+ Flex._getFlashPlayerVersionAsActiveX = function () {
65
+ var versions = [
66
+ {'default': '7.0.0', 'code':'ShockwaveFlash.ShockwaveFlash.7', 'variable':true},
67
+ {'default': '6.0.0', 'code':'ShockwaveFlash.ShockwaveFlash.6', 'variable':true, 'acceess':true},
68
+ {'default': '3.0.0', 'code':'ShockwaveFlash.ShockwaveFlash.3', 'variable':false},
69
+ {'default': '2.0.0', 'code':'ShockwaveFlash.ShockwaveFlash', 'variable':false},
70
+ ];
71
+
72
+ var detector = function (options) {
73
+ var activeXObject = new ActiveXObject(options.code);
74
+ if (options.access && options.variable) {
75
+ activeXObject.AllowScriptAccess = 'always';
76
+ }
77
+
78
+ if (options.variable) {
79
+ return activeXObject.GetVariable('$version');
80
+ }
81
+
82
+ return options['default'];
83
+ }
84
+
85
+ var version = false;
86
+
87
+ for (var i = 0, l = versions.length; i < l; i++) {
88
+ try {
89
+ version = detector(versions[i]);
90
+ return version;
91
+ } catch (e) {}
92
+ }
93
+
94
+ return false;
95
+ };
96
+
97
+ /**
98
+ * Transforms version string like 1.0.0 to array [1,0,0]
99
+ *
100
+ * @param String|Array version
101
+ * @return Array|Boolean
102
+ */
103
+ Flex.transformVersionToArray = function (version) {
104
+ if (!Object.isString(version)) {
105
+ return false;
106
+ }
107
+
108
+ var versions = version.match(/[\d]+/g);
109
+
110
+ if (versions.length > 3) {
111
+ return versions.slice(0,3);
112
+ } else if (versions.length) {
113
+ return versions;
114
+ }
115
+
116
+
117
+
118
+ return false;
119
+ };
120
+
121
+ /**
122
+ * Transforms version string like 1.1.1 to float 1.00010001
123
+ *
124
+ * @param String|Array version
125
+ * @param Number range - percition range between version digits
126
+ * @return Array
127
+ */
128
+ Flex.transformVersionToFloat = function (version, range) {
129
+ if (Object.isString(version)) {
130
+ version = Flex.transformVersionToArray(version)
131
+ }
132
+
133
+ if (Object.isArray(version)) {
134
+ var result = 0;
135
+ for (var i =0, l=version.length; i < l; i++) {
136
+ result += parseFloat(version[i]) / Math.pow(10, range*i);
137
+ }
138
+
139
+ return result;
140
+ }
141
+
142
+ return false;
143
+ };
144
+
145
+ /**
146
+ * Return flash player version as array of 0=major, 1=minor, 2=revision
147
+ *
148
+ * @return Array|Boolean
149
+ */
150
+ Flex.getFlashPlayerVersion = function () {
151
+ if (Flex.flashPlayerVersion) {
152
+ return Flex.flashPlayerVersion;
153
+ }
154
+
155
+ var version = false;
156
+ if (navigator.plugins != null && navigator.plugins.length > 0) {
157
+ if (navigator.mimeTypes && navigator.mimeTypes.length > 0) {
158
+ if (navigator.mimeTypes['application/x-shockwave-flash'] &&
159
+ !navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin) {
160
+ return false;
161
+ }
162
+ }
163
+ var flashPlugin = navigator.plugins['Shockwave Flash'] || navigator.plugins['Shockwave Flash 2.0'];
164
+ version = Flex.transformVersionToArray(flashPlugin.description);
165
+ } else {
166
+ version = Flex.transformVersionToArray(Flex._getFlashPlayerVersionAsActiveX());
167
+ }
168
+
169
+ Flex.flashPlayerVersion = version;
170
+ return version;
171
+ };
172
+
173
+ Flex.Object = Class.create({
174
+ /**
175
+ * Initialize object from configuration, where configuration keys,
176
+ * is set of tag attributes for object or embed
177
+ *
178
+ * @example
179
+ * new Flex.Object({'src':'path/to/flashmovie.swf'});
180
+ *
181
+ * @param Object config
182
+ * @return void
183
+ */
184
+ initialize: function (config) {
185
+ this.isIE = Prototype.Browser.IE;
186
+ this.isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;
187
+ this.attributes = {
188
+ quality:"high",
189
+ pluginspage: "http://www.adobe.com/go/getflashplayer",
190
+ type: "application/x-shockwave-flash",
191
+ allowScriptAccess: "always",
192
+ classid: "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
193
+ };
194
+ this.bridgeName = '';
195
+ this.bridge = false;
196
+ this.setAttributes( config );
197
+ this.applied = false;
198
+
199
+ var myTemplatesPattern = /(^|.|\r|\n)(\{(.*?)\})/;
200
+ if(this.detectFlashVersion(9, 0, 28)) {
201
+ if(this.isIE) {
202
+ this.template = new Template( '<object {objectAttributes}><param name="allowFullScreen" value="true"/>{objectParameters}</object>', myTemplatesPattern )
203
+ } else {
204
+ this.template = new Template( '<embed {embedAttributes} allowfullscreen="true" />', myTemplatesPattern );
205
+ }
206
+ } else {
207
+ this.template = new Template( 'This content requires the Adobe Flash Player. '
208
+ +' <a href=http://www.adobe.com/go/getflash/>Get Flash</a>', myTemplatesPattern );
209
+ }
210
+
211
+ this.parametersTemplate = new Template( '<param name="{name}" value="{value}" />', myTemplatesPattern );
212
+ this.attributesTemplate = new Template( ' {name}="{value}" ', myTemplatesPattern );
213
+ },
214
+ /**
215
+ * Set object attribute for generation of html tags
216
+ *
217
+ * @param Sting name
218
+ * @param Object value
219
+ * @return void
220
+ */
221
+ setAttribute : function( name, value ) {
222
+ if(!this.applied) {
223
+ this.attributes[name] = value;
224
+ }
225
+ },
226
+ /**
227
+ * Retrive object attribute value used for generation in html tags
228
+ *
229
+ * @param Sting name
230
+ * @return Object
231
+ */
232
+ getAttribute : function( name ) {
233
+ return this.attributes[name];
234
+ },
235
+ /**
236
+ * Set object attributes in one call
237
+ *
238
+ * @param Object attributesList
239
+ * @return void
240
+ */
241
+ setAttributes : function( attributesList ) {
242
+ $H(attributesList).each(function(pair){
243
+ this.setAttribute(pair.key, pair.value);
244
+ }.bind(this));
245
+ },
246
+ /**
247
+ * Retrieve all object attributes
248
+ *
249
+ * @return Object
250
+ */
251
+ getAttributes : function( ) {
252
+ return this.attributes;
253
+ },
254
+ /**
255
+ * Applies generated HTML content to specified HTML tag
256
+ *
257
+ * @param String|DOMELement container
258
+ * @return void
259
+ */
260
+ apply : function(container) {
261
+ if (!this.applied) {
262
+ this.setAttribute("id", Flex.uniqId());
263
+ this.preInitBridge();
264
+ var readyHTML = this.template.evaluate(this.generateTemplateValues());
265
+ $(container).update(readyHTML);
266
+ }
267
+ this.applied = true;
268
+ },
269
+ /**
270
+ * Applies generated HTML content to window.document
271
+ *
272
+ * @return void
273
+ */
274
+ applyWrite : function( ) {
275
+ if (!this.applied) {
276
+ this.setAttribute( "id", Flex.uniqId());
277
+ this.preInitBridge();
278
+ var readyHTML = this.template.evaluate( this.generateTemplateValues() );
279
+ document.write( readyHTML );
280
+ }
281
+ this.applied = true;
282
+ },
283
+ /**
284
+ * Preinitialize FABridge values
285
+ *
286
+ * @return void
287
+ */
288
+ preInitBridge: function () {
289
+ this.bridgeName = this.getAttribute('id') + 'bridge';
290
+ var flashVars = this.getAttribute('flashVars') || this.getAttribute('flashvars') || '';
291
+ if (flashVars != '') {
292
+ flashVars += '&';
293
+ }
294
+ flashVars += 'bridgeName=' + this.bridgeName;
295
+ this.setAttribute('flashVars', flashVars);
296
+ var scopeObj = this;
297
+ FABridge.addInitializationCallback(
298
+ this.bridgeName,
299
+ function () {
300
+ scopeObj.bridge = this.root();
301
+ scopeObj.initBridge();
302
+ }
303
+ );
304
+ },
305
+ /**
306
+ * Initialize bridge callback passed to FABridge,
307
+ * calls internal callback if it's presented
308
+ *
309
+ * @return void
310
+ */
311
+ initBridge: function() {
312
+ if(this.onBridgeInit) {
313
+ this.onBridgeInit(this.getBridge());
314
+ }
315
+ },
316
+ /**
317
+ * Retrieve FABridge instance for this object
318
+ *
319
+ * @return Object
320
+ */
321
+ getBridge : function() {
322
+ return this.bridge;
323
+ },
324
+ /**
325
+ * Generate temaplate values object for creation of flash player plugin movie HTML
326
+ *
327
+ * @return Object
328
+ */
329
+ generateTemplateValues : function() {
330
+ var attributesMap = {
331
+ embed: {
332
+ 'movie':'src',
333
+ 'id':'name',
334
+ 'flashvars': 'flashVars',
335
+ 'classid':false,
336
+ 'codebase':false
337
+ },
338
+ object: {
339
+ 'pluginspage':false,
340
+ 'src':'movie',
341
+ 'flashvars': 'flashVars',
342
+ 'type':false,
343
+ 'inline': [
344
+ 'type', 'classid', 'codebase', 'id', 'width', 'height',
345
+ 'align', 'vspace', 'hspace', 'class', 'title', 'accesskey', 'name',
346
+ 'tabindex'
347
+ ]
348
+ }
349
+ };
350
+ var embedAttributes = {};
351
+ var objectAttributes = {};
352
+ var parameters = {};
353
+ $H(this.attributes).each(function(pair) {
354
+ var attributeName = pair.key.toLowerCase();
355
+ this.attributes[pair.key] = this.escapeAttributes(pair.value);
356
+
357
+ // Retrieve mapped attribute names
358
+ var attributeNameInObject = (attributesMap.object[attributeName] ? attributesMap.object[attributeName] : attributeName);
359
+ var attributeNameInEmbed = (attributesMap.embed[attributeName] ? attributesMap.embed[attributeName] : attributeName);
360
+
361
+ if (attributesMap.object[attributeName] !== false) {
362
+ if (attributesMap.object.inline.indexOf(attributeNameInObject) !== -1) { // If it included in default object attribute
363
+ objectAttributes[attributeNameInObject] = this.attributes[pair.key];
364
+ } else { // otherwise add it to parameters tag list
365
+ parameters[attributeNameInObject] = this.attributes[pair.key];
366
+ }
367
+ }
368
+
369
+ if (attributesMap.embed[attributeName] !== false) { // If this attribute not ignored for flash in Gecko Browsers
370
+ embedAttributes[attributeNameInEmbed] = this.attributes[pair.key];
371
+ }
372
+ }.bind(this));
373
+
374
+ var result = {
375
+ objectAttributes: '',
376
+ objectParameters: '',
377
+ embedAttributes : ''
378
+ };
379
+
380
+
381
+ $H(objectAttributes).each(function(pair){
382
+ result.objectAttributes += this.attributesTemplate.evaluate({
383
+ name:pair.key,
384
+ value:pair.value
385
+ });
386
+ }.bind(this));
387
+
388
+ $H(embedAttributes).each(function(pair){
389
+ result.embedAttributes += this.attributesTemplate.evaluate({
390
+ name:pair.key,
391
+ value:pair.value
392
+ });
393
+ }.bind(this));
394
+
395
+ $H(parameters).each(function(pair){
396
+ result.objectParameters += this.parametersTemplate.evaluate({
397
+ name:pair.key,
398
+ value:pair.value
399
+ });
400
+ }.bind(this));
401
+
402
+ return result;
403
+ },
404
+ /**
405
+ * Escapes attributes for generation of valid HTML
406
+ *
407
+ * @return String
408
+ */
409
+ escapeAttributes: function (value) {
410
+ if(typeof value == 'string') {
411
+ return value.escapeHTML();
412
+ } else {
413
+ return value;
414
+ }
415
+ },
416
+ /**
417
+ * Detects needed flash player version
418
+ *
419
+ * @param Number major
420
+ * @param Number minor
421
+ * @param Number revision
422
+ * @return Boolean
423
+ */
424
+ detectFlashVersion: function (major, minor, revision) {
425
+ return Flex.checkFlashPlayerVersion(major, minor, revision);
426
+ }
427
+ });
js/mage/adminhtml/accordion.js ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ var varienAccordion = new Class.create();
26
+ varienAccordion.prototype = {
27
+ initialize : function(containerId, activeOnlyOne){
28
+ this.containerId = containerId;
29
+ this.activeOnlyOne = activeOnlyOne || false;
30
+ this.container = $(this.containerId);
31
+ this.items = $$('#'+this.containerId+' dt');
32
+ this.loader = new varienLoader(true);
33
+
34
+ var links = $$('#'+this.containerId+' dt a');
35
+ for(var i in links){
36
+ if(links[i].href){
37
+ Event.observe(links[i],'click',this.clickItem.bind(this));
38
+ this.items[i].dd = this.items[i].next('dd');
39
+ this.items[i].link = links[i];
40
+ }
41
+ }
42
+
43
+ this.initFromCookie();
44
+ },
45
+ initFromCookie : function () {
46
+ var activeItemId, visibility;
47
+ if (this.activeOnlyOne &&
48
+ (activeItemId = Cookie.read(this.cookiePrefix() + 'active-item')) !== null) {
49
+ this.hideAllItems();
50
+ this.showItem(this.getItemById(activeItemId));
51
+ } else if(!this.activeOnlyOne) {
52
+ this.items.each(function(item){
53
+ if((visibility = Cookie.read(this.cookiePrefix() + item.id)) !== null) {
54
+ if(visibility == 0) {
55
+ this.hideItem(item);
56
+ } else {
57
+ this.showItem(item);
58
+ }
59
+ }
60
+ }.bind(this));
61
+ }
62
+ },
63
+ cookiePrefix: function () {
64
+ return 'accordion-' + this.containerId + '-';
65
+ },
66
+ getItemById : function (itemId) {
67
+ var result = null;
68
+
69
+ this.items.each(function(item){
70
+ if (item.id == itemId) {
71
+ result = item;
72
+ throw $break;
73
+ }
74
+ });
75
+
76
+ return result;
77
+ },
78
+ clickItem : function(event){
79
+ var item = Event.findElement(event, 'dt');
80
+ if(this.activeOnlyOne){
81
+ this.hideAllItems();
82
+ this.showItem(item);
83
+ Cookie.write(this.cookiePrefix() + 'active-item', item.id, 30*24*60*60);
84
+ }
85
+ else{
86
+ if(this.isItemVisible(item)){
87
+ this.hideItem(item);
88
+ Cookie.write(this.cookiePrefix() + item.id, 0, 30*24*60*60);
89
+ }
90
+ else {
91
+ this.showItem(item);
92
+ Cookie.write(this.cookiePrefix() + item.id, 1, 30*24*60*60);
93
+ }
94
+ }
95
+ Event.stop(event);
96
+ },
97
+ showItem : function(item){
98
+ if(item && item.link){
99
+ if(item.link.href){
100
+ this.loadContent(item);
101
+ }
102
+
103
+ Element.addClassName(item, 'open');
104
+ Element.addClassName(item.dd, 'open');
105
+ }
106
+ },
107
+ hideItem : function(item){
108
+ Element.removeClassName(item, 'open');
109
+ Element.removeClassName(item.dd, 'open');
110
+ },
111
+ isItemVisible : function(item){
112
+ return Element.hasClassName(item, 'open');
113
+ },
114
+ loadContent : function(item){
115
+ if(item.link.href.indexOf('#') == item.link.href.length-1){
116
+ return;
117
+ }
118
+ if (Element.hasClassName(item.link, 'ajax')) {
119
+ this.loadingItem = item;
120
+ this.loader.load(item.link.href, {updaterId : this.loadingItem.dd.id}, this.setItemContent.bind(this));
121
+ return;
122
+ }
123
+ location.href = item.link.href;
124
+ },
125
+ setItemContent : function(content){
126
+ if (content.isJSON) {
127
+ return;
128
+ }
129
+ this.loadingItem.dd.innerHTML = content;
130
+ },
131
+ hideAllItems : function(){
132
+ for(var i in this.items){
133
+ if(this.items[i].id){
134
+ Element.removeClassName(this.items[i], 'open');
135
+ Element.removeClassName(this.items[i].dd, 'open');
136
+ }
137
+ }
138
+ }
139
+ }
js/mage/adminhtml/browser.js ADDED
@@ -0,0 +1,395 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ MediabrowserUtility = {
26
+ openDialog: function(url, width, height, title) {
27
+ if ($('browser_window') && typeof(Windows) != 'undefined') {
28
+ Windows.focus('browser_window');
29
+ return;
30
+ }
31
+ this.dialogWindow = Dialog.info(null, {
32
+ closable: true,
33
+ resizable: false,
34
+ draggable: true,
35
+ className: 'magento',
36
+ windowClassName: 'popup-window',
37
+ title: title || 'Insert File...',
38
+ top: 50,
39
+ width: width || 950,
40
+ height: height || 600,
41
+ zIndex: 1000,
42
+ recenterAuto: false,
43
+ hideEffect: Element.hide,
44
+ showEffect: Element.show,
45
+ id: 'browser_window',
46
+ onClose: this.closeDialog.bind(this)
47
+ });
48
+ new Ajax.Updater('modal_dialog_message', url, {evalScripts: true});
49
+ },
50
+ closeDialog: function(window) {
51
+ if (!window) {
52
+ window = this.dialogWindow;
53
+ }
54
+ if (window) {
55
+ // IE fix - hidden form select fields after closing dialog
56
+ WindowUtilities._showSelect();
57
+ window.close();
58
+ }
59
+ }
60
+ };
61
+
62
+ Mediabrowser = Class.create();
63
+ Mediabrowser.prototype = {
64
+ targetElementId: null,
65
+ contentsUrl: null,
66
+ onInsertUrl: null,
67
+ newFolderUrl: null,
68
+ deleteFolderUrl: null,
69
+ deleteFilesUrl: null,
70
+ headerText: null,
71
+ tree: null,
72
+ currentNode: null,
73
+ storeId: null,
74
+ initialize: function (setup) {
75
+ this.newFolderPrompt = setup.newFolderPrompt;
76
+ this.deleteFolderConfirmationMessage = setup.deleteFolderConfirmationMessage;
77
+ this.deleteFileConfirmationMessage = setup.deleteFileConfirmationMessage;
78
+ this.targetElementId = setup.targetElementId;
79
+ this.contentsUrl = setup.contentsUrl;
80
+ this.onInsertUrl = setup.onInsertUrl;
81
+ this.newFolderUrl = setup.newFolderUrl;
82
+ this.deleteFolderUrl = setup.deleteFolderUrl;
83
+ this.deleteFilesUrl = setup.deleteFilesUrl;
84
+ this.headerText = setup.headerText;
85
+ },
86
+ setTree: function (tree) {
87
+ this.tree = tree;
88
+ this.currentNode = tree.getRootNode();
89
+ },
90
+
91
+ getTree: function (tree) {
92
+ return this.tree;
93
+ },
94
+
95
+ selectFolder: function (node, event) {
96
+ this.currentNode = node;
97
+ this.hideFileButtons();
98
+ this.activateBlock('contents');
99
+
100
+ if(node.id == 'root') {
101
+ this.hideElement('button_delete_folder');
102
+ } else {
103
+ this.showElement('button_delete_folder');
104
+ }
105
+
106
+ this.updateHeader(this.currentNode);
107
+ this.drawBreadcrumbs(this.currentNode);
108
+
109
+ this.showElement('loading-mask');
110
+ new Ajax.Request(this.contentsUrl, {
111
+ parameters: {node: this.currentNode.id},
112
+ evalJS: true,
113
+ onSuccess: function(transport) {
114
+ try {
115
+ this.currentNode.select();
116
+ this.onAjaxSuccess(transport);
117
+ this.hideElement('loading-mask');
118
+ if ($('contents') != undefined) {
119
+ $('contents').update(transport.responseText);
120
+ $$('div.filecnt').each(function(s) {
121
+ Event.observe(s.id, 'click', this.selectFile.bind(this));
122
+ Event.observe(s.id, 'dblclick', this.insert.bind(this));
123
+ }.bind(this));
124
+ }
125
+ } catch(e) {
126
+ alert(e.message);
127
+ }
128
+ }.bind(this)
129
+ });
130
+ },
131
+
132
+ selectFolderById: function (nodeId) {
133
+ var node = this.tree.getNodeById(nodeId);
134
+ if (node.id) {
135
+ this.selectFolder(node);
136
+ }
137
+ },
138
+
139
+ selectFile: function (event) {
140
+ var div = Event.findElement(event, 'DIV');
141
+ $$('div.filecnt.selected[id!="' + div.id + '"]').each(function(e) {
142
+ e.removeClassName('selected');
143
+ })
144
+ div.toggleClassName('selected');
145
+ if(div.hasClassName('selected')) {
146
+ this.showFileButtons();
147
+ } else {
148
+ this.hideFileButtons();
149
+ }
150
+ },
151
+
152
+ showFileButtons: function () {
153
+ this.showElement('button_delete_files');
154
+ this.showElement('button_insert_files');
155
+ },
156
+
157
+ hideFileButtons: function () {
158
+ this.hideElement('button_delete_files');
159
+ this.hideElement('button_insert_files');
160
+ },
161
+
162
+ handleUploadComplete: function(files) {
163
+ $$('div[class*="file-row complete"]').each(function(e) {
164
+ $(e.id).remove();
165
+ });
166
+ this.selectFolder(this.currentNode);
167
+ },
168
+
169
+ insert: function(event) {
170
+ var div;
171
+ if (event != undefined) {
172
+ div = Event.findElement(event, 'DIV');
173
+ } else {
174
+ $$('div.selected').each(function (e) {
175
+ div = $(e.id);
176
+ });
177
+ }
178
+ if ($(div.id) == undefined) {
179
+ return false;
180
+ }
181
+ var targetEl = this.getTargetElement();
182
+ if (! targetEl) {
183
+ alert("Target element not found for content update");
184
+ Windows.close('browser_window');
185
+ return;
186
+ }
187
+
188
+ var params = {filename:div.id, node:this.currentNode.id, store:this.storeId};
189
+
190
+ if (targetEl.tagName.toLowerCase() == 'textarea') {
191
+ params.as_is = 1;
192
+ }
193
+
194
+ new Ajax.Request(this.onInsertUrl, {
195
+ parameters: params,
196
+ onSuccess: function(transport) {
197
+ try {
198
+ this.onAjaxSuccess(transport);
199
+ if (this.getMediaBrowserOpener()) {
200
+ self.blur();
201
+ }
202
+ Windows.close('browser_window');
203
+ if (targetEl.tagName.toLowerCase() == 'input') {
204
+ targetEl.value = transport.responseText;
205
+ } else {
206
+ updateElementAtCursor(targetEl, transport.responseText);
207
+ if (varienGlobalEvents) {
208
+ varienGlobalEvents.fireEvent('tinymceChange');
209
+ }
210
+ }
211
+ } catch (e) {
212
+ alert(e.message);
213
+ }
214
+ }.bind(this)
215
+ });
216
+ },
217
+
218
+ /**
219
+ * Find document target element in next order:
220
+ * in acive file browser opener:
221
+ * - input field with ID: "src" in opener window
222
+ * - input field with ID: "href" in opener window
223
+ * in document:
224
+ * - element with target ID
225
+ *
226
+ * return HTMLelement | null
227
+ */
228
+ getTargetElement: function() {
229
+ if (typeof(tinyMCE) != 'undefined' && tinyMCE.get(this.targetElementId)) {
230
+ if ((opener = this.getMediaBrowserOpener())) {
231
+ var targetElementId = tinyMceEditors.get(this.targetElementId).getMediaBrowserTargetElementId();
232
+ return opener.document.getElementById(targetElementId);
233
+ } else {
234
+ return null;
235
+ }
236
+ } else {
237
+ return document.getElementById(this.targetElementId);
238
+ }
239
+ },
240
+
241
+ /**
242
+ * Return opener Window object if it exists, not closed and editor is active
243
+ *
244
+ * return object | null
245
+ */
246
+ getMediaBrowserOpener: function() {
247
+ if (typeof(tinyMCE) != 'undefined'
248
+ && tinyMCE.get(this.targetElementId)
249
+ && typeof(tinyMceEditors) != 'undefined'
250
+ && ! tinyMceEditors.get(this.targetElementId).getMediaBrowserOpener().closed) {
251
+ return tinyMceEditors.get(this.targetElementId).getMediaBrowserOpener();
252
+ } else {
253
+ return null;
254
+ }
255
+ },
256
+
257
+ newFolder: function() {
258
+ var folderName = prompt(this.newFolderPrompt);
259
+ if (!folderName) {
260
+ return false;
261
+ }
262
+ new Ajax.Request(this.newFolderUrl, {
263
+ parameters: {name: folderName},
264
+ onSuccess: function(transport) {
265
+ try {
266
+ this.onAjaxSuccess(transport);
267
+ if (transport.responseText.isJSON()) {
268
+ var response = transport.responseText.evalJSON()
269
+ var newNode = new Ext.tree.AsyncTreeNode({
270
+ text: response.short_name,
271
+ draggable:false,
272
+ id:response.id,
273
+ expanded: true
274
+ });
275
+ var child = this.currentNode.appendChild(newNode);
276
+ this.tree.expandPath(child.getPath(), '', function(success, node) {
277
+ this.selectFolder(node);
278
+ }.bind(this));
279
+ }
280
+ } catch (e) {
281
+ alert(e.message);
282
+ }
283
+ }.bind(this)
284
+ })
285
+ },
286
+
287
+ deleteFolder: function() {
288
+ if (!confirm(this.deleteFolderConfirmationMessage)) {
289
+ return false;
290
+ }
291
+ new Ajax.Request(this.deleteFolderUrl, {
292
+ onSuccess: function(transport) {
293
+ try {
294
+ this.onAjaxSuccess(transport);
295
+ var parent = this.currentNode.parentNode;
296
+ parent.removeChild(this.currentNode);
297
+ this.selectFolder(parent);
298
+ }
299
+ catch (e) {
300
+ alert(e.message);
301
+ }
302
+ }.bind(this)
303
+ })
304
+ },
305
+
306
+ deleteFiles: function() {
307
+ if (!confirm(this.deleteFileConfirmationMessage)) {
308
+ return false;
309
+ }
310
+ var ids = [];
311
+ var i = 0;
312
+ $$('div.selected').each(function (e) {
313
+ ids[i] = e.id;
314
+ i++;
315
+ });
316
+ new Ajax.Request(this.deleteFilesUrl, {
317
+ parameters: {files: Object.toJSON(ids)},
318
+ onSuccess: function(transport) {
319
+ try {
320
+ this.onAjaxSuccess(transport);
321
+ this.selectFolder(this.currentNode);
322
+ } catch(e) {
323
+ alert(e.message);
324
+ }
325
+ }.bind(this)
326
+ });
327
+ },
328
+
329
+ drawBreadcrumbs: function(node) {
330
+ if ($('breadcrumbs') != undefined) {
331
+ $('breadcrumbs').remove();
332
+ }
333
+ if (node.id == 'root') {
334
+ return;
335
+ }
336
+ var path = node.getPath().split('/');
337
+ var breadcrumbs = '';
338
+ for(var i = 0, length = path.length; i < length; i++) {
339
+ if (path[i] == '') {
340
+ continue;
341
+ }
342
+ var currNode = this.tree.getNodeById(path[i]);
343
+ if (currNode.id) {
344
+ breadcrumbs += '<li>';
345
+ breadcrumbs += '<a href="#" onclick="MediabrowserInstance.selectFolderById(\'' + currNode.id + '\');">' + currNode.text + '</a>';
346
+ if(i < (length - 1)) {
347
+ breadcrumbs += ' <span>/</span>';
348
+ }
349
+ breadcrumbs += '</li>';
350
+ }
351
+ }
352
+
353
+ if (breadcrumbs != '') {
354
+ breadcrumbs = '<ul class="breadcrumbs" id="breadcrumbs">' + breadcrumbs + '</ul>';
355
+ $('content_header').insert({after: breadcrumbs});
356
+ }
357
+ },
358
+
359
+ updateHeader: function(node) {
360
+ var header = (node.id == 'root' ? this.headerText : node.text);
361
+ if ($('content_header_text') != undefined) {
362
+ $('content_header_text').innerHTML = header;
363
+ }
364
+ },
365
+
366
+ activateBlock: function(id) {
367
+ //$$('div [id^=contents]').each(this.hideElement);
368
+ this.showElement(id);
369
+ },
370
+
371
+ hideElement: function(id) {
372
+ if ($(id) != undefined) {
373
+ $(id).addClassName('no-display');
374
+ $(id).hide();
375
+ }
376
+ },
377
+
378
+ showElement: function(id) {
379
+ if ($(id) != undefined) {
380
+ $(id).removeClassName('no-display');
381
+ $(id).show();
382
+ }
383
+ },
384
+
385
+ onAjaxSuccess: function(transport) {
386
+ if (transport.responseText.isJSON()) {
387
+ var response = transport.responseText.evalJSON()
388
+ if (response.error) {
389
+ throw response;
390
+ } else if (response.ajaxExpired && response.ajaxRedirect) {
391
+ setLocation(response.ajaxRedirect);
392
+ }
393
+ }
394
+ }
395
+ }
js/mage/adminhtml/events.js ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ // from http://www.someelement.com/2007/03/eventpublisher-custom-events-la-pubsub.html
26
+ varienEvents = Class.create();
27
+
28
+ varienEvents.prototype = {
29
+ initialize: function() {
30
+ this.arrEvents = {};
31
+ this.eventPrefix = '';
32
+ },
33
+
34
+ /**
35
+ * Attaches a {handler} function to the publisher's {eventName} event for execution upon the event firing
36
+ * @param {String} eventName
37
+ * @param {Function} handler
38
+ * @param {Boolean} asynchFlag [optional] Defaults to false if omitted. Indicates whether to execute {handler} asynchronously (true) or not (false).
39
+ */
40
+ attachEventHandler : function(eventName, handler) {
41
+ if ((typeof handler == 'undefined') || (handler == null)) {
42
+ return;
43
+ }
44
+ eventName = eventName + this.eventPrefix;
45
+ // using an event cache array to track all handlers for proper cleanup
46
+ if (this.arrEvents[eventName] == null){
47
+ this.arrEvents[eventName] = [];
48
+ }
49
+ //create a custom object containing the handler method and the asynch flag
50
+ var asynchVar = arguments.length > 2 ? arguments[2] : false;
51
+ var handlerObj = {
52
+ method: handler,
53
+ asynch: asynchVar
54
+ };
55
+ this.arrEvents[eventName].push(handlerObj);
56
+ },
57
+
58
+ /**
59
+ * Removes a single handler from a specific event
60
+ * @param {String} eventName The event name to clear the handler from
61
+ * @param {Function} handler A reference to the handler function to un-register from the event
62
+ */
63
+ removeEventHandler : function(eventName, handler) {
64
+ eventName = eventName + this.eventPrefix;
65
+ if (this.arrEvents[eventName] != null){
66
+ this.arrEvents[eventName] = this.arrEvents[eventName].reject(function(obj) { return obj.method == handler; });
67
+ }
68
+ },
69
+
70
+ /**
71
+ * Removes all handlers from a single event
72
+ * @param {String} eventName The event name to clear handlers from
73
+ */
74
+ clearEventHandlers : function(eventName) {
75
+ eventName = eventName + this.eventPrefix;
76
+ this.arrEvents[eventName] = null;
77
+ },
78
+
79
+ /**
80
+ * Removes all handlers from ALL events
81
+ */
82
+ clearAllEventHandlers : function() {
83
+ this.arrEvents = {};
84
+ },
85
+
86
+ /**
87
+ * Fires the event {eventName}, resulting in all registered handlers to be executed.
88
+ * It also collects and returns results of all non-asynchronous handlers
89
+ * @param {String} eventName The name of the event to fire
90
+ * @params {Object} args [optional] Any object, will be passed into the handler function as the only argument
91
+ * @return {Array}
92
+ */
93
+ fireEvent : function(eventName) {
94
+ var evtName = eventName + this.eventPrefix;
95
+ var results = [];
96
+ var result;
97
+ if (this.arrEvents[evtName] != null) {
98
+ var len = this.arrEvents[evtName].length; //optimization
99
+ for (var i = 0; i < len; i++) {
100
+ try {
101
+ if (arguments.length > 1) {
102
+ if (this.arrEvents[evtName][i].asynch) {
103
+ var eventArgs = arguments[1];
104
+ var method = this.arrEvents[evtName][i].method.bind(this);
105
+ setTimeout(function() { method(eventArgs) }.bind(this), 10);
106
+ }
107
+ else{
108
+ result = this.arrEvents[evtName][i].method(arguments[1]);
109
+ }
110
+ }
111
+ else {
112
+ if (this.arrEvents[evtName][i].asynch) {
113
+ var eventHandler = this.arrEvents[evtName][i].method;
114
+ setTimeout(eventHandler, 1);
115
+ }
116
+ else if (this.arrEvents && this.arrEvents[evtName] && this.arrEvents[evtName][i] && this.arrEvents[evtName][i].method){
117
+ result = this.arrEvents[evtName][i].method();
118
+ }
119
+ }
120
+ results.push(result);
121
+ }
122
+ catch (e) {
123
+ if (this.id){
124
+ alert("error: error in " + this.id + ".fireEvent():\n\nevent name: " + eventName + "\n\nerror message: " + e.message);
125
+ }
126
+ else {
127
+ alert("error: error in [unknown object].fireEvent():\n\nevent name: " + eventName + "\n\nerror message: " + e.message);
128
+ }
129
+ }
130
+ }
131
+ }
132
+ return results;
133
+ }
134
+ };
135
+
136
+ varienGlobalEvents = new varienEvents();
137
+
js/mage/adminhtml/flexuploader.js ADDED
@@ -0,0 +1,372 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ if(!window.Flex) {
27
+ alert('Flex library not loaded');
28
+ } else {
29
+ Flex.Uploader = Class.create();
30
+ Flex.Uploader.prototype = {
31
+ flex: null,
32
+ uploader:null,
33
+ filters:null,
34
+ containerId:null,
35
+ flexContainerId:null,
36
+ container:null,
37
+ files:null,
38
+ fileRowTemplate:null,
39
+ fileProgressTemplate:null,
40
+ templatesPattern: /(^|.|\r|\n)(\{\{(.*?)\}\})/,
41
+ onFilesComplete: false,
42
+ onFileProgress: true,
43
+ onFileRemove: false,
44
+ onContainerHideBefore:null,
45
+ initialize: function(containerId, uploaderSrc, config) {
46
+ this.containerId = containerId;
47
+ this.container = $(containerId);
48
+
49
+ this.container.controller = this;
50
+
51
+ this.config = config;
52
+
53
+ this.flexContainerId = this.containerId + '-flash';
54
+ Element.insert(
55
+ // window.document.body,
56
+ this.containerId,
57
+ {'before':'<div id="'+this.flexContainerId+'" class="flex" style="position:relative;float:right;"></div>'}
58
+ );
59
+ flexWidth = 230;
60
+ if (this.config.width) {
61
+ flexWidth = this.config.width;
62
+ }
63
+ this.flex = new Flex.Object({
64
+ left: 100,
65
+ top: 300,
66
+ width: flexWidth,
67
+ height: 20,
68
+ src: uploaderSrc
69
+ // wmode: 'transparent'
70
+ });
71
+ // this.getInnerElement('browse').disabled = true;
72
+ // this.getInnerElement('upload').disabled = true;
73
+ this.fileRowTemplate = new Template(
74
+ this.getInnerElement('template').innerHTML,
75
+ this.templatesPattern
76
+ );
77
+
78
+ this.fileProgressTemplate = new Template(
79
+ this.getInnerElement('template-progress').innerHTML,
80
+ this.templatesPattern
81
+ );
82
+
83
+ this.flex.onBridgeInit = this.handleBridgeInit.bind(this);
84
+ if (this.flex.detectFlashVersion(9, 0, 28)) {
85
+ this.flex.apply(this.flexContainerId);
86
+ } else {
87
+ // this.getInnerElement('browse').hide();
88
+ // this.getInnerElement('upload').hide();
89
+ this.getInnerElement('install-flash').show();
90
+ }
91
+ this.onContainerHideBefore = this.handleContainerHideBefore.bind(this);
92
+ },
93
+ getInnerElement: function(elementName) {
94
+ return $(this.containerId + '-' + elementName);
95
+ },
96
+ getFileId: function(file) {
97
+ var id;
98
+ if(typeof file == 'object') {
99
+ id = file.id;
100
+ } else {
101
+ id = file;
102
+ }
103
+ return this.containerId + '-file-' + id;
104
+ },
105
+ getDeleteButton: function(file) {
106
+ return $(this.getFileId(file) + '-delete');
107
+ },
108
+ handleBridgeInit: function() {
109
+ this.uploader = this.flex.getBridge().getUpload();
110
+ if (this.config.filters) {
111
+ $H(this.config.filters).each(function(pair) {
112
+ this.uploader.addTypeFilter(pair.key, pair.value.label, pair.value.files);
113
+ }.bind(this));
114
+ delete(this.config.filters);
115
+ this.uploader.setUseTypeFilter(true);
116
+ }
117
+
118
+ this.uploader.setConfig(this.config);
119
+ this.uploader.addEventListener('select', this.handleSelect.bind(this));
120
+ this.uploader.addEventListener('complete', this.handleComplete.bind(this));
121
+ this.uploader.addEventListener('progress', this.handleProgress.bind(this));
122
+ this.uploader.addEventListener('error', this.handleError.bind(this));
123
+ this.uploader.addEventListener('removeall', this.handleRemoveAll.bind(this));
124
+ // this.getInnerElement('browse').disabled = false;
125
+ // this.getInnerElement('upload').disabled = false;
126
+ },
127
+ browse: function() {
128
+ this.uploader.browse();
129
+ },
130
+ upload: function() {
131
+ this.uploader.upload();
132
+ this.files = this.uploader.getFilesInfo();
133
+ this.updateFiles();
134
+ },
135
+ removeFile: function(id) {
136
+ this.uploader.removeFile(id);
137
+ $(this.getFileId(id)).remove();
138
+ if (this.onFileRemove) {
139
+ this.onFileRemove(id);
140
+ }
141
+ this.files = this.uploader.getFilesInfo();
142
+ this.updateFiles();
143
+ },
144
+ removeAllFiles: function() {
145
+ this.files.each(function(file) {
146
+ this.removeFile(file.id);
147
+ }.bind(this));
148
+ this.files = this.uploader.getFilesInfo();
149
+ this.updateFiles();
150
+ },
151
+ handleSelect: function (event) {
152
+ this.files = event.getData().files;
153
+ this.checkFileSize();
154
+ this.updateFiles();
155
+ this.getInnerElement('upload').show();
156
+ if (this.onFileSelect) {
157
+ this.onFileSelect();
158
+ }
159
+ },
160
+ handleProgress: function (event) {
161
+ var file = event.getData().file;
162
+ this.updateFile(file);
163
+ if (this.onFileProgress) {
164
+ this.onFileProgress(file);
165
+ }
166
+ },
167
+ handleError: function (event) {
168
+ this.updateFile(event.getData().file);
169
+ },
170
+ handleComplete: function (event) {
171
+ this.files = event.getData().files;
172
+ this.updateFiles();
173
+ if (this.onFilesComplete) {
174
+ this.onFilesComplete(this.files);
175
+ }
176
+ },
177
+ handleRemoveAll: function (event) {
178
+ this.files.each(function(file) {
179
+ $(this.getFileId(file.id)).remove();
180
+ }.bind(this));
181
+ if (this.onFileRemoveAll) {
182
+ this.onFileRemoveAll();
183
+ }
184
+ this.files = this.uploader.getFilesInfo();
185
+ this.updateFiles();
186
+ },
187
+ handleRemove: function (event) {
188
+ this.files = this.uploader.getFilesInfo();
189
+ this.updateFiles();
190
+ },
191
+ updateFiles: function () {
192
+ this.files.each(function(file) {
193
+ this.updateFile(file);
194
+ }.bind(this));
195
+ },
196
+ updateFile: function (file) {
197
+ if (!$(this.getFileId(file))) {
198
+ if (this.config.replace_browse_with_remove) {
199
+ $(this.containerId+'-new').show();
200
+ $(this.containerId+'-new').innerHTML = this.fileRowTemplate.evaluate(this.getFileVars(file));
201
+ $(this.containerId+'-old').hide();
202
+ this.flex.getBridge().hideBrowseButton();
203
+ } else {
204
+ Element.insert(this.container, {bottom: this.fileRowTemplate.evaluate(this.getFileVars(file))});
205
+ }
206
+ }
207
+ if (file.status == 'full_complete' && file.response.isJSON()) {
208
+ var response = file.response.evalJSON();
209
+ if (typeof response == 'object') {
210
+ if (typeof response.cookie == 'object') {
211
+ var date = new Date();
212
+ date.setTime(date.getTime()+(parseInt(response.cookie.lifetime)*1000));
213
+
214
+ document.cookie = escape(response.cookie.name) + "="
215
+ + escape(response.cookie.value)
216
+ + "; expires=" + date.toGMTString()
217
+ + (response.cookie.path.blank() ? "" : "; path=" + response.cookie.path)
218
+ + (response.cookie.domain.blank() ? "" : "; domain=" + response.cookie.domain);
219
+ }
220
+ if (typeof response.error != 'undefined' && response.error != 0) {
221
+ file.status = 'error';
222
+ file.errorText = response.error;
223
+ }
224
+ }
225
+ }
226
+
227
+ if (file.status == 'full_complete' && !file.response.isJSON()) {
228
+ file.status = 'error';
229
+ }
230
+
231
+ var progress = $(this.getFileId(file)).getElementsByClassName('progress-text')[0];
232
+ if ((file.status=='progress') || (file.status=='complete')) {
233
+ $(this.getFileId(file)).addClassName('progress');
234
+ $(this.getFileId(file)).removeClassName('new');
235
+ $(this.getFileId(file)).removeClassName('error');
236
+ if (file.progress && file.progress.total) {
237
+ progress.update(this.fileProgressTemplate.evaluate(this.getFileProgressVars(file)));
238
+ } else {
239
+ progress.update('');
240
+ }
241
+ if (! this.config.replace_browse_with_remove) {
242
+ this.getDeleteButton(file).hide();
243
+ }
244
+ } else if (file.status=='error') {
245
+ $(this.getFileId(file)).addClassName('error');
246
+ $(this.getFileId(file)).removeClassName('progress');
247
+ $(this.getFileId(file)).removeClassName('new');
248
+ var errorText = file.errorText ? file.errorText : this.errorText(file);
249
+ if (this.config.replace_browse_with_remove) {
250
+ this.flex.getBridge().hideBrowseButton();
251
+ } else {
252
+ this.getDeleteButton(file).show();
253
+ }
254
+
255
+ progress.update(errorText);
256
+
257
+ } else if (file.status=='full_complete') {
258
+ $(this.getFileId(file)).addClassName('complete');
259
+ $(this.getFileId(file)).removeClassName('progress');
260
+ $(this.getFileId(file)).removeClassName('error');
261
+ if (this.config.replace_browse_with_remove) {
262
+ this.flex.getBridge().hideRemoveButton();
263
+ }
264
+ progress.update(this.translate('Complete'));
265
+ }
266
+ },
267
+ getDebugStr: function(obj) {
268
+ return Object.toJSON(obj).replace('&', '&amp;').replace('>', '&gt;').replace('<', '&lt;');
269
+ },
270
+ getFileVars: function(file) {
271
+ return {
272
+ id : this.getFileId(file),
273
+ fileId : file.id,
274
+ name : file.name,
275
+ size : this.formatSize(file.size)
276
+ };
277
+ },
278
+ getFileProgressVars: function(file) {
279
+ return {
280
+ total : this.formatSize(file.progress.total),
281
+ uploaded : this.formatSize(file.progress.loaded),
282
+ percent : this.round((file.progress.loaded/file.progress.total)*100)
283
+ };
284
+ },
285
+ formatSize: function(size) {
286
+ if (size > 1024*1024*1024*1024) {
287
+ return this.round(size/(1024*1024*1024*1024)) + ' ' + this.translate('Tb');
288
+ } else if (size > 1024*1024*1024) {
289
+ return this.round(size/(1024*1024*1024)) + ' ' + this.translate('Gb');
290
+ } else if (size > 1024*1024) {
291
+ return this.round(size/(1024*1024)) + ' ' + this.translate('Mb');
292
+ } else if (size > 1024) {
293
+ return this.round(size/(1024)) + ' ' + this.translate('Kb');
294
+ }
295
+ return size + ' ' + this.translate('b');
296
+ },
297
+ round: function(number) {
298
+ return Math.round(number*100)/100;
299
+ },
300
+ checkFileSize: function() {
301
+ newFiles = [];
302
+ hasTooBigFiles = false;
303
+ this.files.each(function(file){
304
+ if (file.size > maxUploadFileSizeInBytes) {
305
+ hasTooBigFiles = true;
306
+ this.uploader.removeFile(file.id)
307
+ } else {
308
+ newFiles.push(file)
309
+ }
310
+ }.bind(this));
311
+ this.files = newFiles;
312
+ if (hasTooBigFiles) {
313
+ alert(
314
+ this.translate('Maximum allowed file size for upload is')+' '+maxUploadFileSize+".\n"+this.translate('Please check your server PHP settings.')
315
+ );
316
+ }
317
+ },
318
+ translate: function(text) {
319
+ try {
320
+ if(Translator){
321
+ return Translator.translate(text);
322
+ }
323
+ }
324
+ catch(e){}
325
+ return text;
326
+ },
327
+ errorText: function(file) {
328
+ var error = '';
329
+
330
+ switch(file.errorCode) {
331
+ case 1: // Size 0
332
+ error = 'File size should be more than 0 bytes';
333
+ break;
334
+ case 2: // Http error
335
+ error = 'Upload HTTP Error';
336
+ break;
337
+ case 3: // I/O error
338
+ error = 'Upload I/O Error';
339
+ break;
340
+ case 4: // Security error
341
+ error = 'Upload Security Error';
342
+ break;
343
+ case 5: // SSL self-signed certificate
344
+ error = 'SSL Error: Invalid or self-signed certificate';
345
+ break;
346
+ }
347
+
348
+ if(error) {
349
+ return this.translate(error);
350
+ }
351
+
352
+ return error;
353
+ },
354
+ handleContainerHideBefore: function(container) {
355
+ if (container && Element.descendantOf(this.container, container) && !this.checkAllComplete()) {
356
+ if (! confirm('There are files that were selected but not uploaded yet. After switching to another tab your selections will be lost. Do you wish to continue ?')) {
357
+ return 'cannotchange';
358
+ } else {
359
+ this.removeAllFiles();
360
+ }
361
+ }
362
+ },
363
+ checkAllComplete: function() {
364
+ if (this.files) {
365
+ return !this.files.any(function(file) {
366
+ return (file.status !== 'full_complete')
367
+ });
368
+ }
369
+ return true;
370
+ }
371
+ }
372
+ }
js/mage/adminhtml/form.js ADDED
@@ -0,0 +1,470 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ var varienForm = new Class.create();
26
+
27
+ varienForm.prototype = {
28
+ initialize : function(formId, validationUrl){
29
+ this.formId = formId;
30
+ this.validationUrl = validationUrl;
31
+ this.submitUrl = false;
32
+
33
+ if($(this.formId)){
34
+ this.validator = new Validation(this.formId, {onElementValidate : this.checkErrors.bind(this)});
35
+ }
36
+ this.errorSections = $H({});
37
+ },
38
+
39
+ checkErrors : function(result, elm){
40
+ if(!result)
41
+ elm.setHasError(true, this);
42
+ else
43
+ elm.setHasError(false, this);
44
+ },
45
+
46
+ validate : function(){
47
+ if(this.validator && this.validator.validate()){
48
+ if(this.validationUrl){
49
+ this._validate();
50
+ }
51
+ return true;
52
+ }
53
+ return false;
54
+ },
55
+
56
+ submit : function(url){
57
+ if (typeof varienGlobalEvents != undefined) {
58
+ varienGlobalEvents.fireEvent('formSubmit', this.formId);
59
+ }
60
+ this.errorSections = $H({});
61
+ this.canShowError = true;
62
+ this.submitUrl = url;
63
+ if(this.validator && this.validator.validate()){
64
+ if(this.validationUrl){
65
+ this._validate();
66
+ }
67
+ else{
68
+ this._submit();
69
+ }
70
+ return true;
71
+ }
72
+ return false;
73
+ },
74
+
75
+ _validate : function(){
76
+ new Ajax.Request(this.validationUrl,{
77
+ method: 'post',
78
+ parameters: $(this.formId).serialize(),
79
+ onComplete: this._processValidationResult.bind(this),
80
+ onFailure: this._processFailure.bind(this)
81
+ });
82
+ },
83
+
84
+ _processValidationResult : function(transport){
85
+ if (typeof varienGlobalEvents != undefined) {
86
+ varienGlobalEvents.fireEvent('formValidateAjaxComplete', transport);
87
+ }
88
+ var response = transport.responseText.evalJSON();
89
+ if(response.error){
90
+ if($('messages')){
91
+ $('messages').innerHTML = response.message;
92
+ }
93
+ }
94
+ else{
95
+ this._submit();
96
+ }
97
+ },
98
+
99
+ _processFailure : function(transport){
100
+ location.href = BASE_URL;
101
+ },
102
+
103
+ _submit : function(){
104
+ if(this.submitUrl){
105
+ $(this.formId).action = this.submitUrl;
106
+ }
107
+ $(this.formId).submit();
108
+ }
109
+ }
110
+
111
+ /**
112
+ * redeclare Validation.isVisible function
113
+ *
114
+ * use for not visible elements validation
115
+ */
116
+ Validation.isVisible = function(elm){
117
+ while (elm && elm.tagName != 'BODY') {
118
+ if (elm.disabled) return false;
119
+ if ((Element.hasClassName(elm, 'template') && Element.hasClassName(elm, 'no-display'))
120
+ || Element.hasClassName(elm, 'ignore-validate')){
121
+ return false;
122
+ }
123
+ elm = elm.parentNode;
124
+ }
125
+ return true;
126
+ }
127
+
128
+ /**
129
+ * Additional elements methods
130
+ */
131
+ var varienElementMethods = {
132
+ setHasChanges : function(element, event){
133
+ if($(element) && $(element).hasClassName('no-changes')) return;
134
+ var elm = element;
135
+ while(elm && elm.tagName != 'BODY') {
136
+ if(elm.statusBar)
137
+ Element.addClassName($(elm.statusBar), 'changed')
138
+ elm = elm.parentNode;
139
+ }
140
+ },
141
+ setHasError : function(element, flag, form){
142
+ var elm = element;
143
+ while(elm && elm.tagName != 'BODY') {
144
+ if(elm.statusBar){
145
+ if(form.errorSections.keys().indexOf(elm.statusBar.id)<0)
146
+ form.errorSections.set(elm.statusBar.id, flag);
147
+ if(flag){
148
+ Element.addClassName($(elm.statusBar), 'error');
149
+ if(form.canShowError && $(elm.statusBar).show){
150
+ form.canShowError = false;
151
+ $(elm.statusBar).show();
152
+ }
153
+ form.errorSections.set(elm.statusBar.id, flag);
154
+ }
155
+ else if(!form.errorSections.get(elm.statusBar.id)){
156
+ Element.removeClassName($(elm.statusBar), 'error')
157
+ }
158
+ }
159
+ elm = elm.parentNode;
160
+ }
161
+ this.canShowElement = false;
162
+ }
163
+ }
164
+
165
+ Element.addMethods(varienElementMethods);
166
+
167
+ // Global bind changes
168
+ varienWindowOnloadCache = {};
169
+ function varienWindowOnload(useCache){
170
+ var dataElements = $$('input', 'select', 'textarea');
171
+ for(var i=0; i<dataElements.length;i++){
172
+ if(dataElements[i] && dataElements[i].id){
173
+ if ((!useCache) || (!varienWindowOnloadCache[dataElements[i].id])) {
174
+ Event.observe(dataElements[i], 'change', dataElements[i].setHasChanges.bind(dataElements[i]));
175
+ if (useCache) {
176
+ varienWindowOnloadCache[dataElements[i].id] = true;
177
+ }
178
+ }
179
+ }
180
+ }
181
+ }
182
+ Event.observe(window, 'load', varienWindowOnload);
183
+
184
+ RegionUpdater = Class.create();
185
+ RegionUpdater.prototype = {
186
+ initialize: function (countryEl, regionTextEl, regionSelectEl, regions, disableAction, clearRegionValueOnDisable)
187
+ {
188
+ this.countryEl = $(countryEl);
189
+ this.regionTextEl = $(regionTextEl);
190
+ this.regionSelectEl = $(regionSelectEl);
191
+ // // clone for select element (#6924)
192
+ // this._regionSelectEl = {};
193
+ // this.tpl = new Template('<select class="#{className}" name="#{name}" id="#{id}">#{innerHTML}</select>');
194
+ this.regions = regions;
195
+ this.disableAction = (typeof disableAction=='undefined') ? 'hide' : disableAction;
196
+ this.clearRegionValueOnDisable = (typeof clearRegionValueOnDisable == 'undefined') ? false : clearRegionValueOnDisable;
197
+
198
+ if (this.regionSelectEl.options.length<=1) {
199
+ this.update();
200
+ }
201
+ else {
202
+ this.lastCountryId = this.countryEl.value;
203
+ }
204
+
205
+ this.countryEl.changeUpdater = this.update.bind(this);
206
+
207
+ Event.observe(this.countryEl, 'change', this.update.bind(this));
208
+ },
209
+
210
+ update: function()
211
+ {
212
+ if (this.regions[this.countryEl.value]) {
213
+ // if (!this.regionSelectEl) {
214
+ // Element.insert(this.regionTextEl, {after : this.tpl.evaluate(this._regionSelectEl)});
215
+ // this.regionSelectEl = $(this._regionSelectEl.id);
216
+ // }
217
+ if (this.lastCountryId!=this.countryEl.value) {
218
+ var i, option, region, def;
219
+
220
+ if (this.regionTextEl) {
221
+ def = this.regionTextEl.value.toLowerCase();
222
+ this.regionTextEl.value = '';
223
+ }
224
+ if (!def) {
225
+ def = this.regionSelectEl.getAttribute('defaultValue');
226
+ }
227
+
228
+ this.regionSelectEl.options.length = 1;
229
+ for (regionId in this.regions[this.countryEl.value]) {
230
+ region = this.regions[this.countryEl.value][regionId];
231
+
232
+ option = document.createElement('OPTION');
233
+ option.value = regionId;
234
+ option.text = region.name;
235
+
236
+ if (this.regionSelectEl.options.add) {
237
+ this.regionSelectEl.options.add(option);
238
+ } else {
239
+ this.regionSelectEl.appendChild(option);
240
+ }
241
+
242
+ if (regionId==def || region.name.toLowerCase()==def || region.code.toLowerCase()==def) {
243
+ this.regionSelectEl.value = regionId;
244
+ }
245
+ }
246
+ }
247
+
248
+ if (this.disableAction=='hide') {
249
+ if (this.regionTextEl) {
250
+ this.regionTextEl.style.display = 'none';
251
+ this.regionTextEl.style.disabled = true;
252
+ }
253
+ this.regionSelectEl.style.display = '';
254
+ this.regionSelectEl.disabled = false;
255
+ } else if (this.disableAction=='disable') {
256
+ if (this.regionTextEl) {
257
+ this.regionTextEl.disabled = true;
258
+ }
259
+ this.regionSelectEl.disabled = false;
260
+ }
261
+ this.setMarkDisplay(this.regionSelectEl, true);
262
+
263
+ this.lastCountryId = this.countryEl.value;
264
+ } else {
265
+ if (this.disableAction=='hide') {
266
+ if (this.regionTextEl) {
267
+ this.regionTextEl.style.display = '';
268
+ this.regionTextEl.style.disabled = false;
269
+ }
270
+ this.regionSelectEl.style.display = 'none';
271
+ this.regionSelectEl.disabled = true;
272
+ } else if (this.disableAction=='disable') {
273
+ if (this.regionTextEl) {
274
+ this.regionTextEl.disabled = false;
275
+ }
276
+ this.regionSelectEl.disabled = true;
277
+ if (this.clearRegionValueOnDisable) {
278
+ this.regionSelectEl.value = '';
279
+ }
280
+ } else if (this.disableAction=='nullify') {
281
+ this.regionSelectEl.options.length = 1;
282
+ this.regionSelectEl.value = '';
283
+ this.regionSelectEl.selectedIndex = 0;
284
+ this.lastCountryId = '';
285
+ }
286
+ this.setMarkDisplay(this.regionSelectEl, false);
287
+
288
+ // // clone required stuff from select element and then remove it
289
+ // this._regionSelectEl.className = this.regionSelectEl.className;
290
+ // this._regionSelectEl.name = this.regionSelectEl.name;
291
+ // this._regionSelectEl.id = this.regionSelectEl.id;
292
+ // this._regionSelectEl.innerHTML = this.regionSelectEl.innerHTML;
293
+ // Element.remove(this.regionSelectEl);
294
+ // this.regionSelectEl = null;
295
+ }
296
+ varienGlobalEvents.fireEvent("address_country_changed", this.countryEl);
297
+ },
298
+
299
+ setMarkDisplay: function(elem, display){
300
+ if(elem.parentNode.parentNode){
301
+ var marks = Element.select(elem.parentNode.parentNode, '.required');
302
+ if(marks[0]){
303
+ display ? marks[0].show() : marks[0].hide();
304
+ }
305
+ }
306
+ }
307
+ }
308
+
309
+ regionUpdater = RegionUpdater;
310
+
311
+ /**
312
+ * Fix errorrs in IE
313
+ */
314
+ Event.pointerX = function(event){
315
+ try{
316
+ return event.pageX || (event.clientX +(document.documentElement.scrollLeft || document.body.scrollLeft));
317
+ }
318
+ catch(e){
319
+
320
+ }
321
+ }
322
+ Event.pointerY = function(event){
323
+ try{
324
+ return event.pageY || (event.clientY +(document.documentElement.scrollTop || document.body.scrollTop));
325
+ }
326
+ catch(e){
327
+
328
+ }
329
+ }
330
+
331
+ SelectUpdater = Class.create();
332
+ SelectUpdater.prototype = {
333
+ initialize: function (firstSelect, secondSelect, selectFirstMessage, noValuesMessage, values, selected)
334
+ {
335
+ this.first = $(firstSelect);
336
+ this.second = $(secondSelect);
337
+ this.message = selectFirstMessage;
338
+ this.values = values;
339
+ this.noMessage = noValuesMessage;
340
+ this.selected = selected;
341
+
342
+ this.update();
343
+
344
+ Event.observe(this.first, 'change', this.update.bind(this));
345
+ },
346
+
347
+ update: function()
348
+ {
349
+ this.second.length = 0;
350
+ this.second.value = '';
351
+
352
+ if (this.first.value && this.values[this.first.value]) {
353
+ for (optionValue in this.values[this.first.value]) {
354
+ optionTitle = this.values[this.first.value][optionValue];
355
+
356
+ this.addOption(this.second, optionValue, optionTitle);
357
+ }
358
+ this.second.disabled = false;
359
+ } else if (this.first.value && !this.values[this.first.value]) {
360
+ this.addOption(this.second, '', this.noMessage);
361
+ } else {
362
+ this.addOption(this.second, '', this.message);
363
+ this.second.disabled = true;
364
+ }
365
+ },
366
+
367
+ addOption: function(select, value, text)
368
+ {
369
+ option = document.createElement('OPTION');
370
+ option.value = value;
371
+ option.text = text;
372
+
373
+ if (this.selected && option.value == this.selected) {
374
+ option.selected = true;
375
+ this.selected = false;
376
+ }
377
+
378
+ if (select.options.add) {
379
+ select.options.add(option);
380
+ } else {
381
+ select.appendChild(option);
382
+ }
383
+ }
384
+ }
385
+
386
+
387
+ /**
388
+ * Observer that watches for dependent form elements
389
+ * If an element depends on 1 or more of other elements, it should show up only when all of them gain specified values
390
+ * TODO: implement multiple values per "master" elements
391
+ */
392
+ FormElementDependenceController = Class.create();
393
+ FormElementDependenceController.prototype = {
394
+ /**
395
+ * Structure of elements: {
396
+ * 'id_of_dependent_element' : {
397
+ * 'id_of_master_element_1' : 'reference_value',
398
+ * 'id_of_master_element_2' : 'reference_value'
399
+ * ...
400
+ * }
401
+ * }
402
+ * @param object elementsMap
403
+ * @param object config
404
+ */
405
+ initialize : function (elementsMap, config)
406
+ {
407
+ if (config) {
408
+ this._config = config;
409
+ }
410
+ for (var idTo in elementsMap) {
411
+ for (var idFrom in elementsMap[idTo]) {
412
+ if ($(idFrom)) {
413
+ Event.observe($(idFrom), 'change', this.trackChange.bindAsEventListener(this, idTo, elementsMap[idTo]));
414
+ this.trackChange(null, idTo, elementsMap[idTo]);
415
+ } else {
416
+ this.trackChange(null, idTo, elementsMap[idTo]);
417
+ }
418
+ }
419
+ }
420
+ },
421
+
422
+ /**
423
+ * Misc. config options
424
+ * Keys are underscored intentionally
425
+ */
426
+ _config : {
427
+ levels_up : 1 // how many levels up to travel when toggling element
428
+ },
429
+
430
+ /**
431
+ * Define whether target element should be toggled and show/hide its row
432
+ *
433
+ * @param object e - event
434
+ * @param string idTo - id of target element
435
+ * @param valuesFrom - ids of master elements and reference values
436
+ * @return
437
+ */
438
+ trackChange : function(e, idTo, valuesFrom)
439
+ {
440
+ // define whether the target should show up
441
+ var shouldShowUp = true;
442
+ for (var idFrom in valuesFrom) {
443
+ var from = $(idFrom);
444
+ if (!from || from.value != valuesFrom[idFrom]) {
445
+ shouldShowUp = false;
446
+ }
447
+ }
448
+
449
+ // toggle target row
450
+ if (shouldShowUp) {
451
+ var currentConfig = this._config;
452
+ $(idTo).up(this._config.levels_up).select('input', 'select', 'td').each(function (item) {
453
+ // don't touch hidden inputs (and Use Default inputs too), bc they may have custom logic
454
+ if ((!item.type || item.type != 'hidden') && !($(item.id+'_inherit') && $(item.id+'_inherit').checked)
455
+ && !(currentConfig.can_edit_price != undefined && !currentConfig.can_edit_price)) {
456
+ item.disabled = false;
457
+ }
458
+ });
459
+ $(idTo).up(this._config.levels_up).show();
460
+ } else {
461
+ $(idTo).up(this._config.levels_up).select('input', 'select', 'td').each(function (item){
462
+ // don't touch hidden inputs (and Use Default inputs too), bc they may have custom logic
463
+ if ((!item.type || item.type != 'hidden') && !($(item.id+'_inherit') && $(item.id+'_inherit').checked)) {
464
+ item.disabled = true;
465
+ }
466
+ });
467
+ $(idTo).up(this._config.levels_up).hide();
468
+ }
469
+ }
470
+ }
js/mage/adminhtml/giftmessage.js ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ var giftMessagesController = {
27
+ toogleRequired: function(source, objects)
28
+ {
29
+ if(!$(source).value.blank()) {
30
+ objects.each(function(item) {
31
+ $(item).addClassName('required-entry');
32
+ var label = findFieldLabel($(item));
33
+ if (label) {
34
+ var span = label.down('span');
35
+ if (!span) {
36
+ Element.insert(label, {bottom: '&nbsp;<span class="required">*</span>'});
37
+ }
38
+ }
39
+ });
40
+ } else {
41
+ objects.each(function(item) {
42
+ if($(source).formObj && $(source).formObj.validator) {
43
+ $(source).formObj.validator.reset(item);
44
+ }
45
+ $(item).removeClassName('required-entry');
46
+ var label = findFieldLabel($(item));
47
+ if (label) {
48
+ var span = label.down('span');
49
+ if (span) {
50
+ Element.remove(span);
51
+ }
52
+ }
53
+ // Hide validation advices if exist
54
+ if ($(item) && $(item).advices) {
55
+ $(item).advices.each(function (pair) {
56
+ if (pair.value != null) pair.value.hide();
57
+ });
58
+ }
59
+ });
60
+ }
61
+ },
62
+ toogleGiftMessage: function(container) {
63
+ if(!$(container).toogleGiftMessage) {
64
+ $(container).toogleGiftMessage = true;
65
+ $(this.getFieldId(container, 'edit')).show();
66
+ $(container).down('.action-link').addClassName('open');
67
+ $(container).down('.default-text').hide();
68
+ $(container).down('.close-text').show();
69
+ this.toogleRequired(this.getFieldId(container, 'message'), [
70
+ this.getFieldId(container, 'sender'),
71
+ this.getFieldId(container, 'recipient')
72
+ ]);
73
+ } else {
74
+ $(container).toogleGiftMessage = false;
75
+ $(this.getFieldId(container, 'message')).formObj = $(this.getFieldId(container, 'form'));
76
+
77
+ if(!$(this.getFieldId(container, 'form')).validator) {
78
+ $(this.getFieldId(container, 'form')).validator = new Validation(this.getFieldId(container, 'form'));
79
+ }
80
+
81
+ if(!$(this.getFieldId(container, 'form')).validator.validate()) {
82
+ return false;
83
+ }
84
+
85
+ new Ajax.Request($(this.getFieldId(container, 'form')).action, {
86
+ parameters: Form.serialize($(this.getFieldId(container, 'form')), true),
87
+ loaderArea: container,
88
+ onComplete: function(transport) {
89
+
90
+ $(container).down('.action-link').removeClassName('open');
91
+ $(container).down('.default-text').show();
92
+ $(container).down('.close-text').hide();
93
+ $(this.getFieldId(container, 'edit')).hide();
94
+ if (transport.responseText.match(/YES/g)) {
95
+ $(container).down('.default-text').down('.edit').show();
96
+ $(container).down('.default-text').down('.add').hide();
97
+ } else {
98
+ $(container).down('.default-text').down('.add').show();
99
+ $(container).down('.default-text').down('.edit').hide();
100
+ }
101
+
102
+ }.bind(this)
103
+ });
104
+ }
105
+
106
+ return false;
107
+ },
108
+ saveGiftMessage: function(container) {
109
+ this.toogleRequired(this.getFieldId(container, 'message'), [
110
+ this.getFieldId(container, 'sender'),
111
+ this.getFieldId(container, 'recipient')
112
+ ]);
113
+
114
+ $(this.getFieldId(container, 'message')).formObj = $(this.getFieldId(container, 'form'));
115
+
116
+ if(!$(this.getFieldId(container, 'form')).validator) {
117
+ $(this.getFieldId(container, 'form')).validator = new Validation(this.getFieldId(container, 'form'));
118
+ }
119
+
120
+ if(!$(this.getFieldId(container, 'form')).validator.validate()) {
121
+ return;
122
+ }
123
+
124
+ new Ajax.Request($(this.getFieldId(container, 'form')).action, {
125
+ parameters: Form.serialize($(this.getFieldId(container, 'form')), true),
126
+ loaderArea: container
127
+ });
128
+ },
129
+ getFieldId: function(container, name) {
130
+ return container + '_' + name;
131
+ }
132
+ };
133
+
134
+ function findFieldLabel(field) {
135
+ var tdField = $(field).up('td');
136
+ if (tdField) {
137
+ var tdLabel = tdField.previous('td');
138
+ if (tdLabel) {
139
+ var label = tdLabel.down('label');
140
+ if (label) {
141
+ return label;
142
+ }
143
+ }
144
+ }
145
+
146
+ return false;
147
+ }
148
+
149
+
150
+ /********************* GIFT OPTIONS POPUP ***********************/
151
+ var GiftOptionsPopup = Class.create();
152
+ GiftOptionsPopup.prototype = {
153
+ giftOptionsWindowMask: null,
154
+ giftOptionsWindow: null,
155
+
156
+ initialize: function() {
157
+ $$('.action-link').each(function (el) {
158
+ Event.observe(el, 'click', this.showItemGiftOptions.bind(this));
159
+ }, this);
160
+
161
+ // Move giftcard popup to start of body, because soon it will contain FORM tag that can break DOM layout if within other FORM
162
+ var oldPopupContainer = $('gift_options_configure');
163
+ if (oldPopupContainer) {
164
+ oldPopupContainer.remove();
165
+ }
166
+
167
+ var newPopupContainer = $('gift_options_configure_new');
168
+ $(document.body).insert({top: newPopupContainer});
169
+ newPopupContainer.id = 'gift_options_configure';
170
+
171
+ // Put controls container inside a FORM tag so we can use Validator
172
+ var form = new Element('form', {action: '#', id: 'gift_options_configuration_form', method: 'post'});
173
+ var formContents = $('gift_options_form_contents');
174
+ if (formContents) {
175
+ formContents.parentNode.appendChild(form);
176
+ form.appendChild(formContents);
177
+ }
178
+ },
179
+
180
+ showItemGiftOptions : function(event) {
181
+ var element = Event.element(event).id;
182
+ var itemId = element.sub('gift_options_link_','');
183
+
184
+ toggleSelectsUnderBlock(this.giftOptionsWindowMask, false);
185
+ this.giftOptionsWindowMask = $('gift_options_window_mask');
186
+ this.giftOptionsWindow = $('gift_options_configure');
187
+ this.giftOptionsWindow.select('select').each(function(el){
188
+ el.style.visibility = 'visible';
189
+ });
190
+
191
+ this.giftOptionsWindowMask.setStyle({'height': $('html-body').getHeight() + 'px'}).show();
192
+ this.giftOptionsWindow.setStyle({'marginTop': -this.giftOptionsWindow.getHeight()/2 + 'px', 'display': 'block'});
193
+ this.setTitle(itemId);
194
+
195
+ Event.observe($('gift_options_cancel_button'), 'click', this.onCloseButton.bind(this));
196
+ Event.observe($('gift_options_ok_button'), 'click', this.onOkButton.bind(this));
197
+ Event.stop(event);
198
+ },
199
+
200
+ setTitle : function (itemId) {
201
+ var productTitleElement = $('order_item_' + itemId + '_title');
202
+ var productTitle = '';
203
+ if (productTitleElement) {
204
+ productTitle = productTitleElement.innerHTML;
205
+ }
206
+ $('gift_options_configure_title').update(productTitle);
207
+ },
208
+
209
+ onOkButton : function() {
210
+ var giftOptionsForm = new varienForm('gift_options_configuration_form');
211
+ giftOptionsForm.canShowError = true;
212
+ if (!giftOptionsForm.validate()) {
213
+ return false;
214
+ }
215
+ giftOptionsForm.validator.reset();
216
+ this.closeWindow();
217
+ return true;
218
+ },
219
+
220
+ onCloseButton : function() {
221
+ this.closeWindow();
222
+ },
223
+
224
+ closeWindow : function() {
225
+ toggleSelectsUnderBlock(this.giftOptionsWindowMask, true);
226
+ this.giftOptionsWindowMask.style.display = 'none';
227
+ this.giftOptionsWindow.style.display = 'none';
228
+ }
229
+ }
230
+
231
+
232
+ /********************* GIFT OPTIONS SET ***********************/
233
+ GiftMessageSet = Class.create();
234
+ GiftMessageSet.prototype = {
235
+ destPrefix: 'current_item_giftmessage_',
236
+ sourcePrefix: 'giftmessage_',
237
+ fields: ['sender', 'recipient', 'message'],
238
+ isObserved: false,
239
+
240
+ initialize: function() {
241
+ $$('.action-link').each(function (el) {
242
+ Event.observe(el, 'click', this.setData.bind(this));
243
+ }, this);
244
+ },
245
+
246
+ setData: function(event) {
247
+ var element = Event.element(event).id;
248
+ this.id = element.sub('gift_options_link_','');
249
+
250
+ if ($('gift-message-form-data-' + this.id)) {
251
+ this.fields.each(function(el) {
252
+ if ($(this.sourcePrefix + this.id + '_' + el) && $(this.destPrefix + el)) {
253
+ $(this.destPrefix + el).value = $(this.sourcePrefix + this.id + '_' + el).value
254
+ }
255
+ }, this);
256
+ $('gift_options_giftmessage').show();
257
+ } else {
258
+ $('gift_options_giftmessage').hide();
259
+ }
260
+
261
+ if (!this.isObserved) {
262
+ Event.observe('gift_options_ok_button', 'click', this.saveData.bind(this));
263
+ this.isObserved = true;
264
+ }
265
+ },
266
+
267
+ saveData: function(event){
268
+ this.fields.each(function(el) {
269
+ if ($(this.sourcePrefix + this.id + '_' + el) && $(this.destPrefix + el)) {
270
+ $(this.sourcePrefix + this.id + '_' + el).value = $(this.destPrefix + el).value;
271
+ }
272
+ }, this);
273
+ if ($(this.sourcePrefix + this.id + '_form')) {
274
+ $(this.sourcePrefix + this.id + '_form').request();
275
+ } else if (typeof(order) != 'undefined') {
276
+ var data = order.serializeData('gift_options_data_' + this.id);
277
+ order.loadArea(['items'], true, data.toObject());
278
+ }
279
+ }
280
+ }
js/mage/adminhtml/giftoptions/tooltip.js ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ /**
27
+ * Gift Options Tooltip Model
28
+ *
29
+ * @category Mage
30
+ * @package Mage_Adminhtml
31
+ * @author Magento Core Team <core@magentocommerce.com>
32
+ */
33
+ GiftOptionsTooltip = Class.create();
34
+ GiftOptionsTooltip.prototype = {
35
+ _tooltipLines: [],
36
+ _tooltipWindow: null,
37
+ _tooltipWindowContent: null,
38
+ _targetLinks: [],
39
+ _eventMouseOver: null,
40
+ _eventMouseOut: null,
41
+ _styleOptions: null,
42
+ _tooltipContentLoaderFunction: null,
43
+
44
+ /**
45
+ * Initialize tooltip object
46
+ */
47
+ initialize: function ()
48
+ {
49
+ var options = Object.extend({
50
+ delta_x: 30,
51
+ delta_y: 0,
52
+ zindex: 1000
53
+ });
54
+ this._styleOptions = options;
55
+ this._eventMouseOver = this.showTooltip.bindAsEventListener(this);
56
+ this._eventMouseOut = this.hideTooltip.bindAsEventListener(this);
57
+ },
58
+
59
+ /**
60
+ * Set gift options tooltip window
61
+ *
62
+ * @param string windowId
63
+ * @param string contentId
64
+ *
65
+ * @return boolean success
66
+ */
67
+ setTooltipWindow: function (windowId, contentId)
68
+ {
69
+ if (!$(windowId) || !$(contentId)) {
70
+ return false;
71
+ }
72
+ this._tooltipWindow = $(windowId);
73
+ this._tooltipWindowContent = $(contentId);
74
+ this.hideTooltip();
75
+ return true;
76
+ },
77
+
78
+ /**
79
+ * Add tooltip to specified link
80
+ *
81
+ * @param string linkId
82
+ * @param string itemId identifier of the item related to link
83
+ *
84
+ * @return boolean success
85
+ */
86
+ addTargetLink: function (linkId, itemId)
87
+ {
88
+ if ($(linkId)) {
89
+ this._targetLinks[linkId] = [];
90
+ this._targetLinks[linkId]['object'] = $(linkId);
91
+ this._targetLinks[linkId]['itemId'] = itemId;
92
+ this._registerEvents(this._targetLinks[linkId]['object']);
93
+ return true;
94
+ }
95
+ return false;
96
+ },
97
+
98
+ /**
99
+ * Detach event listeners from target links when tooltip is destroyed
100
+ */
101
+ destroy: function ()
102
+ {
103
+ for (var linkId in this._targetLinks) {
104
+ Event.stopObserving(this._targetLinks[linkId]['object'], 'mouseover', this._eventMouseOver);
105
+ Event.stopObserving(this._targetLinks[linkId]['object'], 'mouseout', this._eventMouseOut);
106
+ }
107
+ },
108
+
109
+ /**
110
+ * Register event listeners
111
+ *
112
+ * @param object element
113
+ */
114
+ _registerEvents: function (element)
115
+ {
116
+ Event.observe(element, 'mouseover', this._eventMouseOver);
117
+ Event.observe(element, 'mouseout', this._eventMouseOut);
118
+ },
119
+
120
+ /**
121
+ * Move tooltip to mouse position
122
+ *
123
+ * @patram object event
124
+ */
125
+ _moveTooltip: function (event)
126
+ {
127
+ Event.stop(event);
128
+ var mouseX = Event.pointerX(event);
129
+ var mouseY = Event.pointerY(event);
130
+
131
+ this.setStyles(mouseX, mouseY);
132
+ },
133
+
134
+ /**
135
+ * Show tooltip
136
+ *
137
+ * @param object event
138
+ *
139
+ * @return boolean success
140
+ */
141
+ showTooltip: function (event)
142
+ {
143
+ Event.stop(event);
144
+ if (this._tooltipWindow) {
145
+ var link = Event.element(event);
146
+ var itemId = this._targetLinks[link.id]['itemId'];
147
+ var tooltipContent = '';
148
+ if (Object.isFunction(this._tooltipContentLoaderFunction)) {
149
+ tooltipContent = this._tooltipContentLoaderFunction(itemId);
150
+ }
151
+ if (tooltipContent != '') {
152
+ this._updateTooltipWindowContent(tooltipContent)
153
+ this._moveTooltip(event);
154
+ new Element.show(this._tooltipWindow);
155
+ return true;
156
+ }
157
+ }
158
+ return false;
159
+ },
160
+
161
+ /**
162
+ * Set tooltip window styles
163
+ *
164
+ * @param int x
165
+ * @param int y
166
+ */
167
+ setStyles: function (x, y)
168
+ {
169
+ Element.setStyle(this._tooltipWindow, {
170
+ position:'absolute',
171
+ top: y + this._styleOptions.delta_y + 'px',
172
+ left: x + this._styleOptions.delta_x + 'px',
173
+ zindex: this._styleOptions.zindex
174
+ });
175
+ },
176
+
177
+ /**
178
+ * Hide tooltip
179
+ *
180
+ * @param object event
181
+ */
182
+ hideTooltip: function (event)
183
+ {
184
+ if (this._tooltipWindow) {
185
+ new Element.hide(this._tooltipWindow);
186
+ }
187
+ },
188
+
189
+ /**
190
+ * Set gift options tooltip content loader function
191
+ * This function should accept at least one parameter that will serve as an item ID
192
+ *
193
+ * @param Function loaderFunction loader function
194
+ */
195
+ setTooltipContentLoaderFunction: function (loaderFunction)
196
+ {
197
+ this._tooltipContentLoaderFunction = loaderFunction;
198
+ },
199
+
200
+ /**
201
+ * Update tooltip window content
202
+ *
203
+ * @param string content
204
+ */
205
+ _updateTooltipWindowContent: function (content)
206
+ {
207
+ this._tooltipWindowContent.update(content);
208
+ }
209
+ }
210
+
211
+ giftOptionsTooltip = new GiftOptionsTooltip();
js/mage/adminhtml/grid.js ADDED
@@ -0,0 +1,850 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ var varienGrid = new Class.create();
26
+
27
+ varienGrid.prototype = {
28
+ initialize : function(containerId, url, pageVar, sortVar, dirVar, filterVar){
29
+ this.containerId = containerId;
30
+ this.url = url;
31
+ this.pageVar = pageVar || false;
32
+ this.sortVar = sortVar || false;
33
+ this.dirVar = dirVar || false;
34
+ this.filterVar = filterVar || false;
35
+ this.tableSufix = '_table';
36
+ this.useAjax = false;
37
+ this.rowClickCallback = false;
38
+ this.checkboxCheckCallback = false;
39
+ this.preInitCallback = false;
40
+ this.initCallback = false;
41
+ this.initRowCallback = false;
42
+ this.doFilterCallback = false;
43
+
44
+ this.reloadParams = false;
45
+
46
+ this.trOnMouseOver = this.rowMouseOver.bindAsEventListener(this);
47
+ this.trOnMouseOut = this.rowMouseOut.bindAsEventListener(this);
48
+ this.trOnClick = this.rowMouseClick.bindAsEventListener(this);
49
+ this.trOnDblClick = this.rowMouseDblClick.bindAsEventListener(this);
50
+ this.trOnKeyPress = this.keyPress.bindAsEventListener(this);
51
+
52
+ this.thLinkOnClick = this.doSort.bindAsEventListener(this);
53
+ this.initGrid();
54
+ },
55
+ initGrid : function(){
56
+ if(this.preInitCallback){
57
+ this.preInitCallback(this);
58
+ }
59
+ if($(this.containerId+this.tableSufix)){
60
+ this.rows = $$('#'+this.containerId+this.tableSufix+' tbody tr');
61
+ for (var row=0; row<this.rows.length; row++) {
62
+ if(row%2==0){
63
+ Element.addClassName(this.rows[row], 'even');
64
+ }
65
+
66
+ Event.observe(this.rows[row],'mouseover',this.trOnMouseOver);
67
+ Event.observe(this.rows[row],'mouseout',this.trOnMouseOut);
68
+ Event.observe(this.rows[row],'click',this.trOnClick);
69
+ Event.observe(this.rows[row],'dblclick',this.trOnDblClick);
70
+ }
71
+ }
72
+ if(this.sortVar && this.dirVar){
73
+ var columns = $$('#'+this.containerId+this.tableSufix+' thead a');
74
+
75
+ for(var col=0; col<columns.length; col++){
76
+ Event.observe(columns[col],'click',this.thLinkOnClick);
77
+ }
78
+ }
79
+ this.bindFilterFields();
80
+ this.bindFieldsChange();
81
+ if(this.initCallback){
82
+ try {
83
+ this.initCallback(this);
84
+ }
85
+ catch (e) {
86
+ if(console) {
87
+ console.log(e);
88
+ }
89
+ }
90
+ }
91
+ },
92
+ initGridAjax: function () {
93
+ this.initGrid();
94
+ this.initGridRows();
95
+ },
96
+ initGridRows: function() {
97
+ if(this.initRowCallback){
98
+ for (var row=0; row<this.rows.length; row++) {
99
+ try {
100
+ this.initRowCallback(this, this.rows[row]);
101
+ } catch (e) {
102
+ if(console) {
103
+ console.log(e);
104
+ }
105
+ }
106
+ }
107
+ }
108
+ },
109
+ getContainerId : function(){
110
+ return this.containerId;
111
+ },
112
+ rowMouseOver : function(event){
113
+ var element = Event.findElement(event, 'tr');
114
+
115
+ if (!element.title) return;
116
+
117
+ Element.addClassName(element, 'on-mouse');
118
+
119
+ if (!Element.hasClassName('pointer')
120
+ && (this.rowClickCallback !== openGridRow || element.title)) {
121
+ if (element.title) {
122
+ Element.addClassName(element, 'pointer');
123
+ }
124
+ }
125
+ },
126
+ rowMouseOut : function(event){
127
+ var element = Event.findElement(event, 'tr');
128
+ Element.removeClassName(element, 'on-mouse');
129
+ },
130
+ rowMouseClick : function(event){
131
+ if(this.rowClickCallback){
132
+ try{
133
+ this.rowClickCallback(this, event);
134
+ }
135
+ catch(e){}
136
+ }
137
+ varienGlobalEvents.fireEvent('gridRowClick', event);
138
+ },
139
+ rowMouseDblClick : function(event){
140
+ varienGlobalEvents.fireEvent('gridRowDblClick', event);
141
+ },
142
+ keyPress : function(event){
143
+
144
+ },
145
+ doSort : function(event){
146
+ var element = Event.findElement(event, 'a');
147
+
148
+ if(element.name && element.title){
149
+ this.addVarToUrl(this.sortVar, element.name);
150
+ this.addVarToUrl(this.dirVar, element.title);
151
+ this.reload(this.url);
152
+ }
153
+ Event.stop(event);
154
+ return false;
155
+ },
156
+ loadByElement : function(element){
157
+ if(element && element.name){
158
+ this.reload(this.addVarToUrl(element.name, element.value));
159
+ }
160
+ },
161
+ reload : function(url){
162
+ if (!this.reloadParams) {
163
+ this.reloadParams = {form_key: FORM_KEY};
164
+ }
165
+ else {
166
+ this.reloadParams.form_key = FORM_KEY;
167
+ }
168
+ url = url || this.url;
169
+ if(this.useAjax){
170
+ new Ajax.Request(url + (url.match(new RegExp('\\?')) ? '&ajax=true' : '?ajax=true' ), {
171
+ loaderArea: this.containerId,
172
+ parameters: this.reloadParams || {},
173
+ evalScripts: true,
174
+ onFailure: this._processFailure.bind(this),
175
+ onComplete: this.initGridAjax.bind(this),
176
+ onSuccess: function(transport) {
177
+ try {
178
+ if (transport.responseText.isJSON()) {
179
+ var response = transport.responseText.evalJSON()
180
+ if (response.error) {
181
+ alert(response.message);
182
+ }
183
+ if(response.ajaxExpired && response.ajaxRedirect) {
184
+ setLocation(response.ajaxRedirect);
185
+ }
186
+ } else {
187
+ /**
188
+ * For IE <= 7.
189
+ * If there are two elements, and first has name, that equals id of second.
190
+ * In this case, IE will choose one that is above
191
+ *
192
+ * @see https://prototype.lighthouseapp.com/projects/8886/tickets/994-id-selector-finds-elements-by-name-attribute-in-ie7
193
+ */
194
+ var divId = $(this.containerId);
195
+ if (divId.id == this.containerId) {
196
+ divId.update(transport.responseText);
197
+ } else {
198
+ $$('div[id="'+this.containerId+'"]')[0].update(transport.responseText);
199
+ }
200
+ }
201
+ } catch (e) {
202
+ var divId = $(this.containerId);
203
+ if (divId.id == this.containerId) {
204
+ divId.update(transport.responseText);
205
+ } else {
206
+ $$('div[id="'+this.containerId+'"]')[0].update(transport.responseText);
207
+ }
208
+ }
209
+ }.bind(this)
210
+ });
211
+ return;
212
+ }
213
+ else{
214
+ if(this.reloadParams){
215
+ $H(this.reloadParams).each(function(pair){
216
+ url = this.addVarToUrl(pair.key, pair.value);
217
+ }.bind(this));
218
+ }
219
+ location.href = url;
220
+ }
221
+ },
222
+ /*_processComplete : function(transport){
223
+ console.log(transport);
224
+ if (transport && transport.responseText){
225
+ try{
226
+ response = eval('(' + transport.responseText + ')');
227
+ }
228
+ catch (e) {
229
+ response = {};
230
+ }
231
+ }
232
+ if (response.ajaxExpired && response.ajaxRedirect) {
233
+ location.href = response.ajaxRedirect;
234
+ return false;
235
+ }
236
+ this.initGrid();
237
+ },*/
238
+ _processFailure : function(transport){
239
+ location.href = BASE_URL;
240
+ },
241
+ addVarToUrl : function(varName, varValue){
242
+ var re = new RegExp('\/('+varName+'\/.*?\/)');
243
+ var parts = this.url.split(new RegExp('\\?'));
244
+ this.url = parts[0].replace(re, '/');
245
+ this.url+= varName+'/'+varValue+'/';
246
+ if(parts.size()>1) {
247
+ this.url+= '?' + parts[1];
248
+ }
249
+ //this.url = this.url.replace(/([^:])\/{2,}/g, '$1/');
250
+ return this.url;
251
+ },
252
+ doExport : function(){
253
+ if($(this.containerId+'_export')){
254
+ location.href = $(this.containerId+'_export').value;
255
+ }
256
+ },
257
+ bindFilterFields : function(){
258
+ var filters = $$('#'+this.containerId+' .filter input', '#'+this.containerId+' .filter select');
259
+ for (var i=0; i<filters.length; i++) {
260
+ Event.observe(filters[i],'keypress',this.filterKeyPress.bind(this));
261
+ }
262
+ },
263
+ bindFieldsChange : function(){
264
+ if (!$(this.containerId)) {
265
+ return;
266
+ }
267
+ // var dataElements = $(this.containerId+this.tableSufix).down('.data tbody').select('input', 'select');
268
+ var dataElements = $(this.containerId+this.tableSufix).down('tbody').select('input', 'select');
269
+ for(var i=0; i<dataElements.length;i++){
270
+ Event.observe(dataElements[i], 'change', dataElements[i].setHasChanges.bind(dataElements[i]));
271
+ }
272
+ },
273
+ filterKeyPress : function(event){
274
+ if(event.keyCode==Event.KEY_RETURN){
275
+ this.doFilter();
276
+ }
277
+ },
278
+ doFilter : function(){
279
+ var filters = $$('#'+this.containerId+' .filter input', '#'+this.containerId+' .filter select');
280
+ var elements = [];
281
+ for(var i in filters){
282
+ if(filters[i].value && filters[i].value.length) elements.push(filters[i]);
283
+ }
284
+ if (!this.doFilterCallback || (this.doFilterCallback && this.doFilterCallback())) {
285
+ this.reload(this.addVarToUrl(this.filterVar, encode_base64(Form.serializeElements(elements))));
286
+ }
287
+ },
288
+ resetFilter : function(){
289
+ this.reload(this.addVarToUrl(this.filterVar, ''));
290
+ },
291
+ checkCheckboxes : function(element){
292
+ elements = Element.select($(this.containerId), 'input[name="'+element.name+'"]');
293
+ for(var i=0; i<elements.length;i++){
294
+ this.setCheckboxChecked(elements[i], element.checked);
295
+ }
296
+ },
297
+ setCheckboxChecked : function(element, checked){
298
+ element.checked = checked;
299
+ element.setHasChanges({});
300
+ if(this.checkboxCheckCallback){
301
+ this.checkboxCheckCallback(this,element,checked);
302
+ }
303
+ },
304
+ inputPage : function(event, maxNum){
305
+ var element = Event.element(event);
306
+ var keyCode = event.keyCode || event.which;
307
+ if(keyCode==Event.KEY_RETURN){
308
+ this.setPage(element.value);
309
+ }
310
+ /*if(keyCode>47 && keyCode<58){
311
+
312
+ }
313
+ else{
314
+ Event.stop(event);
315
+ }*/
316
+ },
317
+ setPage : function(pageNumber){
318
+ this.reload(this.addVarToUrl(this.pageVar, pageNumber));
319
+ }
320
+ };
321
+
322
+ function openGridRow(grid, event){
323
+ var element = Event.findElement(event, 'tr');
324
+ if(['a', 'input', 'select', 'option'].indexOf(Event.element(event).tagName.toLowerCase())!=-1) {
325
+ return;
326
+ }
327
+
328
+ if(element.title){
329
+ setLocation(element.title);
330
+ }
331
+ }
332
+
333
+ var varienGridMassaction = Class.create();
334
+ varienGridMassaction.prototype = {
335
+ /* Predefined vars */
336
+ checkedValues: $H({}),
337
+ checkedString: '',
338
+ oldCallbacks: {},
339
+ errorText:'',
340
+ items: {},
341
+ gridIds: [],
342
+ useSelectAll: false,
343
+ currentItem: false,
344
+ fieldTemplate: new Template('<input type="hidden" name="#{name}" value="#{value}" />'),
345
+ initialize: function (containerId, grid, checkedValues, formFieldNameInternal, formFieldName) {
346
+ this.setOldCallback('row_click', grid.rowClickCallback);
347
+ this.setOldCallback('init', grid.initCallback);
348
+ this.setOldCallback('init_row', grid.initRowCallback);
349
+ this.setOldCallback('pre_init', grid.preInitCallback);
350
+
351
+ this.useAjax = false;
352
+ this.grid = grid;
353
+ this.containerId = containerId;
354
+ this.initMassactionElements();
355
+
356
+ this.checkedString = checkedValues;
357
+ this.formFieldName = formFieldName;
358
+ this.formFieldNameInternal = formFieldNameInternal;
359
+
360
+ this.grid.initCallback = this.onGridInit.bind(this);
361
+ this.grid.preInitCallback = this.onGridPreInit.bind(this);
362
+ this.grid.initRowCallback = this.onGridRowInit.bind(this);
363
+ this.grid.rowClickCallback = this.onGridRowClick.bind(this);
364
+ this.initCheckboxes();
365
+ this.checkCheckboxes();
366
+ },
367
+ setUseAjax: function(flag) {
368
+ this.useAjax = flag;
369
+ },
370
+ setUseSelectAll: function(flag) {
371
+ this.useSelectAll = flag;
372
+ },
373
+ initMassactionElements: function() {
374
+ this.container = $(this.containerId);
375
+ this.count = $(this.containerId + '-count');
376
+ this.formHiddens = $(this.containerId + '-form-hiddens');
377
+ this.formAdditional = $(this.containerId + '-form-additional');
378
+ this.select = $(this.containerId + '-select');
379
+ this.form = this.prepareForm();
380
+ this.validator = new Validation(this.form);
381
+ this.select.observe('change', this.onSelectChange.bindAsEventListener(this));
382
+ },
383
+ prepareForm: function() {
384
+ var form = $(this.containerId + '-form'), formPlace = null,
385
+ formElement = this.formHiddens || this.formAdditional;
386
+
387
+ if (!formElement) {
388
+ formElement = this.container.getElementsByTagName('button')[0];
389
+ formElement && formElement.parentNode;
390
+ }
391
+ if (!form && formElement) {
392
+ /* fix problem with rendering form in FF through innerHTML property */
393
+ form = document.createElement('form');
394
+ form.setAttribute('method', 'post');
395
+ form.setAttribute('action', '');
396
+ form.id = this.containerId + '-form';
397
+ formPlace = formElement.parentNode.parentNode;
398
+ formPlace.parentNode.appendChild(form);
399
+ form.appendChild(formPlace);
400
+ }
401
+
402
+ return form;
403
+ },
404
+ setGridIds: function(gridIds) {
405
+ this.gridIds = gridIds;
406
+ this.updateCount();
407
+ },
408
+ getGridIds: function() {
409
+ return this.gridIds;
410
+ },
411
+ setItems: function(items) {
412
+ this.items = items;
413
+ this.updateCount();
414
+ },
415
+ getItems: function() {
416
+ return this.items;
417
+ },
418
+ getItem: function(itemId) {
419
+ if(this.items[itemId]) {
420
+ return this.items[itemId];
421
+ }
422
+ return false;
423
+ },
424
+ getOldCallback: function (callbackName) {
425
+ return this.oldCallbacks[callbackName] ? this.oldCallbacks[callbackName] : Prototype.emptyFunction;
426
+ },
427
+ setOldCallback: function (callbackName, callback) {
428
+ this.oldCallbacks[callbackName] = callback;
429
+ },
430
+ onGridPreInit: function(grid) {
431
+ this.initMassactionElements();
432
+ this.getOldCallback('pre_init')(grid);
433
+ },
434
+ onGridInit: function(grid) {
435
+ this.initCheckboxes();
436
+ this.checkCheckboxes();
437
+ this.updateCount();
438
+ this.getOldCallback('init')(grid);
439
+ },
440
+ onGridRowInit: function(grid, row) {
441
+ this.getOldCallback('init_row')(grid, row);
442
+ },
443
+ onGridRowClick: function(grid, evt) {
444
+
445
+ var tdElement = Event.findElement(evt, 'td');
446
+ var trElement = Event.findElement(evt, 'tr');
447
+
448
+ if(!$(tdElement).down('input')) {
449
+ if($(tdElement).down('a') || $(tdElement).down('select')) {
450
+ return;
451
+ }
452
+ if (trElement.title) {
453
+ setLocation(trElement.title);
454
+ }
455
+ else{
456
+ var checkbox = Element.select(trElement, 'input');
457
+ var isInput = Event.element(evt).tagName == 'input';
458
+ var checked = isInput ? checkbox[0].checked : !checkbox[0].checked;
459
+
460
+ if(checked) {
461
+ this.checkedString = varienStringArray.add(checkbox[0].value, this.checkedString);
462
+ } else {
463
+ this.checkedString = varienStringArray.remove(checkbox[0].value, this.checkedString);
464
+ }
465
+ this.grid.setCheckboxChecked(checkbox[0], checked);
466
+ this.updateCount();
467
+ }
468
+ return;
469
+ }
470
+
471
+ if(Event.element(evt).isMassactionCheckbox) {
472
+ this.setCheckbox(Event.element(evt));
473
+ } else if (checkbox = this.findCheckbox(evt)) {
474
+ checkbox.checked = !checkbox.checked;
475
+ this.setCheckbox(checkbox);
476
+ }
477
+ },
478
+ onSelectChange: function(evt) {
479
+ var item = this.getSelectedItem();
480
+ if(item) {
481
+ this.formAdditional.update($(this.containerId + '-item-' + item.id + '-block').innerHTML);
482
+ } else {
483
+ this.formAdditional.update('');
484
+ }
485
+
486
+ this.validator.reset();
487
+ },
488
+ findCheckbox: function(evt) {
489
+ if(['a', 'input', 'select'].indexOf(Event.element(evt).tagName.toLowerCase())!==-1) {
490
+ return false;
491
+ }
492
+ checkbox = false;
493
+ Event.findElement(evt, 'tr').select('.massaction-checkbox').each(function(element){
494
+ if(element.isMassactionCheckbox) {
495
+ checkbox = element;
496
+ }
497
+ }.bind(this));
498
+ return checkbox;
499
+ },
500
+ initCheckboxes: function() {
501
+ this.getCheckboxes().each(function(checkbox) {
502
+ checkbox.isMassactionCheckbox = true;
503
+ }.bind(this));
504
+ },
505
+ checkCheckboxes: function() {
506
+ this.getCheckboxes().each(function(checkbox) {
507
+ checkbox.checked = varienStringArray.has(checkbox.value, this.checkedString);
508
+ }.bind(this));
509
+ },
510
+ selectAll: function() {
511
+ this.setCheckedValues((this.useSelectAll ? this.getGridIds() : this.getCheckboxesValuesAsString()));
512
+ this.checkCheckboxes();
513
+ this.updateCount();
514
+ return false;
515
+ },
516
+ unselectAll: function() {
517
+ this.setCheckedValues('');
518
+ this.checkCheckboxes();
519
+ this.updateCount();
520
+ return false;
521
+ },
522
+ selectVisible: function() {
523
+ this.setCheckedValues(this.getCheckboxesValuesAsString());
524
+ this.checkCheckboxes();
525
+ this.updateCount();
526
+ return false;
527
+ },
528
+ unselectVisible: function() {
529
+ this.getCheckboxesValues().each(function(key){
530
+ this.checkedString = varienStringArray.remove(key, this.checkedString);
531
+ }.bind(this));
532
+ this.checkCheckboxes();
533
+ this.updateCount();
534
+ return false;
535
+ },
536
+ setCheckedValues: function(values) {
537
+ this.checkedString = values;
538
+ },
539
+ getCheckedValues: function() {
540
+ return this.checkedString;
541
+ },
542
+ getCheckboxes: function() {
543
+ var result = [];
544
+ this.grid.rows.each(function(row){
545
+ var checkboxes = row.select('.massaction-checkbox');
546
+ checkboxes.each(function(checkbox){
547
+ result.push(checkbox);
548
+ });
549
+ });
550
+ return result;
551
+ },
552
+ getCheckboxesValues: function() {
553
+ var result = [];
554
+ this.getCheckboxes().each(function(checkbox) {
555
+ result.push(checkbox.value);
556
+ }.bind(this));
557
+ return result;
558
+ },
559
+ getCheckboxesValuesAsString: function()
560
+ {
561
+ return this.getCheckboxesValues().join(',');
562
+ },
563
+ setCheckbox: function(checkbox) {
564
+ if(checkbox.checked) {
565
+ this.checkedString = varienStringArray.add(checkbox.value, this.checkedString);
566
+ } else {
567
+ this.checkedString = varienStringArray.remove(checkbox.value, this.checkedString);
568
+ }
569
+ this.updateCount();
570
+ },
571
+ updateCount: function() {
572
+ this.count.update(varienStringArray.count(this.checkedString));
573
+ if(!this.grid.reloadParams) {
574
+ this.grid.reloadParams = {};
575
+ }
576
+ this.grid.reloadParams[this.formFieldNameInternal] = this.checkedString;
577
+ },
578
+ getSelectedItem: function() {
579
+ if(this.getItem(this.select.value)) {
580
+ return this.getItem(this.select.value);
581
+ } else {
582
+ return false;
583
+ }
584
+ },
585
+ apply: function() {
586
+ if(varienStringArray.count(this.checkedString) == 0) {
587
+ alert(this.errorText);
588
+ return;
589
+ }
590
+
591
+ var item = this.getSelectedItem();
592
+ if(!item) {
593
+ this.validator.validate();
594
+ return;
595
+ }
596
+ this.currentItem = item;
597
+ var fieldName = (item.field ? item.field : this.formFieldName);
598
+ var fieldsHtml = '';
599
+
600
+ if(this.currentItem.confirm && !window.confirm(this.currentItem.confirm)) {
601
+ return;
602
+ }
603
+
604
+ this.formHiddens.update('');
605
+ new Insertion.Bottom(this.formHiddens, this.fieldTemplate.evaluate({name: fieldName, value: this.checkedString}));
606
+ new Insertion.Bottom(this.formHiddens, this.fieldTemplate.evaluate({name: 'massaction_prepare_key', value: fieldName}));
607
+
608
+ if(!this.validator.validate()) {
609
+ return;
610
+ }
611
+
612
+ if(this.useAjax && item.url) {
613
+ new Ajax.Request(item.url, {
614
+ 'method': 'post',
615
+ 'parameters': this.form.serialize(true),
616
+ 'onComplete': this.onMassactionComplete.bind(this)
617
+ });
618
+ } else if(item.url) {
619
+ this.form.action = item.url;
620
+ this.form.submit();
621
+ }
622
+ },
623
+ onMassactionComplete: function(transport) {
624
+ if(this.currentItem.complete) {
625
+ try {
626
+ var listener = this.getListener(this.currentItem.complete) || Prototype.emptyFunction;
627
+ listener(this.grid, this, transport);
628
+ } catch (e) {}
629
+ }
630
+ },
631
+ getListener: function(strValue) {
632
+ return eval(strValue);
633
+ }
634
+ };
635
+
636
+ var varienGridAction = {
637
+ execute: function(select) {
638
+ if(!select.value || !select.value.isJSON()) {
639
+ return;
640
+ }
641
+
642
+ var config = select.value.evalJSON();
643
+ if(config.confirm && !window.confirm(config.confirm)) {
644
+ select.options[0].selected = true;
645
+ return;
646
+ }
647
+
648
+ if(config.popup) {
649
+ var win = window.open(config.href, 'action_window', 'width=500,height=600,resizable=1,scrollbars=1');
650
+ win.focus();
651
+ select.options[0].selected = true;
652
+ } else {
653
+ setLocation(config.href);
654
+ }
655
+ }
656
+ };
657
+
658
+ var varienStringArray = {
659
+ remove: function(str, haystack)
660
+ {
661
+ haystack = ',' + haystack + ',';
662
+ haystack = haystack.replace(new RegExp(',' + str + ',', 'g'), ',');
663
+ return this.trimComma(haystack);
664
+ },
665
+ add: function(str, haystack)
666
+ {
667
+ haystack = ',' + haystack + ',';
668
+ if (haystack.search(new RegExp(',' + str + ',', 'g'), haystack) === -1) {
669
+ haystack += str + ',';
670
+ }
671
+ return this.trimComma(haystack);
672
+ },
673
+ has: function(str, haystack)
674
+ {
675
+ haystack = ',' + haystack + ',';
676
+ if (haystack.search(new RegExp(',' + str + ',', 'g'), haystack) === -1) {
677
+ return false;
678
+ }
679
+ return true;
680
+ },
681
+ count: function(haystack)
682
+ {
683
+ if (typeof haystack != 'string') {
684
+ return 0;
685
+ }
686
+ if (match = haystack.match(new RegExp(',', 'g'))) {
687
+ return match.length + 1;
688
+ } else if (haystack.length != 0) {
689
+ return 1;
690
+ }
691
+ return 0;
692
+ },
693
+ each: function(haystack, fnc)
694
+ {
695
+ var haystack = haystack.split(',');
696
+ for (var i=0; i<haystack.length; i++) {
697
+ fnc(haystack[i]);
698
+ }
699
+ },
700
+ trimComma: function(string)
701
+ {
702
+ string = string.replace(new RegExp('^(,+)','i'), '');
703
+ string = string.replace(new RegExp('(,+)$','i'), '');
704
+ return string;
705
+ }
706
+ };
707
+
708
+ var serializerController = Class.create();
709
+ serializerController.prototype = {
710
+ oldCallbacks: {},
711
+ initialize: function(hiddenDataHolder, predefinedData, inputsToManage, grid, reloadParamName){
712
+ //Grid inputs
713
+ this.tabIndex = 1000;
714
+ this.inputsToManage = inputsToManage;
715
+ this.multidimensionalMode = inputsToManage.length > 0;
716
+
717
+ //Hash with grid data
718
+ this.gridData = this.getGridDataHash(predefinedData);
719
+
720
+ //Hidden input data holder
721
+ this.hiddenDataHolder = $(hiddenDataHolder);
722
+ this.hiddenDataHolder.value = this.serializeObject();
723
+
724
+ this.grid = grid;
725
+
726
+ // Set old callbacks
727
+ this.setOldCallback('row_click', this.grid.rowClickCallback);
728
+ this.setOldCallback('init_row', this.grid.initRowCallback);
729
+ this.setOldCallback('checkbox_check', this.grid.checkboxCheckCallback);
730
+
731
+ //Grid
732
+ this.reloadParamName = reloadParamName;
733
+ this.grid.reloadParams = {};
734
+ this.grid.reloadParams[this.reloadParamName+'[]'] = this.getDataForReloadParam();
735
+ this.grid.rowClickCallback = this.rowClick.bind(this);
736
+ this.grid.initRowCallback = this.rowInit.bind(this);
737
+ this.grid.checkboxCheckCallback = this.registerData.bind(this);
738
+ this.grid.rows.each(this.eachRow.bind(this));
739
+ },
740
+ setOldCallback: function (callbackName, callback) {
741
+ this.oldCallbacks[callbackName] = callback;
742
+ },
743
+ getOldCallback: function (callbackName) {
744
+ return this.oldCallbacks[callbackName] ? this.oldCallbacks[callbackName] : Prototype.emptyFunction;
745
+ },
746
+ registerData : function(grid, element, checked) {
747
+ if(this.multidimensionalMode){
748
+ if(checked){
749
+ if(element.inputElements) {
750
+ this.gridData.set(element.value, {});
751
+ for(var i = 0; i < element.inputElements.length; i++) {
752
+ element.inputElements[i].disabled = false;
753
+ this.gridData.get(element.value)[element.inputElements[i].name] = element.inputElements[i].value;
754
+ }
755
+ }
756
+ }
757
+ else{
758
+ if(element.inputElements){
759
+ for(var i = 0; i < element.inputElements.length; i++) {
760
+ element.inputElements[i].disabled = true;
761
+ }
762
+ }
763
+ this.gridData.unset(element.value);
764
+ }
765
+ }
766
+ else{
767
+ if(checked){
768
+ this.gridData.set(element.value, element.value);
769
+ }
770
+ else{
771
+ this.gridData.unset(element.value);
772
+ }
773
+ }
774
+
775
+ this.hiddenDataHolder.value = this.serializeObject();
776
+ this.grid.reloadParams = {};
777
+ this.grid.reloadParams[this.reloadParamName+'[]'] = this.getDataForReloadParam();
778
+ this.getOldCallback('checkbox_check')(grid, element, checked);
779
+ },
780
+ eachRow : function(row) {
781
+ this.rowInit(this.grid, row);
782
+ },
783
+ rowClick : function(grid, event) {
784
+ var trElement = Event.findElement(event, 'tr');
785
+ var isInput = Event.element(event).tagName == 'INPUT';
786
+ if(trElement){
787
+ var checkbox = Element.select(trElement, 'input');
788
+ if(checkbox[0] && !checkbox[0].disabled){
789
+ var checked = isInput ? checkbox[0].checked : !checkbox[0].checked;
790
+ this.grid.setCheckboxChecked(checkbox[0], checked);
791
+ }
792
+ }
793
+ this.getOldCallback('row_click')(grid, event);
794
+ },
795
+ inputChange : function(event) {
796
+ var element = Event.element(event);
797
+ if(element && element.checkboxElement && element.checkboxElement.checked){
798
+ this.gridData.get(element.checkboxElement.value)[element.name] = element.value;
799
+ this.hiddenDataHolder.value = this.serializeObject();
800
+ }
801
+ },
802
+ rowInit : function(grid, row) {
803
+ if(this.multidimensionalMode){
804
+ var checkbox = $(row).select('.checkbox')[0];
805
+ var selectors = this.inputsToManage.map(function (name) { return ['input[name="' + name + '"]', 'select[name="' + name + '"]']; });
806
+ var inputs = $(row).select.apply($(row), selectors.flatten());
807
+ if(checkbox && inputs.length > 0) {
808
+ checkbox.inputElements = inputs;
809
+ for(var i = 0; i < inputs.length; i++) {
810
+ inputs[i].checkboxElement = checkbox;
811
+ if(this.gridData.get(checkbox.value) && this.gridData.get(checkbox.value)[inputs[i].name]) {
812
+ inputs[i].value = this.gridData.get(checkbox.value)[inputs[i].name];
813
+ }
814
+ inputs[i].disabled = !checkbox.checked;
815
+ inputs[i].tabIndex = this.tabIndex++;
816
+ Event.observe(inputs[i],'keyup', this.inputChange.bind(this));
817
+ Event.observe(inputs[i],'change', this.inputChange.bind(this));
818
+ }
819
+ }
820
+ }
821
+ this.getOldCallback('init_row')(grid, row);
822
+ },
823
+
824
+ //Stuff methods
825
+ getGridDataHash: function (_object){
826
+ return $H(this.multidimensionalMode ? _object : this.convertArrayToObject(_object))
827
+ },
828
+ getDataForReloadParam: function(){
829
+ return this.multidimensionalMode ? this.gridData.keys() : this.gridData.values();
830
+ },
831
+ serializeObject: function(){
832
+ if(this.multidimensionalMode){
833
+ var clone = this.gridData.clone();
834
+ clone.each(function(pair) {
835
+ clone.set(pair.key, encode_base64(Object.toQueryString(pair.value)));
836
+ });
837
+ return clone.toQueryString();
838
+ }
839
+ else{
840
+ return this.gridData.values().join('&');
841
+ }
842
+ },
843
+ convertArrayToObject: function (_array){
844
+ var _object = {};
845
+ for(var i = 0, l = _array.length; i < l; i++){
846
+ _object[_array[i]] = _array[i];
847
+ }
848
+ return _object;
849
+ }
850
+ };
js/mage/adminhtml/hash.js ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ /*
26
+ * Caudium - An extensible World Wide Web server
27
+ * Copyright C 2002 The Caudium Group
28
+ *
29
+ * This program is free software; you can redistribute it and/or
30
+ * modify it under the terms of the GNU General Public License as
31
+ * published by the Free Software Foundation; either version 2 of the
32
+ * License, or (at your option) any later version.
33
+ *
34
+ * This program is distributed in the hope that it will be useful, but
35
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
36
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
37
+ * General Public License for more details.
38
+ *
39
+ * You should have received a copy of the GNU General Public License
40
+ * along with this program; if not, write to the Free Software
41
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
42
+ *
43
+ */
44
+
45
+ /*
46
+ * base64.js - a JavaScript implementation of the base64 algorithm,
47
+ * (mostly) as defined in RFC 2045.
48
+ *
49
+ * This is a direct JavaScript reimplementation of the original C code
50
+ * as found in the Exim mail transport agent, by Philip Hazel.
51
+ *
52
+ * $Id: base64.js,v 1.7 2002/07/16 17:21:23 kazmer Exp $
53
+ *
54
+ */
55
+
56
+
57
+ function encode_base64( what )
58
+ {
59
+ var base64_encodetable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
60
+ var result = "";
61
+ var len = what.length;
62
+ var x, y;
63
+ var ptr = 0;
64
+
65
+ while( len-- > 0 )
66
+ {
67
+ x = what.charCodeAt( ptr++ );
68
+ result += base64_encodetable.charAt( ( x >> 2 ) & 63 );
69
+
70
+ if( len-- <= 0 )
71
+ {
72
+ result += base64_encodetable.charAt( ( x << 4 ) & 63 );
73
+ result += "==";
74
+ break;
75
+ }
76
+
77
+ y = what.charCodeAt( ptr++ );
78
+ result += base64_encodetable.charAt( ( ( x << 4 ) | ( ( y >> 4 ) & 15 ) ) & 63 );
79
+
80
+ if ( len-- <= 0 )
81
+ {
82
+ result += base64_encodetable.charAt( ( y << 2 ) & 63 );
83
+ result += "=";
84
+ break;
85
+ }
86
+
87
+ x = what.charCodeAt( ptr++ );
88
+ result += base64_encodetable.charAt( ( ( y << 2 ) | ( ( x >> 6 ) & 3 ) ) & 63 );
89
+ result += base64_encodetable.charAt( x & 63 );
90
+
91
+ }
92
+
93
+ return result;
94
+ }
95
+
96
+
97
+ function decode_base64( what )
98
+ {
99
+ var base64_decodetable = new Array (
100
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
101
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
102
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
103
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
104
+ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
105
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
106
+ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
107
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255
108
+ );
109
+ var result = "";
110
+ var len = what.length;
111
+ var x, y;
112
+ var ptr = 0;
113
+
114
+ while( !isNaN( x = what.charCodeAt( ptr++ ) ) )
115
+ {
116
+ if( x == 13 || x == 10 )
117
+ continue;
118
+
119
+ if( ( x > 127 ) || (( x = base64_decodetable[x] ) == 255) )
120
+ return false;
121
+ if( ( isNaN( y = what.charCodeAt( ptr++ ) ) ) || (( y = base64_decodetable[y] ) == 255) )
122
+ return false;
123
+
124
+ result += String.fromCharCode( (x << 2) | (y >> 4) );
125
+
126
+ if( (x = what.charCodeAt( ptr++ )) == 61 )
127
+ {
128
+ if( (what.charCodeAt( ptr++ ) != 61) || (!isNaN(what.charCodeAt( ptr ) ) ) )
129
+ return false;
130
+ }
131
+ else
132
+ {
133
+ if( ( x > 127 ) || (( x = base64_decodetable[x] ) == 255) )
134
+ return false;
135
+ result += String.fromCharCode( (y << 4) | (x >> 2) );
136
+ if( (y = what.charCodeAt( ptr++ )) == 61 )
137
+ {
138
+ if( !isNaN(what.charCodeAt( ptr ) ) )
139
+ return false;
140
+ }
141
+ else
142
+ {
143
+ if( (y > 127) || ((y = base64_decodetable[y]) == 255) )
144
+ return false;
145
+ result += String.fromCharCode( (x << 6) | y );
146
+ }
147
+ }
148
+ }
149
+ return result;
150
+ }
151
+
152
+ function wrap76( what )
153
+ {
154
+ var result = "";
155
+ var i;
156
+
157
+ for(i=0; i < what.length; i+=76)
158
+ {
159
+ result += what.substring(i, i+76) + String.fromCharCode(13) + String.fromCharCode(10);
160
+ }
161
+ return result;
162
+ }
js/mage/adminhtml/image.js ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ if(!window.Flex) {
27
+ alert('Flex library not loaded');
28
+ } else {
29
+ Flex.ImageEditor = Class.create();
30
+ Flex.ImageEditor.prototype = {
31
+ flex: null,
32
+ filters:null,
33
+ containerId:null,
34
+ flexContainerId:null,
35
+ container:null,
36
+ initialize: function(containerId, movieSrc, config) {
37
+ this.containerId = containerId;
38
+ this.container = $(containerId);
39
+
40
+ this.container.controller = this;
41
+
42
+ this.config = config;
43
+ this.flexContainerId = this.containerId + '-flash';
44
+ Element.insert(this.container, {bottom: '<div id="'+this.flexContainerId+'"></div>'});
45
+
46
+ this.flex = new Flex.Object({
47
+ width: "1024",
48
+ height: "786",
49
+ src: movieSrc,
50
+ wmode: 'transparent'
51
+ });
52
+
53
+
54
+ this.flex.onBridgeInit = this.handleBridgeInit.bind(this);
55
+ this.flex.apply(this.flexContainerId);
56
+ },
57
+ getInnerElement: function(elementName) {
58
+ return $(this.containerId + '-' + elementName);
59
+ },
60
+ handleBridgeInit: function() {
61
+ this.flex.getBridge().addEventListener('image_loaded', this.handleImageLoad.bind(this));
62
+ this.flex.getBridge().setImage(this.config.image);
63
+
64
+
65
+ },
66
+ handleImageLoad: function(event) {
67
+ alert('image_loaded:' + this.config.image);
68
+ this.hangleImageResize();
69
+ },
70
+ hangleImageResize: function() {
71
+ var size = this.flex.getBridge().getSize();
72
+ this.getInnerElement('width').value = size.width;
73
+ this.getInnerElement('height').value = size.height;
74
+
75
+ },
76
+ rotateCw: function() {
77
+ this.flex.getBridge().rotateFw();
78
+ this.hangleImageResize();
79
+ },
80
+ rotateCCw: function() {
81
+ this.flex.getBridge().rotateBw();
82
+ this.hangleImageResize();
83
+ },
84
+ resize: function() {
85
+ this.flex.getBridge().resize(parseFloat(this.getInnerElement('width').value), parseFloat(this.getInnerElement('height').value));
86
+ },
87
+ getImage: function() {
88
+ this.getInnerElement('b64').value = this.flex.getBridge().getBase64Image();
89
+ }
90
+ }
91
+ }
js/mage/adminhtml/loader.js ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ var SessionError = Class.create();
27
+ SessionError.prototype = {
28
+ initialize: function(errorText) {
29
+ this.errorText = errorText;
30
+ },
31
+ toString: function()
32
+ {
33
+ return 'Session Error:' + this.errorText;
34
+ }
35
+ };
36
+
37
+ Ajax.Request.addMethods({
38
+ initialize: function($super, url, options){
39
+ $super(options);
40
+ this.transport = Ajax.getTransport();
41
+ if (!url.match(new RegExp('[?&]isAjax=true',''))) {
42
+ url = url.match(new RegExp('\\?',"g")) ? url + '&isAjax=true' : url + '?isAjax=true';
43
+ }
44
+ if (Object.isString(this.options.parameters)
45
+ && this.options.parameters.indexOf('form_key=') == -1
46
+ ) {
47
+ this.options.parameters += '&' + Object.toQueryString({
48
+ form_key: FORM_KEY
49
+ });
50
+ } else {
51
+ if (!this.options.parameters) {
52
+ this.options.parameters = {
53
+ form_key: FORM_KEY
54
+ };
55
+ }
56
+ if (!this.options.parameters.form_key) {
57
+ this.options.parameters.form_key = FORM_KEY;
58
+ }
59
+ }
60
+
61
+ this.request(url);
62
+ },
63
+ respondToReadyState: function(readyState) {
64
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
65
+
66
+ if (state == 'Complete') {
67
+ try {
68
+ this._complete = true;
69
+ if (response.responseText.isJSON()) {
70
+ var jsonObject = response.responseText.evalJSON();
71
+ if (jsonObject.ajaxExpired && jsonObject.ajaxRedirect) {
72
+ window.location.replace(jsonObject.ajaxRedirect);
73
+ throw new SessionError('session expired');
74
+ }
75
+ }
76
+
77
+ (this.options['on' + response.status]
78
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
79
+ || Prototype.emptyFunction)(response, response.headerJSON);
80
+ } catch (e) {
81
+ this.dispatchException(e);
82
+ if (e instanceof SessionError) {
83
+ return;
84
+ }
85
+ }
86
+
87
+ var contentType = response.getHeader('Content-type');
88
+ if (this.options.evalJS == 'force'
89
+ || (this.options.evalJS && this.isSameOrigin() && contentType
90
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) {
91
+ this.evalResponse();
92
+ }
93
+ }
94
+
95
+ try {
96
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
97
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
98
+ } catch (e) {
99
+ this.dispatchException(e);
100
+ }
101
+
102
+ if (state == 'Complete') {
103
+ // avoid memory leak in MSIE: clean up
104
+ this.transport.onreadystatechange = Prototype.emptyFunction;
105
+ }
106
+ }
107
+ });
108
+
109
+ Ajax.Updater.respondToReadyState = Ajax.Request.respondToReadyState;
110
+ //Ajax.Updater = Object.extend(Ajax.Updater, {
111
+ // initialize: function($super, container, url, options) {
112
+ // this.container = {
113
+ // success: (container.success || container),
114
+ // failure: (container.failure || (container.success ? null : container))
115
+ // };
116
+ //
117
+ // options = Object.clone(options);
118
+ // var onComplete = options.onComplete;
119
+ // options.onComplete = (function(response, json) {
120
+ // this.updateContent(response.responseText);
121
+ // if (Object.isFunction(onComplete)) onComplete(response, json);
122
+ // }).bind(this);
123
+ //
124
+ // $super((url.match(new RegExp('\\?',"g")) ? url + '&isAjax=1' : url + '?isAjax=1'), options);
125
+ // }
126
+ //});
127
+
128
+ var varienLoader = new Class.create();
129
+
130
+ varienLoader.prototype = {
131
+ initialize : function(caching){
132
+ this.callback= false;
133
+ this.cache = $H();
134
+ this.caching = caching || false;
135
+ this.url = false;
136
+ },
137
+
138
+ getCache : function(url){
139
+ if(this.cache.get(url)){
140
+ return this.cache.get(url)
141
+ }
142
+ return false;
143
+ },
144
+
145
+ load : function(url, params, callback){
146
+ this.url = url;
147
+ this.callback = callback;
148
+
149
+ if(this.caching){
150
+ var transport = this.getCache(url);
151
+ if(transport){
152
+ this.processResult(transport);
153
+ return;
154
+ }
155
+ }
156
+
157
+ if (typeof(params.updaterId) != 'undefined') {
158
+ new varienUpdater(params.updaterId, url, {
159
+ evalScripts : true,
160
+ onComplete: this.processResult.bind(this),
161
+ onFailure: this._processFailure.bind(this)
162
+ });
163
+ }
164
+ else {
165
+ new Ajax.Request(url,{
166
+ method: 'post',
167
+ parameters: params || {},
168
+ onComplete: this.processResult.bind(this),
169
+ onFailure: this._processFailure.bind(this)
170
+ });
171
+ }
172
+ },
173
+
174
+ _processFailure : function(transport){
175
+ location.href = BASE_URL;
176
+ },
177
+
178
+ processResult : function(transport){
179
+ if(this.caching){
180
+ this.cache.set(this.url, transport);
181
+ }
182
+ if(this.callback){
183
+ this.callback(transport.responseText);
184
+ }
185
+ }
186
+ }
187
+
188
+ if (!window.varienLoaderHandler)
189
+ var varienLoaderHandler = new Object();
190
+
191
+ varienLoaderHandler.handler = {
192
+ onCreate: function(request) {
193
+ if(request.options.loaderArea===false){
194
+ return;
195
+ }
196
+
197
+ request.options.loaderArea = $$('#html-body .wrapper')[0]; // Blocks all page
198
+
199
+ if(request && request.options.loaderArea){
200
+ Element.clonePosition($('loading-mask'), $(request.options.loaderArea), {offsetLeft:-2})
201
+ toggleSelectsUnderBlock($('loading-mask'), false);
202
+ Element.show('loading-mask');
203
+ setLoaderPosition();
204
+ if(request.options.loaderArea=='html-body'){
205
+ //Element.show('loading-process');
206
+ }
207
+ }
208
+ else{
209
+ //Element.show('loading-process');
210
+ }
211
+ },
212
+
213
+ onComplete: function(transport) {
214
+ if(Ajax.activeRequestCount == 0) {
215
+ //Element.hide('loading-process');
216
+ toggleSelectsUnderBlock($('loading-mask'), true);
217
+ Element.hide('loading-mask');
218
+ }
219
+ }
220
+ };
221
+
222
+ /**
223
+ * @todo need calculate middle of visible area and scroll bind
224
+ */
225
+ function setLoaderPosition(){
226
+ var elem = $('loading_mask_loader');
227
+ if (elem && Prototype.Browser.IE) {
228
+ var middle = parseInt(document.body.clientHeight/2)+document.body.scrollTop;
229
+ elem.style.position = 'absolute';
230
+ elem.style.top = middle;
231
+ }
232
+ }
233
+
234
+ /*function getRealHeight() {
235
+ var body = document.body;
236
+ if (window.innerHeight && window.scrollMaxY) {
237
+ return window.innerHeight + window.scrollMaxY;
238
+ }
239
+ return Math.max(body.scrollHeight, body.offsetHeight);
240
+ }*/
241
+
242
+
243
+
244
+ function toggleSelectsUnderBlock(block, flag){
245
+ if(Prototype.Browser.IE){
246
+ var selects = document.getElementsByTagName("select");
247
+ for(var i=0; i<selects.length; i++){
248
+ /**
249
+ * @todo: need check intersection
250
+ */
251
+ if(flag){
252
+ if(selects[i].needShowOnSuccess){
253
+ selects[i].needShowOnSuccess = false;
254
+ // Element.show(selects[i])
255
+ selects[i].style.visibility = '';
256
+ }
257
+ }
258
+ else{
259
+ if(Element.visible(selects[i])){
260
+ // Element.hide(selects[i]);
261
+ selects[i].style.visibility = 'hidden';
262
+ selects[i].needShowOnSuccess = true;
263
+ }
264
+ }
265
+ }
266
+ }
267
+ }
268
+
269
+ Ajax.Responders.register(varienLoaderHandler.handler);
270
+
271
+ var varienUpdater = Class.create(Ajax.Updater, {
272
+ updateContent: function($super, responseText) {
273
+ if (responseText.isJSON()) {
274
+ var responseJSON = responseText.evalJSON();
275
+ if (responseJSON.ajaxExpired && responseJSON.ajaxRedirect) {
276
+ window.location.replace(responseJSON.ajaxRedirect);
277
+ }
278
+ } else {
279
+ $super(responseText);
280
+ }
281
+ }
282
+ });
js/mage/adminhtml/magento-all.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
js/mage/adminhtml/product.js ADDED
@@ -0,0 +1,1052 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ var Product = {};
27
+
28
+ Product.Gallery = Class.create();
29
+ Product.Gallery.prototype = {
30
+ images : [],
31
+ file2id : {
32
+ 'no_selection' :0
33
+ },
34
+ idIncrement :1,
35
+ containerId :'',
36
+ container :null,
37
+ uploader :null,
38
+ imageTypes : {},
39
+ initialize : function(containerId, uploader, imageTypes) {
40
+ this.containerId = containerId, this.container = $(this.containerId);
41
+ this.uploader = uploader;
42
+ this.imageTypes = imageTypes;
43
+ if (this.uploader) {
44
+ this.uploader.onFilesComplete = this.handleUploadComplete
45
+ .bind(this);
46
+ }
47
+ // this.uploader.onFileProgress = this.handleUploadProgress.bind(this);
48
+ // this.uploader.onFileError = this.handleUploadError.bind(this);
49
+ this.images = this.getElement('save').value.evalJSON();
50
+ this.imagesValues = this.getElement('save_image').value.evalJSON();
51
+ this.template = new Template('<tr id="__id__" class="preview">' + this
52
+ .getElement('template').innerHTML + '</tr>', new RegExp(
53
+ '(^|.|\\r|\\n)(__([a-zA-Z0-9_]+)__)', ''));
54
+ this.fixParentTable();
55
+ this.updateImages();
56
+ varienGlobalEvents.attachEventHandler('moveTab', this.onImageTabMove
57
+ .bind(this));
58
+ },
59
+ onImageTabMove : function(event) {
60
+ var imagesTab = false;
61
+ this.container.ancestors().each( function(parentItem) {
62
+ if (parentItem.tabObject) {
63
+ imagesTab = parentItem.tabObject;
64
+ throw $break;
65
+ }
66
+ }.bind(this));
67
+
68
+ if (imagesTab && event.tab && event.tab.name && imagesTab.name == event.tab.name) {
69
+ this.container.select('input[type="radio"]').each(function(radio) {
70
+ radio.observe('change', this.onChangeRadio);
71
+ }.bind(this));
72
+ this.updateImages();
73
+ }
74
+
75
+ },
76
+ fixParentTable : function() {
77
+ this.container.ancestors().each( function(parentItem) {
78
+ if (parentItem.tagName.toLowerCase() == 'td') {
79
+ parentItem.style.width = '100%';
80
+ }
81
+ if (parentItem.tagName.toLowerCase() == 'table') {
82
+ parentItem.style.width = '100%';
83
+ throw $break;
84
+ }
85
+ });
86
+ },
87
+ getElement : function(name) {
88
+ return $(this.containerId + '_' + name);
89
+ },
90
+ showUploader : function() {
91
+ this.getElement('add_images_button').hide();
92
+ this.getElement('uploader').show();
93
+ },
94
+ handleUploadComplete : function(files) {
95
+ files.each( function(item) {
96
+ if (!item.response.isJSON()) {
97
+ try {
98
+ console.log(item.response);
99
+ } catch (e2) {
100
+ alert(item.response);
101
+ }
102
+ return;
103
+ }
104
+ var response = item.response.evalJSON();
105
+ if (response.error) {
106
+ return;
107
+ }
108
+ var newImage = {};
109
+ newImage.url = response.url;
110
+ newImage.file = response.file;
111
+ newImage.label = '';
112
+ newImage.position = this.getNextPosition();
113
+ newImage.disabled = 0;
114
+ newImage.removed = 0;
115
+ this.images.push(newImage);
116
+ this.uploader.removeFile(item.id);
117
+ }.bind(this));
118
+ this.container.setHasChanges();
119
+ this.updateImages();
120
+ },
121
+ updateImages : function() {
122
+ this.getElement('save').value = Object.toJSON(this.images);
123
+ $H(this.imageTypes).each(
124
+ function(pair) {
125
+ this.getFileElement('no_selection',
126
+ 'cell-' + pair.key + ' input').checked = true;
127
+ }.bind(this));
128
+ this.images.each( function(row) {
129
+ if (!$(this.prepareId(row.file))) {
130
+ this.createImageRow(row);
131
+ }
132
+ this.updateVisualisation(row.file);
133
+ }.bind(this));
134
+ this.updateUseDefault(false);
135
+ },
136
+ onChangeRadio: function (evt) {
137
+ var element = Event.element(evt);
138
+ element.setHasChanges();
139
+ },
140
+ createImageRow : function(image) {
141
+ var vars = Object.clone(image);
142
+ vars.id = this.prepareId(image.file);
143
+ var html = this.template.evaluate(vars);
144
+ Element.insert(this.getElement('list'), {
145
+ bottom :html
146
+ });
147
+
148
+ $(vars.id).select('input[type="radio"]').each(function(radio) {
149
+ radio.observe('change', this.onChangeRadio);
150
+ }.bind(this));
151
+ },
152
+ prepareId : function(file) {
153
+ if (typeof this.file2id[file] == 'undefined') {
154
+ this.file2id[file] = this.idIncrement++;
155
+ }
156
+ return this.containerId + '-image-' + this.file2id[file];
157
+ },
158
+ getNextPosition : function() {
159
+ var maxPosition = 0;
160
+ this.images.each( function(item) {
161
+ if (parseInt(item.position) > maxPosition) {
162
+ maxPosition = parseInt(item.position);
163
+ }
164
+ });
165
+ return maxPosition + 1;
166
+ },
167
+ updateImage : function(file) {
168
+ var index = this.getIndexByFile(file);
169
+ this.images[index].label = this
170
+ .getFileElement(file, 'cell-label input').value;
171
+ this.images[index].position = this.getFileElement(file,
172
+ 'cell-position input').value;
173
+ this.images[index].removed = (this.getFileElement(file,
174
+ 'cell-remove input').checked ? 1 : 0);
175
+ this.images[index].disabled = (this.getFileElement(file,
176
+ 'cell-disable input').checked ? 1 : 0);
177
+ this.getElement('save').value = Object.toJSON(this.images);
178
+ this.updateState(file);
179
+ this.container.setHasChanges();
180
+ },
181
+ loadImage : function(file) {
182
+ var image = this.getImageByFile(file);
183
+ this.getFileElement(file, 'cell-image img').src = image.url;
184
+ this.getFileElement(file, 'cell-image img').show();
185
+ this.getFileElement(file, 'cell-image .place-holder').hide();
186
+ },
187
+ setProductImages : function(file) {
188
+ $H(this.imageTypes)
189
+ .each(
190
+ function(pair) {
191
+ if (this.getFileElement(file,
192
+ 'cell-' + pair.key + ' input').checked) {
193
+ this.imagesValues[pair.key] = (file == 'no_selection' ? null
194
+ : file);
195
+ }
196
+ }.bind(this));
197
+
198
+ this.getElement('save_image').value = Object.toJSON($H(this.imagesValues));
199
+ },
200
+ updateVisualisation : function(file) {
201
+ var image = this.getImageByFile(file);
202
+ this.getFileElement(file, 'cell-label input').value = image.label;
203
+ this.getFileElement(file, 'cell-position input').value = image.position;
204
+ this.getFileElement(file, 'cell-remove input').checked = (image.removed == 1);
205
+ this.getFileElement(file, 'cell-disable input').checked = (image.disabled == 1);
206
+ $H(this.imageTypes)
207
+ .each(
208
+ function(pair) {
209
+ if (this.imagesValues[pair.key] == file) {
210
+ this.getFileElement(file,
211
+ 'cell-' + pair.key + ' input').checked = true;
212
+ }
213
+ }.bind(this));
214
+ this.updateState(file);
215
+ },
216
+ updateState : function(file) {
217
+ if (this.getFileElement(file, 'cell-disable input').checked) {
218
+ this.getFileElement(file, 'cell-position input').disabled = true;
219
+ } else {
220
+ this.getFileElement(file, 'cell-position input').disabled = false;
221
+ }
222
+ },
223
+ getFileElement : function(file, element) {
224
+ var selector = '#' + this.prepareId(file) + ' .' + element;
225
+ var elems = $$(selector);
226
+ if (!elems[0]) {
227
+ try {
228
+ console.log(selector);
229
+ } catch (e2) {
230
+ alert(selector);
231
+ }
232
+ }
233
+
234
+ return $$('#' + this.prepareId(file) + ' .' + element)[0];
235
+ },
236
+ getImageByFile : function(file) {
237
+ if (this.getIndexByFile(file) === null) {
238
+ return false;
239
+ }
240
+
241
+ return this.images[this.getIndexByFile(file)];
242
+ },
243
+ getIndexByFile : function(file) {
244
+ var index;
245
+ this.images.each( function(item, i) {
246
+ if (item.file == file) {
247
+ index = i;
248
+ }
249
+ });
250
+ return index;
251
+ },
252
+ updateUseDefault : function() {
253
+ if (this.getElement('default')) {
254
+ this.getElement('default').select('input').each(
255
+ function(input) {
256
+ $(this.containerId).select(
257
+ '.cell-' + input.value + ' input').each(
258
+ function(radio) {
259
+ radio.disabled = input.checked;
260
+ });
261
+ }.bind(this));
262
+ }
263
+
264
+ if (arguments.length == 0) {
265
+ this.container.setHasChanges();
266
+ }
267
+ },
268
+ handleUploadProgress : function(file) {
269
+
270
+ },
271
+ handleUploadError : function(fileId) {
272
+
273
+ }
274
+ };
275
+
276
+ Product.AttributesBridge = {
277
+ tabsObject :false,
278
+ bindTabs2Attributes : {},
279
+ bind : function(tabId, attributesObject) {
280
+ this.bindTabs2Attributes[tabId] = attributesObject;
281
+ },
282
+ getAttributes : function(tabId) {
283
+ return this.bindTabs2Attributes[tabId];
284
+ },
285
+ setTabsObject : function(tabs) {
286
+ this.tabsObject = tabs;
287
+ },
288
+ getTabsObject : function() {
289
+ return this.tabsObject;
290
+ },
291
+ addAttributeRow : function(data) {
292
+ $H(data).each( function(item) {
293
+ if (this.getTabsObject().activeTab.name != item.key) {
294
+ this.getTabsObject().showTabContent($(item.key));
295
+ }
296
+ this.getAttributes(item.key).addRow(item.value);
297
+ }.bind(this));
298
+ }
299
+ };
300
+
301
+ Product.Attributes = Class.create();
302
+ Product.Attributes.prototype = {
303
+ config : {},
304
+ containerId :null,
305
+ initialize : function(containerId) {
306
+ this.containerId = containerId;
307
+ },
308
+ setConfig : function(config) {
309
+ this.config = config;
310
+ Product.AttributesBridge.bind(this.getConfig().tab_id, this);
311
+ },
312
+ getConfig : function() {
313
+ return this.config;
314
+ },
315
+ create : function() {
316
+ var win = window.open(this.getConfig().url, 'new_attribute',
317
+ 'width=900,height=600,resizable=1,scrollbars=1');
318
+ win.focus();
319
+ },
320
+ addRow : function(html) {
321
+ var attributesContainer = $$('#group_fields' + this.getConfig().group_id + ' .form-list tbody')[0];
322
+ Element.insert(attributesContainer, {
323
+ bottom :html
324
+ });
325
+
326
+ var childs = attributesContainer.childElements();
327
+ var element = childs[childs.size() - 1].select('input', 'select',
328
+ 'textarea')[0];
329
+ if (element) {
330
+ window.scrollTo(0, Position.cumulativeOffset(element)[1]
331
+ + element.offsetHeight);
332
+ }
333
+ }
334
+ };
335
+
336
+ Product.Configurable = Class.create();
337
+ Product.Configurable.prototype = {
338
+ initialize : function(attributes, links, idPrefix, grid, readonly) {
339
+ this.templatesSyntax = new RegExp(
340
+ '(^|.|\\r|\\n)(\'{{\\s*(\\w+)\\s*}}\')', "");
341
+ this.attributes = attributes; // Attributes
342
+ this.idPrefix = idPrefix; // Container id prefix
343
+ this.links = $H(links); // Associated products
344
+ this.newProducts = []; // For product that's created through Create
345
+ // Empty and Copy from Configurable
346
+ this.readonly = readonly;
347
+
348
+ /* Generation templates */
349
+ this.addAttributeTemplate = new Template(
350
+ $(idPrefix + 'attribute_template').innerHTML.replace(/__id__/g,
351
+ "'{{html_id}}'").replace(/ template no-display/g, ''),
352
+ this.templatesSyntax);
353
+ this.addValueTemplate = new Template(
354
+ $(idPrefix + 'value_template').innerHTML.replace(/__id__/g,
355
+ "'{{html_id}}'").replace(/ template no-display/g, ''),
356
+ this.templatesSyntax);
357
+ this.pricingValueTemplate = new Template(
358
+ $(idPrefix + 'simple_pricing').innerHTML, this.templatesSyntax);
359
+ this.pricingValueViewTemplate = new Template(
360
+ $(idPrefix + 'simple_pricing_view').innerHTML,
361
+ this.templatesSyntax);
362
+
363
+ this.container = $(idPrefix + 'attributes');
364
+
365
+ /* Listeners */
366
+ this.onLabelUpdate = this.updateLabel.bindAsEventListener(this); // Update
367
+ // attribute
368
+ // label
369
+ this.onValuePriceUpdate = this.updateValuePrice
370
+ .bindAsEventListener(this); // Update pricing value
371
+ this.onValueTypeUpdate = this.updateValueType.bindAsEventListener(this); // Update
372
+ // pricing
373
+ // type
374
+ this.onValueDefaultUpdate = this.updateValueUseDefault
375
+ .bindAsEventListener(this);
376
+
377
+ /* Grid initialization and attributes initialization */
378
+ this.createAttributes(); // Creation of default attributes
379
+
380
+ this.grid = grid;
381
+ this.grid.rowClickCallback = this.rowClick.bind(this);
382
+ this.grid.initRowCallback = this.rowInit.bind(this);
383
+ this.grid.checkboxCheckCallback = this.registerProduct.bind(this); // Associate/Unassociate
384
+ // simple
385
+ // product
386
+
387
+ this.grid.rows.each( function(row) {
388
+ this.rowInit(this.grid, row);
389
+ }.bind(this));
390
+ },
391
+ createAttributes : function() {
392
+ this.attributes.each( function(attribute, index) {
393
+ // var li = Builder.node('li', {className:'attribute'});
394
+ var li = $(document.createElement('LI'));
395
+ li.className = 'attribute';
396
+
397
+ li.id = this.idPrefix + '_attribute_' + index;
398
+ attribute.html_id = li.id;
399
+ if (attribute && attribute.label && attribute.label.blank()) {
400
+ attribute.label = '&nbsp;'
401
+ }
402
+ var label_readonly = '';
403
+ var use_default_checked = '';
404
+ if (attribute.use_default == '1') {
405
+ use_default_checked = ' checked="checked"';
406
+ label_readonly = ' redonly="redonly"';
407
+ }
408
+
409
+ var template = this.addAttributeTemplate.evaluate(attribute);
410
+ template = template.replace(
411
+ new RegExp(' readonly="label"', 'g'), label_readonly);
412
+ template = template.replace(new RegExp(
413
+ ' checked="use_default"', 'g'), use_default_checked);
414
+ li.update(template);
415
+ li.attributeObject = attribute;
416
+
417
+ this.container.appendChild(li);
418
+ li.attributeValues = li.down('.attribute-values');
419
+
420
+ if (attribute.values) {
421
+ attribute.values.each( function(value) {
422
+ this.createValueRow(li, value); // Add pricing values
423
+ }.bind(this));
424
+ }
425
+
426
+ /* Observe label change */
427
+ Event.observe(li.down('.attribute-label'), 'change',
428
+ this.onLabelUpdate);
429
+ Event.observe(li.down('.attribute-label'), 'keyup',
430
+ this.onLabelUpdate);
431
+ Event.observe(li.down('.attribute-use-default-label'),
432
+ 'change', this.onLabelUpdate);
433
+ }.bind(this));
434
+ if (!this.readonly) {
435
+ // Creation of sortable for attributes sorting
436
+ Sortable.create(this.container, {
437
+ handle :'attribute-name-container',
438
+ onUpdate :this.updatePositions.bind(this)
439
+ });
440
+ }
441
+ this.updateSaveInput();
442
+ },
443
+
444
+ updateLabel : function(event) {
445
+ var li = Event.findElement(event, 'LI');
446
+ var labelEl = li.down('.attribute-label');
447
+ var defEl = li.down('.attribute-use-default-label');
448
+
449
+ li.attributeObject.label = labelEl.value;
450
+ if (defEl.checked) {
451
+ labelEl.readOnly = true;
452
+ li.attributeObject.use_default = 1;
453
+ } else {
454
+ labelEl.readOnly = false;
455
+ li.attributeObject.use_default = 0;
456
+ }
457
+
458
+ this.updateSaveInput();
459
+ },
460
+ updatePositions : function(param) {
461
+ this.container.childElements().each( function(row, index) {
462
+ row.attributeObject.position = index;
463
+ });
464
+ this.updateSaveInput();
465
+ },
466
+ addNewProduct : function(productId, attributes) {
467
+ if (this.checkAttributes(attributes)) {
468
+ this.links.set(productId, this.cloneAttributes(attributes));
469
+ } else {
470
+ this.newProducts.push(productId);
471
+ }
472
+
473
+ this.updateGrid();
474
+ this.updateValues();
475
+ this.grid.reload(null);
476
+ },
477
+ createEmptyProduct : function() {
478
+ this.createPopup(this.createEmptyUrl)
479
+ },
480
+ createNewProduct : function() {
481
+ this.createPopup(this.createNormalUrl);
482
+ },
483
+ createPopup : function(url) {
484
+ if (this.win && !this.win.closed) {
485
+ this.win.close();
486
+ }
487
+
488
+ this.win = window.open(url, '',
489
+ 'width=1000,height=700,resizable=1,scrollbars=1');
490
+ this.win.focus();
491
+ },
492
+ registerProduct : function(grid, element, checked) {
493
+ if (checked) {
494
+ if (element.linkAttributes) {
495
+ this.links.set(element.value, element.linkAttributes);
496
+ }
497
+ } else {
498
+ this.links.unset(element.value);
499
+ }
500
+ this.updateGrid();
501
+ this.grid.rows.each( function(row) {
502
+ this.revalidateRow(this.grid, row);
503
+ }.bind(this));
504
+ this.updateValues();
505
+ },
506
+ updateProduct : function(productId, attributes) {
507
+ var isAssociated = false;
508
+
509
+ if (typeof this.links.get(productId) != 'undefined') {
510
+ isAssociated = true;
511
+ this.links.unset(productId);
512
+ }
513
+
514
+ if (isAssociated && this.checkAttributes(attributes)) {
515
+ this.links.set(productId, this.cloneAttributes(attributes));
516
+ } else if (isAssociated) {
517
+ this.newProducts.push(productId);
518
+ }
519
+
520
+ this.updateGrid();
521
+ this.updateValues();
522
+ this.grid.reload(null);
523
+ },
524
+ cloneAttributes : function(attributes) {
525
+ var newObj = [];
526
+ for ( var i = 0, length = attributes.length; i < length; i++) {
527
+ newObj[i] = Object.clone(attributes[i]);
528
+ }
529
+ return newObj;
530
+ },
531
+ rowClick : function(grid, event) {
532
+ var trElement = Event.findElement(event, 'tr');
533
+ var isInput = Event.element(event).tagName.toUpperCase() == 'INPUT';
534
+
535
+ if ($(Event.findElement(event, 'td')).down('a')) {
536
+ return;
537
+ }
538
+
539
+ if (trElement) {
540
+ var checkbox = $(trElement).down('input');
541
+ if (checkbox && !checkbox.disabled) {
542
+ var checked = isInput ? checkbox.checked : !checkbox.checked;
543
+ grid.setCheckboxChecked(checkbox, checked);
544
+ }
545
+ }
546
+ },
547
+ rowInit : function(grid, row) {
548
+ var checkbox = $(row).down('.checkbox');
549
+ var input = $(row).down('.value-json');
550
+ if (checkbox && input) {
551
+ checkbox.linkAttributes = input.value.evalJSON();
552
+ if (!checkbox.checked) {
553
+ if (!this.checkAttributes(checkbox.linkAttributes)) {
554
+ $(row).addClassName('invalid');
555
+ checkbox.disable();
556
+ } else {
557
+ $(row).removeClassName('invalid');
558
+ checkbox.enable();
559
+ }
560
+ }
561
+ }
562
+ },
563
+ revalidateRow : function(grid, row) {
564
+ var checkbox = $(row).down('.checkbox');
565
+ if (checkbox) {
566
+ if (!checkbox.checked) {
567
+ if (!this.checkAttributes(checkbox.linkAttributes)) {
568
+ $(row).addClassName('invalid');
569
+ checkbox.disable();
570
+ } else {
571
+ $(row).removeClassName('invalid');
572
+ checkbox.enable();
573
+ }
574
+ }
575
+ }
576
+ },
577
+ checkAttributes : function(attributes) {
578
+ var result = true;
579
+ this.links
580
+ .each( function(pair) {
581
+ var fail = false;
582
+ for ( var i = 0; i < pair.value.length && !fail; i++) {
583
+ for ( var j = 0; j < attributes.length && !fail; j++) {
584
+ if (pair.value[i].attribute_id == attributes[j].attribute_id
585
+ && pair.value[i].value_index != attributes[j].value_index) {
586
+ fail = true;
587
+ }
588
+ }
589
+ }
590
+ if (!fail) {
591
+ result = false;
592
+ }
593
+ });
594
+ return result;
595
+ },
596
+ updateGrid : function() {
597
+ this.grid.reloadParams = {
598
+ 'products[]' :this.links.keys().size() ? this.links.keys() : [ 0 ],
599
+ 'new_products[]' :this.newProducts
600
+ };
601
+ },
602
+ updateValues : function() {
603
+ var uniqueAttributeValues = $H( {});
604
+ /* Collect unique attributes */
605
+ this.links.each( function(pair) {
606
+ for ( var i = 0, length = pair.value.length; i < length; i++) {
607
+ var attribute = pair.value[i];
608
+ if (uniqueAttributeValues.keys()
609
+ .indexOf(attribute.attribute_id) == -1) {
610
+ uniqueAttributeValues.set(attribute.attribute_id, $H( {}));
611
+ }
612
+ uniqueAttributeValues.get(attribute.attribute_id).set(
613
+ attribute.value_index, attribute);
614
+ }
615
+ });
616
+ /* Updating attributes value container */
617
+ this.container
618
+ .childElements()
619
+ .each(
620
+ function(row) {
621
+ var attribute = row.attributeObject;
622
+ for ( var i = 0, length = attribute.values.length; i < length; i++) {
623
+ if (uniqueAttributeValues.keys().indexOf(
624
+ attribute.attribute_id) == -1
625
+ || uniqueAttributeValues
626
+ .get(attribute.attribute_id)
627
+ .keys()
628
+ .indexOf(
629
+ attribute.values[i].value_index) == -1) {
630
+ row.attributeValues
631
+ .childElements()
632
+ .each(
633
+ function(elem) {
634
+ if (elem.valueObject.value_index == attribute.values[i].value_index) {
635
+ elem.remove();
636
+ }
637
+ });
638
+ attribute.values[i] = undefined;
639
+
640
+ } else {
641
+ uniqueAttributeValues.get(
642
+ attribute.attribute_id).unset(
643
+ attribute.values[i].value_index);
644
+ }
645
+ }
646
+ attribute.values = attribute.values.compact();
647
+ if (uniqueAttributeValues
648
+ .get(attribute.attribute_id)) {
649
+ uniqueAttributeValues.get(
650
+ attribute.attribute_id).each(
651
+ function(pair) {
652
+ attribute.values.push(pair.value);
653
+ this
654
+ .createValueRow(row,
655
+ pair.value);
656
+ }.bind(this));
657
+ }
658
+ }.bind(this));
659
+ this.updateSaveInput();
660
+ this.updateSimpleForm();
661
+ },
662
+ createValueRow : function(container, value) {
663
+ var templateVariables = $H( {});
664
+ if (!this.valueAutoIndex) {
665
+ this.valueAutoIndex = 1;
666
+ }
667
+ templateVariables.set('html_id', container.id + '_'
668
+ + this.valueAutoIndex);
669
+ templateVariables.update(value);
670
+ var pricingValue = parseFloat(templateVariables.get('pricing_value'));
671
+ if (!isNaN(pricingValue)) {
672
+ templateVariables.set('pricing_value', pricingValue);
673
+ } else {
674
+ templateVariables.unset('pricing_value');
675
+ }
676
+ this.valueAutoIndex++;
677
+
678
+ // var li = $(Builder.node('li', {className:'attribute-value'}));
679
+ var li = $(document.createElement('LI'));
680
+ li.className = 'attribute-value';
681
+ li.id = templateVariables.get('html_id');
682
+ li.update(this.addValueTemplate.evaluate(templateVariables));
683
+ li.valueObject = value;
684
+ if (typeof li.valueObject.is_percent == 'undefined') {
685
+ li.valueObject.is_percent = 0;
686
+ }
687
+
688
+ if (typeof li.valueObject.pricing_value == 'undefined') {
689
+ li.valueObject.pricing_value = '';
690
+ }
691
+
692
+ container.attributeValues.appendChild(li);
693
+
694
+ var priceField = li.down('.attribute-price');
695
+ var priceTypeField = li.down('.attribute-price-type');
696
+
697
+ if (priceTypeField != undefined && priceTypeField.options != undefined) {
698
+ if (parseInt(value.is_percent)) {
699
+ priceTypeField.options[1].selected = !(priceTypeField.options[0].selected = false);
700
+ } else {
701
+ priceTypeField.options[1].selected = !(priceTypeField.options[0].selected = true);
702
+ }
703
+ }
704
+
705
+ Event.observe(priceField, 'keyup', this.onValuePriceUpdate);
706
+ Event.observe(priceField, 'change', this.onValuePriceUpdate);
707
+ Event.observe(priceTypeField, 'change', this.onValueTypeUpdate);
708
+ var useDefaultEl = li.down('.attribute-use-default-value');
709
+ if (useDefaultEl) {
710
+ if (li.valueObject.use_default_value) {
711
+ useDefaultEl.checked = true;
712
+ this.updateUseDefaultRow(useDefaultEl, li);
713
+ }
714
+ Event.observe(useDefaultEl, 'change', this.onValueDefaultUpdate);
715
+ }
716
+ },
717
+ updateValuePrice : function(event) {
718
+ var li = Event.findElement(event, 'LI');
719
+ li.valueObject.pricing_value = (Event.element(event).value.blank() ? null
720
+ : Event.element(event).value);
721
+ this.updateSimpleForm();
722
+ this.updateSaveInput();
723
+ },
724
+ updateValueType : function(event) {
725
+ var li = Event.findElement(event, 'LI');
726
+ li.valueObject.is_percent = (Event.element(event).value.blank() ? null
727
+ : Event.element(event).value);
728
+ this.updateSimpleForm();
729
+ this.updateSaveInput();
730
+ },
731
+ updateValueUseDefault : function(event) {
732
+ var li = Event.findElement(event, 'LI');
733
+ var useDefaultEl = Event.element(event);
734
+ li.valueObject.use_default_value = useDefaultEl.checked;
735
+ this.updateUseDefaultRow(useDefaultEl, li);
736
+ },
737
+ updateUseDefaultRow : function(useDefaultEl, li) {
738
+ var priceField = li.down('.attribute-price');
739
+ var priceTypeField = li.down('.attribute-price-type');
740
+ if (useDefaultEl.checked) {
741
+ priceField.disabled = true;
742
+ priceTypeField.disabled = true;
743
+ } else {
744
+ priceField.disabled = false;
745
+ priceTypeField.disabled = false;
746
+ }
747
+ this.updateSimpleForm();
748
+ this.updateSaveInput();
749
+ },
750
+ updateSaveInput : function() {
751
+ $(this.idPrefix + 'save_attributes').value = Object.toJSON(this.attributes);
752
+ $(this.idPrefix + 'save_links').value = Object.toJSON(this.links);
753
+ },
754
+ initializeAdvicesForSimpleForm : function() {
755
+ if ($(this.idPrefix + 'simple_form').advicesInited) {
756
+ return;
757
+ }
758
+
759
+ $(this.idPrefix + 'simple_form').select('td.value').each( function(td) {
760
+ var adviceContainer = $(Builder.node('div'));
761
+ td.appendChild(adviceContainer);
762
+ td.select('input', 'select').each( function(element) {
763
+ element.advaiceContainer = adviceContainer;
764
+ });
765
+ });
766
+ $(this.idPrefix + 'simple_form').advicesInited = true;
767
+ },
768
+ quickCreateNewProduct : function() {
769
+ this.initializeAdvicesForSimpleForm();
770
+ $(this.idPrefix + 'simple_form').removeClassName('ignore-validate');
771
+ var validationResult = $(this.idPrefix + 'simple_form').select('input',
772
+ 'select', 'textarea').collect( function(elm) {
773
+ return Validation.validate(elm, {
774
+ useTitle :false,
775
+ onElementValidate : function() {
776
+ }
777
+ });
778
+ }).all();
779
+ $(this.idPrefix + 'simple_form').addClassName('ignore-validate');
780
+
781
+ if (!validationResult) {
782
+ return;
783
+ }
784
+
785
+ var params = Form.serializeElements($(this.idPrefix + 'simple_form')
786
+ .select('input', 'select', 'textarea'), true);
787
+ params.form_key = FORM_KEY;
788
+ $('messages').update();
789
+ new Ajax.Request(this.createQuickUrl, {
790
+ parameters :params,
791
+ method :'post',
792
+ area :$(this.idPrefix + 'simple_form'),
793
+ onComplete :this.quickCreateNewProductComplete.bind(this)
794
+ });
795
+ },
796
+ quickCreateNewProductComplete : function(transport) {
797
+ var result = transport.responseText.evalJSON();
798
+
799
+ if (result.error) {
800
+ if (result.error.fields) {
801
+ $(this.idPrefix + 'simple_form').removeClassName(
802
+ 'ignore-validate');
803
+ $H(result.error.fields)
804
+ .each(
805
+ function(pair) {
806
+ $('simple_product_' + pair.key).value = pair.value;
807
+ $('simple_product_' + pair.key + '_autogenerate').checked = false;
808
+ toggleValueElements(
809
+ $('simple_product_' + pair.key + '_autogenerate'),
810
+ $('simple_product_' + pair.key + '_autogenerate').parentNode);
811
+ Validation.ajaxError(
812
+ $('simple_product_' + pair.key),
813
+ result.error.message);
814
+ });
815
+ $(this.idPrefix + 'simple_form')
816
+ .addClassName('ignore-validate');
817
+ } else {
818
+ if (result.error.message) {
819
+ alert(result.error.message);
820
+ } else {
821
+ alert(result.error);
822
+ }
823
+ }
824
+ return;
825
+ } else if (result.messages) {
826
+ $('messages').update(result.messages);
827
+ }
828
+
829
+ result.attributes
830
+ .each( function(attribute) {
831
+ var attr = this.getAttributeById(attribute.attribute_id);
832
+ if (!this.getValueByIndex(attr, attribute.value_index)
833
+ && result.pricing
834
+ && result.pricing[attr.attribute_code]) {
835
+
836
+ attribute.is_percent = result.pricing[attr.attribute_code].is_percent;
837
+ attribute.pricing_value = (result.pricing[attr.attribute_code].value == null ? ''
838
+ : result.pricing[attr.attribute_code].value);
839
+ }
840
+ }.bind(this));
841
+
842
+ this.attributes.each( function(attribute) {
843
+ if ($('simple_product_' + attribute.attribute_code)) {
844
+ $('simple_product_' + attribute.attribute_code).value = '';
845
+ }
846
+ }.bind(this));
847
+
848
+ this.links.set(result.product_id, result.attributes);
849
+ this.updateGrid();
850
+ this.updateValues();
851
+ this.grid.reload();
852
+ },
853
+ checkCreationUniqueAttributes : function() {
854
+ var attributes = [];
855
+ this.attributes
856
+ .each( function(attribute) {
857
+ attributes
858
+ .push( {
859
+ attribute_id :attribute.attribute_id,
860
+ value_index :$('simple_product_' + attribute.attribute_code).value
861
+ });
862
+ }.bind(this));
863
+
864
+ return this.checkAttributes(attributes);
865
+ },
866
+ getAttributeByCode : function(attributeCode) {
867
+ var attribute = null;
868
+ this.attributes.each( function(item) {
869
+ if (item.attribute_code == attributeCode) {
870
+ attribute = item;
871
+ throw $break;
872
+ }
873
+ });
874
+ return attribute;
875
+ },
876
+ getAttributeById : function(attributeId) {
877
+ var attribute = null;
878
+ this.attributes.each( function(item) {
879
+ if (item.attribute_id == attributeId) {
880
+ attribute = item;
881
+ throw $break;
882
+ }
883
+ });
884
+ return attribute;
885
+ },
886
+ getValueByIndex : function(attribute, valueIndex) {
887
+ var result = null;
888
+ attribute.values.each( function(value) {
889
+ if (value.value_index == valueIndex) {
890
+ result = value;
891
+ throw $break;
892
+ }
893
+ });
894
+ return result;
895
+ },
896
+ showPricing : function(select, attributeCode) {
897
+ var attribute = this.getAttributeByCode(attributeCode);
898
+ if (!attribute) {
899
+ return;
900
+ }
901
+
902
+ select = $(select);
903
+ if (select.value
904
+ && !$('simple_product_' + attributeCode + '_pricing_container')) {
905
+ Element
906
+ .insert(
907
+ select,
908
+ {
909
+ after :'<div class="left"></div> <div id="simple_product_' + attributeCode + '_pricing_container" class="left"></div>'
910
+ });
911
+ var newContainer = select.next('div');
912
+ select.parentNode.removeChild(select);
913
+ newContainer.appendChild(select);
914
+ // Fix visualization bug
915
+ $(this.idPrefix + 'simple_form').down('.form-list').style.width = '100%';
916
+ }
917
+
918
+ var container = $('simple_product_' + attributeCode + '_pricing_container');
919
+
920
+ if (select.value) {
921
+ var value = this.getValueByIndex(attribute, select.value);
922
+ if (!value) {
923
+ if (!container.down('.attribute-price')) {
924
+ if (value == null) {
925
+ value = {};
926
+ }
927
+ container.update(this.pricingValueTemplate.evaluate(value));
928
+ var priceValueField = container.down('.attribute-price');
929
+ var priceTypeField = container
930
+ .down('.attribute-price-type');
931
+
932
+ priceValueField.attributeCode = attributeCode;
933
+ priceValueField.priceField = priceValueField;
934
+ priceValueField.typeField = priceTypeField;
935
+
936
+ priceTypeField.attributeCode = attributeCode;
937
+ priceTypeField.priceField = priceValueField;
938
+ priceTypeField.typeField = priceTypeField;
939
+
940
+ Event.observe(priceValueField, 'change',
941
+ this.updateSimplePricing.bindAsEventListener(this));
942
+ Event.observe(priceValueField, 'keyup',
943
+ this.updateSimplePricing.bindAsEventListener(this));
944
+ Event.observe(priceTypeField, 'change',
945
+ this.updateSimplePricing.bindAsEventListener(this));
946
+
947
+ $('simple_product_' + attributeCode + '_pricing_value').value = null;
948
+ $('simple_product_' + attributeCode + '_pricing_type').value = null;
949
+ }
950
+ } else if (!isNaN(parseFloat(value.pricing_value))) {
951
+ container.update(this.pricingValueViewTemplate.evaluate( {
952
+ 'value' :(parseFloat(value.pricing_value) > 0 ? '+' : '')
953
+ + parseFloat(value.pricing_value)
954
+ + (parseInt(value.is_percent) > 0 ? '%' : '')
955
+ }));
956
+ $('simple_product_' + attributeCode + '_pricing_value').value = value.pricing_value;
957
+ $('simple_product_' + attributeCode + '_pricing_type').value = value.is_percent;
958
+ } else {
959
+ container.update('');
960
+ $('simple_product_' + attributeCode + '_pricing_value').value = null;
961
+ $('simple_product_' + attributeCode + '_pricing_type').value = null;
962
+ }
963
+ } else if (container) {
964
+ container.update('');
965
+ $('simple_product_' + attributeCode + '_pricing_value').value = null;
966
+ $('simple_product_' + attributeCode + '_pricing_type').value = null;
967
+ }
968
+ },
969
+ updateSimplePricing : function(evt) {
970
+ var element = Event.element(evt);
971
+ if (!element.priceField.value.blank()) {
972
+ $('simple_product_' + element.attributeCode + '_pricing_value').value = element.priceField.value;
973
+ $('simple_product_' + element.attributeCode + '_pricing_type').value = element.typeField.value;
974
+ } else {
975
+ $('simple_product_' + element.attributeCode + '_pricing_value').value = null;
976
+ $('simple_product_' + element.attributeCode + '_pricing_type').value = null;
977
+ }
978
+ },
979
+ updateSimpleForm : function() {
980
+ this.attributes.each( function(attribute) {
981
+ if ($('simple_product_' + attribute.attribute_code)) {
982
+ this.showPricing(
983
+ $('simple_product_' + attribute.attribute_code),
984
+ attribute.attribute_code);
985
+ }
986
+ }.bind(this));
987
+ },
988
+ showNoticeMessage : function() {
989
+ $('assign_product_warrning').show();
990
+ }
991
+ }
992
+
993
+ var onInitDisableFieldsList = [];
994
+
995
+ function toogleFieldEditMode(toogleIdentifier, fieldContainer) {
996
+ if ($(toogleIdentifier).checked) {
997
+ enableFieldEditMode(fieldContainer);
998
+ } else {
999
+ disableFieldEditMode(fieldContainer);
1000
+ }
1001
+ }
1002
+
1003
+ function disableFieldEditMode(fieldContainer) {
1004
+ $(fieldContainer).disabled = true;
1005
+ if ($(fieldContainer + '_hidden')) {
1006
+ $(fieldContainer + '_hidden').disabled = true;
1007
+ }
1008
+ }
1009
+
1010
+ function enableFieldEditMode(fieldContainer) {
1011
+ $(fieldContainer).disabled = false;
1012
+ if ($(fieldContainer + '_hidden')) {
1013
+ $(fieldContainer + '_hidden').disabled = false;
1014
+ }
1015
+ }
1016
+
1017
+ function initDisableFields(fieldContainer) {
1018
+ onInitDisableFieldsList.push(fieldContainer);
1019
+ }
1020
+
1021
+ function onCompleteDisableInited() {
1022
+ onInitDisableFieldsList.each( function(item) {
1023
+ disableFieldEditMode(item);
1024
+ });
1025
+ }
1026
+
1027
+ function onUrlkeyChanged(urlKey) {
1028
+ urlKey = $(urlKey);
1029
+ var hidden = urlKey.next('input[type=hidden]');
1030
+ var chbx = urlKey.next('input[type=checkbox]');
1031
+ var oldValue = chbx.value;
1032
+ chbx.disabled = (oldValue == urlKey.value);
1033
+ hidden.disabled = chbx.disabled;
1034
+ }
1035
+
1036
+ function onCustomUseParentChanged(element) {
1037
+ var useParent = (element.value == 1) ? true : false;
1038
+ element.up(2).select('input', 'select', 'textarea').each(function(el){
1039
+ if (element.id != el.id) {
1040
+ el.disabled = useParent;
1041
+ }
1042
+ });
1043
+ element.up(2).select('img').each(function(el){
1044
+ if (useParent) {
1045
+ el.hide();
1046
+ } else {
1047
+ el.show();
1048
+ }
1049
+ });
1050
+ }
1051
+
1052
+ Event.observe(window, 'load', onCompleteDisableInited);
js/mage/adminhtml/product/composite/configure.js ADDED
@@ -0,0 +1,765 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ ProductConfigure = Class.create();
27
+ ProductConfigure.prototype = {
28
+
29
+ listTypes: $H({}),
30
+ current: $H({}),
31
+ itemsFilter: $H({}),
32
+ blockWindow: null,
33
+ blockForm: null,
34
+ blockFormFields: null,
35
+ blockFormAdd: null,
36
+ blockFormConfirmed: null,
37
+ blockConfirmed: null,
38
+ blockIFrame: null,
39
+ blockCancelBtn: null,
40
+ blockMask: null,
41
+ blockMsg: null,
42
+ blockMsgError: null,
43
+ windowHeight: null,
44
+ confirmedCurrentId: null,
45
+ confirmCallback: {},
46
+ cancelCallback: {},
47
+ onLoadIFrameCallback: {},
48
+ showWindowCallback: {},
49
+ beforeSubmitCallback: {},
50
+ iFrameJSVarname: null,
51
+ _listTypeId: 1,
52
+
53
+ /**
54
+ * Initialize object
55
+ */
56
+ initialize: function() {
57
+ this._initWindowElements();
58
+ },
59
+
60
+ /**
61
+ * Initialize window elements
62
+ */
63
+ _initWindowElements: function() {
64
+ this.blockWindow = $('product_composite_configure');
65
+ this.blockForm = $('product_composite_configure_form');
66
+ this.blockFormFields = $('product_composite_configure_form_fields');
67
+ this.blockFormAdd = $('product_composite_configure_form_additional');
68
+ this.blockFormConfirmed = $('product_composite_configure_form_confirmed');
69
+ this.blockConfirmed = $('product_composite_configure_confirmed');
70
+ this.blockIFrame = $('product_composite_configure_iframe');
71
+ this.blockCancelBtn = $('product_composite_configure_form_cancel');
72
+ this.blockMask = $('popup-window-mask');
73
+ this.blockMsg = $('product_composite_configure_messages');
74
+ this.blockMsgError = this.blockMsg.select('.error-msg')[0];
75
+ this.windowHeight = $('html-body').getHeight();
76
+ this.iFrameJSVarname = this.blockForm.select('input[name="as_js_varname"]')[0].value;
77
+ },
78
+
79
+ /**
80
+ * Returns next unique list type id
81
+ */
82
+ _generateListTypeId: function () {
83
+ return '_internal_lt_' + (this._listTypeId++);
84
+ },
85
+
86
+ /**
87
+ * Add product list types as scope and their urls
88
+ * expamle: addListType('product_to_add', {urlFetch: 'http://magento...'})
89
+ * expamle: addListType('wishlist', {urlSubmit: 'http://magento...'})
90
+ *
91
+ * @param type types as scope
92
+ * @param urls obj can be
93
+ * - {urlFetch: 'http://magento...'} for fetching configuration fields through ajax
94
+ * - {urlConfirm: 'http://magento...'} for submit configured data through iFrame when clicked confirm button
95
+ * - {urlSubmit: 'http://magento...'} for submit configured data through iFrame
96
+ */
97
+ addListType: function(type, urls) {
98
+ if ('undefined' == typeof this.listTypes[type]) {
99
+ this.listTypes[type] = {};
100
+ }
101
+ Object.extend(this.listTypes[type], urls);
102
+ return this;
103
+ },
104
+
105
+ /**
106
+ * Adds complex list type - that is used to submit several list types at once
107
+ * Only urlSubmit is possible for this list type
108
+ * expamle: addComplexListType(['wishlist', 'product_list'], 'http://magento...')
109
+ *
110
+ * @param type types as scope
111
+ * @param urls obj can be
112
+ * - {urlSubmit: 'http://magento...'} for submit configured data through iFrame
113
+ * @return type string
114
+ */
115
+ addComplexListType: function(types, urlSubmit) {
116
+ var type = this._generateListTypeId();
117
+ this.listTypes[type] = {};
118
+ this.listTypes[type].complexTypes = types;
119
+ this.listTypes[type].urlSubmit = urlSubmit;
120
+ return type;
121
+ },
122
+
123
+ /**
124
+ * Add filter of items
125
+ *
126
+ * @param listType scope name
127
+ * @param itemsFilter
128
+ */
129
+ addItemsFilter: function(listType, itemsFilter) {
130
+ if (!listType || !itemsFilter) {
131
+ return false;
132
+ }
133
+ if ('undefined' == typeof this.itemsFilter[listType]) {
134
+ this.itemsFilter[listType] = [];
135
+ }
136
+ this.itemsFilter[listType] = this.itemsFilter[listType].concat(itemsFilter);
137
+ return this;
138
+ },
139
+
140
+ /**
141
+ * Returns id of block where configuration for an item is stored
142
+ *
143
+ * @param listType scope name
144
+ * @param itemId
145
+ * @return string
146
+ */
147
+ _getConfirmedBlockId: function (listType, itemId) {
148
+ return this.blockConfirmed.id + '[' + listType + '][' + itemId + ']';
149
+ },
150
+
151
+ /**
152
+ * Checks whether item has some configuration fields
153
+ *
154
+ * @param listType scope name
155
+ * @param itemId
156
+ * @return bool
157
+ */
158
+ itemConfigured: function (listType, itemId) {
159
+ var confirmedBlockId = this._getConfirmedBlockId(listType, itemId);
160
+ var itemBlock = $(confirmedBlockId);
161
+ return !!(itemBlock && itemBlock.innerHTML);
162
+ },
163
+
164
+ /**
165
+ * Show configuration fields of item, if it not found then get it through ajax
166
+ *
167
+ * @param listType scope name
168
+ * @param itemId
169
+ */
170
+ showItemConfiguration: function(listType, itemId) {
171
+ if (!listType || !itemId) {
172
+ return false;
173
+ }
174
+
175
+ this._initWindowElements();
176
+ this.current.listType = listType;
177
+ this.current.itemId = itemId;
178
+ this.confirmedCurrentId = this._getConfirmedBlockId(listType, itemId);
179
+
180
+ if (!this.itemConfigured(listType, itemId)) {
181
+ this._requestItemConfiguration(listType, itemId);
182
+ } else {
183
+ this._processFieldsData('item_restore');
184
+ this._showWindow();
185
+ }
186
+ },
187
+
188
+ /**
189
+ * Get configuration fields of product through ajax and show them
190
+ *
191
+ * @param listType scope name
192
+ * @param itemId
193
+ */
194
+ _requestItemConfiguration: function(listType, itemId) {
195
+ if (!this.listTypes[listType].urlFetch) {
196
+ return false;
197
+ }
198
+ var url = this.listTypes[listType].urlFetch;
199
+ if (url) {
200
+ new Ajax.Request(url, {
201
+ parameters: {id: itemId},
202
+ onSuccess: function(transport) {
203
+ var response = transport.responseText;
204
+ if (response.isJSON()) {
205
+ response = response.evalJSON();
206
+ if (response.error) {
207
+ this.blockMsg.show();
208
+ this.blockMsgError.innerHTML = response.message;
209
+ this.blockCancelBtn.hide();
210
+ this.setConfirmCallback(listType, null);
211
+ this._showWindow();
212
+ }
213
+ } else if (response) {
214
+ response = response + '';
215
+ this.blockFormFields.update(response);
216
+
217
+ // Add special div to hold mage data, e.g. scripts to execute on every popup show
218
+ var mageData = {};
219
+ var scripts = response.extractScripts();
220
+ mageData.scripts = scripts;
221
+
222
+ var scriptHolder = new Element('div', {'style': 'display:none'});
223
+ scriptHolder.mageData = mageData;
224
+ this.blockFormFields.insert(scriptHolder);
225
+
226
+ // Show window
227
+ this._showWindow();
228
+ }
229
+ }.bind(this)
230
+ });
231
+ }
232
+ },
233
+
234
+ /**
235
+ * Triggered on confirm button click
236
+ * Do submit configured data through iFrame if needed
237
+ */
238
+ onConfirmBtn: function() {
239
+ if (productCompositeConfigureForm.validate()) {
240
+ if (this.listTypes[this.current.listType].urlConfirm) {
241
+ this.submit();
242
+ } else {
243
+ this._processFieldsData('item_confirm');
244
+ this._closeWindow();
245
+ if (Object.isFunction(this.confirmCallback[this.current.listType])) {
246
+ this.confirmCallback[this.current.listType]();
247
+ }
248
+ }
249
+ }
250
+ return this;
251
+ },
252
+
253
+ /**
254
+ * Triggered on cancel button click
255
+ */
256
+ onCancelBtn: function() {
257
+ this._closeWindow();
258
+ if (Object.isFunction(this.cancelCallback[this.current.listType])) {
259
+ this.cancelCallback[this.current.listType]();
260
+ }
261
+ return this;
262
+ },
263
+
264
+ /**
265
+ * Submit configured data through iFrame
266
+ *
267
+ * @param listType scope name
268
+ */
269
+ submit: function (listType) {
270
+ // prepare data
271
+ if (listType) {
272
+ this.current.listType = listType;
273
+ this.current.itemId = null;
274
+ }
275
+ var urlConfirm = this.listTypes[this.current.listType].urlConfirm;
276
+ var urlSubmit = this.listTypes[this.current.listType].urlSubmit;
277
+ if (!urlConfirm && !urlSubmit) {
278
+ return false;
279
+ }
280
+ if (urlConfirm) {
281
+ this.blockForm.action = urlConfirm;
282
+ this.addFields([new Element('input', {type: 'hidden', name: 'id', value: this.current.itemId})]);
283
+ } else {
284
+ this.blockForm.action = urlSubmit;
285
+
286
+ var complexTypes = this.listTypes[this.current.listType].complexTypes;
287
+ if (complexTypes) {
288
+ this.addFields([new Element('input', {type: 'hidden', name: 'configure_complex_list_types', value: complexTypes.join(',')})]);
289
+ }
290
+
291
+ this._processFieldsData('current_confirmed_to_form');
292
+
293
+ // Disable item controls that duplicate added fields (e.g. sometimes qty controls can intersect)
294
+ // so they won't be submitted
295
+ var tagNames = ['input', 'select', 'textarea'];
296
+
297
+ var names = {}; // Map of added field names
298
+ for (var i = 0, len = tagNames.length; i < len; i++) {
299
+ var tagName = tagNames[i];
300
+ var elements = this.blockFormAdd.getElementsByTagName(tagName);
301
+ for (var index = 0, elLen = elements.length; index < elLen; index++) {
302
+ names[elements[index].name] = true;
303
+ }
304
+ }
305
+
306
+ for (var i = 0, len = tagNames.length; i < len; i++) {
307
+ var tagName = tagNames[i];
308
+ var elements = this.blockFormConfirmed.getElementsByTagName(tagName);
309
+ for (var index = 0, elLen = elements.length; index < elLen; index++) {
310
+ var element = elements[index];
311
+ if (names[element.name]) {
312
+ element.setAttribute('configure_disabled', 1);
313
+ element.setAttribute('configure_prev_disabled', element.disabled ? 1 : 0);
314
+ element.disabled = true;
315
+ } else {
316
+ element.setAttribute('configure_disabled', 0);
317
+ }
318
+ }
319
+ }
320
+ }
321
+ // do submit
322
+ if (Object.isFunction(this.beforeSubmitCallback[this.current.listType])) {
323
+ this.beforeSubmitCallback[this.current.listType]();
324
+ }
325
+ this.blockForm.submit();
326
+ varienLoaderHandler.handler.onCreate({options: {loaderArea: true}});
327
+ return this;
328
+ },
329
+
330
+ /**
331
+ * Add dynamically additional fields for form
332
+ *
333
+ * @param fields
334
+ */
335
+ addFields: function(fields) {
336
+ fields.each(function(elm) {
337
+ this.blockFormAdd.insert(elm);
338
+ }.bind(this));
339
+ return this;
340
+ },
341
+
342
+ /**
343
+ * Triggered when form was submitted and iFrame was loaded. Get response from iFrame and handle it
344
+ */
345
+ onLoadIFrame: function() {
346
+ varienLoaderHandler.handler.onComplete();
347
+
348
+ this.blockFormConfirmed.select('[configure_disabled=1]').each(function (element) {
349
+ element.disabled = element.getAttribute('configure_prev_disabled') == '1';
350
+ });
351
+
352
+ this._processFieldsData('form_confirmed_to_confirmed');
353
+
354
+ var response = this.blockIFrame.contentWindow[this.iFrameJSVarname];
355
+ if (response && "object" == typeof response) {
356
+ if (this.listTypes[this.current.listType].urlConfirm) {
357
+ if (response.ok) {
358
+ this._closeWindow();
359
+ this.clean('current');
360
+ } else if (response.error) {
361
+ this.showItemConfiguration(this.current.listType, this.current.itemId);
362
+ this.blockMsg.show();
363
+ this.blockMsgError.innerHTML = response.message;
364
+ this._showWindow();
365
+ return false;
366
+ }
367
+ }
368
+ if (Object.isFunction(this.onLoadIFrameCallback[this.current.listType])) {
369
+ this.onLoadIFrameCallback[this.current.listType](response);
370
+ }
371
+
372
+ document.fire(this.current.listType + ':afterIFrameLoaded');
373
+ }
374
+ this.clean('current');
375
+ },
376
+
377
+ /**
378
+ * Helper for fetching content from iFrame
379
+ */
380
+ _getIFrameContent: function() {
381
+ var content = (this.blockIFrame.contentWindow || this.blockIFrame.contentDocument);
382
+ if (content.document) {
383
+ content=content.document;
384
+ }
385
+ return content;
386
+ },
387
+
388
+ /**
389
+ * Helper to find qty of currently confirmed item
390
+ */
391
+ getCurrentConfirmedQtyElement: function() {
392
+ var elms = $(this.confirmedCurrentId).getElementsByTagName('input');
393
+ for (var i = 0; i < elms.length; i++) {
394
+ if (elms[i].name == 'qty') {
395
+ return elms[i];
396
+ }
397
+ }
398
+ },
399
+
400
+ /**
401
+ * Helper to find qty of active form
402
+ */
403
+ getCurrentFormQtyElement: function() {
404
+ var elms = this.blockFormFields.getElementsByTagName('input');
405
+ for (var i = 0; i < elms.length; i++) {
406
+ if (elms[i].name == 'qty') {
407
+ return elms[i];
408
+ }
409
+ }
410
+ },
411
+
412
+ /**
413
+ * Show configuration window
414
+ */
415
+ _showWindow: function() {
416
+ this._toggleSelectsExceptBlock(false);
417
+ this.blockMask.setStyle({'height':this.windowHeight+'px'}).show();
418
+ this.blockWindow.setStyle({'marginTop':-this.blockWindow.getHeight()/2 + "px", 'display':'block'});
419
+ if (Object.isFunction(this.showWindowCallback[this.current.listType])) {
420
+ this.showWindowCallback[this.current.listType]();
421
+ }
422
+ },
423
+
424
+ /**
425
+ * toggles Selects states (for IE) except those to be shown in popup
426
+ */
427
+ _toggleSelectsExceptBlock: function(flag) {
428
+ if(Prototype.Browser.IE){
429
+ if (this.blockForm) {
430
+ var states = new Array;
431
+ var selects = this.blockForm.getElementsByTagName("select");
432
+ for(var i=0; i<selects.length; i++){
433
+ states[i] = selects[i].style.visibility
434
+ }
435
+ }
436
+ toggleSelectsUnderBlock(this.blockMask, flag);
437
+ if (this.blockForm) {
438
+ for(i=0; i<selects.length; i++){
439
+ selects[i].style.visibility = states[i]
440
+ }
441
+ }
442
+ }
443
+ },
444
+
445
+ /**
446
+ * Close configuration window
447
+ */
448
+ _closeWindow: function() {
449
+ toggleSelectsUnderBlock(this.blockMask, true);
450
+ this.blockMask.style.display = 'none';
451
+ this.blockWindow.style.display = 'none';
452
+ this.clean('window');
453
+ },
454
+
455
+ /**
456
+ * Attach callback function triggered when confirm button was clicked
457
+ *
458
+ * @param confirmCallback
459
+ */
460
+ setConfirmCallback: function(listType, confirmCallback) {
461
+ this.confirmCallback[listType] = confirmCallback;
462
+ return this;
463
+ },
464
+
465
+ /**
466
+ * Attach callback function triggered when cancel button was clicked
467
+ *
468
+ * @param cancelCallback
469
+ */
470
+ setCancelCallback: function(listType, cancelCallback) {
471
+ this.cancelCallback[listType] = cancelCallback;
472
+ return this;
473
+ },
474
+
475
+ /**
476
+ * Attach callback function triggered when iFrame was loaded
477
+ *
478
+ * @param onLoadIFrameCallback
479
+ */
480
+ setOnLoadIFrameCallback: function(listType, onLoadIFrameCallback) {
481
+ this.onLoadIFrameCallback[listType] = onLoadIFrameCallback;
482
+ return this;
483
+ },
484
+
485
+ /**
486
+ * Attach callback function triggered when iFrame was loaded
487
+ *
488
+ * @param showWindowCallback
489
+ */
490
+ setShowWindowCallback: function(listType, showWindowCallback) {
491
+ this.showWindowCallback[listType] = showWindowCallback;
492
+ return this;
493
+ },
494
+
495
+ /**
496
+ * Attach callback function triggered before submitting form
497
+ *
498
+ * @param beforeSubmitCallback
499
+ */
500
+ setBeforeSubmitCallback: function(listType, beforeSubmitCallback) {
501
+ this.beforeSubmitCallback[listType] = beforeSubmitCallback;
502
+ return this;
503
+ },
504
+
505
+ /**
506
+ * Clean object data
507
+ *
508
+ * @param method can be 'all' or 'current'
509
+ */
510
+ clean: function(method) {
511
+ var listInfo = null;
512
+ var listTypes = null;
513
+ var removeConfirmed = function (listTypes) {
514
+ this.blockConfirmed.childElements().each(function(elm) {
515
+ for (var i = 0, len = listTypes.length; i < len; i++) {
516
+ var pattern = this.blockConfirmed.id + '[' + listTypes[i] + ']';
517
+ if (elm.id.indexOf(pattern) == 0) {
518
+ elm.remove();
519
+ break;
520
+ }
521
+ }
522
+ }.bind(this));
523
+ }.bind(this);
524
+
525
+ switch (method) {
526
+ case 'current':
527
+ listInfo = this.listTypes[this.current.listType];
528
+ listTypes = [this.current.listType];
529
+ if (listInfo.complexTypes) {
530
+ listTypes = listTypes.concat(listInfo.complexTypes);
531
+ }
532
+ removeConfirmed(listTypes);
533
+ break;
534
+ case 'window':
535
+ this.blockFormFields.update();
536
+ this.blockMsg.hide();
537
+ this.blockMsgError.update();
538
+ this.blockCancelBtn.show();
539
+ break;
540
+ default:
541
+ // search in list types for its cleaning
542
+ if (this.listTypes[method]) {
543
+ listInfo = this.listTypes[method];
544
+ listTypes = [method];
545
+ if (listInfo.complexTypes) {
546
+ listTypes = listTypes.concat(listInfo.complexTypes);
547
+ }
548
+ removeConfirmed(listTypes);
549
+ // clean all
550
+ } else if (!method) {
551
+ this.current = $H({});
552
+ this.blockConfirmed.update();
553
+ this.blockFormFields.update();
554
+ this.blockMsg.hide();
555
+ this.blockMsgError.update();
556
+ this.blockCancelBtn.show();
557
+ }
558
+ break;
559
+ }
560
+ this._getIFrameContent().body.innerHTML = '';
561
+ this.blockIFrame.contentWindow[this.iFrameJSVarname] = {};
562
+ this.blockFormAdd.update();
563
+ this.blockFormConfirmed.update();
564
+ this.blockForm.action = '';
565
+
566
+ return this;
567
+ },
568
+
569
+ /**
570
+ * Process fields data: save, restore, move saved to form and back
571
+ *
572
+ * @param method can be 'item_confirm', 'item_restore', 'current_confirmed_to_form', 'form_confirmed_to_confirmed'
573
+ */
574
+ _processFieldsData: function(method) {
575
+
576
+ /**
577
+ * Internal function for rename fields names of some list type
578
+ * if listType is not specified, then it won't be added as prefix to all names
579
+ *
580
+ * @param method can be 'current_confirmed_to_form', 'form_confirmed_to_confirmed'
581
+ * @param blockItem
582
+ */
583
+ var _renameFields = function(method, blockItem, listType) {
584
+ var pattern = null;
585
+ var patternFlat = null;
586
+ var replacement = null;
587
+ var replacementFlat = null
588
+ var scopeArr = blockItem.id.match(/.*\[\w+\]\[(\w+)\]$/);
589
+ var itemId = scopeArr[1];
590
+ if (method == 'current_confirmed_to_form') {
591
+ pattern = RegExp('(\\w+)(\\[?)');
592
+ patternFlat = RegExp('(\\w+)');
593
+ replacement = 'item[' + itemId + '][$1]$2';
594
+ replacementFlat = 'item_' + itemId + '_$1';
595
+ if (listType) {
596
+ replacement = 'list[' + listType + '][item][' + itemId + '][$1]$2';
597
+ replacementFlat = 'list_' + listType + '_' + replacementFlat;
598
+ }
599
+ } else if (method == 'form_confirmed_to_confirmed') {
600
+ var stPattern = 'item\\[' + itemId + '\\]\\[(\\w+)\\](.*)';
601
+ var stPatternFlat = 'item_' + itemId + '_(\\w+)';
602
+ if (listType) {
603
+ stPattern = 'list\\[' + listType + '\\]\\[item\\]\\[' + itemId + '\\]\\[(\\w+)\\](.*)';
604
+ stPatternFlat = 'list_' + listType + '_' + stPatternFlat;
605
+ }
606
+ pattern = new RegExp(stPattern);
607
+ patternFlat = new RegExp(stPatternFlat);
608
+ replacement = '$1$2';
609
+ replacementFlat = '$1';
610
+ } else {
611
+ return false;
612
+ }
613
+ var rename = function (elms) {
614
+ for (var i = 0; i < elms.length; i++) {
615
+ if (elms[i].name && elms[i].type == 'file') {
616
+ elms[i].name = elms[i].name.replace(patternFlat, replacementFlat);
617
+ } else if (elms[i].name) {
618
+ elms[i].name = elms[i].name.replace(pattern, replacement);
619
+ }
620
+ }
621
+ };
622
+ rename(blockItem.getElementsByTagName('input'));
623
+ rename(blockItem.getElementsByTagName('select'));
624
+ rename(blockItem.getElementsByTagName('textarea'));
625
+ }.bind(this);
626
+
627
+ switch (method) {
628
+ case 'item_confirm':
629
+ if (!$(this.confirmedCurrentId)) {
630
+ this.blockConfirmed.insert(new Element('div', {id: this.confirmedCurrentId}));
631
+ } else {
632
+ $(this.confirmedCurrentId).update();
633
+ }
634
+ this.blockFormFields.childElements().each(function(elm) {
635
+ $(this.confirmedCurrentId).insert(elm);
636
+ }.bind(this));
637
+ break;
638
+ case 'item_restore':
639
+ this.blockFormFields.update();
640
+
641
+ // clone confirmed to form
642
+ var mageData = null;
643
+ $(this.confirmedCurrentId).childElements().each(function(elm) {
644
+ var cloned = elm.cloneNode(true);
645
+ if (elm.mageData) {
646
+ cloned.mageData = elm.mageData;
647
+ mageData = elm.mageData;
648
+ }
649
+ this.blockFormFields.insert(cloned);
650
+ }.bind(this));
651
+
652
+ // get confirmed values
653
+ var fieldsValue = {};
654
+ var getConfirmedValues = function (elms) {
655
+ for (var i = 0; i < elms.length; i++) {
656
+ if (elms[i].name) {
657
+ if ('undefined' == typeof fieldsValue[elms[i].name] ) {
658
+ fieldsValue[elms[i].name] = {};
659
+ }
660
+ if (elms[i].type == 'checkbox') {
661
+ fieldsValue[elms[i].name][elms[i].value] = elms[i].checked;
662
+ } else if (elms[i].type == 'radio') {
663
+ if (elms[i].checked) {
664
+ fieldsValue[elms[i].name] = elms[i].value;
665
+ }
666
+ } else {
667
+ fieldsValue[elms[i].name] = Form.Element.getValue(elms[i]);
668
+ }
669
+ }
670
+ }
671
+ }.bind(this);
672
+ getConfirmedValues($(this.confirmedCurrentId).getElementsByTagName('input'));
673
+ getConfirmedValues($(this.confirmedCurrentId).getElementsByTagName('select'));
674
+ getConfirmedValues($(this.confirmedCurrentId).getElementsByTagName('textarea'));
675
+
676
+ // restore confirmed values
677
+ var restoreConfirmedValues = function (elms) {
678
+ for (var i = 0; i < elms.length; i++) {
679
+ if ('undefined' != typeof fieldsValue[elms[i].name]) {
680
+ if (elms[i].type != 'file') {
681
+ if (elms[i].type == 'checkbox') {
682
+ elms[i].checked = fieldsValue[elms[i].name][elms[i].value];
683
+ } else if (elms[i].type == 'radio') {
684
+ if (elms[i].value == fieldsValue[elms[i].name]) {
685
+ elms[i].checked = true;
686
+ }
687
+ } else {
688
+ elms[i].setValue(fieldsValue[elms[i].name]);
689
+ }
690
+ }
691
+ }
692
+ }
693
+ }.bind(this);
694
+ restoreConfirmedValues(this.blockFormFields.getElementsByTagName('input'));
695
+ restoreConfirmedValues(this.blockFormFields.getElementsByTagName('select'));
696
+ restoreConfirmedValues(this.blockFormFields.getElementsByTagName('textarea'));
697
+
698
+ // Execute scripts
699
+ if (mageData && mageData.scripts) {
700
+ this.restorePhase = true;
701
+ try {
702
+ mageData.scripts.map(function(script) {
703
+ return eval(script);
704
+ });
705
+ } catch (e) {}
706
+ this.restorePhase = false;
707
+ }
708
+ break;
709
+ case 'current_confirmed_to_form':
710
+ var allowedListTypes = {};
711
+ allowedListTypes[this.current.listType] = true;
712
+ var listInfo = this.listTypes[this.current.listType];
713
+ if (listInfo.complexTypes) {
714
+ for (var i = 0, len = listInfo.complexTypes.length; i < len; i++) {
715
+ allowedListTypes[listInfo.complexTypes[i]] = true;
716
+ }
717
+ }
718
+
719
+ this.blockFormConfirmed.update();
720
+ this.blockConfirmed.childElements().each(function(blockItem) {
721
+ var scopeArr = blockItem.id.match(/.*\[(\w+)\]\[(\w+)\]$/);
722
+ var listType = scopeArr[1];
723
+ var itemId = scopeArr[2];
724
+ if (allowedListTypes[listType] && (!this.itemsFilter[listType]
725
+ || this.itemsFilter[listType].indexOf(itemId) != -1)) {
726
+ _renameFields(method, blockItem, listInfo.complexTypes ? listType : null);
727
+ this.blockFormConfirmed.insert(blockItem);
728
+ }
729
+ }.bind(this));
730
+ break;
731
+ case 'form_confirmed_to_confirmed':
732
+ var listInfo = this.listTypes[this.current.listType];
733
+ this.blockFormConfirmed.childElements().each(function(blockItem) {
734
+ var scopeArr = blockItem.id.match(/.*\[(\w+)\]\[(\w+)\]$/);
735
+ var listType = scopeArr[1];
736
+ _renameFields(method, blockItem, listInfo.complexTypes ? listType : null);
737
+ this.blockConfirmed.insert(blockItem);
738
+ }.bind(this));
739
+ break;
740
+ }
741
+ },
742
+
743
+ /**
744
+ * Check if qty selected correctly
745
+ *
746
+ * @param object element
747
+ * @param object event
748
+ */
749
+ changeOptionQty: function(element, event)
750
+ {
751
+ var checkQty = true;
752
+ if ('undefined' != typeof event) {
753
+ if (event.keyCode == 8 || event.keyCode == 46) {
754
+ checkQty = false;
755
+ }
756
+ }
757
+ if (checkQty && (Number(element.value) <= 0 || isNaN(Number(element.value)))) {
758
+ element.value = 1;
759
+ }
760
+ }
761
+ };
762
+
763
+ Event.observe(window, 'load', function() {
764
+ productConfigure = new ProductConfigure();
765
+ });
js/mage/adminhtml/rules.js ADDED
@@ -0,0 +1,383 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ var VarienRulesForm = new Class.create();
27
+ VarienRulesForm.prototype = {
28
+ initialize : function(parent, newChildUrl){
29
+ this.parent = $(parent);
30
+ this.newChildUrl = newChildUrl;
31
+ this.shownElement = null;
32
+ this.updateElement = null;
33
+ this.chooserSelectedItems = $H({});
34
+ this.readOnly = false;
35
+
36
+ var elems = this.parent.getElementsByClassName('rule-param');
37
+ for (var i=0; i<elems.length; i++) {
38
+ this.initParam(elems[i]);
39
+ }
40
+ },
41
+
42
+ setReadonly: function (readonly){
43
+ this.readOnly = readonly;
44
+ var elems = this.parent.getElementsByClassName('rule-param-remove');
45
+ for (var i=0; i<elems.length; i++) {
46
+ var element = elems[i];
47
+ if (this.readOnly) {
48
+ element.hide();
49
+ } else {
50
+ element.show();
51
+ }
52
+ }
53
+
54
+ var elems = this.parent.getElementsByClassName('rule-param-new-child');
55
+ for (var i=0; i<elems.length; i++) {
56
+ var element = elems[i];
57
+ if (this.readOnly) {
58
+ element.hide();
59
+ } else {
60
+ element.show();
61
+ }
62
+ }
63
+
64
+ var elems = this.parent.getElementsByClassName('rule-param');
65
+ for (var i=0; i<elems.length; i++) {
66
+ var container = elems[i];
67
+ var label = Element.down(container, '.label');
68
+ if (label) {
69
+ if (this.readOnly) {
70
+ label.addClassName('label-disabled');
71
+ } else {
72
+ label.removeClassName('label-disabled');
73
+ }
74
+ }
75
+ }
76
+ },
77
+
78
+ initParam: function (container) {
79
+ container.rulesObject = this;
80
+ var label = Element.down(container, '.label');
81
+ if (label) {
82
+ Event.observe(label, 'click', this.showParamInputField.bind(this, container));
83
+ }
84
+
85
+ var elem = Element.down(container, '.element');
86
+ if (elem) {
87
+ var trig = elem.down('.rule-chooser-trigger');
88
+ if (trig) {
89
+ Event.observe(trig, 'click', this.toggleChooser.bind(this, container));
90
+ }
91
+
92
+ var apply = elem.down('.rule-param-apply');
93
+ if (apply) {
94
+ Event.observe(apply, 'click', this.hideParamInputField.bind(this, container));
95
+ } else {
96
+ elem = elem.down('.element-value-changer');
97
+ elem.container = container;
98
+ if (!elem.multiple) {
99
+ Event.observe(elem, 'change', this.hideParamInputField.bind(this, container));
100
+ }
101
+ Event.observe(elem, 'blur', this.hideParamInputField.bind(this, container));
102
+ }
103
+ }
104
+
105
+ var remove = Element.down(container, '.rule-param-remove');
106
+ if (remove) {
107
+ Event.observe(remove, 'click', this.removeRuleEntry.bind(this, container));
108
+ }
109
+ },
110
+
111
+ showChooserElement: function (chooser) {
112
+ this.chooserSelectedItems = $H({});
113
+ if (chooser.hasClassName('no-split')) {
114
+ this.chooserSelectedItems.set(this.updateElement.value, 1);
115
+ } else {
116
+ var values = this.updateElement.value.split(','), s = '';
117
+ for (i=0; i<values.length; i++) {
118
+ s = values[i].strip();
119
+ if (s!='') {
120
+ this.chooserSelectedItems.set(s,1);
121
+ }
122
+ }
123
+ }
124
+ new Ajax.Request(chooser.getAttribute('url'), {
125
+ evalScripts: true,
126
+ parameters: {'form_key': FORM_KEY, 'selected[]':this.chooserSelectedItems.keys() },
127
+ onSuccess: function(transport) {
128
+ if (this._processSuccess(transport)) {
129
+ $(chooser).update(transport.responseText);
130
+ this.showChooserLoaded(chooser, transport);
131
+ }
132
+ }.bind(this),
133
+ onFailure: this._processFailure.bind(this)
134
+ });
135
+ },
136
+
137
+ showChooserLoaded: function(chooser, transport) {
138
+ chooser.style.display = 'block';
139
+ },
140
+
141
+ showChooser: function (container, event) {
142
+ var chooser = container.up('li');
143
+ if (!chooser) {
144
+ return;
145
+ }
146
+ chooser = chooser.down('.rule-chooser');
147
+ if (!chooser) {
148
+ return;
149
+ }
150
+ this.showChooserElement(chooser);
151
+ },
152
+
153
+ hideChooser: function (container, event) {
154
+ var chooser = container.up('li');
155
+ if (!chooser) {
156
+ return;
157
+ }
158
+ chooser = chooser.down('.rule-chooser');
159
+ if (!chooser) {
160
+ return;
161
+ }
162
+ chooser.style.display = 'none';
163
+ },
164
+
165
+ toggleChooser: function (container, event) {
166
+ if (this.readOnly) {
167
+ return false;
168
+ }
169
+
170
+ var chooser = container.up('li').down('.rule-chooser');
171
+ if (!chooser) {
172
+ return;
173
+ }
174
+ if (chooser.style.display=='block') {
175
+ chooser.style.display = 'none';
176
+ this.cleanChooser(container, event);
177
+ } else {
178
+ this.showChooserElement(chooser);
179
+ }
180
+ },
181
+
182
+ cleanChooser: function (container, event) {
183
+ var chooser = container.up('li').down('.rule-chooser');
184
+ if (!chooser) {
185
+ return;
186
+ }
187
+ chooser.innerHTML = '';
188
+ },
189
+
190
+ showParamInputField: function (container, event) {
191
+ if (this.readOnly) {
192
+ return false;
193
+ }
194
+
195
+ if (this.shownElement) {
196
+ this.hideParamInputField(this.shownElement, event);
197
+ }
198
+
199
+ Element.addClassName(container, 'rule-param-edit');
200
+ var elemContainer = Element.down(container, '.element');
201
+
202
+ var elem = Element.down(elemContainer, 'input.input-text');
203
+ if (elem) {
204
+ elem.focus();
205
+ if (elem && elem.id && elem.id.match(/__value$/)) {
206
+ this.updateElement = elem;
207
+ //this.showChooser(container, event);
208
+ }
209
+
210
+ }
211
+
212
+ var elem = Element.down(elemContainer, '.element-value-changer');
213
+ if (elem) {
214
+ elem.focus();
215
+ // trying to emulate enter to open dropdown
216
+ // if (document.createEventObject) {
217
+ // var event = document.createEventObject();
218
+ // event.altKey = true;
219
+ // event.keyCode = 40;
220
+ // elem.fireEvent("onkeydown", evt);
221
+ // } else {
222
+ // var event = document.createEvent("Events");
223
+ // event.altKey = true;
224
+ // event.keyCode = 40;
225
+ // elem.dispatchEvent(event);
226
+ // }
227
+ }
228
+
229
+ this.shownElement = container;
230
+ },
231
+
232
+ hideParamInputField: function (container, event) {
233
+ Element.removeClassName(container, 'rule-param-edit');
234
+ var label = Element.down(container, '.label'), elem;
235
+
236
+ if (!container.hasClassName('rule-param-new-child')) {
237
+ elem = Element.down(container, '.element-value-changer');
238
+ if (elem && elem.options) {
239
+ var selectedOptions = [];
240
+ for (i=0; i<elem.options.length; i++) {
241
+ if (elem.options[i].selected) {
242
+ selectedOptions.push(elem.options[i].text);
243
+ }
244
+ }
245
+
246
+ var str = selectedOptions.join(', ');
247
+ label.innerHTML = str!='' ? str : '...';
248
+ // if (elem && elem.selectedIndex>=0) {
249
+ // var str = elem.options[elem.selectedIndex].text;
250
+ // label.innerHTML = str!='' ? str : '...';
251
+ // }
252
+ }
253
+
254
+ elem = Element.down(container, 'input.input-text');
255
+ if (elem) {
256
+ var str = elem.value.replace(/(^\s+|\s+$)/g, '');
257
+ elem.value = str;
258
+ if (str=='') {
259
+ str = '...';
260
+ } else if (str.length>30) {
261
+ str = str.substr(0, 30)+'...';
262
+ }
263
+ label.innerHTML = str.escapeHTML();
264
+ }
265
+ } else {
266
+ elem = Element.down(container, '.element-value-changer');
267
+ if (elem.value) {
268
+ this.addRuleNewChild(elem);
269
+ }
270
+ elem.value = '';
271
+ }
272
+
273
+ if (elem && elem.id && elem.id.match(/__value$/)) {
274
+ this.hideChooser(container, event);
275
+ this.updateElement = null;
276
+ }
277
+
278
+ this.shownElement = null;
279
+ },
280
+
281
+ addRuleNewChild: function (elem) {
282
+ var parent_id = elem.id.replace(/^.*__(.*)__.*$/, '$1');
283
+ var children_ul = $(elem.id.replace(/__/g, ':').replace(/[^:]*$/, 'children').replace(/:/g, '__'));
284
+ var max_id = 0, i;
285
+ var children_inputs = Selector.findChildElements(children_ul, $A(['input.hidden']));
286
+ if (children_inputs.length) {
287
+ children_inputs.each(function(el){
288
+ if (el.id.match(/__type$/)) {
289
+ i = 1 * el.id.replace(/^.*__.*?([0-9]+)__.*$/, '$1');
290
+ max_id = i > max_id ? i : max_id;
291
+ }
292
+ });
293
+ }
294
+ var new_id = parent_id + '--' + (max_id + 1);
295
+ var new_type = elem.value;
296
+ var new_elem = document.createElement('LI');
297
+ new_elem.className = 'rule-param-wait';
298
+ new_elem.innerHTML = Translator.translate('Please wait, loading...');
299
+ children_ul.insertBefore(new_elem, $(elem).up('li'));
300
+
301
+ new Ajax.Request(this.newChildUrl, {
302
+ evalScripts: true,
303
+ parameters: {form_key: FORM_KEY, type:new_type.replace('/','-'), id:new_id },
304
+ onComplete: this.onAddNewChildComplete.bind(this, new_elem),
305
+ onSuccess: function(transport) {
306
+ if(this._processSuccess(transport)) {
307
+ $(new_elem).update(transport.responseText);
308
+ }
309
+ }.bind(this),
310
+ onFailure: this._processFailure.bind(this)
311
+ });
312
+ },
313
+
314
+ _processSuccess : function(transport) {
315
+ if (transport.responseText.isJSON()) {
316
+ var response = transport.responseText.evalJSON()
317
+ if (response.error) {
318
+ alert(response.message);
319
+ }
320
+ if(response.ajaxExpired && response.ajaxRedirect) {
321
+ setLocation(response.ajaxRedirect);
322
+ }
323
+ return false;
324
+ }
325
+ return true;
326
+ },
327
+
328
+ _processFailure : function(transport) {
329
+ location.href = BASE_URL;
330
+ },
331
+
332
+ onAddNewChildComplete: function (new_elem) {
333
+ if (this.readOnly) {
334
+ return false;
335
+ }
336
+
337
+ $(new_elem).removeClassName('rule-param-wait');
338
+ var elems = new_elem.getElementsByClassName('rule-param');
339
+ for (var i=0; i<elems.length; i++) {
340
+ this.initParam(elems[i]);
341
+ }
342
+ },
343
+
344
+ removeRuleEntry: function (container, event) {
345
+ var li = Element.up(container, 'li');
346
+ li.parentNode.removeChild(li);
347
+ },
348
+
349
+ chooserGridInit: function (grid) {
350
+ //grid.reloadParams = {'selected[]':this.chooserSelectedItems.keys()};
351
+ },
352
+
353
+ chooserGridRowInit: function (grid, row) {
354
+ if (!grid.reloadParams) {
355
+ grid.reloadParams = {'selected[]':this.chooserSelectedItems.keys()};
356
+ }
357
+ },
358
+
359
+ chooserGridRowClick: function (grid, event) {
360
+ var trElement = Event.findElement(event, 'tr');
361
+ var isInput = Event.element(event).tagName == 'INPUT';
362
+ if (trElement) {
363
+ var checkbox = Element.select(trElement, 'input');
364
+ if (checkbox[0]) {
365
+ var checked = isInput ? checkbox[0].checked : !checkbox[0].checked;
366
+ grid.setCheckboxChecked(checkbox[0], checked);
367
+
368
+ }
369
+ }
370
+ },
371
+
372
+ chooserGridCheckboxCheck: function (grid, element, checked) {
373
+ if (checked) {
374
+ if (!element.up('th')) {
375
+ this.chooserSelectedItems.set(element.value,1);
376
+ }
377
+ } else {
378
+ this.chooserSelectedItems.unset(element.value);
379
+ }
380
+ grid.reloadParams = {'selected[]':this.chooserSelectedItems.keys()};
381
+ this.updateElement.value = this.chooserSelectedItems.keys().join(', ');
382
+ }
383
+ }
js/mage/adminhtml/sales.js ADDED
@@ -0,0 +1,1055 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ var AdminOrder = new Class.create();
26
+ AdminOrder.prototype = {
27
+ initialize : function(data){
28
+ if(!data) data = {};
29
+ this.loadBaseUrl = false;
30
+ this.customerId = data.customer_id ? data.customer_id : false;
31
+ this.storeId = data.store_id ? data.store_id : false;
32
+ this.currencyId = false;
33
+ this.currencySymbol = data.currency_symbol ? data.currency_symbol : '';
34
+ this.addresses = data.addresses ? data.addresses : $H({});
35
+ this.shippingAsBilling = data.shippingAsBilling ? data.shippingAsBilling : false;
36
+ this.gridProducts = $H({});
37
+ this.gridProductsGift = $H({});
38
+ this.billingAddressContainer = '';
39
+ this.shippingAddressContainer= '';
40
+ this.isShippingMethodReseted = data.shipping_method_reseted ? data.shipping_method_reseted : false;
41
+ this.overlayData = $H({});
42
+ this.giftMessageDataChanged = false;
43
+ this.productConfigureAddFields = {};
44
+ this.productPriceBase = {};
45
+ },
46
+
47
+ setLoadBaseUrl : function(url){
48
+ this.loadBaseUrl = url;
49
+ },
50
+
51
+ setAddresses : function(addresses){
52
+ this.addresses = addresses;
53
+ },
54
+
55
+ setCustomerId : function(id){
56
+ this.customerId = id;
57
+ this.loadArea('header', true);
58
+ $(this.getAreaId('header')).callback = 'setCustomerAfter';
59
+ $('back_order_top_button').hide();
60
+ $('reset_order_top_button').show();
61
+ },
62
+
63
+ setCustomerAfter : function () {
64
+ this.customerSelectorHide();
65
+ if (this.storeId) {
66
+ $(this.getAreaId('data')).callback = 'dataShow';
67
+ this.loadArea(['data'], true);
68
+ }
69
+ else {
70
+ this.storeSelectorShow();
71
+ }
72
+ },
73
+
74
+ setStoreId : function(id){
75
+ this.storeId = id;
76
+ this.storeSelectorHide();
77
+ this.sidebarShow();
78
+ //this.loadArea(['header', 'sidebar','data'], true);
79
+ this.dataShow();
80
+ this.loadArea(['header', 'data'], true);
81
+ },
82
+
83
+ setCurrencyId : function(id){
84
+ this.currencyId = id;
85
+ //this.loadArea(['sidebar', 'data'], true);
86
+ this.loadArea(['data'], true);
87
+ },
88
+
89
+ setCurrencySymbol : function(symbol){
90
+ this.currencySymbol = symbol;
91
+ },
92
+
93
+ selectAddress : function(el, container){
94
+ id = el.value;
95
+ if (id.length == 0) {
96
+ id = '0';
97
+ }
98
+ if(this.addresses[id]){
99
+ this.fillAddressFields(container, this.addresses[id]);
100
+ }
101
+ else{
102
+ this.fillAddressFields(container, {});
103
+ }
104
+
105
+ var data = this.serializeData(container);
106
+ data[el.name] = id;
107
+ if(this.isShippingField(container) && !this.isShippingMethodReseted){
108
+ this.resetShippingMethod(data);
109
+ }
110
+ else{
111
+ this.saveData(data);
112
+ }
113
+ },
114
+
115
+ isShippingField : function(fieldId){
116
+ if(this.shippingAsBilling){
117
+ return fieldId.include('billing');
118
+ }
119
+ return fieldId.include('shipping');
120
+ },
121
+
122
+ isBillingField : function(fieldId){
123
+ return fieldId.include('billing');
124
+ },
125
+
126
+ bindAddressFields : function(container) {
127
+ var fields = $(container).select('input', 'select', 'textarea');
128
+ for(var i=0;i<fields.length;i++){
129
+ Event.observe(fields[i], 'change', this.changeAddressField.bind(this));
130
+ }
131
+ },
132
+
133
+ changeAddressField : function(event){
134
+ var field = Event.element(event);
135
+ var re = /[^\[]*\[([^\]]*)_address\]\[([^\]]*)\](\[(\d)\])?/;
136
+ var matchRes = field.name.match(re);
137
+ var type = matchRes[1];
138
+ var name = matchRes[2];
139
+ var data;
140
+
141
+ if(this.isBillingField(field.id)){
142
+ data = this.serializeData(this.billingAddressContainer)
143
+ }
144
+ else{
145
+ data = this.serializeData(this.shippingAddressContainer)
146
+ }
147
+ data = data.toObject();
148
+
149
+ if( (type == 'billing' && this.shippingAsBilling)
150
+ || (type == 'shipping' && !this.shippingAsBilling) ) {
151
+ data['reset_shipping'] = true;
152
+ }
153
+
154
+ data['order['+type+'_address][customer_address_id]'] = $('order-'+type+'_address_customer_address_id').value;
155
+
156
+ if (data['reset_shipping']) {
157
+ this.resetShippingMethod(data);
158
+ }
159
+ else {
160
+ this.saveData(data);
161
+ if (name == 'country_id' || name == 'customer_address_id') {
162
+ this.loadArea(['shipping_method', 'billing_method', 'totals', 'items'], true, data);
163
+ }
164
+ // added for reloading of default sender and default recipient for giftmessages
165
+ //this.loadArea(['giftmessage'], true, data);
166
+ }
167
+ },
168
+
169
+ fillAddressFields : function(container, data){
170
+ var regionIdElem = false;
171
+ var regionIdElemValue = false;
172
+
173
+ var fields = $(container).select('input', 'select', 'textarea');
174
+ var re = /[^\[]*\[[^\]]*\]\[([^\]]*)\](\[(\d)\])?/;
175
+ for(var i=0;i<fields.length;i++){
176
+ // skip input type file @Security error code: 1000
177
+ if (fields[i].tagName.toLowerCase() == 'input' && fields[i].type.toLowerCase() == 'file') {
178
+ continue;
179
+ }
180
+ var matchRes = fields[i].name.match(re);
181
+ if (matchRes === null) {
182
+ continue;
183
+ }
184
+ var name = matchRes[1];
185
+ var index = matchRes[3];
186
+
187
+ if (index){
188
+ // multiply line
189
+ if (data[name]){
190
+ var values = data[name].split("\n");
191
+ fields[i].value = values[index] ? values[index] : '';
192
+ } else {
193
+ fields[i].value = '';
194
+ }
195
+ } else if (fields[i].tagName.toLowerCase() == 'select' && fields[i].multiple) {
196
+ // multiselect
197
+ if (data[name]) {
198
+ values = [''];
199
+ if (Object.isString(data[name])) {
200
+ values = data[name].split(',');
201
+ } else if (Object.isArray(data[name])) {
202
+ values = data[name];
203
+ }
204
+ fields[i].setValue(values);
205
+ }
206
+ } else {
207
+ fields[i].setValue(data[name] ? data[name] : '');
208
+ }
209
+
210
+ if (fields[i].changeUpdater) fields[i].changeUpdater();
211
+ if (name == 'region' && data['region_id'] && !data['region']){
212
+ fields[i].value = data['region_id'];
213
+ }
214
+ }
215
+ },
216
+
217
+ disableShippingAddress : function(flag){
218
+ this.shippingAsBilling = flag;
219
+ if($('order-shipping_address_customer_address_id')) {
220
+ $('order-shipping_address_customer_address_id').disabled=flag;
221
+ }
222
+ if($(this.shippingAddressContainer)){
223
+ var dataFields = $(this.shippingAddressContainer).select('input', 'select', 'textarea');
224
+ for(var i=0;i<dataFields.length;i++) dataFields[i].disabled = flag;
225
+ }
226
+ },
227
+
228
+ setShippingAsBilling : function(flag){
229
+ this.disableShippingAddress(flag);
230
+ if(flag){
231
+ var data = this.serializeData(this.billingAddressContainer);
232
+ }
233
+ else{
234
+ var data = this.serializeData(this.shippingAddressContainer);
235
+ }
236
+ data = data.toObject();
237
+ data['shipping_as_billing'] = flag ? 1 : 0;
238
+ data['reset_shipping'] = 1;
239
+ this.loadArea(['shipping_method', 'billing_method', 'shipping_address', 'totals', 'giftmessage'], true, data);
240
+ },
241
+
242
+ resetShippingMethod : function(data){
243
+ data['reset_shipping'] = 1;
244
+ this.isShippingMethodReseted = true;
245
+ this.loadArea(['shipping_method', 'billing_method', 'shipping_address', 'totals', 'giftmessage', 'items'], true, data);
246
+ },
247
+
248
+ loadShippingRates : function(){
249
+ this.isShippingMethodReseted = false;
250
+ this.loadArea(['shipping_method', 'totals'], true, {collect_shipping_rates: 1});
251
+ },
252
+
253
+ setShippingMethod : function(method){
254
+ var data = {};
255
+ data['order[shipping_method]'] = method;
256
+ this.loadArea(['shipping_method', 'totals', 'billing_method'], true, data);
257
+ },
258
+
259
+ switchPaymentMethod : function(method){
260
+ this.setPaymentMethod(method);
261
+ var data = {};
262
+ data['order[payment_method]'] = method;
263
+ this.loadArea(['card_validation'], true, data);
264
+ },
265
+
266
+ setPaymentMethod : function(method){
267
+ if (this.paymentMethod && $('payment_form_'+this.paymentMethod)) {
268
+ var form = 'payment_form_'+this.paymentMethod;
269
+ [form + '_before', form, form + '_after'].each(function(el) {
270
+ var block = $(el);
271
+ if (block) {
272
+ block.hide();
273
+ block.select('input', 'select', 'textarea').each(function(field) {
274
+ field.disabled = true;
275
+ });
276
+ }
277
+ });
278
+ }
279
+
280
+ if(!this.paymentMethod || method){
281
+ $('order-billing_method_form').select('input', 'select', 'textarea').each(function(elem){
282
+ if(elem.type != 'radio') elem.disabled = true;
283
+ })
284
+ }
285
+
286
+ if ($('payment_form_'+method)){
287
+ this.paymentMethod = method;
288
+ var form = 'payment_form_'+method;
289
+ [form + '_before', form, form + '_after'].each(function(el) {
290
+ var block = $(el);
291
+ if (block) {
292
+ block.show();
293
+ block.select('input', 'select', 'textarea').each(function(field) {
294
+ field.disabled = false;
295
+ if (!el.include('_before') && !el.include('_after') && !field.bindChange) {
296
+ field.bindChange = true;
297
+ field.paymentContainer = form; //@deprecated after 1.4.0.0-rc1
298
+ field.method = method;
299
+ field.observe('change', this.changePaymentData.bind(this))
300
+ }
301
+ },this);
302
+ }
303
+ },this);
304
+ }
305
+ },
306
+
307
+ changePaymentData : function(event){
308
+ var elem = Event.element(event);
309
+ if(elem && elem.method){
310
+ var data = this.getPaymentData(elem.method);
311
+ if (data) {
312
+ this.loadArea(['card_validation'], true, data);
313
+ } else {
314
+ return;
315
+ }
316
+ }
317
+ },
318
+
319
+ getPaymentData : function(currentMethod){
320
+ if (typeof(currentMethod) == 'undefined') {
321
+ if (this.paymentMethod) {
322
+ currentMethod = this.paymentMethod;
323
+ } else {
324
+ return false;
325
+ }
326
+ }
327
+ var data = {};
328
+ var fields = $('payment_form_' + currentMethod).select('input', 'select');
329
+ for(var i=0;i<fields.length;i++){
330
+ data[fields[i].name] = fields[i].getValue();
331
+ }
332
+ if ((typeof data['payment[cc_type]']) != 'undefined' && (!data['payment[cc_type]'] || !data['payment[cc_number]'])) {
333
+ return false;
334
+ }
335
+ return data;
336
+ },
337
+
338
+ applyCoupon : function(code){
339
+ this.loadArea(['items', 'shipping_method', 'totals', 'billing_method'], true, {'order[coupon][code]':code, reset_shipping: true});
340
+ },
341
+
342
+ addProduct : function(id){
343
+ this.loadArea(['items', 'shipping_method', 'totals', 'billing_method'], true, {add_product:id, reset_shipping: true});
344
+ },
345
+
346
+ removeQuoteItem : function(id){
347
+ this.loadArea(['items', 'shipping_method', 'totals', 'billing_method'], true,
348
+ {remove_item:id, from:'quote',reset_shipping: true});
349
+ },
350
+
351
+ moveQuoteItem : function(id, to){
352
+ this.loadArea(['sidebar_'+to, 'items', 'shipping_method', 'totals', 'billing_method'], this.getAreaId('items'),
353
+ {move_item:id, to:to, reset_shipping: true});
354
+ },
355
+
356
+ productGridShow : function(buttonElement){
357
+ this.productGridShowButton = buttonElement;
358
+ Element.hide(buttonElement);
359
+ this.showArea('search');
360
+ },
361
+
362
+ productGridRowInit : function(grid, row){
363
+ var checkbox = $(row).select('.checkbox')[0];
364
+ var inputs = $(row).select('.input-text');
365
+ if (checkbox && inputs.length > 0) {
366
+ checkbox.inputElements = inputs;
367
+ for (var i = 0; i < inputs.length; i++) {
368
+ var input = inputs[i];
369
+ input.checkboxElement = checkbox;
370
+
371
+ var product = this.gridProducts.get(checkbox.value);
372
+ if (product) {
373
+ var defaultValue = product[input.name];
374
+ if (defaultValue) {
375
+ if (input.name == 'giftmessage') {
376
+ input.checked = true;
377
+ } else {
378
+ input.value = defaultValue;
379
+ }
380
+ }
381
+ }
382
+
383
+ input.disabled = !checkbox.checked || input.hasClassName('input-inactive');
384
+
385
+ Event.observe(input,'keyup', this.productGridRowInputChange.bind(this));
386
+ Event.observe(input,'change',this.productGridRowInputChange.bind(this));
387
+ }
388
+ }
389
+ },
390
+
391
+ productGridRowInputChange : function(event){
392
+ var element = Event.element(event);
393
+ if (element && element.checkboxElement && element.checkboxElement.checked){
394
+ if (element.name!='giftmessage' || element.checked) {
395
+ this.gridProducts.get(element.checkboxElement.value)[element.name] = element.value;
396
+ } else if (element.name=='giftmessage' && this.gridProducts.get(element.checkboxElement.value)[element.name]) {
397
+ delete(this.gridProducts.get(element.checkboxElement.value)[element.name]);
398
+ }
399
+ }
400
+ },
401
+
402
+ productGridRowClick : function(grid, event){
403
+ var trElement = Event.findElement(event, 'tr');
404
+ var qtyElement = trElement.select('input[name="qty"]')[0];
405
+ var eventElement = Event.element(event);
406
+ var isInputCheckbox = eventElement.tagName == 'INPUT' && eventElement.type == 'checkbox';
407
+ var isInputQty = eventElement.tagName == 'INPUT' && eventElement.name == 'qty';
408
+ if (trElement && !isInputQty) {
409
+ var checkbox = Element.select(trElement, 'input[type="checkbox"]')[0];
410
+ var confLink = Element.select(trElement, 'a')[0];
411
+ var priceColl = Element.select(trElement, '.price')[0];
412
+ if (checkbox) {
413
+ // processing non composite product
414
+ if (confLink.readAttribute('disabled')) {
415
+ var checked = isInputCheckbox ? checkbox.checked : !checkbox.checked;
416
+ grid.setCheckboxChecked(checkbox, checked);
417
+ // processing composite product
418
+ } else if (isInputCheckbox && !checkbox.checked) {
419
+ grid.setCheckboxChecked(checkbox, false);
420
+ // processing composite product
421
+ } else if (!isInputCheckbox || (isInputCheckbox && checkbox.checked)) {
422
+ var listType = confLink.readAttribute('list_type');
423
+ var productId = confLink.readAttribute('product_id');
424
+ if (typeof this.productPriceBase[productId] == 'undefined') {
425
+ var priceBase = priceColl.innerHTML.match(/.*?([0-9\.,]+)/);
426
+ if (!priceBase) {
427
+ this.productPriceBase[productId] = 0;
428
+ } else {
429
+ this.productPriceBase[productId] = parseFloat(priceBase[1].replace(/,/g,''));
430
+ }
431
+ }
432
+ productConfigure.setConfirmCallback(listType, function() {
433
+ // sync qty of popup and qty of grid
434
+ var confirmedCurrentQty = productConfigure.getCurrentConfirmedQtyElement();
435
+ if (qtyElement && confirmedCurrentQty && !isNaN(confirmedCurrentQty.value)) {
436
+ qtyElement.value = confirmedCurrentQty.value;
437
+ }
438
+ // calc and set product price
439
+ var productPrice = parseFloat(this._calcProductPrice() + this.productPriceBase[productId]);
440
+ priceColl.innerHTML = this.currencySymbol + productPrice.toFixed(2);
441
+ // and set checkbox checked
442
+ grid.setCheckboxChecked(checkbox, true);
443
+ }.bind(this));
444
+ productConfigure.setCancelCallback(listType, function() {
445
+ if (!$(productConfigure.confirmedCurrentId) || !$(productConfigure.confirmedCurrentId).innerHTML) {
446
+ grid.setCheckboxChecked(checkbox, false);
447
+ }
448
+ });
449
+ productConfigure.setShowWindowCallback(listType, function() {
450
+ // sync qty of grid and qty of popup
451
+ var formCurrentQty = productConfigure.getCurrentFormQtyElement();
452
+ if (formCurrentQty && qtyElement && !isNaN(qtyElement.value)) {
453
+ formCurrentQty.value = qtyElement.value;
454
+ }
455
+ }.bind(this));
456
+ productConfigure.showItemConfiguration(listType, productId);
457
+ }
458
+ }
459
+ }
460
+ },
461
+
462
+ /**
463
+ * Calc product price through its options
464
+ */
465
+ _calcProductPrice: function () {
466
+ var productPrice = 0;
467
+ var getPriceFields = function (elms) {
468
+ var productPrice = 0;
469
+ var getPrice = function (elm) {
470
+ var optQty = 1;
471
+ if (elm.hasAttribute('qtyId')) {
472
+ if (!$(elm.getAttribute('qtyId')).value) {
473
+ return 0;
474
+ } else {
475
+ optQty = parseFloat($(elm.getAttribute('qtyId')).value);
476
+ }
477
+ }
478
+ if (elm.hasAttribute('price') && !elm.disabled) {
479
+ return parseFloat(elm.readAttribute('price')) * optQty;
480
+ }
481
+ return 0;
482
+ };
483
+ for(var i = 0; i < elms.length; i++) {
484
+ if (elms[i].type == 'select-one' || elms[i].type == 'select-multiple') {
485
+ for(var ii = 0; ii < elms[i].options.length; ii++) {
486
+ if (elms[i].options[ii].selected) {
487
+ productPrice += getPrice(elms[i].options[ii]);
488
+ }
489
+ }
490
+ }
491
+ else if (((elms[i].type == 'checkbox' || elms[i].type == 'radio') && elms[i].checked)
492
+ || ((elms[i].type == 'file' || elms[i].type == 'text' || elms[i].type == 'textarea' || elms[i].type == 'hidden')
493
+ && Form.Element.getValue(elms[i]))
494
+ ) {
495
+ productPrice += getPrice(elms[i]);
496
+ }
497
+ }
498
+ return productPrice;
499
+ }.bind(this);
500
+ productPrice += getPriceFields($(productConfigure.confirmedCurrentId).getElementsByTagName('input'));
501
+ productPrice += getPriceFields($(productConfigure.confirmedCurrentId).getElementsByTagName('select'));
502
+ productPrice += getPriceFields($(productConfigure.confirmedCurrentId).getElementsByTagName('textarea'));
503
+ return productPrice;
504
+ },
505
+
506
+ productGridCheckboxCheck : function(grid, element, checked){
507
+ if (checked) {
508
+ if(element.inputElements) {
509
+ this.gridProducts.set(element.value, {});
510
+ var product = this.gridProducts.get(element.value);
511
+ for (var i = 0; i < element.inputElements.length; i++) {
512
+ var input = element.inputElements[i];
513
+ if (!input.hasClassName('input-inactive')) {
514
+ input.disabled = false;
515
+ if (input.name == 'qty' && !input.value) {
516
+ input.value = 1;
517
+ }
518
+ }
519
+
520
+ if (input.checked || input.name != 'giftmessage') {
521
+ product[input.name] = input.value;
522
+ } else if (product[input.name]) {
523
+ delete(product[input.name]);
524
+ }
525
+ }
526
+ }
527
+ } else {
528
+ if(element.inputElements){
529
+ for(var i = 0; i < element.inputElements.length; i++) {
530
+ element.inputElements[i].disabled = true;
531
+ }
532
+ }
533
+ this.gridProducts.unset(element.value);
534
+ }
535
+ grid.reloadParams = {'products[]':this.gridProducts.keys()};
536
+ },
537
+
538
+ /**
539
+ * Submit configured products to quote
540
+ */
541
+ productGridAddSelected : function(){
542
+ if(this.productGridShowButton) Element.show(this.productGridShowButton);
543
+ var area = ['search', 'items', 'shipping_method', 'totals', 'giftmessage','billing_method'];
544
+ // prepare additional fields and filtered items of products
545
+ var fieldsPrepare = {};
546
+ var itemsFilter = [];
547
+ var products = this.gridProducts.toObject();
548
+ for (var productId in products) {
549
+ itemsFilter.push(productId);
550
+ var paramKey = 'item['+productId+']';
551
+ for (var productParamKey in products[productId]) {
552
+ paramKey += '['+productParamKey+']';
553
+ fieldsPrepare[paramKey] = products[productId][productParamKey];
554
+ }
555
+ }
556
+ this.productConfigureSubmit('product_to_add', area, fieldsPrepare, itemsFilter);
557
+ productConfigure.clean('quote_items');
558
+ this.hideArea('search');
559
+ this.gridProducts = $H({});
560
+ },
561
+
562
+ selectCustomer : function(grid, event){
563
+ var element = Event.findElement(event, 'tr');
564
+ if (element.title){
565
+ this.setCustomerId(element.title);
566
+ }
567
+ },
568
+
569
+ customerSelectorHide : function(){
570
+ this.hideArea('customer-selector');
571
+ },
572
+
573
+ customerSelectorShow : function(){
574
+ this.showArea('customer-selector');
575
+ },
576
+
577
+ storeSelectorHide : function(){
578
+ this.hideArea('store-selector');
579
+ },
580
+
581
+ storeSelectorShow : function(){
582
+ this.showArea('store-selector');
583
+ },
584
+
585
+ dataHide : function(){
586
+ this.hideArea('data');
587
+ },
588
+
589
+ dataShow : function(){
590
+ if ($('submit_order_top_button')) {
591
+ $('submit_order_top_button').show();
592
+ }
593
+ this.showArea('data');
594
+ },
595
+
596
+ sidebarApplyChanges : function(){
597
+ if($(this.getAreaId('sidebar'))){
598
+ var data = {};
599
+ var elems = $(this.getAreaId('sidebar')).select('input');
600
+ for(var i=0; i<elems.length; i++){
601
+ if(elems[i].getValue()){
602
+ data[elems[i].name] = elems[i].getValue();
603
+ }
604
+ }
605
+ data.reset_shipping = true;
606
+ this.loadArea(['sidebar', 'items', 'shipping_method', 'billing_method','totals', 'giftmessage'], true, data);
607
+ }
608
+ },
609
+
610
+ sidebarHide : function(){
611
+ if(this.storeId === false && $('page:left') && $('page:container')){
612
+ $('page:left').hide();
613
+ $('page:container').removeClassName('container');
614
+ $('page:container').addClassName('container-collapsed');
615
+ }
616
+ },
617
+
618
+ sidebarShow : function(){
619
+ if($('page:left') && $('page:container')){
620
+ $('page:left').show();
621
+ $('page:container').removeClassName('container-collapsed');
622
+ $('page:container').addClassName('container');
623
+ }
624
+ },
625
+
626
+ /**
627
+ * Show configuration of product and add handlers on submit form
628
+ *
629
+ * @param productId
630
+ */
631
+ sidebarConfigureProduct: function (listType, productId, itemId) {
632
+ // create additional fields
633
+ var params = {};
634
+ params.reset_shipping = true;
635
+ params.add_product = productId;
636
+ this.prepareParams(params);
637
+ for (var i in params) {
638
+ if (params[i] === null) {
639
+ unset(params[i]);
640
+ } else if (typeof(params[i]) == 'boolean') {
641
+ params[i] = params[i] ? 1 : 0;
642
+ }
643
+ }
644
+ var fields = [];
645
+ for (var name in params) {
646
+ fields.push(new Element('input', {type: 'hidden', name: name, value: params[name]}));
647
+ }
648
+ // add additional fields before triggered submit
649
+ productConfigure.setBeforeSubmitCallback(listType, function() {
650
+ productConfigure.addFields(fields);
651
+ }.bind(this));
652
+ // response handler
653
+ productConfigure.setOnLoadIFrameCallback(listType, function(response) {
654
+ if (!response.ok) {
655
+ return;
656
+ }
657
+ this.loadArea(['items', 'shipping_method', 'billing_method','totals', 'giftmessage'], true);
658
+ }.bind(this));
659
+ // show item configuration
660
+ itemId = itemId ? itemId : productId;
661
+ productConfigure.showItemConfiguration(listType, itemId);
662
+ return false;
663
+ },
664
+
665
+ removeSidebarItem : function(id, from){
666
+ this.loadArea(['sidebar_'+from], 'sidebar_data_'+from, {remove_item:id, from:from});
667
+ },
668
+
669
+ itemsUpdate : function(){
670
+ var area = ['sidebar', 'items', 'shipping_method', 'billing_method','totals', 'giftmessage'];
671
+ // prepare additional fields
672
+ var fieldsPrepare = {update_items: 1};
673
+ var info = $('order-items_grid').select('input', 'select', 'textarea');
674
+ for(var i=0; i<info.length; i++){
675
+ if(!info[i].disabled && (info[i].type != 'checkbox' || info[i].checked)) {
676
+ fieldsPrepare[info[i].name] = info[i].getValue();
677
+ }
678
+ }
679
+ fieldsPrepare = Object.extend(fieldsPrepare, this.productConfigureAddFields);
680
+ this.productConfigureSubmit('quote_items', area, fieldsPrepare);
681
+ this.orderItemChanged = false;
682
+ },
683
+
684
+ itemsOnchangeBind : function(){
685
+ var elems = $('order-items_grid').select('input', 'select', 'textarea');
686
+ for(var i=0; i<elems.length; i++){
687
+ if(!elems[i].bindOnchange){
688
+ elems[i].bindOnchange = true;
689
+ elems[i].observe('change', this.itemChange.bind(this))
690
+ }
691
+ }
692
+ },
693
+
694
+ itemChange : function(event){
695
+ this.giftmessageOnItemChange(event);
696
+ this.orderItemChanged = true;
697
+ },
698
+
699
+ /**
700
+ * Submit batch of configured products
701
+ *
702
+ * @param listType
703
+ * @param area
704
+ * @param fieldsPrepare
705
+ * @param itemsFilter
706
+ */
707
+ productConfigureSubmit : function(listType, area, fieldsPrepare, itemsFilter) {
708
+ // prepare loading areas and build url
709
+ area = this.prepareArea(area);
710
+ this.loadingAreas = area;
711
+ var url = this.loadBaseUrl + 'block/' + area + '?isAjax=true';
712
+
713
+ // prepare additional fields
714
+ fieldsPrepare = this.prepareParams(fieldsPrepare);
715
+ fieldsPrepare.reset_shipping = 1;
716
+ fieldsPrepare.json = 1;
717
+
718
+ // create fields
719
+ var fields = [];
720
+ for (var name in fieldsPrepare) {
721
+ fields.push(new Element('input', {type: 'hidden', name: name, value: fieldsPrepare[name]}));
722
+ }
723
+ productConfigure.addFields(fields);
724
+
725
+ // filter items
726
+ if (itemsFilter) {
727
+ productConfigure.addItemsFilter(listType, itemsFilter);
728
+ }
729
+
730
+ // prepare and do submit
731
+ productConfigure.addListType(listType, {urlSubmit: url});
732
+ productConfigure.setOnLoadIFrameCallback(listType, function(response){
733
+ this.loadAreaResponseHandler(response);
734
+ }.bind(this));
735
+ productConfigure.submit(listType);
736
+ // clean
737
+ this.productConfigureAddFields = {};
738
+ },
739
+
740
+ /**
741
+ * Show configuration of quote item
742
+ *
743
+ * @param itemId
744
+ */
745
+ showQuoteItemConfiguration: function(itemId){
746
+ var listType = 'quote_items';
747
+ var qtyElement = $('order-items_grid').select('input[name="item\['+itemId+'\]\[qty\]"]')[0];
748
+ productConfigure.setConfirmCallback(listType, function() {
749
+ // sync qty of popup and qty of grid
750
+ var confirmedCurrentQty = productConfigure.getCurrentConfirmedQtyElement();
751
+ if (qtyElement && confirmedCurrentQty && !isNaN(confirmedCurrentQty.value)) {
752
+ qtyElement.value = confirmedCurrentQty.value;
753
+ }
754
+ this.productConfigureAddFields['item['+itemId+'][configured]'] = 1;
755
+
756
+ }.bind(this));
757
+ productConfigure.setShowWindowCallback(listType, function() {
758
+ // sync qty of grid and qty of popup
759
+ var formCurrentQty = productConfigure.getCurrentFormQtyElement();
760
+ if (formCurrentQty && qtyElement && !isNaN(qtyElement.value)) {
761
+ formCurrentQty.value = qtyElement.value;
762
+ }
763
+ }.bind(this));
764
+ productConfigure.showItemConfiguration(listType, itemId);
765
+ },
766
+
767
+ accountFieldsBind : function(container){
768
+ if($(container)){
769
+ var fields = $(container).select('input', 'select', 'textarea');
770
+ for(var i=0; i<fields.length; i++){
771
+ if(fields[i].id == 'group_id'){
772
+ fields[i].observe('change', this.accountGroupChange.bind(this))
773
+ }
774
+ else{
775
+ fields[i].observe('change', this.accountFieldChange.bind(this))
776
+ }
777
+ }
778
+ }
779
+ },
780
+
781
+ accountGroupChange : function(){
782
+ this.loadArea(['data'], true, this.serializeData('order-form_account').toObject());
783
+ },
784
+
785
+ accountFieldChange : function(){
786
+ this.saveData(this.serializeData('order-form_account'));
787
+ },
788
+
789
+ commentFieldsBind : function(container){
790
+ if($(container)){
791
+ var fields = $(container).select('input', 'textarea');
792
+ for(var i=0; i<fields.length; i++)
793
+ fields[i].observe('change', this.commentFieldChange.bind(this))
794
+ }
795
+ },
796
+
797
+ commentFieldChange : function(){
798
+ this.saveData(this.serializeData('order-comment'));
799
+ },
800
+
801
+ giftmessageFieldsBind : function(container){
802
+ if($(container)){
803
+ var fields = $(container).select('input', 'textarea');
804
+ for(var i=0; i<fields.length; i++)
805
+ fields[i].observe('change', this.giftmessageFieldChange.bind(this))
806
+ }
807
+ },
808
+
809
+ giftmessageFieldChange : function(){
810
+ this.giftMessageDataChanged = true;
811
+ },
812
+
813
+ giftmessageOnItemChange : function(event) {
814
+ var element = Event.element(event);
815
+ if(element.name.indexOf("giftmessage") != -1 && element.type == "checkbox" && !element.checked) {
816
+ var messages = $("order-giftmessage").select('textarea');
817
+ var name;
818
+ for(var i=0; i<messages.length; i++) {
819
+ name = messages[i].id.split("_");
820
+ if(name.length < 2) continue;
821
+ if (element.name.indexOf("[" + name[1] + "]") != -1 && messages[i].value != "") {
822
+ alert("First, clean the Message field in Gift Message form");
823
+ element.checked = true;
824
+ }
825
+ }
826
+ }
827
+ },
828
+
829
+ loadArea : function(area, indicator, params){
830
+ var url = this.loadBaseUrl;
831
+ if (area) {
832
+ area = this.prepareArea(area);
833
+ url += 'block/' + area;
834
+ }
835
+ if (indicator === true) indicator = 'html-body';
836
+ params = this.prepareParams(params);
837
+ params.json = true;
838
+ if (!this.loadingAreas) this.loadingAreas = [];
839
+ if (indicator) {
840
+ this.loadingAreas = area;
841
+ new Ajax.Request(url, {
842
+ parameters:params,
843
+ loaderArea: indicator,
844
+ onSuccess: function(transport) {
845
+ var response = transport.responseText.evalJSON();
846
+ this.loadAreaResponseHandler(response);
847
+ }.bind(this)
848
+ });
849
+ }
850
+ else {
851
+ new Ajax.Request(url, {parameters:params,loaderArea: indicator});
852
+ }
853
+ if (typeof productConfigure != 'undefined' && area instanceof Array && area.indexOf('items' != -1)) {
854
+ productConfigure.clean('quote_items');
855
+ }
856
+ },
857
+
858
+ loadAreaResponseHandler : function (response){
859
+ if (response.error) {
860
+ alert(response.message);
861
+ }
862
+ if(response.ajaxExpired && response.ajaxRedirect) {
863
+ setLocation(response.ajaxRedirect);
864
+ }
865
+ if(!this.loadingAreas){
866
+ this.loadingAreas = [];
867
+ }
868
+ if(typeof this.loadingAreas == 'string'){
869
+ this.loadingAreas = [this.loadingAreas];
870
+ }
871
+ if(this.loadingAreas.indexOf('message'==-1)) this.loadingAreas.push('message');
872
+ for(var i=0; i<this.loadingAreas.length; i++){
873
+ var id = this.loadingAreas[i];
874
+ if($(this.getAreaId(id))){
875
+ if ('message' != id || response[id]) {
876
+ var wrapper = new Element('div');
877
+ wrapper.update(response[id] ? response[id] : '');
878
+ $(this.getAreaId(id)).update(wrapper);
879
+ }
880
+ if ($(this.getAreaId(id)).callback) {
881
+ this[$(this.getAreaId(id)).callback]();
882
+ }
883
+ }
884
+ }
885
+ },
886
+
887
+ prepareArea : function(area){
888
+ if (this.giftMessageDataChanged) {
889
+ return area.without('giftmessage');
890
+ }
891
+ return area;
892
+ },
893
+
894
+ saveData : function(data){
895
+ this.loadArea(false, false, data);
896
+ },
897
+
898
+ showArea : function(area){
899
+ var id = this.getAreaId(area);
900
+ if($(id)) {
901
+ $(id).show();
902
+ this.areaOverlay();
903
+ }
904
+ },
905
+
906
+ hideArea : function(area){
907
+ var id = this.getAreaId(area);
908
+ if($(id)) {
909
+ $(id).hide();
910
+ this.areaOverlay();
911
+ }
912
+ },
913
+
914
+ areaOverlay : function()
915
+ {
916
+ $H(order.overlayData).each(function(e){
917
+ e.value.fx();
918
+ });
919
+ },
920
+
921
+ getAreaId : function(area){
922
+ return 'order-'+area;
923
+ },
924
+
925
+ prepareParams : function(params){
926
+ if (!params) {
927
+ params = {};
928
+ }
929
+ if (!params.customer_id) {
930
+ params.customer_id = this.customerId;
931
+ }
932
+ if (!params.store_id) {
933
+ params.store_id = this.storeId;
934
+ }
935
+ if (!params.currency_id) {
936
+ params.currency_id = this.currencyId;
937
+ }
938
+ if (!params.form_key) {
939
+ params.form_key = FORM_KEY;
940
+ }
941
+ var data = this.serializeData('order-billing_method');
942
+ if (data) {
943
+ data.each(function(value) {
944
+ params[value[0]] = value[1];
945
+ });
946
+ }
947
+ return params;
948
+ },
949
+
950
+ serializeData : function(container){
951
+ var fields = $(container).select('input', 'select', 'textarea');
952
+ var data = Form.serializeElements(fields, true);
953
+
954
+ return $H(data);
955
+ },
956
+
957
+ toggleCustomPrice: function(checkbox, elemId, tierBlock) {
958
+ if (checkbox.checked) {
959
+ $(elemId).disabled = false;
960
+ $(elemId).show();
961
+ if($(tierBlock)) $(tierBlock).hide();
962
+ }
963
+ else {
964
+ $(elemId).disabled = true;
965
+ $(elemId).hide();
966
+ if($(tierBlock)) $(tierBlock).show();
967
+ }
968
+ },
969
+
970
+ submit : function()
971
+ {
972
+ if (this.orderItemChanged) {
973
+ if (confirm('You have item changes')) {
974
+ if (editForm.submit()) {
975
+ disableElements('save');
976
+ }
977
+ } else {
978
+ this.itemsUpdate();
979
+ }
980
+ } else {
981
+ if (editForm.submit()) {
982
+ disableElements('save');
983
+ }
984
+ }
985
+ },
986
+
987
+ overlay : function(elId, show, observe)
988
+ {
989
+ if (typeof(show) == 'undefined') { show = true; }
990
+
991
+ var orderObj = this;
992
+ var obj = this.overlayData.get(elId)
993
+ if (!obj) {
994
+ obj = {
995
+ show: show,
996
+ el: elId,
997
+ order: orderObj,
998
+ fx: function(event) {
999
+ this.order.processOverlay(this.el, this.show);
1000
+ }
1001
+ }
1002
+ obj.bfx = obj.fx.bindAsEventListener(obj);
1003
+ this.overlayData.set(elId, obj);
1004
+ }
1005
+ else {
1006
+ obj.show = show;
1007
+ Event.stopObserving(window, 'resize', obj.bfx);
1008
+ }
1009
+
1010
+ Event.observe(window, 'resize', obj.bfx);
1011
+
1012
+ this.processOverlay(elId, show);
1013
+ },
1014
+
1015
+ processOverlay : function(elId, show)
1016
+ {
1017
+ var el = $(elId);
1018
+
1019
+ if (!el) {
1020
+ return false;
1021
+ }
1022
+
1023
+ var parentEl = el.up(1);
1024
+ var parentPos = Element.cumulativeOffset(parentEl);
1025
+ if (show) {
1026
+ parentEl.removeClassName('ignore-validate');
1027
+ }
1028
+ else {
1029
+ parentEl.addClassName('ignore-validate');
1030
+ }
1031
+
1032
+ if (Prototype.Browser.IE) {
1033
+ parentEl.select('select').each(function (elem) {
1034
+ if (show) {
1035
+ elem.needShowOnSuccess = false;
1036
+ elem.style.visibility = '';
1037
+ } else {
1038
+ elem.style.visibility = 'hidden';
1039
+ elem.needShowOnSuccess = true;
1040
+ }
1041
+ });
1042
+ }
1043
+
1044
+ el.setStyle({
1045
+ display: show ? 'none' : '',
1046
+ position: 'absolute',
1047
+ backgroundColor: '#999999',
1048
+ opacity: 0.8,
1049
+ width: parentEl.getWidth() + 'px',
1050
+ height: parentEl.getHeight() + 'px',
1051
+ top: parentPos[1] + 'px',
1052
+ left: parentPos[0] + 'px'
1053
+ });
1054
+ }
1055
+ }
js/mage/adminhtml/sales/packaging.js ADDED
@@ -0,0 +1,813 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ var Packaging = Class.create();
26
+ Packaging.prototype = {
27
+ /**
28
+ * Initialize object
29
+ */
30
+ initialize: function(params) {
31
+ this.packageIncrement = 0;
32
+ this.packages = [];
33
+ this.itemsAll = [];
34
+ this.createLabelUrl = params.createLabelUrl ? params.createLabelUrl : null;
35
+ this.itemsGridUrl = params.itemsGridUrl ? params.itemsGridUrl : null;
36
+ this.errorQtyOverLimit = params.errorQtyOverLimit;
37
+ this.titleDisabledSaveBtn = params.titleDisabledSaveBtn;
38
+ this.window = $('packaging_window');
39
+ this.windowMask = $('popup-window-mask');
40
+ this.messages = this.window.select('.messages')[0];
41
+ this.packagesContent = $('packages_content');
42
+ this.template = $('package_template');
43
+ this.paramsCreateLabelRequest = {};
44
+ this.validationErrorMsg = params.validationErrorMsg;
45
+
46
+ this.defaultItemsQty = params.shipmentItemsQty ? params.shipmentItemsQty : null;
47
+ this.defaultItemsPrice = params.shipmentItemsPrice ? params.shipmentItemsPrice : null;
48
+ this.defaultItemsName = params.shipmentItemsName ? params.shipmentItemsName : null;
49
+ this.defaultItemsWeight = params.shipmentItemsWeight ? params.shipmentItemsWeight : null;
50
+ this.defaultItemsProductId = params.shipmentItemsProductId ? params.shipmentItemsProductId : null;
51
+ this.defaultItemsOrderItemId = params.shipmentItemsOrderItemId ? params.shipmentItemsOrderItemId : null;
52
+
53
+ this.shippingInformation= params.shippingInformation ? params.shippingInformation : null;
54
+ this.thisPage = params.thisPage ? params.thisPage : null;
55
+ this.customizableContainers = params.customizable ? params.customizable : [];
56
+
57
+ this.eps = .000001;
58
+ },
59
+
60
+ //******************** Setters **********************************//
61
+ setLabelCreatedCallback: function(callback) {
62
+ this.labelCreatedCallback = callback;
63
+ },
64
+ setCancelCallback: function(callback) {
65
+ this.cancelCallback = callback;
66
+ },
67
+ setConfirmPackagingCallback: function(callback) {
68
+ this.confirmPackagingCallback = callback;
69
+ },
70
+ setItemQtyCallback: function(callback) {
71
+ this.itemQtyCallback = callback;
72
+ },
73
+ setCreateLabelUrl: function(url) {
74
+ this.createLabelUrl = url;
75
+ },
76
+ setParamsCreateLabelRequest: function(params) {
77
+ Object.extend(this.paramsCreateLabelRequest, params);
78
+ },
79
+ //******************** End Setters *******************************//
80
+
81
+ showWindow: function() {
82
+ if (this.packagesContent.childElements().length == 0) {
83
+ this.newPackage();
84
+ }
85
+ this.window.show().setStyle({
86
+ 'marginLeft': -this.window.getDimensions().width/2 + 'px'
87
+ });
88
+ this.windowMask.setStyle({
89
+ height: $('html-body').getHeight() + 'px'
90
+ }).show();
91
+ },
92
+
93
+ cancelPackaging: function() {
94
+ packaging.window.hide();
95
+ packaging.windowMask.hide();
96
+ if (Object.isFunction(this.cancelCallback)) {
97
+ this.cancelCallback();
98
+ }
99
+ },
100
+
101
+ confirmPackaging: function(params) {
102
+ if (Object.isFunction(this.confirmPackagingCallback)) {
103
+ this.confirmPackagingCallback();
104
+ }
105
+ },
106
+
107
+ checkAllItems: function(headCheckbox) {
108
+ $(headCheckbox).up('table').select('tbody input[type="checkbox"]').each(function(checkbox){
109
+ checkbox.checked = headCheckbox.checked;
110
+ this._observeQty.call(checkbox);
111
+ }.bind(this));
112
+ },
113
+
114
+ cleanPackages: function() {
115
+ this.packagesContent.update();
116
+ this.packages = [];
117
+ this.itemsAll = [];
118
+ this.packageIncrement = 0;
119
+ this._setAllItemsPackedState();
120
+ this.messages.hide().update();
121
+ },
122
+
123
+ sendCreateLabelRequest: function() {
124
+ var package = this;
125
+ if (!this.validate()) {
126
+ this.messages.show().update(this.validationErrorMsg);
127
+ return;
128
+ } else {
129
+ this.messages.hide().update();
130
+ }
131
+ if (this.createLabelUrl) {
132
+ var weight, length, width, height = null;
133
+ var packagesParams = [];
134
+ this.packagesContent.childElements().each(function(pack) {
135
+ var packageId = pack.id.match(/\d$/)[0];
136
+ weight = parseFloat(pack.select('input[name="container_weight"]')[0].value);
137
+ length = parseFloat(pack.select('input[name="container_length"]')[0].value);
138
+ width = parseFloat(pack.select('input[name="container_width"]')[0].value);
139
+ height = parseFloat(pack.select('input[name="container_height"]')[0].value);
140
+ packagesParams[packageId] = {
141
+ container: pack.select('select[name="package_container"]')[0].value,
142
+ customs_value: parseInt(pack.select('input[name="package_customs_value"]')[0].value, 10),
143
+ weight: isNaN(weight) ? '' : weight,
144
+ length: isNaN(length) ? '' : length,
145
+ width: isNaN(width) ? '' : width,
146
+ height: isNaN(height) ? '' : height,
147
+ weight_units: pack.select('select[name="container_weight_units"]')[0].value,
148
+ dimension_units: pack.select('select[name="container_dimension_units"]')[0].value
149
+ };
150
+ if (isNaN(packagesParams[packageId]['customs_value'])) {
151
+ packagesParams[packageId]['customs_value'] = 0;
152
+ }
153
+ if ('undefined' != typeof pack.select('select[name="package_size"]')[0]) {
154
+ if ('' != pack.select('select[name="package_size"]')[0].value) {
155
+ packagesParams[packageId]['size'] = pack.select('select[name="package_size"]')[0].value;
156
+ }
157
+ }
158
+ if ('undefined' != typeof pack.select('input[name="container_girth"]')[0]) {
159
+ if ('' != pack.select('input[name="container_girth"]')[0].value) {
160
+ packagesParams[packageId]['girth'] = pack.select('input[name="container_girth"]')[0].value;
161
+ packagesParams[packageId]['girth_dimension_units'] = pack.select('select[name="container_girth_dimension_units"]')[0].value;
162
+ }
163
+ }
164
+ if ('undefined' != typeof pack.select('select[name="content_type"]')[0] && 'undefined' != typeof pack.select('input[name="content_type_other"]')[0]) {
165
+ packagesParams[packageId]['content_type'] = pack.select('select[name="content_type"]')[0].value;
166
+ packagesParams[packageId]['content_type_other'] = pack.select('input[name="content_type_other"]')[0].value;
167
+ } else {
168
+ packagesParams[packageId]['content_type'] = '';
169
+ packagesParams[packageId]['content_type_other'] = '';
170
+ }
171
+ var deliveryConfirmation = pack.select('select[name="delivery_confirmation_types"]');
172
+ if (deliveryConfirmation.length) {
173
+ packagesParams[packageId]['delivery_confirmation'] = deliveryConfirmation[0].value
174
+ }
175
+ }.bind(this));
176
+ for (var packageId in this.packages) {
177
+ if (!isNaN(packageId)) {
178
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[container]'] = packagesParams[packageId]['container'];
179
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[weight]'] = packagesParams[packageId]['weight'];
180
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[customs_value]'] = packagesParams[packageId]['customs_value'];
181
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[length]'] = packagesParams[packageId]['length'];
182
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[width]'] = packagesParams[packageId]['width'];
183
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[height]'] = packagesParams[packageId]['height'];
184
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[weight_units]'] = packagesParams[packageId]['weight_units'];
185
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[dimension_units]'] = packagesParams[packageId]['dimension_units'];
186
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[content_type]'] = packagesParams[packageId]['content_type'];
187
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[content_type_other]'] = packagesParams[packageId]['content_type_other'];
188
+
189
+ if ('undefined' != typeof packagesParams[packageId]['size']) {
190
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[size]'] = packagesParams[packageId]['size'];
191
+ }
192
+
193
+ if ('undefined' != typeof packagesParams[packageId]['girth']) {
194
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[girth]'] = packagesParams[packageId]['girth'];
195
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[girth_dimension_units]'] = packagesParams[packageId]['girth_dimension_units'];
196
+ }
197
+
198
+ if ('undefined' != typeof packagesParams[packageId]['delivery_confirmation']) {
199
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[params]'+'[delivery_confirmation]'] = packagesParams[packageId]['delivery_confirmation'];
200
+ }
201
+ for (var packedItemId in this.packages[packageId]['items']) {
202
+ if (!isNaN(packedItemId)) {
203
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[items]'+'['+packedItemId+'][qty]'] = this.packages[packageId]['items'][packedItemId]['qty'];
204
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[items]'+'['+packedItemId+'][customs_value]'] = this.packages[packageId]['items'][packedItemId]['customs_value'];
205
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[items]'+'['+packedItemId+'][price]'] = package.defaultItemsPrice[packedItemId];
206
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[items]'+'['+packedItemId+'][name]'] = package.defaultItemsName[packedItemId];
207
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[items]'+'['+packedItemId+'][weight]'] = package.defaultItemsWeight[packedItemId];
208
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[items]'+'['+packedItemId+'][product_id]'] = package.defaultItemsProductId[packedItemId];
209
+ this.paramsCreateLabelRequest['packages['+packageId+']'+'[items]'+'['+packedItemId+'][order_item_id]'] = package.defaultItemsOrderItemId[packedItemId];
210
+ }
211
+ }
212
+ }
213
+ }
214
+
215
+ new Ajax.Request(this.createLabelUrl, {
216
+ parameters: this.paramsCreateLabelRequest,
217
+ onSuccess: function(transport) {
218
+ var response = transport.responseText;
219
+ if (response.isJSON()) {
220
+ response = response.evalJSON();
221
+ if (response.error) {
222
+ this.messages.show().innerHTML = response.message;
223
+ } else if (response.ok && Object.isFunction(this.labelCreatedCallback)) {
224
+ this.labelCreatedCallback(response);
225
+ }
226
+ }
227
+ }.bind(this)
228
+ });
229
+ if (this.paramsCreateLabelRequest['code']
230
+ && this.paramsCreateLabelRequest['carrier_title']
231
+ && this.paramsCreateLabelRequest['method_title']
232
+ && this.paramsCreateLabelRequest['price']
233
+ ) {
234
+ var a = this.paramsCreateLabelRequest['code'];
235
+ var b = this.paramsCreateLabelRequest['carrier_title'];
236
+ var c = this.paramsCreateLabelRequest['method_title'];
237
+ var d = this.paramsCreateLabelRequest['price'];
238
+
239
+ this.paramsCreateLabelRequest = {};
240
+ this.paramsCreateLabelRequest['code'] = a;
241
+ this.paramsCreateLabelRequest['carrier_title'] = b;
242
+ this.paramsCreateLabelRequest['method_title'] = c;
243
+ this.paramsCreateLabelRequest['price'] = d;
244
+ } else {
245
+ this.paramsCreateLabelRequest = {};
246
+ }
247
+ }
248
+ },
249
+
250
+ validate: function() {
251
+ return result = $$('[id^="package_block_"] input').collect(function (element) {
252
+ return this.validateElement(element)
253
+ }, this).all();
254
+ },
255
+
256
+ validateElement: function(elm) {
257
+ var cn = $w(elm.className);
258
+ return result = cn.all(function(value) {
259
+ var v = Validation.get(value);
260
+ if (Validation.isVisible(elm) && !v.test($F(elm), elm)) {
261
+ $(elm).addClassName('validation-failed');
262
+ return false;
263
+ } else {
264
+ $(elm).removeClassName('validation-failed');
265
+ return true;
266
+ }
267
+ });
268
+ },
269
+
270
+ validateCustomsValue: function() {
271
+ var items = [];
272
+ var isValid = true;
273
+ var itemsPrepare = [];
274
+ var itemsPacked = [];
275
+
276
+ this.packagesContent.childElements().each(function(pack) {
277
+ itemsPrepare = pack.select('.package_prapare')[0];
278
+ if (itemsPrepare) {
279
+ items = items.concat(itemsPrepare.select('.grid tbody tr'));
280
+ }
281
+ itemsPacked = pack.select('.package_items')[0];
282
+ if (itemsPacked) {
283
+ items = items.concat(itemsPacked.select('.grid tbody tr'));
284
+ }
285
+ }.bind(this));
286
+
287
+ items.each(function(item) {
288
+ var itemCustomsValue = item.select('[name="customs_value"]')[0];
289
+ if (!this.validateElement(itemCustomsValue)) {
290
+ isValid = false;
291
+ }
292
+ }.bind(this));
293
+
294
+ if (isValid) {
295
+ this.messages.hide().update();
296
+ } else {
297
+ this.messages.show().update(this.validationErrorMsg);
298
+ }
299
+ return isValid;
300
+ },
301
+
302
+ newPackage: function() {
303
+ var pack = this.template.cloneNode(true);
304
+ pack.id = 'package_block_' + ++this.packageIncrement;
305
+ pack.addClassName('package-block');
306
+ pack.select('.package-number span')[0].update(this.packageIncrement);
307
+ this.packagesContent.insert({top: pack});
308
+ pack.select('.AddSelectedBtn')[0].hide();
309
+ pack.show();
310
+ },
311
+
312
+ deletePackage: function(obj) {
313
+ var pack = $(obj).up('div[id^="package_block"]');
314
+ var packItems = pack.select('.package_items')[0];
315
+ var packageId = pack.id.match(/\d$/)[0];
316
+
317
+ delete this.packages[packageId];
318
+ pack.remove();
319
+ this.messages.hide().update();
320
+ this._setAllItemsPackedState();
321
+ },
322
+
323
+ deleteItem: function(obj) {
324
+ var item = $(obj).up('tr');
325
+ var itemId = item.select('[type="checkbox"]')[0].value;
326
+ var pack = $(obj).up('div[id^="package_block"]');
327
+ var packItems = pack.select('.package_items')[0];
328
+ var packageId = pack.id.match(/\d$/)[0];
329
+
330
+ delete this.packages[packageId]['items'][itemId];
331
+ if (item.offsetParent.rows.length <= 2) { /* head + this last row */
332
+ $(packItems).hide();
333
+ }
334
+ item.remove();
335
+ this.messages.hide().update();
336
+ this._recalcContainerWeightAndCustomsValue(packItems);
337
+ this._setAllItemsPackedState()
338
+ },
339
+
340
+ recalcContainerWeightAndCustomsValue: function(obj) {
341
+ var pack = $(obj).up('div[id^="package_block"]');
342
+ var packItems = pack.select('.package_items')[0];
343
+ if (packItems) {
344
+ if (!this.validateCustomsValue()) {
345
+ return;
346
+ }
347
+ this._recalcContainerWeightAndCustomsValue(packItems);
348
+ }
349
+ },
350
+
351
+ getItemsForPack: function(obj) {
352
+ if (this.itemsGridUrl) {
353
+ var parameters = $H({'shipment_id': this.shipmentId});
354
+ var packageBlock = $(obj).up('[id^="package_block"]');
355
+ var packagePrapare = packageBlock.select('.package_prapare')[0];
356
+ var packagePrapareGrid = packagePrapare.select('.grid_prepare')[0];
357
+ new Ajax.Request(this.itemsGridUrl, {
358
+ parameters: parameters,
359
+ onSuccess: function(transport) {
360
+ var response = transport.responseText;
361
+ if (response) {
362
+ packagePrapareGrid.update(response);
363
+ this._processPackagePrapare(packagePrapareGrid);
364
+ if (packagePrapareGrid.select('.grid tbody tr').length) {
365
+ packageBlock.select('.AddItemsBtn')[0].hide();
366
+ packageBlock.select('.AddSelectedBtn')[0].show();
367
+ packagePrapare.show();
368
+ } else {
369
+ packagePrapareGrid.update();
370
+ }
371
+ }
372
+ }.bind(this)
373
+ });
374
+ }
375
+ },
376
+
377
+ getPackedItemsQty: function() {
378
+ var items = [];
379
+ for (var packageId in this.packages) {
380
+ if (!isNaN(packageId)) {
381
+ for (var packedItemId in this.packages[packageId]['items']) {
382
+ if (!isNaN(packedItemId)) {
383
+ if (items[packedItemId]) {
384
+ items[packedItemId] += this.packages[packageId]['items'][packedItemId]['qty'];
385
+ } else {
386
+ items[packedItemId] = this.packages[packageId]['items'][packedItemId]['qty']
387
+ }
388
+ }
389
+ }
390
+ }
391
+ }
392
+ return items;
393
+ },
394
+
395
+ _parseQty: function(obj) {
396
+ var qty = $(obj).hasClassName('qty-decimal') ? parseFloat(obj.value) : parseInt(obj.value);
397
+ if (isNaN(qty) || qty <= 0) {
398
+ qty = 1;
399
+ }
400
+ return qty;
401
+ },
402
+
403
+ packItems: function(obj) {
404
+ var anySelected = false;
405
+ var packageBlock = $(obj).up('[id^="package_block"]');
406
+ var packageId = packageBlock.id.match(/\d$/)[0];
407
+ var packagePrepare = packageBlock.select('.package_prapare')[0];
408
+ var packagePrepareGrid = packagePrepare.select('.grid_prepare')[0];
409
+
410
+ // check for exceeds the total shipped quantity
411
+ var checkExceedsQty = false;
412
+ this.messages.hide().update();
413
+ packagePrepareGrid.select('.grid tbody tr').each(function(item) {
414
+ var checkbox = item.select('[type="checkbox"]')[0];
415
+ var itemId = checkbox.value;
416
+ var qtyValue = this._parseQty(item.select('[name="qty"]')[0]);
417
+ item.select('[name="qty"]')[0].value = qtyValue;
418
+ if (checkbox.checked && this._checkExceedsQty(itemId, qtyValue)) {
419
+ this.messages.show().update(this.errorQtyOverLimit);
420
+ checkExceedsQty = true;
421
+ }
422
+ }.bind(this));
423
+ if (checkExceedsQty) {
424
+ return;
425
+ }
426
+
427
+ if (!this.validateCustomsValue()) {
428
+ return;
429
+ }
430
+
431
+ // prepare items for packing
432
+ packagePrepareGrid.select('.grid tbody tr').each(function(item) {
433
+ var checkbox = item.select('[type="checkbox"]')[0];
434
+ if (checkbox.checked) {
435
+ var qty = item.select('[name="qty"]')[0];
436
+ var qtyValue = this._parseQty(qty);
437
+ item.select('[name="qty"]')[0].value = qtyValue;
438
+ anySelected = true;
439
+ qty.disabled = 'disabled';
440
+ checkbox.up('td').hide();
441
+ packagePrepareGrid.select('.grid th [type="checkbox"]')[0].up('th').hide();
442
+ item.select('.delete')[0].show();
443
+ } else {
444
+ item.remove();
445
+ }
446
+ }.bind(this));
447
+
448
+ // packing items
449
+ if (anySelected) {
450
+ var packItems = packageBlock.select('.package_items')[0];
451
+ if (!packItems) {
452
+ packagePrepare.insert(new Element('div').addClassName('grid_prepare'));
453
+ packagePrepare.insert({after: packagePrepareGrid});
454
+ packItems = packagePrepareGrid.removeClassName('grid_prepare').addClassName('package_items');
455
+ packItems.select('.grid tbody tr').each(function(item) {
456
+ var itemId = item.select('[type="checkbox"]')[0].value;
457
+ var qtyValue = parseFloat(item.select('[name="qty"]')[0].value);
458
+ qtyValue = (qtyValue <= 0) ? 1 : qtyValue;
459
+
460
+ if ('undefined' == typeof this.packages[packageId]) {
461
+ this.packages[packageId] = {'items': [], 'params': {}};
462
+ }
463
+ if ('undefined' == typeof this.packages[packageId]['items'][itemId]) {
464
+ this.packages[packageId]['items'][itemId] = {};
465
+ this.packages[packageId]['items'][itemId]['qty'] = qtyValue;
466
+ } else {
467
+ this.packages[packageId]['items'][itemId]['qty'] += qtyValue;
468
+ }
469
+ }.bind(this));
470
+ } else {
471
+ packagePrepareGrid.select('.grid tbody tr').each(function(item) {
472
+ var itemId = item.select('[type="checkbox"]')[0].value;
473
+ var qtyValue = parseFloat(item.select('[name="qty"]')[0].value);
474
+ qtyValue = (qtyValue <= 0) ? 1 : qtyValue;
475
+
476
+ if ('undefined' == typeof this.packages[packageId]['items'][itemId]) {
477
+ this.packages[packageId]['items'][itemId] = {};
478
+ this.packages[packageId]['items'][itemId]['qty'] = qtyValue;
479
+ packItems.select('.grid tbody')[0].insert(item);
480
+ } else {
481
+ this.packages[packageId]['items'][itemId]['qty'] += qtyValue;
482
+ var packItem = packItems.select('[type="checkbox"][value="'+itemId+'"]')[0].up('tr').select('[name="qty"]')[0];
483
+ packItem.value = this.packages[packageId]['items'][itemId]['qty'];
484
+ }
485
+ }.bind(this));
486
+ packagePrepareGrid.update();
487
+ }
488
+ $(packItems).show();
489
+ this._recalcContainerWeightAndCustomsValue(packItems);
490
+ } else {
491
+ packagePrepareGrid.update();
492
+ }
493
+
494
+ // show/hide disable/enable
495
+ packagePrepare.hide();
496
+ packageBlock.select('.AddSelectedBtn')[0].hide();
497
+ packageBlock.select('.AddItemsBtn')[0].show();
498
+ this._setAllItemsPackedState()
499
+ },
500
+
501
+ validateItemQty: function (itemId, qty) {
502
+ return (this.defaultItemsQty[itemId] < qty) ? this.defaultItemsQty[itemId] : qty;
503
+ },
504
+
505
+ changeMeasures: function(obj) {
506
+ var incr = 0;
507
+ var incrSelected = 0;
508
+ obj.childElements().each(function(option) {
509
+ if (option.selected) {
510
+ incrSelected = incr;
511
+ }
512
+ incr++;
513
+ }.bind(this));
514
+
515
+ var packageBlock = $(obj).up('[id^="package_block"]');
516
+ packageBlock.select('.measures').each(function(item){
517
+ if (item.name != obj.name) {
518
+ var incr = 0;
519
+ item.select('option').each(function(option){
520
+ if (incr == incrSelected) {
521
+ item.value = option.value;
522
+ //option.selected = true
523
+ }
524
+ incr++;
525
+ }.bind(this));
526
+ }
527
+ }.bind(this));
528
+
529
+ },
530
+
531
+ checkSizeAndGirthParameter: function(obj, enabled) {
532
+ if (enabled == 0) {
533
+ return;
534
+ }
535
+ var currentNode = obj;
536
+
537
+ while (currentNode.nodeName != 'TBODY') {
538
+ currentNode = currentNode.parentNode;
539
+ }
540
+ if (!currentNode) {
541
+ return;
542
+ }
543
+
544
+ var packageSize = currentNode.select('select[name=package_size]');
545
+ var packageContainer = currentNode.select('select[name=package_container]');
546
+ var packageGirth = currentNode.select('input[name=container_girth]');
547
+ var packageGirthDimensionUnits = currentNode.select('select[name=container_girth_dimension_units]');
548
+
549
+ if (packageSize.length <= 0) {
550
+ return;
551
+ }
552
+
553
+ var girthEnabled = (packageSize[0].value == 'LARGE' && (packageContainer[0].value == 'NONRECTANGULAR'
554
+ || packageContainer[0].value == 'VARIABLE' ));
555
+
556
+ if (!girthEnabled) {
557
+ packageGirth[0].value='';
558
+ packageGirth[0].disable();
559
+ packageGirth[0].addClassName('disabled');
560
+ packageGirthDimensionUnits[0].disable();
561
+ packageGirthDimensionUnits[0].addClassName('disabled');
562
+ } else {
563
+ packageGirth[0].enable();
564
+ packageGirth[0].removeClassName('disabled');
565
+ packageGirthDimensionUnits[0].enable();
566
+ packageGirthDimensionUnits[0].removeClassName('disabled');
567
+ }
568
+
569
+ var sizeEnabled = (packageContainer[0].value == 'NONRECTANGULAR' || packageContainer[0].value == 'RECTANGULAR'
570
+ || packageContainer[0].value == 'VARIABLE');
571
+
572
+ if (!sizeEnabled) {
573
+ option = document.createElement('OPTION');
574
+ option.value = '';
575
+ option.text = '';
576
+ packageSize[0].options.add(option);
577
+ packageSize[0].value = '';
578
+ packageSize[0].disable();
579
+ packageSize[0].addClassName('disabled');
580
+ } else {
581
+ for (i = 0; i < packageSize[0].length; i ++) {
582
+ if (packageSize[0].options[i].value == '') {
583
+ packageSize[0].removeChild(packageSize[0].options[i]);
584
+ }
585
+ }
586
+ packageSize[0].enable();
587
+ packageSize[0].removeClassName('disabled');
588
+ }
589
+ },
590
+
591
+ changeContainerType: function(obj) {
592
+ if (this.customizableContainers.length <= 0) {
593
+ return;
594
+ }
595
+
596
+ var disable = true;
597
+ for (var i in this.customizableContainers) {
598
+ if (this.customizableContainers[i] == obj.value) {
599
+ disable = false;
600
+ break;
601
+ }
602
+ }
603
+
604
+ var currentNode = obj;
605
+ while (currentNode.nodeName != 'TBODY') {
606
+ currentNode = currentNode.parentNode;
607
+ }
608
+ if (!currentNode) {
609
+ return;
610
+ }
611
+
612
+ currentNode.select(
613
+ 'input[name=container_length],input[name=container_width],input[name=container_height],select[name=container_dimension_units]'
614
+ ).each(function(inputElement) {
615
+ if (disable) {
616
+ Form.Element.disable(inputElement);
617
+ inputElement.addClassName('disabled');
618
+ if (inputElement.nodeName == 'INPUT') {
619
+ $(inputElement).value = ''
620
+ }
621
+ } else {
622
+ Form.Element.enable(inputElement);
623
+ inputElement.removeClassName('disabled');
624
+ }
625
+ })
626
+ },
627
+
628
+ changeContentTypes: function(obj) {
629
+ var packageBlock = $(obj).up('[id^="package_block"]');
630
+ var contentType = packageBlock.select('[name=content_type]')[0];
631
+ var contentTypeOther = packageBlock.select('[name=content_type_other]')[0];
632
+ if (contentType.value == 'OTHER') {
633
+ Form.Element.enable(contentTypeOther);
634
+ contentTypeOther.removeClassName('disabled');
635
+ } else {
636
+ Form.Element.disable(contentTypeOther);
637
+ contentTypeOther.addClassName('disabled');
638
+ }
639
+
640
+ },
641
+
642
+ //******************** Private functions **********************************//
643
+ _getItemsCount: function(items) {
644
+ var count = 0;
645
+ items.each(function(itemCount) {
646
+ if (!isNaN(itemCount)) {
647
+ count += parseFloat(itemCount);
648
+ }
649
+ }.bind(this));
650
+ return count;
651
+ },
652
+
653
+ /**
654
+ * Show/hide disable/enable buttons in case of all items packed state
655
+ */
656
+ _setAllItemsPackedState: function() {
657
+ var addPackageBtn = this.window.select('.AddPackageBtn')[0];
658
+ var savePackagesBtn = this.window.select('.SavePackagesBtn')[0];
659
+ if (this._getItemsCount(this.itemsAll) > 0
660
+ && (this._checkExceedsQtyFinal(this._getItemsCount(this.getPackedItemsQty()),this._getItemsCount(this.itemsAll)))
661
+ ) {
662
+ this.packagesContent.select('.AddItemsBtn').each(function(button){
663
+ button.disabled = 'disabled';
664
+ button.addClassName('disabled');
665
+ });
666
+ addPackageBtn.addClassName('disabled');
667
+ Form.Element.disable(addPackageBtn);
668
+ savePackagesBtn.removeClassName('disabled');
669
+ Form.Element.enable(savePackagesBtn);
670
+ savePackagesBtn.title = '';
671
+
672
+ // package number recalculation
673
+ var packagesRecalc = [];
674
+ this.packagesContent.childElements().each(function(pack) {
675
+ if (!pack.select('.package_items .grid tbody tr').length) {
676
+ pack.remove();
677
+ }
678
+ }.bind(this));
679
+ var packagesCount = this.packagesContent.childElements().length;
680
+ this.packageIncrement = packagesCount;
681
+ this.packagesContent.childElements().each(function(pack) {
682
+ var packageId = pack.id.match(/\d$/)[0];
683
+ pack.id = 'package_block_' + packagesCount;
684
+ pack.select('.package-number span')[0].update(packagesCount);
685
+ packagesRecalc[packagesCount] = this.packages[packageId];
686
+ --packagesCount;
687
+ }.bind(this));
688
+ this.packages = packagesRecalc;
689
+
690
+ } else {
691
+ this.packagesContent.select('.AddItemsBtn').each(function(button){
692
+ button.removeClassName('disabled');
693
+ Form.Element.enable(button);
694
+ });
695
+ addPackageBtn.removeClassName('disabled');
696
+ Form.Element.enable(addPackageBtn);
697
+ savePackagesBtn.addClassName('disabled');
698
+ Form.Element.disable(savePackagesBtn);
699
+ savePackagesBtn.title = this.titleDisabledSaveBtn;
700
+ }
701
+ },
702
+
703
+ _processPackagePrapare: function(packagePrapare) {
704
+ var itemsAll = [];
705
+ packagePrapare.select('.grid tbody tr').each(function(item) {
706
+ var qty = item.select('[name="qty"]')[0];
707
+ var itemId = item.select('[type="checkbox"]')[0].value;
708
+ var qtyValue = 0;
709
+ if (Object.isFunction(this.itemQtyCallback)) {
710
+ var value = this.itemQtyCallback(itemId);
711
+ qtyValue = ((typeof value == 'string') && (value.length == 0)) ? 0 : parseFloat(value);
712
+ if (isNaN(qtyValue) || qtyValue < 0) {
713
+ qtyValue = 1;
714
+ }
715
+ qtyValue = this.validateItemQty(itemId, qtyValue);
716
+ qty.value = qtyValue;
717
+ } else {
718
+ var value = item.select('[name="qty"]')[0].value;
719
+ qtyValue = ((typeof value == 'string') && (value.length == 0)) ? 0 : parseFloat(value);
720
+ if (isNaN(qtyValue) || qtyValue < 0) {
721
+ qtyValue = 1;
722
+ }
723
+ }
724
+ if (qtyValue == 0) {
725
+ item.remove();
726
+ return;
727
+ }
728
+ var packedItems = this.getPackedItemsQty();
729
+ itemsAll[itemId] = qtyValue;
730
+ for (var packedItemId in packedItems) {
731
+ if (!isNaN(packedItemId)) {
732
+ var packedQty = packedItems[packedItemId];
733
+ if (itemId == packedItemId) {
734
+ if (qtyValue == packedQty || qtyValue <= packedQty) {
735
+ item.remove();
736
+ } else if (qtyValue > packedQty) {
737
+ /* fix float number precision */
738
+ qty.value = Number((qtyValue - packedQty).toFixed(4));
739
+ }
740
+ }
741
+ }
742
+ }
743
+ }.bind(this));
744
+ if (!this.itemsAll.length) {
745
+ this.itemsAll = itemsAll;
746
+ }
747
+
748
+ packagePrapare.select('tbody input[type="checkbox"]').each(function(item){
749
+ $(item).observe('change', this._observeQty);
750
+ this._observeQty.call(item);
751
+ }.bind(this))
752
+ },
753
+
754
+ _observeQty: function() {
755
+ /** this = input[type="checkbox"] */
756
+ var tr = this.parentNode.parentNode,
757
+ qty = $(tr.cells[tr.cells.length - 1]).select('input[name="qty"]')[0];
758
+
759
+ if (qty.disabled = !this.checked) {
760
+ $(qty).addClassName('disabled');
761
+ } else {
762
+ $(qty).removeClassName('disabled');
763
+ }
764
+ },
765
+
766
+ _checkExceedsQty: function(itemId, qty) {
767
+ var packedItemQty = this.getPackedItemsQty()[itemId] ? this.getPackedItemsQty()[itemId] : 0;
768
+ var allItemQty = this.itemsAll[itemId];
769
+ return (qty * (1 - this.eps) > (allItemQty * (1 + this.eps) - packedItemQty * (1 - this.eps)));
770
+ },
771
+
772
+ _checkExceedsQtyFinal: function(checkOne, defQty) {
773
+ return checkOne * (1 + this.eps) >= defQty * (1 - this.eps);
774
+ },
775
+
776
+ _recalcContainerWeightAndCustomsValue: function(container) {
777
+ var packageBlock = container.up('[id^="package_block"]');
778
+ var packageId = packageBlock.id.match(/\d$/)[0];
779
+ var containerWeight = packageBlock.select('[name="container_weight"]')[0];
780
+ var containerCustomsValue = packageBlock.select('[name="package_customs_value"]')[0];
781
+ containerWeight.value = 0;
782
+ containerCustomsValue.value = 0;
783
+ container.select('.grid tbody tr').each(function(item) {
784
+ var itemId = item.select('[type="checkbox"]')[0].value;
785
+ var qtyValue = parseFloat(item.select('[name="qty"]')[0].value);
786
+ if (isNaN(qtyValue) || qtyValue <= 0) {
787
+ qtyValue = 1;
788
+ item.select('[name="qty"]')[0].value = qtyValue;
789
+ }
790
+ var itemWeight = parseFloat(this._getElementText(item.select('.weight')[0]));
791
+ containerWeight.value = parseFloat(containerWeight.value) + (itemWeight * qtyValue);
792
+ var itemCustomsValue = parseFloat(item.select('[name="customs_value"]')[0].value) || 0;
793
+ containerCustomsValue.value = parseFloat(containerCustomsValue.value) + itemCustomsValue * qtyValue;
794
+ this.packages[packageId]['items'][itemId]['customs_value'] = itemCustomsValue;
795
+ }.bind(this));
796
+ containerWeight.value = parseFloat(parseFloat(containerWeight.value).toFixed(4));
797
+ containerCustomsValue.value = parseFloat(containerCustomsValue.value).toFixed(2);
798
+ if (containerCustomsValue.value == 0) {
799
+ containerCustomsValue.value = '';
800
+ }
801
+ },
802
+
803
+ _getElementText: function(el) {
804
+ if ('string' == typeof el.textContent) {
805
+ return el.textContent;
806
+ }
807
+ if ('string' == typeof el.innerText) {
808
+ return el.innerText;
809
+ }
810
+ return el.innerHTML.replace(/<[^>]*>/g,'');
811
+ }
812
+ //******************** End Private functions ******************************//
813
+ };
js/mage/adminhtml/scrollbar.js ADDED
@@ -0,0 +1,397 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ /**************************************************
26
+ * dom-drag.js
27
+ * 09.25.2001
28
+ * www.youngpup.net
29
+ **************************************************
30
+ * 10.28.2001 - fixed minor bug where events
31
+ * sometimes fired off the handle, not the root.
32
+ **************************************************/
33
+
34
+ var Drag = {
35
+
36
+ obj : null,
37
+
38
+ init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper)
39
+ {
40
+ o.onmousedown = Drag.start;
41
+
42
+ o.hmode = bSwapHorzRef ? false : true ;
43
+ o.vmode = bSwapVertRef ? false : true ;
44
+
45
+ o.root = oRoot && oRoot != null ? oRoot : o ;
46
+
47
+ if (o.hmode && isNaN(parseInt(o.root.style.left ))) o.root.style.left = "0px";
48
+ if (o.vmode && isNaN(parseInt(o.root.style.top ))) o.root.style.top = "0px";
49
+ if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right = "0px";
50
+ if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";
51
+
52
+ o.minX = typeof minX != 'undefined' ? minX : null;
53
+ o.minY = typeof minY != 'undefined' ? minY : null;
54
+ o.maxX = typeof maxX != 'undefined' ? maxX : null;
55
+ o.maxY = typeof maxY != 'undefined' ? maxY : null;
56
+
57
+ o.xMapper = fXMapper ? fXMapper : null;
58
+ o.yMapper = fYMapper ? fYMapper : null;
59
+
60
+ o.root.onDragStart = new Function();
61
+ o.root.onDragEnd = new Function();
62
+ o.root.onDrag = new Function();
63
+ },
64
+
65
+ start : function(e)
66
+ {
67
+ var o = Drag.obj = this;
68
+ e = Drag.fixE(e);
69
+ var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom);
70
+ var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
71
+ o.root.onDragStart(x, y);
72
+
73
+ o.lastMouseX = e.clientX;
74
+ o.lastMouseY = e.clientY;
75
+
76
+ if (o.hmode) {
77
+ if (o.minX != null) o.minMouseX = e.clientX - x + o.minX;
78
+ if (o.maxX != null) o.maxMouseX = o.minMouseX + o.maxX - o.minX;
79
+ } else {
80
+ if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
81
+ if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
82
+ }
83
+
84
+ if (o.vmode) {
85
+ if (o.minY != null) o.minMouseY = e.clientY - y + o.minY;
86
+ if (o.maxY != null) o.maxMouseY = o.minMouseY + o.maxY - o.minY;
87
+ } else {
88
+ if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
89
+ if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
90
+ }
91
+
92
+ document.onmousemove = Drag.drag;
93
+ document.onmouseup = Drag.end;
94
+
95
+ return false;
96
+ },
97
+
98
+ drag : function(e)
99
+ {
100
+ e = Drag.fixE(e);
101
+ var o = Drag.obj;
102
+
103
+ var ey = e.clientY;
104
+ var ex = e.clientX;
105
+ var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom);
106
+ var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
107
+ var nx, ny;
108
+
109
+ if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
110
+ if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
111
+ if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
112
+ if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);
113
+
114
+ nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
115
+ ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));
116
+
117
+ if (o.xMapper) nx = o.xMapper(y)
118
+ else if (o.yMapper) ny = o.yMapper(x)
119
+
120
+ Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
121
+ Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
122
+ Drag.obj.lastMouseX = ex;
123
+ Drag.obj.lastMouseY = ey;
124
+
125
+ Drag.obj.root.onDrag(nx, ny);
126
+ return false;
127
+ },
128
+
129
+ end : function()
130
+ {
131
+ document.onmousemove = null;
132
+ document.onmouseup = null;
133
+ Drag.obj.root.onDragEnd( parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]),
134
+ parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
135
+ Drag.obj = null;
136
+ },
137
+
138
+ fixE : function(e)
139
+ {
140
+ if (typeof e == 'undefined') e = window.event;
141
+ if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
142
+ if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
143
+ return e;
144
+ }
145
+ };
146
+
147
+ /* =======================================================
148
+ * ypSimpleScroll
149
+ * 3/11/2001
150
+ *
151
+ * http://www.youngpup.net/
152
+ * ======================================================= */
153
+
154
+ // Modified by Sergi Meseguer (www.zigotica.com) 04/2004
155
+ // Now it works with dragger and can use multiple instances in a page
156
+
157
+
158
+
159
+ ypSimpleScroll.prototype.scrollNorth = function(count) { this.startScroll(90, count) }
160
+ ypSimpleScroll.prototype.scrollSouth = function(count) { this.startScroll(270, count) }
161
+ ypSimpleScroll.prototype.scrollWest = function(count) { this.startScroll(180, count) }
162
+ ypSimpleScroll.prototype.scrollEast = function(count) { this.startScroll(0, count) }
163
+
164
+ ypSimpleScroll.prototype.startScroll = function(deg, count) {
165
+ if (this.loaded){
166
+ if (this.aniTimer) window.clearTimeout(this.aniTimer)
167
+ this.overrideScrollAngle(deg)
168
+ this.speed = this.origSpeed
169
+ this.lastTime = (new Date()).getTime() - this.y.minRes
170
+ this.aniTimer = window.setTimeout(this.gRef + ".scroll('"+deg+"','"+count+"')", this.y.minRes)
171
+ }
172
+ }
173
+
174
+ ypSimpleScroll.prototype.endScroll = function() {
175
+ if (this.loaded){
176
+ window.clearTimeout(this.aniTimer)
177
+ this.aniTimer = 0;
178
+ this.speed = this.origSpeed
179
+ }
180
+ }
181
+
182
+ ypSimpleScroll.prototype.overrideScrollAngle = function(deg) {
183
+ if (this.loaded){
184
+ deg = deg % 360
185
+ if (deg % 90 == 0) {
186
+ var cos = deg == 0 ? 1 : deg == 180 ? -1 : 0
187
+ var sin = deg == 90 ? -1 : deg == 270 ? 1 : 0
188
+ }
189
+ else {
190
+ var angle = deg * Math.PI / 180
191
+ var cos = Math.cos(angle)
192
+ var sin = Math.sin(angle)
193
+ sin = -sin
194
+ }
195
+ this.fx = cos / (Math.abs(cos) + Math.abs(sin))
196
+ this.fy = sin / (Math.abs(cos) + Math.abs(sin))
197
+ this.stopH = deg == 90 || deg == 270 ? this.scrollLeft : deg < 90 || deg > 270 ? this.scrollW : 0
198
+ this.stopV = deg == 0 || deg == 180 ? this.scrollTop : deg < 180 ? 0 : this.scrollH
199
+ }
200
+ }
201
+
202
+ ypSimpleScroll.prototype.overrideScrollSpeed = function(speed) {
203
+ if (this.loaded) this.speed = speed
204
+ }
205
+
206
+
207
+ ypSimpleScroll.prototype.scrollTo = function(stopH, stopV, aniLen) {
208
+ if (this.loaded){
209
+ if (stopH != this.scrollLeft || stopV != this.scrollTop) {
210
+ if (this.aniTimer) window.clearTimeout(this.aniTimer)
211
+ this.lastTime = (new Date()).getTime()
212
+ var dx = Math.abs(stopH - this.scrollLeft)
213
+ var dy = Math.abs(stopV - this.scrollTop)
214
+ var d = Math.sqrt(Math.pow(dx,2) + Math.pow(dy,2))
215
+ this.fx = (stopH - this.scrollLeft) / (dx + dy)
216
+ this.fy = (stopV - this.scrollTop) / (dx + dy)
217
+ this.stopH = stopH
218
+ this.stopV = stopV
219
+ this.speed = d / aniLen * 1000
220
+ window.setTimeout(this.gRef + ".scroll()", this.y.minRes)
221
+ }
222
+ }
223
+ }
224
+
225
+ ypSimpleScroll.prototype.jumpTo = function(nx, ny) {
226
+ if (this.loaded){
227
+ nx = Math.min(Math.max(nx, 0), this.scrollW)
228
+ ny = Math.min(Math.max(ny, 0), this.scrollH)
229
+ this.scrollLeft = nx
230
+ this.scrollTop = ny
231
+ if (this.y.ns4)this.content.moveTo(-nx, -ny)
232
+ else {
233
+ this.content.style.left = -nx + "px"
234
+ this.content.style.top = -ny + "px"
235
+ }
236
+ }
237
+ }
238
+
239
+ ypSimpleScroll.minRes = 10
240
+ ypSimpleScroll.ie = document.all ? 1 : 0
241
+ ypSimpleScroll.ns4 = document.layers ? 1 : 0
242
+ ypSimpleScroll.dom = document.getElementById ? 1 : 0
243
+ ypSimpleScroll.mac = navigator.platform == "MacPPC"
244
+ ypSimpleScroll.mo5 = document.getElementById && !document.all ? 1 : 0
245
+
246
+ ypSimpleScroll.prototype.scroll = function(deg,count) {
247
+ this.aniTimer = window.setTimeout(this.gRef + ".scroll('"+deg+"','"+count+"')", this.y.minRes)
248
+ var nt = (new Date()).getTime()
249
+ var d = Math.round((nt - this.lastTime) / 1000 * this.speed)
250
+ if (d > 0){
251
+ var nx = d * this.fx + this.scrollLeft
252
+ var ny = d * this.fy + this.scrollTop
253
+ var xOut = (nx >= this.scrollLeft && nx >= this.stopH) || (nx <= this.scrollLeft && nx <= this.stopH)
254
+ var yOut = (ny >= this.scrollTop && ny >= this.stopV) || (ny <= this.scrollTop && ny <= this.stopV)
255
+ if (nt - this.lastTime != 0 &&
256
+ ((this.fx == 0 && this.fy == 0) ||
257
+ (this.fy == 0 && xOut) ||
258
+ (this.fx == 0 && yOut) ||
259
+ (this.fx != 0 && this.fy != 0 &&
260
+ xOut && yOut))) {
261
+ this.jumpTo(this.stopH, this.stopV)
262
+ this.endScroll()
263
+ }
264
+ else {
265
+ this.jumpTo(nx, ny)
266
+ this.lastTime = nt
267
+ }
268
+ // (zgtc) now we also update dragger position:
269
+ if(deg=='270') theThumb[count].style.top = parseInt(((theThumb[count].maxY-theThumb[count].minY)*this.scrollTop/this.stopV)+theThumb[count].minY) + "px"; //ok nomes down
270
+ if(deg=='90') theThumb[count].style.top = parseInt(((theThumb[count].maxY-theThumb[count].minY)*this.scrollTop/this.scrollH)+theThumb[count].minY) + "px"; //ok nomes down
271
+ }
272
+ }
273
+
274
+ function ypSimpleScroll(id, left, top, width, height, speed) {
275
+ width -= 2;
276
+ var y = this.y = ypSimpleScroll
277
+ if (document.layers && !y.ns4) history.go(0)
278
+ if (y.ie || y.ns4 || y.dom) {
279
+ this.loaded = false
280
+ this.id = id
281
+ this.origSpeed = speed
282
+ this.aniTimer = false
283
+ this.op = ""
284
+ this.lastTime = 0
285
+ this.clipH = height
286
+ this.clipW = width
287
+ this.scrollTop = 0
288
+ this.scrollLeft = 0
289
+ this.gRef = "ypSimpleScroll_"+id
290
+ eval(this.gRef+"=this")
291
+ var d = document
292
+ d.write('<style type="text/css">')
293
+ d.write('#' + this.id + 'Container { left:0px; top:' + top + 'px; width:' + (width+15) + 'px; height:' + (height+12) + 'px; clip:rect(0 ' + (width+15) + ' ' + (height+12) + ' 0); overflow:hidden; }')
294
+ d.write('#' + this.id + 'Container, #' + this.id + 'Content { position:absolute; }')
295
+ d.write('#' + this.id + 'Content { left:' + (-this.scrollLeft) + 'px; top:' + (-this.scrollTop) + 'px; width:' + width + 'px; }')
296
+ // (zgtc) fix to overwrite p/div/ul width (would be clipped if wider than scroller in css):
297
+ // d.write('#' + this.id + 'Container p, #' + this.id + 'Container div {width:' + parseInt(width-10) + 'px; }')
298
+ d.write('</style>')
299
+ }
300
+ }
301
+
302
+ ypSimpleScroll.prototype.load = function() {
303
+ var d, lyrId1, lyrId2
304
+ d = document
305
+ lyrId1 = this.id + "Container"
306
+ lyrId2 = this.id + "Content"
307
+ this.container = this.y.dom ? d.getElementById(lyrId1) : this.y.ie ? d.all[lyrId1] : d.layers[lyrId1]
308
+ this.content = obj2 = this.y.ns4 ? this.container.layers[lyrId2] : this.y.ie ? d.all[lyrId2] : d.getElementById(lyrId2)
309
+ this.docH = Math.max(this.y.ns4 ? this.content.document.height : this.content.offsetHeight, this.clipH)
310
+ this.docW = Math.max(this.y.ns4 ? this.content.document.width : this.content.offsetWidth, this.clipW)
311
+ this.scrollH = this.docH - this.clipH
312
+ this.scrollW = this.docW - this.clipW
313
+ this.loaded = true
314
+ this.scrollLeft = Math.max(Math.min(this.scrollLeft, this.scrollW),0)
315
+ this.scrollTop = Math.max(Math.min(this.scrollTop, this.scrollH),0)
316
+ this.jumpTo(this.scrollLeft, this.scrollTop)
317
+ }
318
+
319
+ // ==============================================================
320
+ // HANDLES SCROLLER/S
321
+ // Modified from Aaron Boodman http://webapp.youngpup.net/?request=/components/ypSimpleScroll.xml
322
+ // mixed ypSimpleScroll with dom-drag script and allowed multiple scrolelrs through array instances
323
+ // (c)2004 Sergi Meseguer (http://zigotica.com/), 04/2004:
324
+ // ==============================================================
325
+ var theHandle = []; var theRoot = []; var theThumb = []; var theScroll = []; var thumbTravel = []; var ratio = [];
326
+
327
+ function instantiateScroller(count, id, left, top, width, height, speed){
328
+ if(document.getElementById) {
329
+ theScroll[count] = new ypSimpleScroll(id, left, top, width, height, speed);
330
+ }
331
+ }
332
+
333
+ function createDragger(count, handler, root, thumb, minX, maxX, minY, maxY){
334
+ var buttons = '<div class="scroll-cont"><div class="up" id="up'+count+'">'+
335
+ '<a href="#" onmousedown="theScroll['+count+'].scrollNorth(\''+count+'\')" '+
336
+ 'onmouseout="theScroll['+count+'].endScroll()" onmouseup="theScroll['+count+'].endScroll()" onclick="return false;">'+
337
+ '<img src="'+db_but_top+'" width="16" height="16"></a></div>'+
338
+ '<div class="dn" id="dn'+count+'"">'+
339
+ '<a href="#" onmousedown="theScroll['+count+'].scrollSouth(\''+count+'\')" '+
340
+ 'onmouseout="theScroll['+count+'].endScroll()" onmouseup="theScroll['+count+'].endScroll()" onclick="return false;">'+
341
+ '<img src="'+db_but_bot+'" width="16" height="15"></a></div>'+
342
+ '</div><div class="thumb" id="'+thumb+'">'+
343
+ '<img src="'+db_but_rol+'" width="16" height="40"></div>';
344
+
345
+ document.getElementById(root).innerHTML = buttons + document.getElementById(root).innerHTML;
346
+
347
+ theRoot[count] = document.getElementById(root);
348
+ theThumb[count] = document.getElementById(thumb);
349
+ var thisup = document.getElementById("up"+count);
350
+ var thisdn = document.getElementById("dn"+count);
351
+ theThumb[count].style.left = parseInt(minX+15) + "px";
352
+ thisup.style.left = parseInt(minX+15) + "px";
353
+ thisdn.style.left = parseInt(minX+15) + "px";
354
+ theThumb[count].style.border =0;
355
+ theThumb[count].style.top = parseInt(minY) + "px";
356
+ thisup.style.top = 0 + "px";
357
+ thisdn.style.top = parseInt(minY+maxY) + "px";
358
+ //thisdn.style.top = 15 + "px";
359
+
360
+ theScroll[count].load();
361
+
362
+ //Drag.init(theHandle[count], theRoot[count]); //not draggable on screen
363
+ Drag.init(theThumb[count], null, minX+15, maxX+15, minY, maxY);
364
+
365
+ // the number of pixels the thumb can travel vertically (max - min)
366
+ thumbTravel[count] = theThumb[count].maxY - theThumb[count].minY;
367
+
368
+ // the ratio between scroller movement and thumbMovement
369
+ ratio[count] = theScroll[count].scrollH / thumbTravel[count];
370
+
371
+ theThumb[count].onDrag = function(x, y) {
372
+ theScroll[count].jumpTo(null, Math.round((y - theThumb[count].minY) * ratio[count]));
373
+ }
374
+ }
375
+
376
+ // INITIALIZER:
377
+ // ==============================================================
378
+ // ala Simon Willison http://simon.incutio.com/archive/2004/05/26/addLoadEvent
379
+ function addLoadEvent(fn) {
380
+ var old = window.onload;
381
+ if (typeof window.onload != 'function') {
382
+ window.onload = fn;
383
+ }
384
+ else {
385
+ window.onload = function() {
386
+ old();
387
+ fn();
388
+ }
389
+ }
390
+ }
391
+ addLoadEvent(function(){
392
+ if(theScroll.length>0) {
393
+ for(var i=0;i<theScroll.length;i++){
394
+ createDragger(i, "handle"+i, "root"+i, "thumb"+i, theScroll[i].clipW, theScroll[i].clipW, 15, theScroll[i].clipH-30);
395
+ }
396
+ }
397
+ })
js/mage/adminhtml/tabs.js ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ var varienTabs = new Class.create();
26
+
27
+ varienTabs.prototype = {
28
+ initialize : function(containerId, destElementId, activeTabId, shadowTabs){
29
+ this.containerId = containerId;
30
+ this.destElementId = destElementId;
31
+ this.activeTab = null;
32
+
33
+ this.tabOnClick = this.tabMouseClick.bindAsEventListener(this);
34
+
35
+ this.tabs = $$('#'+this.containerId+' li a.tab-item-link');
36
+
37
+ this.hideAllTabsContent();
38
+ for (var tab=0; tab<this.tabs.length; tab++) {
39
+ Event.observe(this.tabs[tab],'click',this.tabOnClick);
40
+ // move tab contents to destination element
41
+ if($(this.destElementId)){
42
+ var tabContentElement = $(this.getTabContentElementId(this.tabs[tab]));
43
+ if(tabContentElement && tabContentElement.parentNode.id != this.destElementId){
44
+ $(this.destElementId).appendChild(tabContentElement);
45
+ tabContentElement.container = this;
46
+ tabContentElement.statusBar = this.tabs[tab];
47
+ tabContentElement.tabObject = this.tabs[tab];
48
+ this.tabs[tab].contentMoved = true;
49
+ this.tabs[tab].container = this;
50
+ this.tabs[tab].show = function(){
51
+ this.container.showTabContent(this);
52
+ }
53
+ if(varienGlobalEvents){
54
+ varienGlobalEvents.fireEvent('moveTab', {tab:this.tabs[tab]});
55
+ }
56
+ }
57
+ }
58
+ /*
59
+ // this code is pretty slow in IE, so lets do it in tabs*.phtml
60
+ // mark ajax tabs as not loaded
61
+ if (Element.hasClassName($(this.tabs[tab].id), 'ajax')) {
62
+ Element.addClassName($(this.tabs[tab].id), 'notloaded');
63
+ }
64
+ */
65
+ // bind shadow tabs
66
+ if (this.tabs[tab].id && shadowTabs && shadowTabs[this.tabs[tab].id]) {
67
+ this.tabs[tab].shadowTabs = shadowTabs[this.tabs[tab].id];
68
+ }
69
+ }
70
+
71
+ this.displayFirst = activeTabId;
72
+ Event.observe(window,'load',this.moveTabContentInDest.bind(this));
73
+ },
74
+
75
+ setSkipDisplayFirstTab : function(){
76
+ this.displayFirst = null;
77
+ },
78
+
79
+ moveTabContentInDest : function(){
80
+ for(var tab=0; tab<this.tabs.length; tab++){
81
+ if($(this.destElementId) && !this.tabs[tab].contentMoved){
82
+ var tabContentElement = $(this.getTabContentElementId(this.tabs[tab]));
83
+ if(tabContentElement && tabContentElement.parentNode.id != this.destElementId){
84
+ $(this.destElementId).appendChild(tabContentElement);
85
+ tabContentElement.container = this;
86
+ tabContentElement.statusBar = this.tabs[tab];
87
+ tabContentElement.tabObject = this.tabs[tab];
88
+ this.tabs[tab].container = this;
89
+ this.tabs[tab].show = function(){
90
+ this.container.showTabContent(this);
91
+ }
92
+ if(varienGlobalEvents){
93
+ varienGlobalEvents.fireEvent('moveTab', {tab:this.tabs[tab]});
94
+ }
95
+ }
96
+ }
97
+ }
98
+ if (this.displayFirst) {
99
+ this.showTabContent($(this.displayFirst));
100
+ this.displayFirst = null;
101
+ }
102
+ },
103
+
104
+ getTabContentElementId : function(tab){
105
+ if(tab){
106
+ return tab.id+'_content';
107
+ }
108
+ return false;
109
+ },
110
+
111
+ tabMouseClick : function(event) {
112
+ var tab = Event.findElement(event, 'a');
113
+
114
+ // go directly to specified url or switch tab
115
+ if ((tab.href.indexOf('#') != tab.href.length-1)
116
+ && !(Element.hasClassName(tab, 'ajax'))
117
+ ) {
118
+ location.href = tab.href;
119
+ }
120
+ else {
121
+ this.showTabContent(tab);
122
+ }
123
+ Event.stop(event);
124
+ },
125
+
126
+ hideAllTabsContent : function(){
127
+ for(var tab in this.tabs){
128
+ this.hideTabContent(this.tabs[tab]);
129
+ }
130
+ },
131
+
132
+ // show tab, ready or not
133
+ showTabContentImmediately : function(tab) {
134
+ this.hideAllTabsContent();
135
+ var tabContentElement = $(this.getTabContentElementId(tab));
136
+ if (tabContentElement) {
137
+ Element.show(tabContentElement);
138
+ Element.addClassName(tab, 'active');
139
+ // load shadow tabs, if any
140
+ if (tab.shadowTabs && tab.shadowTabs.length) {
141
+ for (var k in tab.shadowTabs) {
142
+ this.loadShadowTab($(tab.shadowTabs[k]));
143
+ }
144
+ }
145
+ if (!Element.hasClassName(tab, 'ajax only')) {
146
+ Element.removeClassName(tab, 'notloaded');
147
+ }
148
+ this.activeTab = tab;
149
+ }
150
+ if (varienGlobalEvents) {
151
+ varienGlobalEvents.fireEvent('showTab', {tab:tab});
152
+ }
153
+ },
154
+
155
+ // the lazy show tab method
156
+ showTabContent : function(tab) {
157
+ var tabContentElement = $(this.getTabContentElementId(tab));
158
+ if (tabContentElement) {
159
+ if (this.activeTab != tab) {
160
+ if (varienGlobalEvents) {
161
+ if (varienGlobalEvents.fireEvent('tabChangeBefore', $(this.getTabContentElementId(this.activeTab))).indexOf('cannotchange') != -1) {
162
+ return;
163
+ };
164
+ }
165
+ }
166
+ // wait for ajax request, if defined
167
+ var isAjax = Element.hasClassName(tab, 'ajax');
168
+ var isEmpty = tabContentElement.innerHTML=='' && tab.href.indexOf('#')!=tab.href.length-1;
169
+ var isNotLoaded = Element.hasClassName(tab, 'notloaded');
170
+
171
+ if ( isAjax && (isEmpty || isNotLoaded) )
172
+ {
173
+ new Ajax.Request(tab.href, {
174
+ parameters: {form_key: FORM_KEY},
175
+ evalScripts: true,
176
+ onSuccess: function(transport) {
177
+ try {
178
+ if (transport.responseText.isJSON()) {
179
+ var response = transport.responseText.evalJSON()
180
+ if (response.error) {
181
+ alert(response.message);
182
+ }
183
+ if(response.ajaxExpired && response.ajaxRedirect) {
184
+ setLocation(response.ajaxRedirect);
185
+ }
186
+ } else {
187
+ $(tabContentElement.id).update(transport.responseText);
188
+ this.showTabContentImmediately(tab)
189
+ }
190
+ }
191
+ catch (e) {
192
+ $(tabContentElement.id).update(transport.responseText);
193
+ this.showTabContentImmediately(tab)
194
+ }
195
+ }.bind(this)
196
+ });
197
+ }
198
+ else {
199
+ this.showTabContentImmediately(tab);
200
+ }
201
+ }
202
+ },
203
+
204
+ loadShadowTab : function(tab) {
205
+ var tabContentElement = $(this.getTabContentElementId(tab));
206
+ if (tabContentElement && Element.hasClassName(tab, 'ajax') && Element.hasClassName(tab, 'notloaded')) {
207
+ new Ajax.Request(tab.href, {
208
+ parameters: {form_key: FORM_KEY},
209
+ evalScripts: true,
210
+ onSuccess: function(transport) {
211
+ try {
212
+ if (transport.responseText.isJSON()) {
213
+ var response = transport.responseText.evalJSON()
214
+ if (response.error) {
215
+ alert(response.message);
216
+ }
217
+ if(response.ajaxExpired && response.ajaxRedirect) {
218
+ setLocation(response.ajaxRedirect);
219
+ }
220
+ } else {
221
+ $(tabContentElement.id).update(transport.responseText);
222
+ if (!Element.hasClassName(tab, 'ajax only')) {
223
+ Element.removeClassName(tab, 'notloaded');
224
+ }
225
+ }
226
+ }
227
+ catch (e) {
228
+ $(tabContentElement.id).update(transport.responseText);
229
+ if (!Element.hasClassName(tab, 'ajax only')) {
230
+ Element.removeClassName(tab, 'notloaded');
231
+ }
232
+ }
233
+ }.bind(this)
234
+ });
235
+ }
236
+ },
237
+
238
+ hideTabContent : function(tab){
239
+ var tabContentElement = $(this.getTabContentElementId(tab));
240
+ if($(this.destElementId) && tabContentElement){
241
+ Element.hide(tabContentElement);
242
+ Element.removeClassName(tab, 'active');
243
+ }
244
+ if(varienGlobalEvents){
245
+ varienGlobalEvents.fireEvent('hideTab', {tab:tab});
246
+ }
247
+ }
248
+ }
js/mage/adminhtml/tools.js ADDED
@@ -0,0 +1,735 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ function setLocation(url){
26
+ window.location.href = url;
27
+ }
28
+
29
+ function confirmSetLocation(message, url){
30
+ if( confirm(message) ) {
31
+ setLocation(url);
32
+ }
33
+ return false;
34
+ }
35
+
36
+ function deleteConfirm(message, url) {
37
+ confirmSetLocation(message, url);
38
+ }
39
+
40
+ function setElementDisable(element, disable){
41
+ if($(element)){
42
+ $(element).disabled = disable;
43
+ }
44
+ }
45
+
46
+ function toggleParentVis(obj) {
47
+ obj = $(obj).parentNode;
48
+ if( obj.style.display == 'none' ) {
49
+ obj.style.display = '';
50
+ } else {
51
+ obj.style.display = 'none';
52
+ }
53
+ }
54
+
55
+ // to fix new app/design/adminhtml/default/default/template/widget/form/renderer/fieldset.phtml
56
+ // with toggleParentVis
57
+ function toggleFieldsetVis(obj) {
58
+ id = obj;
59
+ obj = $(obj);
60
+ if( obj.style.display == 'none' ) {
61
+ obj.style.display = '';
62
+ } else {
63
+ obj.style.display = 'none';
64
+ }
65
+ obj = obj.parentNode.childElements();
66
+ for (var i = 0; i < obj.length; i++) {
67
+ if (obj[i].id != undefined
68
+ && obj[i].id == id
69
+ && obj[(i-1)].classNames() == 'entry-edit-head')
70
+ {
71
+ if (obj[i-1].style.display == 'none') {
72
+ obj[i-1].style.display = '';
73
+ } else {
74
+ obj[i-1].style.display = 'none';
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ function toggleVis(obj) {
81
+ obj = $(obj);
82
+ if( obj.style.display == 'none' ) {
83
+ obj.style.display = '';
84
+ } else {
85
+ obj.style.display = 'none';
86
+ }
87
+ }
88
+
89
+ function imagePreview(element){
90
+ if($(element)){
91
+ var win = window.open('', 'preview', 'width=400,height=400,resizable=1,scrollbars=1');
92
+ win.document.open();
93
+ win.document.write('<body style="padding:0;margin:0"><img src="'+$(element).src+'" id="image_preview"/></body>');
94
+ win.document.close();
95
+ Event.observe(win, 'load', function(){
96
+ var img = win.document.getElementById('image_preview');
97
+ win.resizeTo(img.width+40, img.height+80)
98
+ });
99
+ }
100
+ }
101
+
102
+ function toggleValueElements(checkbox, container, excludedElements, checked){
103
+ if(container && checkbox){
104
+ var ignoredElements = [checkbox];
105
+ if (typeof excludedElements != 'undefined') {
106
+ if (Object.prototype.toString.call(excludedElements) != '[object Array]') {
107
+ excludedElements = [excludedElements];
108
+ }
109
+ for (var i = 0; i < excludedElements.length; i++) {
110
+ ignoredElements.push(excludedElements[i]);
111
+ }
112
+ }
113
+ //var elems = container.select('select', 'input');
114
+ var elems = Element.select(container, ['select', 'input', 'textarea', 'button', 'img']);
115
+ var isDisabled = (checked != undefined ? checked : checkbox.checked);
116
+ elems.each(function (elem) {
117
+ var isIgnored = false;
118
+ for (var i = 0; i < ignoredElements.length; i++) {
119
+ if (elem == ignoredElements[i]) {
120
+ isIgnored = true;
121
+ break;
122
+ }
123
+ }
124
+ if (isIgnored) {
125
+ return;
126
+ }
127
+ elem.disabled=isDisabled;
128
+ if (isDisabled) {
129
+ elem.addClassName('disabled');
130
+ } else {
131
+ elem.removeClassName('disabled');
132
+ }
133
+ if(elem.tagName == 'IMG') {
134
+ isDisabled ? elem.hide() : elem.show();
135
+ }
136
+ })
137
+ }
138
+ }
139
+
140
+ /**
141
+ * @todo add validation for fields
142
+ */
143
+ function submitAndReloadArea(area, url) {
144
+ if($(area)) {
145
+ var fields = $(area).select('input', 'select', 'textarea');
146
+ var data = Form.serializeElements(fields, true);
147
+ url = url + (url.match(new RegExp('\\?')) ? '&isAjax=true' : '?isAjax=true');
148
+ new Ajax.Request(url, {
149
+ parameters: $H(data),
150
+ loaderArea: area,
151
+ onSuccess: function(transport) {
152
+ try {
153
+ if (transport.responseText.isJSON()) {
154
+ var response = transport.responseText.evalJSON()
155
+ if (response.error) {
156
+ alert(response.message);
157
+ }
158
+ if(response.ajaxExpired && response.ajaxRedirect) {
159
+ setLocation(response.ajaxRedirect);
160
+ }
161
+ } else {
162
+ $(area).update(transport.responseText);
163
+ }
164
+ }
165
+ catch (e) {
166
+ $(area).update(transport.responseText);
167
+ }
168
+ }
169
+ });
170
+ }
171
+ }
172
+
173
+ /********** MESSAGES ***********/
174
+ /*
175
+ Event.observe(window, 'load', function() {
176
+ $$('.messages .error-msg').each(function(el) {
177
+ new Effect.Highlight(el, {startcolor:'#E13422', endcolor:'#fdf9f8', duration:1});
178
+ });
179
+ $$('.messages .warning-msg').each(function(el) {
180
+ new Effect.Highlight(el, {startcolor:'#E13422', endcolor:'#fdf9f8', duration:1});
181
+ });
182
+ $$('.messages .notice-msg').each(function(el) {
183
+ new Effect.Highlight(el, {startcolor:'#E5B82C', endcolor:'#fbf7e9', duration:1});
184
+ });
185
+ $$('.messages .success-msg').each(function(el) {
186
+ new Effect.Highlight(el, {startcolor:'#507477', endcolor:'#f2fafb', duration:1});
187
+ });
188
+ });
189
+ */
190
+ function syncOnchangeValue(baseElem, distElem){
191
+ var compare = {baseElem:baseElem, distElem:distElem}
192
+ Event.observe(baseElem, 'change', function(){
193
+ if($(this.baseElem) && $(this.distElem)){
194
+ $(this.distElem).value = $(this.baseElem).value;
195
+ }
196
+ }.bind(compare));
197
+ }
198
+
199
+ // Insert some content to the cursor position of input element
200
+ function updateElementAtCursor(el, value, win) {
201
+ if (win == undefined) {
202
+ win = window.self;
203
+ }
204
+ if (document.selection) {
205
+ el.focus();
206
+ sel = win.document.selection.createRange();
207
+ sel.text = value;
208
+ } else if (el.selectionStart || el.selectionStart == '0') {
209
+ var startPos = el.selectionStart;
210
+ var endPos = el.selectionEnd;
211
+ el.value = el.value.substring(0, startPos) + value + el.value.substring(endPos, el.value.length);
212
+ } else {
213
+ el.value += value;
214
+ }
215
+ }
216
+
217
+ // Firebug detection
218
+ function firebugEnabled() {
219
+ if(window.console && window.console.firebug) {
220
+ return true;
221
+ }
222
+ return false;
223
+ }
224
+
225
+ function disableElement(elem) {
226
+ elem.disabled = true;
227
+ elem.addClassName('disabled');
228
+ }
229
+
230
+ function enableElement(elem) {
231
+ elem.disabled = false;
232
+ elem.removeClassName('disabled');
233
+ }
234
+
235
+ function disableElements(search){
236
+ $$('.' + search).each(disableElement);
237
+ }
238
+
239
+ function enableElements(search){
240
+ $$('.' + search).each(enableElement);
241
+ }
242
+
243
+ /********** Toolbar toggle object to manage normal/floating toolbar toggle during vertical scroll ***********/
244
+ var toolbarToggle = {
245
+ // Properties
246
+ header: null, // Normal toolbar
247
+ headerOffset: null, // Normal toolbar offset - calculated once
248
+ headerCopy: null, // Floating toolbar
249
+ eventsAdded: false, // We're listening to scroll/resize
250
+ compatible: !navigator.appVersion.match('MSIE 6.'), // Whether object is compatible with browser (do not support old browsers, legacy code)
251
+
252
+ // Inits object and pushes it into work. Can be used to init/reset(update) object by current DOM.
253
+ reset: function () {
254
+ // Maybe we are already using floating toolbar - just remove it to update from html
255
+ if (this.headerCopy) {
256
+ this.headerCopy.remove();
257
+ }
258
+ this.createToolbar();
259
+ this.updateForScroll();
260
+ },
261
+
262
+ // Creates toolbar and inits all needed properties
263
+ createToolbar: function () {
264
+ if (!this.compatible) {
265
+ return;
266
+ }
267
+
268
+ // Extract header that we will use as toolbar
269
+ var headers = $$('.content-header');
270
+ for (var i = headers.length - 1; i >= 0; i--) {
271
+ if (!headers[i].hasClassName('skip-header')) {
272
+ this.header = headers[i];
273
+ break;
274
+ }
275
+ }
276
+ if (!this.header) {
277
+ return;
278
+ }
279
+
280
+ // Calculate header offset once - for optimization
281
+ this.headerOffset = Element.cumulativeOffset(this.header)[1];
282
+
283
+ // Toolbar buttons
284
+ var buttons = $$('.content-buttons')[0];
285
+ if (buttons) {
286
+ // Wrap buttons with 'placeholder' div - to serve as container for buttons
287
+ Element.insert(buttons, {before: '<div class="content-buttons-placeholder"></div>'});
288
+ buttons.placeholder = buttons.previous('.content-buttons-placeholder');
289
+ buttons.remove();
290
+ buttons.placeholder.appendChild(buttons);
291
+
292
+ this.headerOffset = Element.cumulativeOffset(buttons)[1];
293
+ }
294
+
295
+ // Create copy of header, that will serve as floating toolbar docked to top of window
296
+ this.headerCopy = $(document.createElement('div'));
297
+ this.headerCopy.appendChild(this.header.cloneNode(true));
298
+ document.body.insertBefore(this.headerCopy, document.body.lastChild)
299
+ this.headerCopy.addClassName('content-header-floating');
300
+
301
+ // Remove duplicated buttons and their container
302
+ var placeholder = this.headerCopy.down('.content-buttons-placeholder');
303
+ if (placeholder) {
304
+ placeholder.remove();
305
+ }
306
+ },
307
+
308
+ // Checks whether object properties are ready and valid
309
+ ready: function () {
310
+ // Return definitely boolean value
311
+ return (this.compatible && this.header && this.headerCopy && this.headerCopy.parentNode) ? true : false;
312
+ },
313
+
314
+ // Updates toolbars for current scroll - shows/hides normal and floating toolbar
315
+ updateForScroll: function () {
316
+ if (!this.ready()) {
317
+ return;
318
+ }
319
+
320
+ // scrolling offset calculation via www.quirksmode.org
321
+ var s;
322
+ if (self.pageYOffset){
323
+ s = self.pageYOffset;
324
+ } else if (document.documentElement && document.documentElement.scrollTop) {
325
+ s = document.documentElement.scrollTop;
326
+ } else if (document.body) {
327
+ s = document.body.scrollTop;
328
+ }
329
+
330
+ // Show floating or normal toolbar
331
+ if (s > this.headerOffset) {
332
+ // Page offset is more than header offset, switch to floating toolbar
333
+ this.showFloatingToolbar();
334
+ } else {
335
+ // Page offset is less than header offset, switch to normal toolbar
336
+ this.showNormalToolbar();
337
+ }
338
+ },
339
+
340
+ // Shows normal toolbar (and hides floating one)
341
+ showNormalToolbar: function () {
342
+ if (!this.ready()) {
343
+ return;
344
+ }
345
+
346
+ var buttons = $$('.content-buttons')[0];
347
+ if (buttons && buttons.oldParent && buttons.oldParent != buttons.parentNode) {
348
+ buttons.remove();
349
+ if(buttons.oldBefore) {
350
+ buttons.oldParent.insertBefore(buttons, buttons.oldBefore);
351
+ } else {
352
+ buttons.oldParent.appendChild(buttons);
353
+ }
354
+ }
355
+
356
+ this.headerCopy.style.display = 'none';
357
+ },
358
+
359
+ // Shows floating toolbar (and hides normal one)
360
+ // Notice that buttons could had changed in html by setting new inner html,
361
+ // so our added custom properties (placeholder, oldParent) can be not present in them any more
362
+ showFloatingToolbar: function () {
363
+ if (!this.ready()) {
364
+ return;
365
+ }
366
+
367
+ var buttons = $$('.content-buttons')[0];
368
+
369
+ if (buttons) {
370
+ // Remember original parent in normal toolbar to which these buttons belong
371
+ if (!buttons.oldParent) {
372
+ buttons.oldParent = buttons.parentNode;
373
+ buttons.oldBefore = buttons.previous();
374
+ }
375
+
376
+ // Move buttons from normal to floating toolbar
377
+ if (buttons.oldParent == buttons.parentNode) {
378
+ // Make static dimensions for placeholder, so it's not collapsed when buttons are removed
379
+ if (buttons.placeholder) {
380
+ var dimensions = buttons.placeholder.getDimensions()
381
+ buttons.placeholder.style.width = dimensions.width + 'px';
382
+ buttons.placeholder.style.height = dimensions.height + 'px';
383
+ }
384
+
385
+ // Move to floating
386
+ var target = this.headerCopy.down('div');
387
+ if (target) {
388
+ buttons.hide();
389
+ buttons.remove();
390
+
391
+ target.appendChild(buttons);
392
+ buttons.show();
393
+ }
394
+ }
395
+ }
396
+
397
+ this.headerCopy.style.display = 'block';
398
+ },
399
+
400
+ // Starts object on window load
401
+ startOnLoad: function () {
402
+ if (!this.compatible) {
403
+ return;
404
+ }
405
+
406
+ if (!this.funcOnWindowLoad) {
407
+ this.funcOnWindowLoad = this.start.bind(this);
408
+ }
409
+ Event.observe(window, 'load', this.funcOnWindowLoad);
410
+ },
411
+
412
+ // Removes object start on window load
413
+ removeOnLoad: function () {
414
+ if (!this.funcOnWindowLoad) {
415
+ return;
416
+ }
417
+ Event.stopObserving(window, 'load', this.funcOnWindowLoad);
418
+ },
419
+
420
+ // Starts object by creating toolbar and enabling scroll/resize events
421
+ start: function () {
422
+ if (!this.compatible) {
423
+ return;
424
+ }
425
+
426
+ this.reset();
427
+ this.startListening();
428
+ },
429
+
430
+ // Stops object by removing toolbar and stopping listening to events
431
+ stop: function () {
432
+ this.stopListening();
433
+ this.removeOnLoad();
434
+ this.showNormalToolbar();
435
+ },
436
+
437
+ // Addes events on scroll/resize
438
+ startListening: function () {
439
+ if (this.eventsAdded) {
440
+ return;
441
+ }
442
+
443
+ if (!this.funcUpdateForViewport) {
444
+ this.funcUpdateForViewport = this.updateForScroll.bind(this);
445
+ }
446
+
447
+ Event.observe(window, 'scroll', this.funcUpdateForViewport);
448
+ Event.observe(window, 'resize', this.funcUpdateForViewport);
449
+
450
+ this.eventsAdded = true;
451
+ },
452
+
453
+ // Removes listening to events on resize/update
454
+ stopListening: function () {
455
+ if (!this.eventsAdded) {
456
+ return;
457
+ }
458
+ Event.stopObserving(window, 'scroll', this.funcUpdateForViewport);
459
+ Event.stopObserving(window, 'resize', this.funcUpdateForViewport);
460
+
461
+ this.eventsAdded = false;
462
+ }
463
+ }
464
+
465
+ // Deprecated since 1.4.2.0-beta1 - use toolbarToggle.reset() instead
466
+ function updateTopButtonToolbarToggle()
467
+ {
468
+ toolbarToggle.reset();
469
+ }
470
+
471
+ // Deprecated since 1.4.2.0-beta1 - use toolbarToggle.createToolbar() instead
472
+ function createTopButtonToolbarToggle()
473
+ {
474
+ toolbarToggle.createToolbar();
475
+ }
476
+
477
+ // Deprecated since 1.4.2.0-beta1 - use toolbarToggle.updateForScroll() instead
478
+ function floatingTopButtonToolbarToggle()
479
+ {
480
+ toolbarToggle.updateForScroll();
481
+ }
482
+
483
+ // Start toolbar on window load
484
+ toolbarToggle.startOnLoad();
485
+
486
+
487
+ /** Cookie Reading And Writing **/
488
+
489
+ var Cookie = {
490
+ all: function() {
491
+ var pairs = document.cookie.split(';');
492
+ var cookies = {};
493
+ pairs.each(function(item, index) {
494
+ var pair = item.strip().split('=');
495
+ cookies[unescape(pair[0])] = unescape(pair[1]);
496
+ });
497
+
498
+ return cookies;
499
+ },
500
+ read: function(cookieName) {
501
+ var cookies = this.all();
502
+ if(cookies[cookieName]) {
503
+ return cookies[cookieName];
504
+ }
505
+ return null;
506
+ },
507
+ write: function(cookieName, cookieValue, cookieLifeTime) {
508
+ var expires = '';
509
+ if (cookieLifeTime) {
510
+ var date = new Date();
511
+ date.setTime(date.getTime()+(cookieLifeTime*1000));
512
+ expires = '; expires='+date.toGMTString();
513
+ }
514
+ var urlPath = '/' + BASE_URL.split('/').slice(3).join('/'); // Get relative path
515
+ document.cookie = escape(cookieName) + "=" + escape(cookieValue) + expires + "; path=" + urlPath;
516
+ },
517
+ clear: function(cookieName) {
518
+ this.write(cookieName, '', -1);
519
+ }
520
+ };
521
+
522
+ var Fieldset = {
523
+ cookiePrefix: 'fh-',
524
+ applyCollapse: function(containerId) {
525
+ //var collapsed = Cookie.read(this.cookiePrefix + containerId);
526
+ //if (collapsed !== null) {
527
+ // Cookie.clear(this.cookiePrefix + containerId);
528
+ //}
529
+ if ($(containerId + '-state')) {
530
+ collapsed = $(containerId + '-state').value == 1 ? 0 : 1;
531
+ } else {
532
+ collapsed = $(containerId + '-head').collapsed;
533
+ }
534
+ if (collapsed==1 || collapsed===undefined) {
535
+ $(containerId + '-head').removeClassName('open');
536
+ $(containerId).hide();
537
+ } else {
538
+ $(containerId + '-head').addClassName('open');
539
+ $(containerId).show();
540
+ }
541
+ },
542
+ toggleCollapse: function(containerId, saveThroughAjax) {
543
+ if ($(containerId + '-state')) {
544
+ collapsed = $(containerId + '-state').value == 1 ? 0 : 1;
545
+ } else {
546
+ collapsed = $(containerId + '-head').collapsed;
547
+ }
548
+ //Cookie.read(this.cookiePrefix + containerId);
549
+ if(collapsed==1 || collapsed===undefined) {
550
+ //Cookie.write(this.cookiePrefix + containerId, 0, 30*24*60*60);
551
+ if ($(containerId + '-state')) {
552
+ $(containerId + '-state').value = 1;
553
+ }
554
+ $(containerId + '-head').collapsed = 0;
555
+ } else {
556
+ //Cookie.clear(this.cookiePrefix + containerId);
557
+ if ($(containerId + '-state')) {
558
+ $(containerId + '-state').value = 0;
559
+ }
560
+ $(containerId + '-head').collapsed = 1;
561
+ }
562
+
563
+ this.applyCollapse(containerId);
564
+ if (typeof saveThroughAjax != "undefined") {
565
+ this.saveState(saveThroughAjax, {container: containerId, value: $(containerId + '-state').value});
566
+ }
567
+ },
568
+ addToPrefix: function (value) {
569
+ this.cookiePrefix += value + '-';
570
+ },
571
+ saveState: function(url, parameters) {
572
+ new Ajax.Request(url, {
573
+ method: 'get',
574
+ parameters: Object.toQueryString(parameters),
575
+ loaderArea: false
576
+ });
577
+ }
578
+ };
579
+
580
+ var Base64 = {
581
+ // private property
582
+ _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
583
+ //'+/=', '-_,'
584
+ // public method for encoding
585
+ encode: function (input) {
586
+ var output = "";
587
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
588
+ var i = 0;
589
+
590
+ input = Base64._utf8_encode(input);
591
+
592
+ while (i < input.length) {
593
+
594
+ chr1 = input.charCodeAt(i++);
595
+ chr2 = input.charCodeAt(i++);
596
+ chr3 = input.charCodeAt(i++);
597
+
598
+ enc1 = chr1 >> 2;
599
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
600
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
601
+ enc4 = chr3 & 63;
602
+
603
+ if (isNaN(chr2)) {
604
+ enc3 = enc4 = 64;
605
+ } else if (isNaN(chr3)) {
606
+ enc4 = 64;
607
+ }
608
+ output = output +
609
+ this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
610
+ this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
611
+ }
612
+
613
+ return output;
614
+ },
615
+
616
+ // public method for decoding
617
+ decode: function (input) {
618
+ var output = "";
619
+ var chr1, chr2, chr3;
620
+ var enc1, enc2, enc3, enc4;
621
+ var i = 0;
622
+
623
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
624
+
625
+ while (i < input.length) {
626
+
627
+ enc1 = this._keyStr.indexOf(input.charAt(i++));
628
+ enc2 = this._keyStr.indexOf(input.charAt(i++));
629
+ enc3 = this._keyStr.indexOf(input.charAt(i++));
630
+ enc4 = this._keyStr.indexOf(input.charAt(i++));
631
+
632
+ chr1 = (enc1 << 2) | (enc2 >> 4);
633
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
634
+ chr3 = ((enc3 & 3) << 6) | enc4;
635
+
636
+ output = output + String.fromCharCode(chr1);
637
+
638
+ if (enc3 != 64) {
639
+ output = output + String.fromCharCode(chr2);
640
+ }
641
+ if (enc4 != 64) {
642
+ output = output + String.fromCharCode(chr3);
643
+ }
644
+ }
645
+ output = Base64._utf8_decode(output);
646
+ return output;
647
+ },
648
+
649
+ mageEncode: function(input){
650
+ return this.encode(input).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ',');
651
+ },
652
+
653
+ mageDecode: function(output){
654
+ output = output.replace(/\-/g, '+').replace(/_/g, '/').replace(/,/g, '=');
655
+ return this.decode(output);
656
+ },
657
+
658
+ idEncode: function(input){
659
+ return this.encode(input).replace(/\+/g, ':').replace(/\//g, '_').replace(/=/g, '-');
660
+ },
661
+
662
+ idDecode: function(output){
663
+ output = output.replace(/\-/g, '=').replace(/_/g, '/').replace(/\:/g, '\+');
664
+ return this.decode(output);
665
+ },
666
+
667
+ // private method for UTF-8 encoding
668
+ _utf8_encode : function (string) {
669
+ string = string.replace(/\r\n/g,"\n");
670
+ var utftext = "";
671
+
672
+ for (var n = 0; n < string.length; n++) {
673
+
674
+ var c = string.charCodeAt(n);
675
+
676
+ if (c < 128) {
677
+ utftext += String.fromCharCode(c);
678
+ }
679
+ else if((c > 127) && (c < 2048)) {
680
+ utftext += String.fromCharCode((c >> 6) | 192);
681
+ utftext += String.fromCharCode((c & 63) | 128);
682
+ }
683
+ else {
684
+ utftext += String.fromCharCode((c >> 12) | 224);
685
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
686
+ utftext += String.fromCharCode((c & 63) | 128);
687
+ }
688
+ }
689
+ return utftext;
690
+ },
691
+
692
+ // private method for UTF-8 decoding
693
+ _utf8_decode : function (utftext) {
694
+ var string = "";
695
+ var i = 0;
696
+ var c = c1 = c2 = 0;
697
+
698
+ while ( i < utftext.length ) {
699
+
700
+ c = utftext.charCodeAt(i);
701
+
702
+ if (c < 128) {
703
+ string += String.fromCharCode(c);
704
+ i++;
705
+ }
706
+ else if((c > 191) && (c < 224)) {
707
+ c2 = utftext.charCodeAt(i+1);
708
+ string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
709
+ i += 2;
710
+ }
711
+ else {
712
+ c2 = utftext.charCodeAt(i+1);
713
+ c3 = utftext.charCodeAt(i+2);
714
+ string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
715
+ i += 3;
716
+ }
717
+ }
718
+ return string;
719
+ }
720
+ };
721
+
722
+ /**
723
+ * Array functions
724
+ */
725
+
726
+ /**
727
+ * Callback function for sort numeric values
728
+ *
729
+ * @param val1
730
+ * @param val2
731
+ */
732
+ function sortNumeric(val1, val2)
733
+ {
734
+ return val1 - val2;
735
+ }
js/mage/adminhtml/uploader.js ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ /**
26
+ * Convert a single file-input element into a 'multiple' input list
27
+ *
28
+ * Usage:
29
+ *
30
+ * 1. Create a file input element (no name)
31
+ * eg. <input type="file" id="first_file_element">
32
+ *
33
+ * 2. Create a DIV for the output to be written to
34
+ * eg. <div id="files_list"></div>
35
+ *
36
+ * 3. Instantiate a MultiSelector object, passing in the DIV and an (optional) maximum number of files
37
+ * eg. var multi_selector = new MultiSelector( document.getElementById( 'files_list' ), 3 );
38
+ *
39
+ * 4. Add the first element
40
+ * eg. multi_selector.addElement( document.getElementById( 'first_file_element' ) );
41
+ *
42
+ * 5. That's it.
43
+ *
44
+ * You might (will) want to play around with the addListRow() method to make the output prettier.
45
+ *
46
+ * You might also want to change the line
47
+ * element.name = 'file_' + this.count;
48
+ * ...to a naming convention that makes more sense to you.
49
+ *
50
+ */
51
+ function MultiSelector( list_target, field_name, max, new_element_html, delete_text, new_file_input ){
52
+
53
+ // Where to write the list
54
+ this.list_target = list_target;
55
+ // Field name
56
+ this.field_name = field_name;
57
+ // How many elements?
58
+ this.count = 0;
59
+ // How many elements?
60
+ this.id = 0;
61
+ // Is there a maximum?
62
+ if( max ){
63
+ this.max = max;
64
+ } else {
65
+ this.max = -1;
66
+ };
67
+ this.new_element_html = new_element_html;
68
+ this.delete_text = delete_text;
69
+ this.new_file_input = new_file_input;
70
+
71
+ /**
72
+ * Add a new file input element
73
+ */
74
+ this.addElement = function( element ){
75
+
76
+ // Make sure it's a file input element
77
+ if( element.tagName == 'INPUT' && element.type == 'file' ){
78
+
79
+ // Element name -- what number am I?
80
+ // element.name = 'file_' + this.id++;
81
+ this.id++;
82
+ element.name = this.field_name + '[]';
83
+
84
+ // Add reference to this object
85
+ element.multi_selector = this;
86
+
87
+ // What to do when a file is selected
88
+ element.onchange = function(){
89
+
90
+ // New file input
91
+ var new_element = document.createElement( 'input' );
92
+ new_element.type = 'file';
93
+
94
+ // Add new element
95
+ this.parentNode.insertBefore( new_element, this );
96
+
97
+ // Apply 'update' to element
98
+ this.multi_selector.addElement( new_element );
99
+
100
+ // Update list
101
+ this.multi_selector.addListRow( this );
102
+
103
+ // Hide this: we can't use display:none because Safari doesn't like it
104
+ this.style.position = 'absolute';
105
+ this.style.left = '-1000px';
106
+
107
+ };
108
+ // If we've reached maximum number, disable input element
109
+ if( this.max != -1 && this.count >= this.max ){
110
+ element.disabled = true;
111
+ };
112
+
113
+ // File element counter
114
+ this.count++;
115
+ // Most recent element
116
+ this.current_element = element;
117
+
118
+ } else {
119
+ // This can only be applied to file input elements!
120
+ alert( 'Error: not a file input element' );
121
+ };
122
+
123
+ };
124
+
125
+ /**
126
+ * Add a new row to the list of files
127
+ */
128
+ this.addListRow = function( element ){
129
+
130
+ /*
131
+ // Row div
132
+ var new_row = document.createElement( 'div' );
133
+ */
134
+
135
+ // Sort order input
136
+ var new_row_input = document.createElement( 'input' );
137
+ new_row_input.type = 'text';
138
+ new_row_input.name = 'general[position_new][]';
139
+ new_row_input.size = '3';
140
+ new_row_input.value = '0';
141
+
142
+ // Delete button
143
+ var new_row_button = document.createElement( 'input' );
144
+ new_row_button.type = 'checkbox';
145
+ new_row_button.value = 'Delete';
146
+
147
+ var new_row_span = document.createElement( 'span' );
148
+ new_row_span.innerHTML = this.delete_text;
149
+
150
+ table = this.list_target;
151
+
152
+ // no of rows in the table:
153
+ noOfRows = table.rows.length;
154
+
155
+ // no of columns in the pre-last row:
156
+ noOfCols = table.rows[noOfRows-2].cells.length;
157
+
158
+ // insert row at pre-last:
159
+ var x=table.insertRow(noOfRows-1);
160
+
161
+ // insert cells in row.
162
+ for (var j = 0; j < noOfCols; j++) {
163
+
164
+ newCell = x.insertCell(j);
165
+ newCell.align = "center";
166
+ newCell.valign = "middle";
167
+
168
+ // if (j==0) {
169
+ // newCell.innerHTML = this.new_element_html.replace(/%file%/g, element.value).replace(/%id%/g, this.id).replace(/%j%/g, j)
170
+ // + this.new_file_input.replace(/%file%/g, element.value).replace(/%id%/g, this.id).replace(/%j%/g, j);
171
+ // }
172
+ if (j==3) {
173
+ newCell.appendChild( new_row_input );
174
+ }
175
+ else if (j==4) {
176
+ newCell.appendChild( new_row_button );
177
+ }
178
+ else {
179
+ // newCell.innerHTML = this.new_file_input.replace(/%file%/g, element.value).replace(/%id%/g, this.id).replace(/%j%/g, j);
180
+ newCell.innerHTML = this.new_file_input.replace(/%id%/g, this.id).replace(/%j%/g, j);
181
+ }
182
+
183
+ // newCell.innerHTML="NEW CELL" + j;
184
+
185
+ }
186
+
187
+ // References
188
+ // new_row.element = element;
189
+
190
+ // Delete function
191
+ new_row_button.onclick= function(){
192
+
193
+ // Remove element from form
194
+ this.parentNode.element.parentNode.removeChild( this.parentNode.element );
195
+
196
+ // Remove this row from the list
197
+ this.parentNode.parentNode.removeChild( this.parentNode );
198
+
199
+ // Decrement counter
200
+ this.parentNode.element.multi_selector.count--;
201
+
202
+ // Re-enable input element (if it's disabled)
203
+ this.parentNode.element.multi_selector.current_element.disabled = false;
204
+
205
+ // Appease Safari
206
+ // without it Safari wants to reload the browser window
207
+ // which nixes your already queued uploads
208
+ return false;
209
+ };
210
+
211
+ // Set row value
212
+ // new_row.innerHTML = this.new_element_html.replace(/%file%/g, element.value).replace(/%id%/g, this.id);
213
+
214
+ // Add button
215
+ // new_row.appendChild( new_row_button );
216
+ // new_row.appendChild( new_row_span );
217
+
218
+ // Add it to the list
219
+ // this.list_target.appendChild( new_row );
220
+
221
+ };
222
+
223
+ // Insert row into table.
224
+ this.insRowLast = function ( table ){
225
+
226
+ // noOfRpws in table.
227
+ noOfRows = table.rows.length;
228
+ // no of columns of last row.
229
+ noOfCols = table.rows[noOfRows-1].cells.length;
230
+
231
+ // insert row at last.
232
+ var x=table.insertRow(noOfRows);
233
+
234
+ // insert cells in row.
235
+ for (var j = 0; j < noOfCols; j++) {
236
+ newCell = x.insertCell(j);
237
+ newCell.innerHTML="NEW CELL" + j;
238
+ }
239
+
240
+ };
241
+
242
+ //delete row
243
+ this.deleteRow = function ( table, row ){
244
+
245
+ table.deleteRow(row);
246
+
247
+ };
248
+
249
+ //delete last row
250
+ this.deleteRow = function ( table ){
251
+
252
+ noOfRows = table.rows.length;
253
+ table.deleteRow(noOfRows-1);
254
+
255
+ };
256
+
257
+
258
+ };
js/mage/adminhtml/variables.js ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ var Variables = {
27
+ textareaElementId: null,
28
+ variablesContent: null,
29
+ dialogWindow: null,
30
+ dialogWindowId: 'variables-chooser',
31
+ overlayShowEffectOptions: null,
32
+ overlayHideEffectOptions: null,
33
+ insertFunction: 'Variables.insertVariable',
34
+ init: function(textareaElementId, insertFunction) {
35
+ if ($(textareaElementId)) {
36
+ this.textareaElementId = textareaElementId;
37
+ }
38
+ if (insertFunction) {
39
+ this.insertFunction = insertFunction;
40
+ }
41
+ },
42
+
43
+ resetData: function() {
44
+ this.variablesContent = null;
45
+ this.dialogWindow = null;
46
+ },
47
+
48
+ openVariableChooser: function(variables) {
49
+ if (this.variablesContent == null && variables) {
50
+ this.variablesContent = '<ul>';
51
+ variables.each(function(variableGroup) {
52
+ if (variableGroup.label && variableGroup.value) {
53
+ this.variablesContent += '<li><b>' + variableGroup.label + '</b></li>';
54
+ (variableGroup.value).each(function(variable){
55
+ if (variable.value && variable.label) {
56
+ this.variablesContent += '<li style="padding-left: 20px;">' +
57
+ this.prepareVariableRow(variable.value, variable.label) + '</li>';
58
+ }
59
+ }.bind(this));
60
+ }
61
+ }.bind(this));
62
+ this.variablesContent += '</ul>';
63
+ }
64
+ if (this.variablesContent) {
65
+ this.openDialogWindow(this.variablesContent);
66
+ }
67
+ },
68
+ openDialogWindow: function(variablesContent) {
69
+ if ($(this.dialogWindowId) && typeof(Windows) != 'undefined') {
70
+ Windows.focus(this.dialogWindowId);
71
+ return;
72
+ }
73
+
74
+ this.overlayShowEffectOptions = Windows.overlayShowEffectOptions;
75
+ this.overlayHideEffectOptions = Windows.overlayHideEffectOptions;
76
+ Windows.overlayShowEffectOptions = {duration:0};
77
+ Windows.overlayHideEffectOptions = {duration:0};
78
+
79
+ this.dialogWindow = Dialog.info(variablesContent, {
80
+ draggable:true,
81
+ resizable:true,
82
+ closable:true,
83
+ className:"magento",
84
+ windowClassName:"popup-window",
85
+ title:'Insert Variable...',
86
+ width:700,
87
+ //height:270,
88
+ zIndex:1000,
89
+ recenterAuto:false,
90
+ hideEffect:Element.hide,
91
+ showEffect:Element.show,
92
+ id:this.dialogWindowId,
93
+ onClose: this.closeDialogWindow.bind(this)
94
+ });
95
+ variablesContent.evalScripts.bind(variablesContent).defer();
96
+ },
97
+ closeDialogWindow: function(window) {
98
+ if (!window) {
99
+ window = this.dialogWindow;
100
+ }
101
+ if (window) {
102
+ window.close();
103
+ Windows.overlayShowEffectOptions = this.overlayShowEffectOptions;
104
+ Windows.overlayHideEffectOptions = this.overlayHideEffectOptions;
105
+ }
106
+ },
107
+ prepareVariableRow: function(varValue, varLabel) {
108
+ var value = (varValue).replace(/"/g, '&quot;').replace(/'/g, '\\&#39;');
109
+ var content = '<a href="#" onclick="'+this.insertFunction+'(\''+ value +'\');">' + varLabel + '</a>';
110
+ return content;
111
+ },
112
+ insertVariable: function(value) {
113
+ this.closeDialogWindow(this.dialogWindow);
114
+ var textareaElm = $(this.textareaElementId);
115
+ if (textareaElm) {
116
+ var scrollPos = textareaElm.scrollTop;
117
+ updateElementAtCursor(textareaElm, value);
118
+ textareaElm.focus();
119
+ textareaElm.scrollTop = scrollPos;
120
+ textareaElm = null;
121
+ }
122
+ return;
123
+ }
124
+ };
125
+
126
+ MagentovariablePlugin = {
127
+ editor: null,
128
+ variables: null,
129
+ textareaId: null,
130
+ setEditor: function(editor) {
131
+ this.editor = editor;
132
+ },
133
+ loadChooser: function(url, textareaId) {
134
+ this.textareaId = textareaId;
135
+ if (this.variables == null) {
136
+ new Ajax.Request(url, {
137
+ parameters: {},
138
+ onComplete: function (transport) {
139
+ if (transport.responseText.isJSON()) {
140
+ Variables.init(null, 'MagentovariablePlugin.insertVariable');
141
+ this.variables = transport.responseText.evalJSON();
142
+ this.openChooser(this.variables);
143
+ }
144
+ }.bind(this)
145
+ });
146
+ } else {
147
+ this.openChooser(this.variables);
148
+ }
149
+ return;
150
+ },
151
+ openChooser: function(variables) {
152
+ Variables.openVariableChooser(variables);
153
+ },
154
+ insertVariable : function (value) {
155
+ if (this.textareaId) {
156
+ Variables.init(this.textareaId);
157
+ Variables.insertVariable(value);
158
+ } else {
159
+ Variables.closeDialogWindow();
160
+ this.editor.execCommand('mceInsertContent', false, value);
161
+ }
162
+ return;
163
+ }
164
+ };
js/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentovariable/editor_plugin.js ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ tinyMCE.addI18n({en:{
27
+ magentovariable:
28
+ {
29
+ insert_variable : "Insert Variable"
30
+ }
31
+ }});
32
+
33
+ (function() {
34
+ tinymce.create('tinymce.plugins.MagentovariablePlugin', {
35
+ /**
36
+ * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
37
+ * @param {string} url Absolute URL to where the plugin is located.
38
+ */
39
+ init : function(ed, url) {
40
+ ed.addCommand('mceMagentovariable', function() {
41
+ var pluginSettings = ed.settings.magentoPluginsOptions.get('magentovariable');
42
+ MagentovariablePlugin.setEditor(ed);
43
+ MagentovariablePlugin.loadChooser(pluginSettings.url, null);
44
+ });
45
+
46
+ // Register Widget plugin button
47
+ ed.addButton('magentovariable', {
48
+ title : 'magentovariable.insert_variable',
49
+ cmd : 'mceMagentovariable',
50
+ image : url + '/img/icon.gif'
51
+ });
52
+ },
53
+
54
+ getInfo : function() {
55
+ return {
56
+ longname : 'Magento Variable Manager Plugin for TinyMCE 3.x',
57
+ author : 'Magento Core Team',
58
+ authorurl : 'http://magentocommerce.com',
59
+ infourl : 'http://magentocommerce.com',
60
+ version : "1.0"
61
+ };
62
+ }
63
+ });
64
+
65
+ // Register plugin
66
+ tinymce.PluginManager.add('magentovariable', tinymce.plugins.MagentovariablePlugin);
67
+ })();
js/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentovariable/img/icon.gif ADDED
Binary file
js/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ tinyMCE.addI18n({en:{
26
+ magentowidget:
27
+ {
28
+ insert_widget : "Insert Widget"
29
+ }
30
+ }});
31
+
32
+ /*
33
+ TODO: Apply JStrim to reduce file size
34
+ */
35
+
36
+ (function() {
37
+ tinymce.create('tinymce.plugins.MagentowidgetPlugin', {
38
+ /**
39
+ * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
40
+ * @param {string} url Absolute URL to where the plugin is located.
41
+ */
42
+ init : function(ed, url) {
43
+ ed.addCommand('mceMagentowidget', function() {
44
+ widgetTools.openDialog(ed.settings.magentowidget_url + 'widget_target_id/' + ed.getElement().id + '/');
45
+ });
46
+
47
+ // Register Widget plugin button
48
+ ed.addButton('magentowidget', {
49
+ title : 'magentowidget.insert_widget',
50
+ cmd : 'mceMagentowidget',
51
+ image : url + '/img/icon.gif'
52
+ });
53
+
54
+ // Add a node change handler, selects the button in the UI when a image is selected
55
+ ed.onNodeChange.add(function(ed, cm, n) {
56
+ cm.setActive('magentowidget', false);
57
+ if (n.id && n.nodeName == 'IMG') {
58
+ var widgetCode = Base64.idDecode(n.id);
59
+ if (widgetCode.indexOf('{{widget') != -1) {
60
+ cm.setActive('magentowidget', true);
61
+ }
62
+ }
63
+ });
64
+
65
+ // Add a widget placeholder image double click callback
66
+ ed.onDblClick.add(function(ed, e) {
67
+ var n = e.target;
68
+ if (n.id && n.nodeName == 'IMG') {
69
+ var widgetCode = Base64.idDecode(n.id);
70
+ if (widgetCode.indexOf('{{widget') != -1) {
71
+ ed.execCommand('mceMagentowidget');
72
+ }
73
+ }
74
+ });
75
+ },
76
+
77
+ getInfo : function() {
78
+ return {
79
+ longname : 'Magento Widget Manager Plugin for TinyMCE 3.x',
80
+ author : 'Magento Core Team',
81
+ authorurl : 'http://magentocommerce.com',
82
+ infourl : 'http://magentocommerce.com',
83
+ version : "1.0"
84
+ };
85
+ }
86
+ });
87
+
88
+ // Register plugin
89
+ tinymce.PluginManager.add('magentowidget', tinymce.plugins.MagentowidgetPlugin);
90
+ })();
js/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/img/icon.gif ADDED
Binary file
js/mage/adminhtml/wysiwyg/tiny_mce/setup.js ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ var tinyMceWysiwygSetup = Class.create();
27
+ tinyMceWysiwygSetup.prototype =
28
+ {
29
+ mediaBrowserOpener: null,
30
+ mediaBrowserTargetElementId: null,
31
+
32
+ initialize: function(htmlId, config)
33
+ {
34
+ this.id = htmlId;
35
+ this.config = config;
36
+ varienGlobalEvents.attachEventHandler('tinymceChange', this.onChangeContent.bind(this));
37
+ this.notifyFirebug();
38
+ if(typeof tinyMceEditors == 'undefined') {
39
+ tinyMceEditors = $H({});
40
+ }
41
+ tinyMceEditors.set(this.id, this);
42
+ },
43
+
44
+ notifyFirebug: function() {
45
+ if (firebugEnabled() && $('fb' + this.id) == undefined) {
46
+ var noticeHtml = '<ul class="messages message-firebug" id="fb' + this.id + '"><li class="notice-msg">';
47
+ noticeHtml+= '<ul><li>';
48
+ noticeHtml+= '<b>' + this.config.firebug_warning_title + ':</b> ';
49
+ noticeHtml+= this.config.firebug_warning_text;
50
+ noticeHtml+= ' <a id="hidefb' + this.id + '" href="">' + this.config.firebug_warning_anchor + '</a>';
51
+ noticeHtml+= '</li></ul>';
52
+ noticeHtml+= '</li></ul>';
53
+ $('buttons' + this.id).insert({before: noticeHtml});
54
+ Event.observe($('hidefb' + this.id), "click", function(e) {
55
+ $('fb' + this.id).remove();
56
+ Event.stop(e);
57
+ }.bind(this));
58
+ }
59
+ },
60
+
61
+ setup: function(mode)
62
+ {
63
+ if (this.config.widget_plugin_src) {
64
+ tinymce.PluginManager.load('magentowidget', this.config.widget_plugin_src);
65
+ }
66
+
67
+ if (this.config.plugins) {
68
+ (this.config.plugins).each(function(plugin){
69
+ tinymce.PluginManager.load(plugin.name, plugin.src);
70
+ });
71
+ }
72
+
73
+ tinyMCE.init(this.getSettings(mode));
74
+ },
75
+
76
+ getSettings: function(mode)
77
+ {
78
+ var plugins = 'safari,pagebreak,style,layer,table,advhr,advimage,emotions,iespell,media,searchreplace,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras';
79
+
80
+ if (this.config.widget_plugin_src) {
81
+ plugins = 'magentowidget,' + plugins;
82
+ }
83
+
84
+ if (this.config.plugins) {
85
+ var magentoPluginsOptions = $H({});
86
+ var magentoPlugins = '';
87
+ (this.config.plugins).each(function(plugin){
88
+ magentoPlugins = plugin.name + ',' + magentoPlugins;
89
+ magentoPluginsOptions.set(plugin.name, plugin.options);
90
+ });
91
+ if (magentoPlugins) {
92
+ plugins = '-' + magentoPlugins + plugins;
93
+ }
94
+ }
95
+
96
+ var settings = {
97
+ mode : (mode != undefined ? mode : 'none'),
98
+ elements : this.id,
99
+ theme : 'advanced',
100
+ plugins : plugins,
101
+ theme_advanced_buttons1 : magentoPlugins + 'magentowidget,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect',
102
+ theme_advanced_buttons2 : 'cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,forecolor,backcolor',
103
+ theme_advanced_buttons3 : 'tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,iespell,media,advhr,|,ltr,rtl,|,fullscreen',
104
+ theme_advanced_buttons4 : 'insertlayer,moveforward,movebackward,absolute,|,styleprops,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,pagebreak',
105
+ theme_advanced_toolbar_location : 'top',
106
+ theme_advanced_toolbar_align : 'left',
107
+ theme_advanced_statusbar_location : 'bottom',
108
+ theme_advanced_resizing : true,
109
+ convert_urls : false,
110
+ relative_urls : false,
111
+ content_css: this.config.content_css,
112
+ custom_popup_css: this.config.popup_css,
113
+ magentowidget_url: this.config.widget_window_url,
114
+ magentoPluginsOptions: magentoPluginsOptions,
115
+ doctype : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
116
+
117
+ setup : function(ed) {
118
+ ed.onSubmit.add(function(ed, e) {
119
+ varienGlobalEvents.fireEvent('tinymceSubmit', e);
120
+ });
121
+
122
+ ed.onPaste.add(function(ed, e, o) {
123
+ varienGlobalEvents.fireEvent('tinymcePaste', o);
124
+ });
125
+
126
+ ed.onBeforeSetContent.add(function(ed, o) {
127
+ varienGlobalEvents.fireEvent('tinymceBeforeSetContent', o);
128
+ });
129
+
130
+ ed.onSetContent.add(function(ed, o) {
131
+ varienGlobalEvents.fireEvent('tinymceSetContent', o);
132
+ });
133
+
134
+ ed.onSaveContent.add(function(ed, o) {
135
+ varienGlobalEvents.fireEvent('tinymceSaveContent', o);
136
+ });
137
+
138
+ ed.onChange.add(function(ed, l) {
139
+ varienGlobalEvents.fireEvent('tinymceChange', l);
140
+ });
141
+
142
+ ed.onExecCommand.add(function(ed, cmd, ui, val) {
143
+ varienGlobalEvents.fireEvent('tinymceExecCommand', cmd);
144
+ });
145
+ }
146
+ };
147
+
148
+ // Set the document base URL
149
+ if (this.config.document_base_url) {
150
+ settings.document_base_url = this.config.document_base_url;
151
+ }
152
+
153
+ if (this.config.files_browser_window_url) {
154
+ settings.file_browser_callback = function(fieldName, url, objectType, w) {
155
+ varienGlobalEvents.fireEvent("open_browser_callback", {win:w, type:objectType, field:fieldName});
156
+ };
157
+ }
158
+
159
+ if (this.config.width) {
160
+ settings.width = this.config.width;
161
+ }
162
+
163
+ if (this.config.height) {
164
+ settings.height = this.config.height;
165
+ }
166
+
167
+ return settings;
168
+ },
169
+
170
+ openFileBrowser: function(o) {
171
+ var typeTitle;
172
+ var storeId = this.config.store_id !== null ? this.config.store_id : 0;
173
+ var wUrl = this.config.files_browser_window_url +
174
+ 'target_element_id/' + this.id + '/' +
175
+ 'store/' + storeId + '/';
176
+
177
+ this.mediaBrowserOpener = o.win;
178
+ this.mediaBrowserOpener.blur();
179
+ this.mediaBrowserTargetElementId = o.field;
180
+
181
+ if (typeof(o.type) != 'undefined' && o.type != "") {
182
+ typeTitle = 'image' == o.type ? this.translate('Insert Image...') : this.translate('Insert Media...');
183
+ wUrl = wUrl + "type/" + o.type + "/";
184
+ } else {
185
+ typeTitle = this.translate('Insert File...');
186
+ }
187
+
188
+ MediabrowserUtility.openDialog(wUrl, false, false, typeTitle);
189
+ },
190
+
191
+ translate: function(string) {
192
+ return 'undefined' != typeof(Translator) ? Translator.translate(string) : string;
193
+ },
194
+
195
+ getMediaBrowserOpener: function() {
196
+ return this.mediaBrowserOpener;
197
+ },
198
+
199
+ getMediaBrowserTargetElementId: function() {
200
+ return this.mediaBrowserTargetElementId;
201
+ },
202
+
203
+ getToggleButton: function() {
204
+ return $('toggle' + this.id);
205
+ },
206
+
207
+ getPluginButtons: function() {
208
+ return $$('#buttons' + this.id + ' > button.plugin');
209
+ },
210
+
211
+ turnOn: function() {
212
+ this.closePopups();
213
+ this.setup();
214
+ tinyMCE.execCommand('mceAddControl', false, this.id);
215
+ this.getPluginButtons().each(function(e) {
216
+ e.hide();
217
+ });
218
+ },
219
+
220
+ turnOff: function() {
221
+ this.closePopups();
222
+ tinyMCE.execCommand('mceRemoveControl', false, this.id);
223
+ this.getPluginButtons().each(function(e) {
224
+ e.show();
225
+ });
226
+ },
227
+
228
+ closePopups: function() {
229
+ // close all popups to avoid problems with updating parent content area
230
+ closeEditorPopup('widget_window' + this.id);
231
+ closeEditorPopup('browser_window' + this.id);
232
+ },
233
+
234
+ toggle: function() {
235
+ if (!tinyMCE.get(this.id)) {
236
+ this.turnOn();
237
+ return true;
238
+ } else {
239
+ this.turnOff();
240
+ return false;
241
+ }
242
+ },
243
+
244
+ onFormValidation: function() {
245
+ if (tinyMCE.get(this.id)) {
246
+ $(this.id).value = tinyMCE.get(this.id).getContent();
247
+ }
248
+ },
249
+
250
+ onChangeContent: function() {
251
+ // Add "changed" to tab class if it exists
252
+ if(this.config.tab_id) {
253
+ var tab = $$('a[id$=' + this.config.tab_id + ']')[0];
254
+ if ($(tab) != undefined && $(tab).hasClassName('tab-item-link')) {
255
+ $(tab).addClassName('changed');
256
+ }
257
+ }
258
+ },
259
+
260
+ // retrieve directives URL with substituted directive value
261
+ makeDirectiveUrl: function(directive) {
262
+ return this.config.directives_url.replace('directive', 'directive/___directive/' + directive);
263
+ },
264
+
265
+ encodeDirectives: function(content) {
266
+ // collect all HTML tags with attributes that contain directives
267
+ return content.gsub(/<([a-z0-9\-\_]+.+?)([a-z0-9\-\_]+=".*?\{\{.+?\}\}.*?".+?)>/i, function(match) {
268
+ var attributesString = match[2];
269
+ // process tag attributes string
270
+ attributesString = attributesString.gsub(/([a-z0-9\-\_]+)="(.*?)(\{\{.+?\}\})(.*?)"/i, function(m) {
271
+ return m[1] + '="' + m[2] + this.makeDirectiveUrl(Base64.mageEncode(m[3])) + m[4] + '"';
272
+ }.bind(this));
273
+
274
+ return '<' + match[1] + attributesString + '>';
275
+
276
+ }.bind(this));
277
+ },
278
+
279
+ encodeWidgets: function(content) {
280
+ return content.gsub(/\{\{widget(.*?)\}\}/i, function(match){
281
+ var attributes = this.parseAttributesString(match[1]);
282
+ if (attributes.type) {
283
+ var placeholderFilename = attributes.type.replace(/\//g, "__") + ".gif";
284
+ if (!this.widgetPlaceholderExist(placeholderFilename)) {
285
+ placeholderFilename = 'default.gif';
286
+ }
287
+ var imageSrc = this.config.widget_images_url + placeholderFilename;
288
+ var imageHtml = '<img';
289
+ imageHtml+= ' id="' + Base64.idEncode(match[0]) + '"';
290
+ imageHtml+= ' src="' + imageSrc + '"';
291
+ imageHtml+= ' title="' + match[0].replace(/\{\{/g, '{').replace(/\}\}/g, '}').replace(/\"/g, '&quot;') + '"';
292
+ imageHtml+= '>';
293
+
294
+ return imageHtml;
295
+ }
296
+ }.bind(this));
297
+ },
298
+
299
+ decodeDirectives: function(content) {
300
+ // escape special chars in directives url to use it in regular expression
301
+ var url = this.makeDirectiveUrl('%directive%').replace(/([$^.?*!+:=()\[\]{}|\\])/g, '\\$1');
302
+ var reg = new RegExp(url.replace('%directive%', '([a-zA-Z0-9,_-]+)'));
303
+ return content.gsub(reg, function(match) {
304
+ return Base64.mageDecode(match[1]);
305
+ }.bind(this));
306
+ },
307
+
308
+ decodeWidgets: function(content) {
309
+ return content.gsub(/<img([^>]+id=\"[^>]+)>/i, function(match) {
310
+ var attributes = this.parseAttributesString(match[1]);
311
+ if(attributes.id) {
312
+ var widgetCode = Base64.idDecode(attributes.id);
313
+ if (widgetCode.indexOf('{{widget') != -1) {
314
+ return widgetCode;
315
+ }
316
+ return match[0];
317
+ }
318
+ return match[0];
319
+ }.bind(this));
320
+ },
321
+
322
+ parseAttributesString: function(attributes) {
323
+ var result = {};
324
+ attributes.gsub(/(\w+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/, function(match){
325
+ result[match[1]] = match[2];
326
+ });
327
+ return result;
328
+ },
329
+
330
+ beforeSetContent: function(o) {
331
+ if (this.config.add_widgets) {
332
+ o.content = this.encodeWidgets(o.content);
333
+ o.content = this.encodeDirectives(o.content);
334
+ } else if (this.config.add_directives) {
335
+ o.content = this.encodeDirectives(o.content);
336
+ }
337
+ },
338
+
339
+ saveContent: function(o) {
340
+ if (this.config.add_widgets) {
341
+ o.content = this.decodeWidgets(o.content);
342
+ o.content = this.decodeDirectives(o.content);
343
+ } else if (this.config.add_directives) {
344
+ o.content = this.decodeDirectives(o.content);
345
+ }
346
+ },
347
+
348
+ widgetPlaceholderExist: function(filename) {
349
+ return this.config.widget_placeholders.indexOf(filename) != -1;
350
+ }
351
+ }
js/mage/adminhtml/wysiwyg/tiny_mce/themes/advanced/skins/default/content.css ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ body, td, pre { color:#2f2f2f; font-family:Arial, Helvetica, sans-serif; font-size:12px; margin:8px; }
27
+ body { background:#fff; }
28
+ body.mceForceColors { background:#fff; color:#2f2f2f; }
29
+ h1 {font-size: 2em}
30
+ h2 {font-size: 1.5em}
31
+ h3 {font-size: 1.17em}
32
+ h4 {font-size: 1em}
33
+ h5 {font-size: .83em}
34
+ h6 {font-size: .75em}
35
+ .mceItemTable, .mceItemTable td, .mceItemTable th, .mceItemTable caption, .mceItemVisualAid {border: 1px dashed #BBB;}
36
+ img {border:0; vertical-align:middle; }
37
+ table {cursor:default}
38
+ table td, table th {cursor:text}
39
+ ins {border-bottom:1px solid green; text-decoration: none; color:green}
40
+ del {color:red; text-decoration:line-through}
41
+ cite {border-bottom:1px dashed blue}
42
+ acronym {border-bottom:1px dotted #CCC; cursor:help}
43
+ abbr, html\:abbr {border-bottom:1px dashed #CCC; cursor:help}
44
+
45
+ /* IE */
46
+ * html body {
47
+ scrollbar-3dlight-color:#F0F0EE;
48
+ scrollbar-arrow-color:#676662;
49
+ scrollbar-base-color:#F0F0EE;
50
+ scrollbar-darkshadow-color:#DDD;
51
+ scrollbar-face-color:#E0E0DD;
52
+ scrollbar-highlight-color:#F0F0EE;
53
+ scrollbar-shadow-color:#F0F0EE;
54
+ scrollbar-track-color:#F5F5F5;
55
+ }
js/mage/adminhtml/wysiwyg/tiny_mce/themes/advanced/skins/default/dialog.css ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ /* Browse */
27
+ a.pickcolor, a.browse {text-decoration:none}
28
+ a.browse span {display:block; width:20px; height:18px; background:url(../../img/icons.gif) -860px 0; border:1px solid #FFF; margin-left:1px;}
29
+ .mceOldBoxModel a.browse span {width:22px; height:20px;}
30
+ a.browse:hover span {border:1px solid #0A246A; background-color:#B2BBD0;}
31
+ a.browse span.disabled {border:1px solid white; opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)}
32
+ a.browse:hover span.disabled {border:1px solid white; background-color:transparent;}
33
+ a.pickcolor span {display:block; width:20px; height:16px; background:url(../../img/icons.gif) -840px 0; margin-left:2px;}
34
+ .mceOldBoxModel a.pickcolor span {width:21px; height:17px;}
35
+ a.pickcolor:hover span {background-color:#B2BBD0;}
36
+ a.pickcolor:hover span.disabled {}
37
+
38
+ /* Charmap */
39
+ table.charmap {border:1px solid #AAA; text-align:center}
40
+ td.charmap, #charmap a {width:18px; height:18px; color:#000; border:1px solid #AAA; text-align:center; font-size:12px; vertical-align:middle; line-height: 18px;}
41
+ #charmap a {display:block; color:#000; text-decoration:none; border:0}
42
+ #charmap a:hover {background:#CCC;color:#2B6FB6}
43
+ #charmap #codeN {font-size:10px; font-family:Arial,Helvetica,sans-serif; text-align:center}
44
+ #charmap #codeV {font-size:40px; height:80px; border:1px solid #AAA; text-align:center}
45
+
46
+ /* Source */
47
+ .wordWrapCode {vertical-align:middle; border:1px none #000000; background:transparent;}
48
+ .mceActionPanel {margin-top:5px;}
49
+
50
+ /* Tabs classes */
51
+ .tabs {width:100%; height:18px; line-height:normal; background:url(img/tabs.gif) repeat-x 0 -72px;}
52
+ .tabs ul {margin:0; padding:0; list-style:none;}
53
+ .tabs li {float:left; background:url(img/tabs.gif) no-repeat 0 0; margin:0 2px 0 0; padding:0 0 0 10px; line-height:17px; height:18px; display:block;}
54
+ .tabs li.current {background:url(img/tabs.gif) no-repeat 0 -18px; margin-right:2px;}
55
+ .tabs span {float:left; display:block; background:url(img/tabs.gif) no-repeat right -36px; padding:0px 10px 0 0;}
56
+ .tabs .current span {background:url(img/tabs.gif) no-repeat right -54px;}
57
+ .tabs a {text-decoration:none; font-family:Verdana, Arial; font-size:10px;}
58
+ .tabs a:link, .tabs a:visited, .tabs a:hover {color:black;}
59
+
60
+ /* Panels */
61
+ .panel_wrapper div.panel {display:none;}
62
+ .panel_wrapper div.current {display:block; width:100%; height:300px; overflow:visible;}
63
+ .panel_wrapper {border:1px solid #919B9C; border-top:0px; padding:10px; padding-top:5px; clear:both; background:white;}
64
+
65
+ /* Columns */
66
+ .column {float:left;}
67
+ .properties {width:100%;}
68
+ .properties .column1 {}
69
+ .properties .column2 {text-align:left;}
70
+
71
+ /* Dialog specific */
72
+ #link .panel_wrapper, #link div.current {height:125px;}
73
+ #image .panel_wrapper, #image div.current {height:200px;}
74
+ #plugintable thead {font-weight:bold; background:#DDD;}
75
+ #plugintable, #about #plugintable td {border:1px solid #919B9C;}
76
+ #plugintable {width:96%; margin-top:10px;}
77
+ #pluginscontainer {height:290px; overflow:auto;}
78
+ #colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;}
79
+ #colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;}
80
+ #colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;}
81
+ #colorpicker #light div {overflow:hidden;}
82
+ #colorpicker #previewblock {float:right; padding-left:10px; height:20px;}
83
+ #colorpicker .panel_wrapper div.current {height:175px;}
84
+ #colorpicker #namedcolors {width:150px;}
85
+ #colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;}
86
+ #colorpicker #colornamecontainer {margin-top:5px;}
87
+ #colorpicker #picker_panel fieldset {margin:auto;width:325px;}
js/mage/adminhtml/wysiwyg/widget.js ADDED
@@ -0,0 +1,396 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package Mage_Adminhtml
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ var widgetTools = {
27
+ getDivHtml: function(id, html) {
28
+ if (!html) html = '';
29
+ return '<div id="' + id + '">' + html + '</div>';
30
+ },
31
+
32
+ onAjaxSuccess: function(transport) {
33
+ if (transport.responseText.isJSON()) {
34
+ var response = transport.responseText.evalJSON()
35
+ if (response.error) {
36
+ throw response;
37
+ } else if (response.ajaxExpired && response.ajaxRedirect) {
38
+ setLocation(response.ajaxRedirect);
39
+ }
40
+ }
41
+ },
42
+
43
+ openDialog: function(widgetUrl) {
44
+ if ($('widget_window') && typeof(Windows) != 'undefined') {
45
+ Windows.focus('widget_window');
46
+ return;
47
+ }
48
+ this.dialogWindow = Dialog.info(null, {
49
+ draggable:true,
50
+ resizable:false,
51
+ closable:true,
52
+ className:'magento',
53
+ windowClassName:"popup-window",
54
+ title:'Insert Widget',
55
+ top:50,
56
+ width:950,
57
+ //height:450,
58
+ zIndex:1000,
59
+ recenterAuto:false,
60
+ hideEffect:Element.hide,
61
+ showEffect:Element.show,
62
+ id:'widget_window',
63
+ onClose: this.closeDialog.bind(this)
64
+ });
65
+ new Ajax.Updater('modal_dialog_message', widgetUrl, {evalScripts: true});
66
+ },
67
+ closeDialog: function(window) {
68
+ if (!window) {
69
+ window = this.dialogWindow;
70
+ }
71
+ if (window) {
72
+ // IE fix - hidden form select fields after closing dialog
73
+ WindowUtilities._showSelect();
74
+ window.close();
75
+ }
76
+ }
77
+ }
78
+
79
+ var WysiwygWidget = {};
80
+ WysiwygWidget.Widget = Class.create();
81
+ WysiwygWidget.Widget.prototype = {
82
+
83
+ initialize: function(formEl, widgetEl, widgetOptionsEl, optionsSourceUrl, widgetTargetId) {
84
+ $(formEl).insert({bottom: widgetTools.getDivHtml(widgetOptionsEl)});
85
+ this.formEl = formEl;
86
+ this.widgetEl = $(widgetEl);
87
+ this.widgetOptionsEl = $(widgetOptionsEl);
88
+ this.optionsUrl = optionsSourceUrl;
89
+ this.optionValues = new Hash({});
90
+ this.widgetTargetId = widgetTargetId;
91
+
92
+ Event.observe(this.widgetEl, "change", this.loadOptions.bind(this));
93
+
94
+ this.initOptionValues();
95
+ },
96
+
97
+ getOptionsContainerId: function() {
98
+ return this.widgetOptionsEl.id + '_' + this.widgetEl.value.gsub(/\//, '_');
99
+ },
100
+
101
+ switchOptionsContainer: function(containerId) {
102
+ $$('#' + this.widgetOptionsEl.id + ' div[id^=' + this.widgetOptionsEl.id + ']').each(function(e) {
103
+ this.disableOptionsContainer(e.id);
104
+ }.bind(this));
105
+ if(containerId != undefined) {
106
+ this.enableOptionsContainer(containerId);
107
+ }
108
+ this._showWidgetDescription();
109
+ },
110
+
111
+ enableOptionsContainer: function(containerId) {
112
+ $$('#' + containerId + ' .widget-option').each(function(e) {
113
+ e.removeClassName('skip-submit');
114
+ if (e.hasClassName('obligatory')) {
115
+ e.removeClassName('obligatory');
116
+ e.addClassName('required-entry');
117
+ }
118
+ });
119
+ $(containerId).removeClassName('no-display');
120
+ },
121
+
122
+ disableOptionsContainer: function(containerId) {
123
+ if ($(containerId).hasClassName('no-display')) {
124
+ return;
125
+ }
126
+ $$('#' + containerId + ' .widget-option').each(function(e) {
127
+ // Avoid submitting fields of unactive container
128
+ if (!e.hasClassName('skip-submit')) {
129
+ e.addClassName('skip-submit');
130
+ }
131
+ // Form validation workaround for unactive container
132
+ if (e.hasClassName('required-entry')) {
133
+ e.removeClassName('required-entry');
134
+ e.addClassName('obligatory');
135
+ }
136
+ });
137
+ $(containerId).addClassName('no-display');
138
+ },
139
+
140
+ // Assign widget options values when existing widget selected in WYSIWYG
141
+ initOptionValues: function() {
142
+
143
+ if (!this.wysiwygExists()) {
144
+ return false;
145
+ }
146
+
147
+ var e = this.getWysiwygNode();
148
+ if (e != undefined && e.id) {
149
+ var widgetCode = Base64.idDecode(e.id);
150
+ if (widgetCode.indexOf('{{widget') != -1) {
151
+ this.optionValues = new Hash({});
152
+ widgetCode.gsub(/([a-z0-9\_]+)\s*\=\s*[\"]{1}([^\"]+)[\"]{1}/i, function(match){
153
+ if (match[1] == 'type') {
154
+ this.widgetEl.value = match[2];
155
+ } else {
156
+ this.optionValues.set(match[1], match[2]);
157
+ }
158
+ }.bind(this));
159
+
160
+ this.loadOptions();
161
+ }
162
+ }
163
+ },
164
+
165
+ loadOptions: function() {
166
+ if (!this.widgetEl.value) {
167
+ this.switchOptionsContainer();
168
+ return;
169
+ }
170
+
171
+ var optionsContainerId = this.getOptionsContainerId();
172
+ if ($(optionsContainerId) != undefined) {
173
+ this.switchOptionsContainer(optionsContainerId);
174
+ return;
175
+ }
176
+
177
+ this._showWidgetDescription();
178
+
179
+ var params = {widget_type: this.widgetEl.value, values: this.optionValues};
180
+ new Ajax.Request(this.optionsUrl,
181
+ {
182
+ parameters: {widget: Object.toJSON(params)},
183
+ onSuccess: function(transport) {
184
+ try {
185
+ widgetTools.onAjaxSuccess(transport);
186
+ this.switchOptionsContainer();
187
+ if ($(optionsContainerId) == undefined) {
188
+ this.widgetOptionsEl.insert({bottom: widgetTools.getDivHtml(optionsContainerId, transport.responseText)});
189
+ } else {
190
+ this.switchOptionsContainer(optionsContainerId);
191
+ }
192
+ } catch(e) {
193
+ alert(e.message);
194
+ }
195
+ }.bind(this)
196
+ }
197
+ );
198
+ },
199
+
200
+ _showWidgetDescription: function() {
201
+ var noteCnt = this.widgetEl.next().down('small');
202
+ var descrCnt = $('widget-description-' + this.widgetEl.selectedIndex);
203
+ if(noteCnt != undefined) {
204
+ var description = (descrCnt != undefined ? descrCnt.innerHTML : '');
205
+ noteCnt.update(descrCnt.innerHTML);
206
+ }
207
+ },
208
+
209
+ insertWidget: function() {
210
+ widgetOptionsForm = new varienForm(this.formEl);
211
+ if(widgetOptionsForm.validator && widgetOptionsForm.validator.validate() || !widgetOptionsForm.validator){
212
+ var formElements = [];
213
+ var i = 0;
214
+ Form.getElements($(this.formEl)).each(function(e) {
215
+ if(!e.hasClassName('skip-submit')) {
216
+ formElements[i] = e;
217
+ i++;
218
+ }
219
+ });
220
+
221
+ // Add as_is flag to parameters if wysiwyg editor doesn't exist
222
+ var params = Form.serializeElements(formElements);
223
+ if (!this.wysiwygExists()) {
224
+ params = params + '&as_is=1';
225
+ }
226
+
227
+ new Ajax.Request($(this.formEl).action,
228
+ {
229
+ parameters: params,
230
+ onComplete: function(transport) {
231
+ try {
232
+ widgetTools.onAjaxSuccess(transport);
233
+ Windows.close("widget_window");
234
+ this.updateContent(transport.responseText);
235
+ } catch(e) {
236
+ alert(e.message);
237
+ }
238
+ }.bind(this)
239
+ });
240
+ }
241
+ },
242
+
243
+ updateContent: function(content) {
244
+ if (this.wysiwygExists()) {
245
+ this.getWysiwyg().execCommand("mceInsertContent", false, content);
246
+ } else {
247
+ var textarea = document.getElementById(this.widgetTargetId);
248
+ updateElementAtCursor(textarea, content);
249
+ varienGlobalEvents.fireEvent('tinymceChange');
250
+ }
251
+ },
252
+
253
+ wysiwygExists: function() {
254
+ return (typeof tinyMCE != 'undefined') && tinyMCE.get(this.widgetTargetId);
255
+ },
256
+
257
+ getWysiwyg: function() {
258
+ return tinyMCE.activeEditor;
259
+ },
260
+
261
+ getWysiwygNode: function() {
262
+ return tinyMCE.activeEditor.selection.getNode();
263
+ }
264
+ }
265
+
266
+ WysiwygWidget.chooser = Class.create();
267
+ WysiwygWidget.chooser.prototype = {
268
+
269
+ // HTML element A, on which click event fired when choose a selection
270
+ chooserId: null,
271
+
272
+ // Source URL for Ajax requests
273
+ chooserUrl: null,
274
+
275
+ // Chooser config
276
+ config: null,
277
+
278
+ // Chooser dialog window
279
+ dialogWindow: null,
280
+
281
+ // Chooser content for dialog window
282
+ dialogContent: null,
283
+
284
+ overlayShowEffectOptions: null,
285
+ overlayHideEffectOptions: null,
286
+
287
+ initialize: function(chooserId, chooserUrl, config) {
288
+ this.chooserId = chooserId;
289
+ this.chooserUrl = chooserUrl;
290
+ this.config = config;
291
+ },
292
+
293
+ getResponseContainerId: function() {
294
+ return 'responseCnt' + this.chooserId;
295
+ },
296
+
297
+ getChooserControl: function() {
298
+ return $(this.chooserId + 'control');
299
+ },
300
+
301
+ getElement: function() {
302
+ return $(this.chooserId + 'value');
303
+ },
304
+
305
+ getElementLabel: function() {
306
+ return $(this.chooserId + 'label');
307
+ },
308
+
309
+ open: function() {
310
+ $(this.getResponseContainerId()).show();
311
+ },
312
+
313
+ close: function() {
314
+ $(this.getResponseContainerId()).hide();
315
+ this.closeDialogWindow();
316
+ },
317
+
318
+ choose: function(event) {
319
+ // Open dialog window with previously loaded dialog content
320
+ if (this.dialogContent) {
321
+ this.openDialogWindow(this.dialogContent);
322
+ return;
323
+ }
324
+ // Show or hide chooser content if it was already loaded
325
+ var responseContainerId = this.getResponseContainerId();
326
+
327
+ // Otherwise load content from server
328
+ new Ajax.Request(this.chooserUrl,
329
+ {
330
+ parameters: {element_value: this.getElementValue(), element_label: this.getElementLabelText()},
331
+ onSuccess: function(transport) {
332
+ try {
333
+ widgetTools.onAjaxSuccess(transport);
334
+ this.dialogContent = widgetTools.getDivHtml(responseContainerId, transport.responseText);
335
+ this.openDialogWindow(this.dialogContent);
336
+ } catch(e) {
337
+ alert(e.message);
338
+ }
339
+ }.bind(this)
340
+ }
341
+ );
342
+ },
343
+
344
+ openDialogWindow: function(content) {
345
+ this.overlayShowEffectOptions = Windows.overlayShowEffectOptions;
346
+ this.overlayHideEffectOptions = Windows.overlayHideEffectOptions;
347
+ Windows.overlayShowEffectOptions = {duration:0};
348
+ Windows.overlayHideEffectOptions = {duration:0};
349
+ this.dialogWindow = Dialog.info(content, {
350
+ draggable:true,
351
+ resizable:true,
352
+ closable:true,
353
+ className:"magento",
354
+ windowClassName:"popup-window",
355
+ title:this.config.buttons.open,
356
+ top:50,
357
+ width:950,
358
+ height:500,
359
+ zIndex:1000,
360
+ recenterAuto:false,
361
+ hideEffect:Element.hide,
362
+ showEffect:Element.show,
363
+ id:"widget-chooser",
364
+ onClose: this.closeDialogWindow.bind(this)
365
+ });
366
+ content.evalScripts.bind(content).defer();
367
+ },
368
+
369
+ closeDialogWindow: function(dialogWindow) {
370
+ if (!dialogWindow) {
371
+ dialogWindow = this.dialogWindow;
372
+ }
373
+ if (dialogWindow) {
374
+ dialogWindow.close();
375
+ Windows.overlayShowEffectOptions = this.overlayShowEffectOptions;
376
+ Windows.overlayHideEffectOptions = this.overlayHideEffectOptions;
377
+ }
378
+ this.dialogWindow = null;
379
+ },
380
+
381
+ getElementValue: function(value) {
382
+ return this.getElement().value;
383
+ },
384
+
385
+ getElementLabelText: function(value) {
386
+ return this.getElementLabel().innerHTML;
387
+ },
388
+
389
+ setElementValue: function(value) {
390
+ this.getElement().value = value;
391
+ },
392
+
393
+ setElementLabel: function(value) {
394
+ this.getElementLabel().innerHTML = value;
395
+ }
396
+ }
js/mage/centinel.js ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ var CentinelAuthenticate = Class.create();
26
+ CentinelAuthenticate.prototype = {
27
+ initialize : function(blockId, iframeId)
28
+ {
29
+ this._isAuthenticationStarted = false;
30
+ this._relatedBlocks = new Array();
31
+ this.centinelBlockId = blockId;
32
+ this.iframeId = iframeId;
33
+ if (this._isCentinelBlocksLoaded()) {
34
+ $(this.centinelBlockId).hide();
35
+ }
36
+ },
37
+
38
+ isAuthenticationStarted : function()
39
+ {
40
+ return this._isAuthenticationStarted;
41
+ },
42
+
43
+ addRelatedBlock : function(blockId)
44
+ {
45
+ this._relatedBlocks[this._relatedBlocks.size()] = blockId;
46
+ },
47
+
48
+ _hideRelatedBlocks : function()
49
+ {
50
+ for (var i = 0; i < this._relatedBlocks.size(); i++) {
51
+ $(this._relatedBlocks[i]).hide();
52
+ }
53
+ },
54
+
55
+ _showRelatedBlocks : function()
56
+ {
57
+ for (var i = 0; i < this._relatedBlocks.size(); i++) {
58
+ $(this._relatedBlocks[i]).show();
59
+ }
60
+ },
61
+
62
+ _isRelatedBlocksLoaded : function()
63
+ {
64
+ for (var i = 0; i < this._relatedBlocks.size(); i++) {
65
+ if(!$(this._relatedBlocks[i])) {
66
+ return false;
67
+ }
68
+ }
69
+ return true;
70
+ },
71
+
72
+ _isCentinelBlocksLoaded : function()
73
+ {
74
+ if(!$(this.centinelBlockId) || !$(this.iframeId)) {
75
+ return false;
76
+ }
77
+ return true;
78
+ },
79
+
80
+ start : function(authenticateUrl)
81
+ {
82
+ if (this._isRelatedBlocksLoaded() && this._isCentinelBlocksLoaded()) {
83
+ this._hideRelatedBlocks();
84
+ $(this.iframeId).src = authenticateUrl;
85
+ $(this.centinelBlockId).show();
86
+ this._isAuthenticationStarted = true;
87
+ }
88
+ },
89
+
90
+ success : function()
91
+ {
92
+ if (this._isRelatedBlocksLoaded() && this._isCentinelBlocksLoaded()) {
93
+ this._showRelatedBlocks();
94
+ $(this.centinelBlockId).hide();
95
+ this._isAuthenticationStarted = false;
96
+ }
97
+ },
98
+
99
+ cancel : function()
100
+ {
101
+ if (this._isAuthenticationStarted) {
102
+ if (this._isRelatedBlocksLoaded()) {
103
+ this._showRelatedBlocks();
104
+ }
105
+ if (this._isCentinelBlocksLoaded()) {
106
+ $(this.centinelBlockId).hide();
107
+ $(this.iframeId).src = '';
108
+ }
109
+ this._isAuthenticationStarted = false;
110
+ }
111
+ }
112
+ };
js/mage/cookies.js ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ // old school cookie functions grabbed off the web
26
+
27
+ if (!window.Mage) var Mage = {};
28
+
29
+ Mage.Cookies = {};
30
+ Mage.Cookies.expires = null;
31
+ Mage.Cookies.path = '/';
32
+ Mage.Cookies.domain = null;
33
+ Mage.Cookies.secure = false;
34
+ Mage.Cookies.set = function(name, value){
35
+ var argv = arguments;
36
+ var argc = arguments.length;
37
+ var expires = (argc > 2) ? argv[2] : Mage.Cookies.expires;
38
+ var path = (argc > 3) ? argv[3] : Mage.Cookies.path;
39
+ var domain = (argc > 4) ? argv[4] : Mage.Cookies.domain;
40
+ var secure = (argc > 5) ? argv[5] : Mage.Cookies.secure;
41
+ document.cookie = name + "=" + escape (value) +
42
+ ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
43
+ ((path == null) ? "" : ("; path=" + path)) +
44
+ ((domain == null) ? "" : ("; domain=" + domain)) +
45
+ ((secure == true) ? "; secure" : "");
46
+ };
47
+
48
+ Mage.Cookies.get = function(name){
49
+ var arg = name + "=";
50
+ var alen = arg.length;
51
+ var clen = document.cookie.length;
52
+ var i = 0;
53
+ var j = 0;
54
+ while(i < clen){
55
+ j = i + alen;
56
+ if (document.cookie.substring(i, j) == arg)
57
+ return Mage.Cookies.getCookieVal(j);
58
+ i = document.cookie.indexOf(" ", i) + 1;
59
+ if(i == 0)
60
+ break;
61
+ }
62
+ return null;
63
+ };
64
+
65
+ Mage.Cookies.clear = function(name) {
66
+ if(Mage.Cookies.get(name)){
67
+ document.cookie = name + "=" +
68
+ "; expires=Thu, 01-Jan-70 00:00:01 GMT";
69
+ }
70
+ };
71
+
72
+ Mage.Cookies.getCookieVal = function(offset){
73
+ var endstr = document.cookie.indexOf(";", offset);
74
+ if(endstr == -1){
75
+ endstr = document.cookie.length;
76
+ }
77
+ return unescape(document.cookie.substring(offset, endstr));
78
+ };
js/mage/directpost.js ADDED
@@ -0,0 +1,414 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ var directPost = Class.create();
26
+ directPost.prototype = {
27
+ initialize : function(methodCode, iframeId, controller, orderSaveUrl,
28
+ cgiUrl, nativeAction) {
29
+ this.iframeId = iframeId;
30
+ this.controller = controller;
31
+ this.orderSaveUrl = orderSaveUrl;
32
+ this.nativeAction = nativeAction;
33
+ this.cgiUrl = cgiUrl;
34
+ this.code = methodCode;
35
+ this.inputs = ['cc_type', 'cc_number', 'expiration', 'expiration_yr', 'cc_cid'];
36
+ this.headers = [];
37
+ this.isValid = true;
38
+ this.paymentRequestSent = false;
39
+ this.isResponse = false;
40
+ this.orderIncrementId = false;
41
+ this.successUrl = false;
42
+ this.hasError = false;
43
+ this.tmpForm = false;
44
+
45
+ this.onSaveOnepageOrderSuccess = this.saveOnepageOrderSuccess.bindAsEventListener(this);
46
+ this.onLoadIframe = this.loadIframe.bindAsEventListener(this);
47
+ this.onLoadOrderIframe = this.loadOrderIframe.bindAsEventListener(this);
48
+ this.onSubmitAdminOrder = this.submitAdminOrder.bindAsEventListener(this);
49
+
50
+ this.preparePayment();
51
+ },
52
+
53
+ validate : function() {
54
+ this.isValid = true;
55
+ this.inputs.each(function(elemIndex) {
56
+ if ($(this.code + '_' + elemIndex)) {
57
+ if (!Validation.validate($(this.code + '_' + elemIndex))) {
58
+ this.isValid = false;
59
+ }
60
+ }
61
+ }, this);
62
+
63
+ return this.isValid;
64
+ },
65
+
66
+ changeInputOptions : function(param, value) {
67
+ this.inputs.each(function(elemIndex) {
68
+ if ($(this.code + '_' + elemIndex)) {
69
+ $(this.code + '_' + elemIndex).writeAttribute(param, value);
70
+ }
71
+ }, this);
72
+ },
73
+
74
+ preparePayment : function() {
75
+ this.changeInputOptions('autocomplete', 'off');
76
+ if ($(this.iframeId)) {
77
+ switch (this.controller) {
78
+ case 'onepage':
79
+ this.headers = $$('#' + checkout.accordion.container.readAttribute('id') + ' .section');
80
+ var button = $('review-buttons-container').down('button');
81
+ button.writeAttribute('onclick', '');
82
+ button.stopObserving('click');
83
+ button.observe('click', function() {
84
+ if ($(this.iframeId)) {
85
+ if (this.validate()) {
86
+ this.saveOnepageOrder();
87
+ }
88
+ } else {
89
+ review.save();
90
+ }
91
+ }.bind(this));
92
+ break;
93
+ case 'sales_order_create':
94
+ case 'sales_order_edit':
95
+ var buttons = document.getElementsByClassName('scalable save');
96
+ for ( var i = 0; i < buttons.length; i++) {
97
+ buttons[i].writeAttribute('onclick', '');
98
+ buttons[i].observe('click', this.onSubmitAdminOrder);
99
+ }
100
+ $('order-' + this.iframeId).observe('load', this.onLoadOrderIframe);
101
+ break;
102
+ }
103
+
104
+ $(this.iframeId).observe('load', this.onLoadIframe);
105
+ }
106
+ },
107
+
108
+ loadIframe : function() {
109
+ if (this.paymentRequestSent) {
110
+ switch (this.controller) {
111
+ case 'onepage':
112
+ this.paymentRequestSent = false;
113
+ if (!this.hasError) {
114
+ this.returnQuote();
115
+ }
116
+ break;
117
+ case 'sales_order_edit':
118
+ case 'sales_order_create':
119
+ if (!this.orderRequestSent) {
120
+ this.paymentRequestSent = false;
121
+ if (!this.hasError) {
122
+ this.returnQuote();
123
+ } else {
124
+ this.changeInputOptions('disabled', false);
125
+ toggleSelectsUnderBlock($('loading-mask'), true);
126
+ $('loading-mask').hide();
127
+ enableElements('save');
128
+ }
129
+ }
130
+ break;
131
+ }
132
+ if (this.tmpForm) {
133
+ document.body.removeChild(this.tmpForm);
134
+ }
135
+ }
136
+ },
137
+
138
+ loadOrderIframe : function() {
139
+ if (this.orderRequestSent) {
140
+ $(this.iframeId).hide();
141
+ var data = $('order-' + this.iframeId).contentWindow.document.body.innerHTML;
142
+ this.saveAdminOrderSuccess(data);
143
+ this.orderRequestSent = false;
144
+ }
145
+ },
146
+
147
+ showError : function(msg) {
148
+ this.hasError = true;
149
+ if (this.controller == 'onepage') {
150
+ $(this.iframeId).hide();
151
+ this.resetLoadWaiting();
152
+ }
153
+ alert(msg);
154
+ },
155
+
156
+ returnQuote : function() {
157
+ var url = this.orderSaveUrl.replace('place', 'returnQuote');
158
+ new Ajax.Request(url, {
159
+ onSuccess : function(transport) {
160
+ try {
161
+ response = eval('(' + transport.responseText + ')');
162
+ } catch (e) {
163
+ response = {};
164
+ }
165
+ if (response.error_message) {
166
+ alert(response.error_message);
167
+ }
168
+ $(this.iframeId).show();
169
+ switch (this.controller) {
170
+ case 'onepage':
171
+ this.resetLoadWaiting();
172
+ break;
173
+ case 'sales_order_edit':
174
+ case 'sales_order_create':
175
+ this.changeInputOptions('disabled', false);
176
+ toggleSelectsUnderBlock($('loading-mask'), true);
177
+ $('loading-mask').hide();
178
+ enableElements('save');
179
+ break;
180
+ }
181
+ }.bind(this)
182
+ });
183
+ },
184
+
185
+ setLoadWaiting : function() {
186
+ this.headers.each(function(header) {
187
+ header.removeClassName('allow');
188
+ });
189
+ checkout.setLoadWaiting('review');
190
+ },
191
+
192
+ resetLoadWaiting : function() {
193
+ this.headers.each(function(header) {
194
+ header.addClassName('allow');
195
+ });
196
+ checkout.setLoadWaiting(false);
197
+ },
198
+
199
+ saveOnepageOrder : function() {
200
+ this.hasError = false;
201
+ this.setLoadWaiting();
202
+ var params = Form.serialize(payment.form);
203
+ if (review.agreementsForm) {
204
+ params += '&' + Form.serialize(review.agreementsForm);
205
+ }
206
+ params += '&controller=' + this.controller;
207
+ new Ajax.Request(this.orderSaveUrl, {
208
+ method : 'post',
209
+ parameters : params,
210
+ onComplete : this.onSaveOnepageOrderSuccess,
211
+ onFailure : function(transport) {
212
+ this.resetLoadWaiting();
213
+ if (transport.status == 403) {
214
+ checkout.ajaxFailure();
215
+ }
216
+ }
217
+ });
218
+ },
219
+
220
+ saveOnepageOrderSuccess : function(transport) {
221
+ if (transport.status == 403) {
222
+ checkout.ajaxFailure();
223
+ }
224
+ try {
225
+ response = eval('(' + transport.responseText + ')');
226
+ } catch (e) {
227
+ response = {};
228
+ }
229
+
230
+ if (response.success && response.directpost) {
231
+ this.orderIncrementId = response.directpost.fields.x_invoice_num;
232
+ var paymentData = {};
233
+ for ( var key in response.directpost.fields) {
234
+ paymentData[key] = response.directpost.fields[key];
235
+ }
236
+ var preparedData = this.preparePaymentRequest(paymentData);
237
+ this.sendPaymentRequest(preparedData);
238
+ } else {
239
+ var msg = response.error_messages;
240
+ if (typeof (msg) == 'object') {
241
+ msg = msg.join("\n");
242
+ }
243
+ if (msg) {
244
+ alert(msg);
245
+ }
246
+
247
+ if (response.update_section) {
248
+ $('checkout-' + response.update_section.name + '-load').update(response.update_section.html);
249
+ response.update_section.html.evalScripts();
250
+ }
251
+
252
+ if (response.goto_section) {
253
+ checkout.gotoSection(response.goto_section);
254
+ checkout.reloadProgressBlock();
255
+ }
256
+ }
257
+ },
258
+
259
+ submitAdminOrder : function() {
260
+ if (editForm.validate()) {
261
+ var paymentMethodEl = $(editForm.formId).getInputs('radio','payment[method]').find(function(radio) {
262
+ return radio.checked;
263
+ });
264
+ this.hasError = false;
265
+ if (paymentMethodEl.value == this.code) {
266
+ toggleSelectsUnderBlock($('loading-mask'), false);
267
+ $('loading-mask').show();
268
+ setLoaderPosition();
269
+ this.changeInputOptions('disabled', 'disabled');
270
+ this.paymentRequestSent = true;
271
+ this.orderRequestSent = true;
272
+ $(editForm.formId).writeAttribute('action', this.orderSaveUrl);
273
+ $(editForm.formId).writeAttribute('target',
274
+ $('order-' + this.iframeId).readAttribute('name'));
275
+ $(editForm.formId).appendChild(this.createHiddenElement('controller', this.controller));
276
+ disableElements('save');
277
+ $(editForm.formId).submit();
278
+ } else {
279
+ $(editForm.formId).writeAttribute('action', this.nativeAction);
280
+ $(editForm.formId).writeAttribute('target', '_top');
281
+ disableElements('save');
282
+ $(editForm.formId).submit();
283
+ }
284
+ }
285
+ },
286
+
287
+ recollectQuote : function() {
288
+ var area = [ 'sidebar', 'items', 'shipping_method', 'billing_method', 'totals', 'giftmessage' ];
289
+ area = order.prepareArea(area);
290
+ var url = order.loadBaseUrl + 'block/' + area;
291
+ var info = $('order-items_grid').select('input', 'select', 'textarea');
292
+ var data = {};
293
+ for ( var i = 0; i < info.length; i++) {
294
+ if (!info[i].disabled && (info[i].type != 'checkbox' || info[i].checked)) {
295
+ data[info[i].name] = info[i].getValue();
296
+ }
297
+ }
298
+ data.reset_shipping = true;
299
+ data.update_items = true;
300
+ if ($('coupons:code') && $F('coupons:code')) {
301
+ data['order[coupon][code]'] = $F('coupons:code');
302
+ }
303
+ data.json = true;
304
+ new Ajax.Request(url, {
305
+ parameters : data,
306
+ loaderArea : 'html-body',
307
+ onSuccess : function(transport) {
308
+ $(editForm.formId).submit();
309
+ }.bind(this)
310
+ });
311
+
312
+ },
313
+
314
+ saveAdminOrderSuccess : function(data) {
315
+ try {
316
+ response = eval('(' + data + ')');
317
+ } catch (e) {
318
+ response = {};
319
+ }
320
+
321
+ if (response.directpost) {
322
+ this.orderIncrementId = response.directpost.fields.x_invoice_num;
323
+ var paymentData = {};
324
+ for ( var key in response.directpost.fields) {
325
+ paymentData[key] = response.directpost.fields[key];
326
+ }
327
+ var preparedData = this.preparePaymentRequest(paymentData);
328
+ this.sendPaymentRequest(preparedData);
329
+ } else {
330
+ if (response.redirect) {
331
+ window.location = response.redirect;
332
+ }
333
+ if (response.error_messages) {
334
+ var msg = response.error_messages;
335
+ if (typeof (msg) == 'object') {
336
+ msg = msg.join("\n");
337
+ }
338
+ if (msg) {
339
+ alert(msg);
340
+ }
341
+ }
342
+ }
343
+ },
344
+
345
+ preparePaymentRequest : function(data) {
346
+ if ($(this.code + '_cc_cid')) {
347
+ data.x_card_code = $(this.code + '_cc_cid').value;
348
+ }
349
+ var year = $(this.code + '_expiration_yr').value;
350
+ if (year.length > 2) {
351
+ year = year.substring(2);
352
+ }
353
+ var month = parseInt($(this.code + '_expiration').value, 10);
354
+ if (month < 10) {
355
+ month = '0' + month;
356
+ }
357
+
358
+ data.x_exp_date = month + '/' + year;
359
+ data.x_card_num = $(this.code + '_cc_number').value;
360
+
361
+ return data;
362
+ },
363
+
364
+ sendPaymentRequest : function(preparedData) {
365
+ this.recreateIframe();
366
+ this.tmpForm = document.createElement('form');
367
+ this.tmpForm.style.display = 'none';
368
+ this.tmpForm.enctype = 'application/x-www-form-urlencoded';
369
+ this.tmpForm.method = 'POST';
370
+ document.body.appendChild(this.tmpForm);
371
+ this.tmpForm.action = this.cgiUrl;
372
+ this.tmpForm.target = $(this.iframeId).readAttribute('name');
373
+ this.tmpForm.setAttribute('target', $(this.iframeId).readAttribute('name'));
374
+
375
+ for ( var param in preparedData) {
376
+ this.tmpForm.appendChild(this.createHiddenElement(param, preparedData[param]));
377
+ }
378
+
379
+ this.paymentRequestSent = true;
380
+ this.tmpForm.submit();
381
+ },
382
+
383
+ createHiddenElement : function(name, value) {
384
+ var field;
385
+ if (isIE) {
386
+ field = document.createElement('input');
387
+ field.setAttribute('type', 'hidden');
388
+ field.setAttribute('name', name);
389
+ field.setAttribute('value', value);
390
+ } else {
391
+ field = document.createElement('input');
392
+ field.type = 'hidden';
393
+ field.name = name;
394
+ field.value = value;
395
+ }
396
+
397
+ return field;
398
+ },
399
+
400
+ recreateIframe : function() {
401
+ if ($(this.iframeId)) {
402
+ var nextElement = $(this.iframeId).next();
403
+ var src = $(this.iframeId).readAttribute('src');
404
+ var name = $(this.iframeId).readAttribute('name');
405
+ $(this.iframeId).stopObserving();
406
+ $(this.iframeId).remove();
407
+ var iframe = '<iframe id="' + this.iframeId +
408
+ '" allowtransparency="true" frameborder="0" name="' + name +
409
+ '" style="display:none;width:100%;background-color:transparent" src="' + src + '" />';
410
+ Element.insert(nextElement, {'before':iframe});
411
+ $(this.iframeId).observe('load', this.onLoadIframe);
412
+ }
413
+ }
414
+ };
js/mage/translate.js ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ var Translate = Class.create();
27
+ Translate.prototype = {
28
+ initialize: function(data){
29
+ this.data = $H(data);
30
+ },
31
+
32
+ translate : function(){
33
+ var args = arguments;
34
+ var text = arguments[0];
35
+
36
+ if(this.data.get(text)){
37
+ return this.data.get(text);
38
+ }
39
+ return text;
40
+ },
41
+ add : function() {
42
+ if (arguments.length > 1) {
43
+ this.data.set(arguments[0], arguments[1]);
44
+ } else if (typeof arguments[0] =='object') {
45
+ $H(arguments[0]).each(function (pair){
46
+ this.data.set(pair.key, pair.value);
47
+ }.bind(this));
48
+ }
49
+ }
50
+ }
js/mage/translate_inline.css ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ .translate-inline { /* background:black; font-weight:bold; color:red; */ border:dotted 1px red;}
27
+ .translate-inline-script, .translate-inline-title { background:yellow; color:black; font-weight:bold; }
28
+ #translate-inline-trig { position:absolute;left:-1000px; opacity:.8; filter:alpha(opacity=80); cursor:pointer; margin-top:10px; z-index:1000;}
29
+
30
+ .magento_table_container { background:#e7efef; margin:10px; padding:10px; }
31
+ .magento_table_container table { width:100%; }
32
+ .magento_table_container td { padding:2px 0 !important; text-align:left; }
33
+ .magento_table_container th.label { width:150px; padding:2px 9px 2px 0 !important; font-weight:bold; }
34
+ .magento_table_container td.value .input-text { width:98%; }
35
+ .magento_table_container td.value textarea.input-text { height:8em; }
36
+ p.accent { color:#d12c01; }
js/mage/translate_inline.js ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Mage
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ var TranslateInline = Class.create();
27
+ TranslateInline.prototype = {
28
+ initialize: function(trigEl, ajaxUrl, area){
29
+ this.ajaxUrl = ajaxUrl;
30
+ this.area = area;
31
+
32
+ this.trigTimer = null;
33
+ this.trigContentEl = null;
34
+
35
+ $$('*[translate]').each(this.initializeElement.bind(this));
36
+ var scope = this;
37
+ Ajax.Responders.register({onComplete: function() {setTimeout(scope.reinitElements.bind(scope), 50)}});
38
+ this.trigEl = $(trigEl);
39
+ this.trigEl.observe('mouseover', this.trigHideClear.bind(this));
40
+ this.trigEl.observe('mouseout', this.trigHideDelayed.bind(this));
41
+ this.trigEl.observe('click', this.formShow.bind(this));
42
+
43
+ this.helperDiv = document.createElement('div');
44
+ },
45
+
46
+ initializeElement: function(el) {
47
+ if(!el.initializedTranslate) {
48
+ el.addClassName('translate-inline');
49
+ el.initializedTranslate = true;
50
+ Event.observe(el, 'mouseover', this.trigShow.bind(this, el));
51
+ Event.observe(el, 'mouseout', this.trigHideDelayed.bind(this));
52
+ }
53
+ },
54
+
55
+ reinitElements: function (el) {
56
+ $$('*[translate]').each(this.initializeElement.bind(this));
57
+ },
58
+
59
+ trigShow: function (el) {
60
+ this.trigHideClear();
61
+
62
+ var p = Element.cumulativeOffset(el);
63
+
64
+ this.trigEl.style.left = p[0]+'px';
65
+ this.trigEl.style.top = p[1]+'px';
66
+ this.trigEl.style.display = 'block';
67
+
68
+ this.trigContentEl = el;
69
+ },
70
+
71
+ trigHide: function() {
72
+ this.trigEl.style.display = 'none';
73
+ this.trigContentEl = null;
74
+ },
75
+
76
+ trigHideDelayed: function () {
77
+ this.trigTimer = window.setTimeout(this.trigHide.bind(this), 500);
78
+ },
79
+
80
+ trigHideClear: function() {
81
+ clearInterval(this.trigTimer);
82
+ },
83
+
84
+ formShow: function () {
85
+ if (this.formIsShown) {
86
+ return;
87
+ }
88
+ this.formIsShown = true;
89
+
90
+ var el = this.trigContentEl;
91
+ if (!el) {
92
+ return;
93
+ }
94
+
95
+ eval('var data = '+el.getAttribute('translate'));
96
+
97
+ var content = '<form id="translate-inline-form">';
98
+ var t = new Template(
99
+ '<div class="magento_table_container"><table cellspacing="0">'+
100
+ '<tr><th class="label">Location:</th><td class="value">#{location}</td></tr>'+
101
+ '<tr><th class="label">Scope:</th><td class="value">#{scope}</td></tr>'+
102
+ '<tr><th class="label">Shown:</th><td class="value">#{shown_escape}</td></tr>'+
103
+ '<tr><th class="label">Original:</th><td class="value">#{original_escape}</td></tr>'+
104
+ '<tr><th class="label">Translated:</th><td class="value">#{translated_escape}</td></tr>'+
105
+ '<tr><th class="label"><label for="perstore_#{i}">Store View Specific:</label></th><td class="value">'+
106
+ '<input id="perstore_#{i}" name="translate[#{i}][perstore]" type="checkbox" value="1"/>'+
107
+ '</td></tr>'+
108
+ '<tr><th class="label"><label for="custom_#{i}">Custom:</label></th><td class="value">'+
109
+ '<input name="translate[#{i}][original]" type="hidden" value="#{scope}::#{original_escape}"/>'+
110
+ '<input id="custom_#{i}" name="translate[#{i}][custom]" class="input-text" value="#{translated_escape}" />'+
111
+ '</td></tr>'+
112
+ '</table></div>'
113
+ );
114
+ for (i=0; i<data.length; i++) {
115
+ data[i]['i'] = i;
116
+ data[i]['shown_escape'] = this.escapeHTML(data[i]['shown']);
117
+ data[i]['translated_escape'] = this.escapeHTML(data[i]['translated']);
118
+ data[i]['original_escape'] = this.escapeHTML(data[i]['original']);
119
+ content += t.evaluate(data[i]);
120
+ }
121
+ content += '</form><p class="a-center accent">Please refresh the page to see your changes after submitting this form.</p>';
122
+
123
+ this.overlayShowEffectOptions = Windows.overlayShowEffectOptions;
124
+ this.overlayHideEffectOptions = Windows.overlayHideEffectOptions;
125
+ Windows.overlayShowEffectOptions = {duration:0};
126
+ Windows.overlayHideEffectOptions = {duration:0};
127
+
128
+ Dialog.confirm(content, {
129
+ draggable:true,
130
+ resizable:true,
131
+ closable:true,
132
+ className:"magento",
133
+ title:"Translation",
134
+ width:650,
135
+ height:470,
136
+ zIndex:1000,
137
+ recenterAuto:false,
138
+ hideEffect:Element.hide,
139
+ showEffect:Element.show,
140
+ id:"translate-inline",
141
+ buttonClass:"form-button button",
142
+ okLabel:"Submit",
143
+ ok: this.formOk.bind(this),
144
+ cancel: this.formClose.bind(this),
145
+ onClose: this.formClose.bind(this)
146
+ });
147
+ },
148
+
149
+ formOk: function(win) {
150
+ if (this.formIsSubmitted) {
151
+ return;
152
+ }
153
+ this.formIsSubmitted = true;
154
+
155
+ var inputs = $('translate-inline-form').getInputs(), parameters = {};
156
+ for (var i=0; i<inputs.length; i++) {
157
+ if (inputs[i].type == 'checkbox') {
158
+ if (inputs[i].checked) {
159
+ parameters[inputs[i].name] = inputs[i].value;
160
+ }
161
+ }
162
+ else {
163
+ parameters[inputs[i].name] = inputs[i].value;
164
+ }
165
+ }
166
+ parameters['area'] = this.area;
167
+
168
+ new Ajax.Request(this.ajaxUrl, {
169
+ method:'post',
170
+ parameters:parameters,
171
+ onComplete:this.ajaxComplete.bind(this, win)
172
+ });
173
+
174
+ this.formIsSubmitted = false;
175
+ },
176
+
177
+ ajaxComplete: function(win, transport) {
178
+ win.close();
179
+ this.formClose(win);
180
+ },
181
+
182
+ formClose: function(win) {
183
+ Windows.overlayShowEffectOptions = this.overlayShowEffectOptions;
184
+ Windows.overlayHideEffectOptions = this.overlayHideEffectOptions;
185
+ this.formIsShown = false;
186
+ },
187
+
188
+ escapeHTML: function (str) {
189
+ this.helperDiv.innerHTML = '';
190
+ var text = document.createTextNode(str);
191
+ this.helperDiv.appendChild(text);
192
+ var escaped = this.helperDiv.innerHTML;
193
+ escaped = escaped.replace(/"/g, '&quot;');
194
+ return escaped;
195
+ }
196
+ }
js/spacer.gif ADDED
Binary file
js/varien/accordion.js ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Varien
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ Accordion = Class.create();
26
+ Accordion.prototype = {
27
+ initialize: function(elem, clickableEntity, checkAllow) {
28
+ this.container = $(elem);
29
+ this.checkAllow = checkAllow || false;
30
+ this.disallowAccessToNextSections = false;
31
+ this.sections = $$('#' + elem + ' .section');
32
+ this.currentSection = false;
33
+ var headers = $$('#' + elem + ' .section ' + clickableEntity);
34
+ headers.each(function(header) {
35
+ Event.observe(header,'click',this.sectionClicked.bindAsEventListener(this));
36
+ }.bind(this));
37
+ },
38
+
39
+ sectionClicked: function(event) {
40
+ this.openSection($(Event.element(event)).up('.section'));
41
+ Event.stop(event);
42
+ },
43
+
44
+ openSection: function(section) {
45
+ var section = $(section);
46
+
47
+ // Check allow
48
+ if (this.checkAllow && !Element.hasClassName(section, 'allow')){
49
+ return;
50
+ }
51
+
52
+ if(section.id != this.currentSection) {
53
+ this.closeExistingSection();
54
+ this.currentSection = section.id;
55
+ $(this.currentSection).addClassName('active');
56
+ var contents = Element.select(section, '.a-item');
57
+ contents[0].show();
58
+ //Effect.SlideDown(contents[0], {duration:.2});
59
+
60
+ if (this.disallowAccessToNextSections) {
61
+ var pastCurrentSection = false;
62
+ for (var i=0; i<this.sections.length; i++) {
63
+ if (pastCurrentSection) {
64
+ Element.removeClassName(this.sections[i], 'allow')
65
+ }
66
+ if (this.sections[i].id==section.id) {
67
+ pastCurrentSection = true;
68
+ }
69
+ }
70
+ }
71
+ }
72
+ },
73
+
74
+ closeSection: function(section) {
75
+ $(section).removeClassName('active');
76
+ var contents = Element.select(section, '.a-item');
77
+ contents[0].hide();
78
+ //Effect.SlideUp(contents[0]);
79
+ },
80
+
81
+ openNextSection: function(setAllow){
82
+ for (section in this.sections) {
83
+ var nextIndex = parseInt(section)+1;
84
+ if (this.sections[section].id == this.currentSection && this.sections[nextIndex]){
85
+ if (setAllow) {
86
+ Element.addClassName(this.sections[nextIndex], 'allow')
87
+ }
88
+ this.openSection(this.sections[nextIndex]);
89
+ return;
90
+ }
91
+ }
92
+ },
93
+
94
+ openPrevSection: function(setAllow){
95
+ for (section in this.sections) {
96
+ var prevIndex = parseInt(section)-1;
97
+ if (this.sections[section].id == this.currentSection && this.sections[prevIndex]){
98
+ if (setAllow) {
99
+ Element.addClassName(this.sections[prevIndex], 'allow')
100
+ }
101
+ this.openSection(this.sections[prevIndex]);
102
+ return;
103
+ }
104
+ }
105
+ },
106
+
107
+ closeExistingSection: function() {
108
+ if(this.currentSection) {
109
+ this.closeSection(this.currentSection);
110
+ }
111
+ }
112
+ }
js/varien/configurable.js ADDED
@@ -0,0 +1,319 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Varien
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ if (typeof Product == 'undefined') {
26
+ var Product = {};
27
+ }
28
+
29
+ /**************************** CONFIGURABLE PRODUCT **************************/
30
+ Product.Config = Class.create();
31
+ Product.Config.prototype = {
32
+ initialize: function(config){
33
+ this.config = config;
34
+ this.taxConfig = this.config.taxConfig;
35
+ if (config.containerId) {
36
+ this.settings = $$('#' + config.containerId + ' ' + '.super-attribute-select');
37
+ } else {
38
+ this.settings = $$('.super-attribute-select');
39
+ }
40
+ this.state = new Hash();
41
+ this.priceTemplate = new Template(this.config.template);
42
+ this.prices = config.prices;
43
+
44
+ // Set default values from config
45
+ if (config.defaultValues) {
46
+ this.values = config.defaultValues;
47
+ }
48
+
49
+ // Overwrite defaults by url
50
+ var separatorIndex = window.location.href.indexOf('#');
51
+ if (separatorIndex != -1) {
52
+ var paramsStr = window.location.href.substr(separatorIndex+1);
53
+ var urlValues = paramsStr.toQueryParams();
54
+ if (!this.values) {
55
+ this.values = {};
56
+ }
57
+ for (var i in urlValues) {
58
+ this.values[i] = urlValues[i];
59
+ }
60
+ }
61
+
62
+ // Overwrite defaults by inputs values if needed
63
+ if (config.inputsInitialized) {
64
+ this.values = {};
65
+ this.settings.each(function(element) {
66
+ if (element.value) {
67
+ var attributeId = element.id.replace(/[a-z]*/, '');
68
+ this.values[attributeId] = element.value;
69
+ }
70
+ }.bind(this));
71
+ }
72
+
73
+ // Put events to check select reloads
74
+ this.settings.each(function(element){
75
+ Event.observe(element, 'change', this.configure.bind(this))
76
+ }.bind(this));
77
+
78
+ // fill state
79
+ this.settings.each(function(element){
80
+ var attributeId = element.id.replace(/[a-z]*/, '');
81
+ if(attributeId && this.config.attributes[attributeId]) {
82
+ element.config = this.config.attributes[attributeId];
83
+ element.attributeId = attributeId;
84
+ this.state[attributeId] = false;
85
+ }
86
+ }.bind(this))
87
+
88
+ // Init settings dropdown
89
+ var childSettings = [];
90
+ for(var i=this.settings.length-1;i>=0;i--){
91
+ var prevSetting = this.settings[i-1] ? this.settings[i-1] : false;
92
+ var nextSetting = this.settings[i+1] ? this.settings[i+1] : false;
93
+ if (i == 0){
94
+ this.fillSelect(this.settings[i])
95
+ } else {
96
+ this.settings[i].disabled = true;
97
+ }
98
+ $(this.settings[i]).childSettings = childSettings.clone();
99
+ $(this.settings[i]).prevSetting = prevSetting;
100
+ $(this.settings[i]).nextSetting = nextSetting;
101
+ childSettings.push(this.settings[i]);
102
+ }
103
+
104
+ // Set values to inputs
105
+ this.configureForValues();
106
+ document.observe("dom:loaded", this.configureForValues.bind(this));
107
+ },
108
+
109
+ configureForValues: function () {
110
+ if (this.values) {
111
+ this.settings.each(function(element){
112
+ var attributeId = element.attributeId;
113
+ element.value = (typeof(this.values[attributeId]) == 'undefined')? '' : this.values[attributeId];
114
+ this.configureElement(element);
115
+ }.bind(this));
116
+ }
117
+ },
118
+
119
+ configure: function(event){
120
+ var element = Event.element(event);
121
+ this.configureElement(element);
122
+ },
123
+
124
+ configureElement : function(element) {
125
+ this.reloadOptionLabels(element);
126
+ if(element.value){
127
+ this.state[element.config.id] = element.value;
128
+ if(element.nextSetting){
129
+ element.nextSetting.disabled = false;
130
+ this.fillSelect(element.nextSetting);
131
+ this.resetChildren(element.nextSetting);
132
+ }
133
+ }
134
+ else {
135
+ this.resetChildren(element);
136
+ }
137
+ this.reloadPrice();
138
+ },
139
+
140
+ reloadOptionLabels: function(element){
141
+ var selectedPrice;
142
+ if(element.options[element.selectedIndex].config && !this.config.stablePrices){
143
+ selectedPrice = parseFloat(element.options[element.selectedIndex].config.price)
144
+ }
145
+ else{
146
+ selectedPrice = 0;
147
+ }
148
+ for(var i=0;i<element.options.length;i++){
149
+ if(element.options[i].config){
150
+ element.options[i].text = this.getOptionLabel(element.options[i].config, element.options[i].config.price-selectedPrice);
151
+ }
152
+ }
153
+ },
154
+
155
+ resetChildren : function(element){
156
+ if(element.childSettings) {
157
+ for(var i=0;i<element.childSettings.length;i++){
158
+ element.childSettings[i].selectedIndex = 0;
159
+ element.childSettings[i].disabled = true;
160
+ if(element.config){
161
+ this.state[element.config.id] = false;
162
+ }
163
+ }
164
+ }
165
+ },
166
+
167
+ fillSelect: function(element){
168
+ var attributeId = element.id.replace(/[a-z]*/, '');
169
+ var options = this.getAttributeOptions(attributeId);
170
+ this.clearSelect(element);
171
+ element.options[0] = new Option(this.config.chooseText, '');
172
+
173
+ var prevConfig = false;
174
+ if(element.prevSetting){
175
+ prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex];
176
+ }
177
+
178
+ if(options) {
179
+ var index = 1;
180
+ for(var i=0;i<options.length;i++){
181
+ var allowedProducts = [];
182
+ if(prevConfig) {
183
+ for(var j=0;j<options[i].products.length;j++){
184
+ if(prevConfig.config.allowedProducts
185
+ && prevConfig.config.allowedProducts.indexOf(options[i].products[j])>-1){
186
+ allowedProducts.push(options[i].products[j]);
187
+ }
188
+ }
189
+ } else {
190
+ allowedProducts = options[i].products.clone();
191
+ }
192
+
193
+ if(allowedProducts.size()>0){
194
+ options[i].allowedProducts = allowedProducts;
195
+ element.options[index] = new Option(this.getOptionLabel(options[i], options[i].price), options[i].id);
196
+ if (typeof options[i].price != 'undefined') {
197
+ element.options[index].setAttribute('price', options[i].price);
198
+ }
199
+ element.options[index].config = options[i];
200
+ index++;
201
+ }
202
+ }
203
+ }
204
+ },
205
+
206
+ getOptionLabel: function(option, price){
207
+ var price = parseFloat(price);
208
+ if (this.taxConfig.includeTax) {
209
+ var tax = price / (100 + this.taxConfig.defaultTax) * this.taxConfig.defaultTax;
210
+ var excl = price - tax;
211
+ var incl = excl*(1+(this.taxConfig.currentTax/100));
212
+ } else {
213
+ var tax = price * (this.taxConfig.currentTax / 100);
214
+ var excl = price;
215
+ var incl = excl + tax;
216
+ }
217
+
218
+ if (this.taxConfig.showIncludeTax || this.taxConfig.showBothPrices) {
219
+ price = incl;
220
+ } else {
221
+ price = excl;
222
+ }
223
+
224
+ var str = option.label;
225
+ if(price){
226
+ if (this.taxConfig.showBothPrices) {
227
+ str+= ' ' + this.formatPrice(excl, true) + ' (' + this.formatPrice(price, true) + ' ' + this.taxConfig.inclTaxTitle + ')';
228
+ } else {
229
+ str+= ' ' + this.formatPrice(price, true);
230
+ }
231
+ }
232
+ return str;
233
+ },
234
+
235
+ formatPrice: function(price, showSign){
236
+ var str = '';
237
+ price = parseFloat(price);
238
+ if(showSign){
239
+ if(price<0){
240
+ str+= '-';
241
+ price = -price;
242
+ }
243
+ else{
244
+ str+= '+';
245
+ }
246
+ }
247
+
248
+ var roundedPrice = (Math.round(price*100)/100).toString();
249
+
250
+ if (this.prices && this.prices[roundedPrice]) {
251
+ str+= this.prices[roundedPrice];
252
+ }
253
+ else {
254
+ str+= this.priceTemplate.evaluate({price:price.toFixed(2)});
255
+ }
256
+ return str;
257
+ },
258
+
259
+ clearSelect: function(element){
260
+ for(var i=element.options.length-1;i>=0;i--){
261
+ element.remove(i);
262
+ }
263
+ },
264
+
265
+ getAttributeOptions: function(attributeId){
266
+ if(this.config.attributes[attributeId]){
267
+ return this.config.attributes[attributeId].options;
268
+ }
269
+ },
270
+
271
+ reloadPrice: function(){
272
+ if (this.config.disablePriceReload) {
273
+ return;
274
+ }
275
+ var price = 0;
276
+ var oldPrice = 0;
277
+ for(var i=this.settings.length-1;i>=0;i--){
278
+ var selected = this.settings[i].options[this.settings[i].selectedIndex];
279
+ if(selected.config){
280
+ price += parseFloat(selected.config.price);
281
+ oldPrice += parseFloat(selected.config.oldPrice);
282
+ }
283
+ }
284
+
285
+ optionsPrice.changePrice('config', {'price': price, 'oldPrice': oldPrice});
286
+ optionsPrice.reload();
287
+
288
+ return price;
289
+
290
+ if($('product-price-'+this.config.productId)){
291
+ $('product-price-'+this.config.productId).innerHTML = price;
292
+ }
293
+ this.reloadOldPrice();
294
+ },
295
+
296
+ reloadOldPrice: function(){
297
+ if (this.config.disablePriceReload) {
298
+ return;
299
+ }
300
+ if ($('old-price-'+this.config.productId)) {
301
+
302
+ var price = parseFloat(this.config.oldPrice);
303
+ for(var i=this.settings.length-1;i>=0;i--){
304
+ var selected = this.settings[i].options[this.settings[i].selectedIndex];
305
+ if(selected.config){
306
+ price+= parseFloat(selected.config.price);
307
+ }
308
+ }
309
+ if (price < 0)
310
+ price = 0;
311
+ price = this.formatPrice(price);
312
+
313
+ if($('old-price-'+this.config.productId)){
314
+ $('old-price-'+this.config.productId).innerHTML = price;
315
+ }
316
+
317
+ }
318
+ }
319
+ }
js/varien/form.js ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Varien
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ VarienForm = Class.create();
26
+ VarienForm.prototype = {
27
+ initialize: function(formId, firstFieldFocus){
28
+ this.form = $(formId);
29
+ if (!this.form) {
30
+ return;
31
+ }
32
+ this.cache = $A();
33
+ this.currLoader = false;
34
+ this.currDataIndex = false;
35
+ this.validator = new Validation(this.form);
36
+ this.elementFocus = this.elementOnFocus.bindAsEventListener(this);
37
+ this.elementBlur = this.elementOnBlur.bindAsEventListener(this);
38
+ this.childLoader = this.onChangeChildLoad.bindAsEventListener(this);
39
+ this.highlightClass = 'highlight';
40
+ this.extraChildParams = '';
41
+ this.firstFieldFocus= firstFieldFocus || false;
42
+ this.bindElements();
43
+ if(this.firstFieldFocus){
44
+ try{
45
+ Form.Element.focus(Form.findFirstElement(this.form))
46
+ }
47
+ catch(e){}
48
+ }
49
+ },
50
+
51
+ submit : function(url){
52
+ if(this.validator && this.validator.validate()){
53
+ this.form.submit();
54
+ }
55
+ return false;
56
+ },
57
+
58
+ bindElements:function (){
59
+ var elements = Form.getElements(this.form);
60
+ for (var row in elements) {
61
+ if (elements[row].id) {
62
+ Event.observe(elements[row],'focus',this.elementFocus);
63
+ Event.observe(elements[row],'blur',this.elementBlur);
64
+ }
65
+ }
66
+ },
67
+
68
+ elementOnFocus: function(event){
69
+ var element = Event.findElement(event, 'fieldset');
70
+ if(element){
71
+ Element.addClassName(element, this.highlightClass);
72
+ }
73
+ },
74
+
75
+ elementOnBlur: function(event){
76
+ var element = Event.findElement(event, 'fieldset');
77
+ if(element){
78
+ Element.removeClassName(element, this.highlightClass);
79
+ }
80
+ },
81
+
82
+ setElementsRelation: function(parent, child, dataUrl, first){
83
+ if (parent=$(parent)) {
84
+ // TODO: array of relation and caching
85
+ if (!this.cache[parent.id]){
86
+ this.cache[parent.id] = $A();
87
+ this.cache[parent.id]['child'] = child;
88
+ this.cache[parent.id]['dataUrl'] = dataUrl;
89
+ this.cache[parent.id]['data'] = $A();
90
+ this.cache[parent.id]['first'] = first || false;
91
+ }
92
+ Event.observe(parent,'change',this.childLoader);
93
+ }
94
+ },
95
+
96
+ onChangeChildLoad: function(event){
97
+ element = Event.element(event);
98
+ this.elementChildLoad(element);
99
+ },
100
+
101
+ elementChildLoad: function(element, callback){
102
+ this.callback = callback || false;
103
+ if (element.value) {
104
+ this.currLoader = element.id;
105
+ this.currDataIndex = element.value;
106
+ if (this.cache[element.id]['data'][element.value]) {
107
+ this.setDataToChild(this.cache[element.id]['data'][element.value]);
108
+ }
109
+ else{
110
+ new Ajax.Request(this.cache[this.currLoader]['dataUrl'],{
111
+ method: 'post',
112
+ parameters: {"parent":element.value},
113
+ onComplete: this.reloadChildren.bind(this)
114
+ });
115
+ }
116
+ }
117
+ },
118
+
119
+ reloadChildren: function(transport){
120
+ var data = eval('(' + transport.responseText + ')');
121
+ this.cache[this.currLoader]['data'][this.currDataIndex] = data;
122
+ this.setDataToChild(data);
123
+ },
124
+
125
+ setDataToChild: function(data){
126
+ if (data.length) {
127
+ var child = $(this.cache[this.currLoader]['child']);
128
+ if (child){
129
+ var html = '<select name="'+child.name+'" id="'+child.id+'" class="'+child.className+'" title="'+child.title+'" '+this.extraChildParams+'>';
130
+ if(this.cache[this.currLoader]['first']){
131
+ html+= '<option value="">'+this.cache[this.currLoader]['first']+'</option>';
132
+ }
133
+ for (var i in data){
134
+ if(data[i].value) {
135
+ html+= '<option value="'+data[i].value+'"';
136
+ if(child.value && (child.value == data[i].value || child.value == data[i].label)){
137
+ html+= ' selected';
138
+ }
139
+ html+='>'+data[i].label+'</option>';
140
+ }
141
+ }
142
+ html+= '</select>';
143
+ Element.insert(child, {before: html});
144
+ Element.remove(child);
145
+ }
146
+ }
147
+ else{
148
+ var child = $(this.cache[this.currLoader]['child']);
149
+ if (child){
150
+ var html = '<input type="text" name="'+child.name+'" id="'+child.id+'" class="'+child.className+'" title="'+child.title+'" '+this.extraChildParams+'>';
151
+ Element.insert(child, {before: html});
152
+ Element.remove(child);
153
+ }
154
+ }
155
+
156
+ this.bindElements();
157
+ if (this.callback) {
158
+ this.callback();
159
+ }
160
+ }
161
+ }
162
+
163
+ RegionUpdater = Class.create();
164
+ RegionUpdater.prototype = {
165
+ initialize: function (countryEl, regionTextEl, regionSelectEl, regions, disableAction, zipEl)
166
+ {
167
+ this.countryEl = $(countryEl);
168
+ this.regionTextEl = $(regionTextEl);
169
+ this.regionSelectEl = $(regionSelectEl);
170
+ this.zipEl = $(zipEl);
171
+ this.regions = regions;
172
+
173
+ this.disableAction = (typeof disableAction=='undefined') ? 'hide' : disableAction;
174
+ this.zipOptions = (typeof zipOptions=='undefined') ? false : zipOptions;
175
+
176
+ if (this.regionSelectEl.options.length<=1) {
177
+ this.update();
178
+ }
179
+
180
+ Event.observe(this.countryEl, 'change', this.update.bind(this));
181
+ },
182
+
183
+ update: function()
184
+ {
185
+ if (this.regions[this.countryEl.value]) {
186
+ var i, option, region, def;
187
+
188
+ if (this.regionTextEl) {
189
+ def = this.regionTextEl.value.toLowerCase();
190
+ this.regionTextEl.value = '';
191
+ }
192
+ if (!def) {
193
+ def = this.regionSelectEl.getAttribute('defaultValue');
194
+ }
195
+
196
+ this.regionSelectEl.options.length = 1;
197
+ for (regionId in this.regions[this.countryEl.value]) {
198
+ region = this.regions[this.countryEl.value][regionId];
199
+
200
+ option = document.createElement('OPTION');
201
+ option.value = regionId;
202
+ option.text = region.name;
203
+
204
+ if (this.regionSelectEl.options.add) {
205
+ this.regionSelectEl.options.add(option);
206
+ } else {
207
+ this.regionSelectEl.appendChild(option);
208
+ }
209
+
210
+ if (regionId==def || region.name.toLowerCase()==def || region.code.toLowerCase()==def) {
211
+ this.regionSelectEl.value = regionId;
212
+ }
213
+ }
214
+
215
+ if (this.disableAction=='hide') {
216
+ if (this.regionTextEl) {
217
+ this.regionTextEl.style.display = 'none';
218
+ }
219
+
220
+ this.regionSelectEl.style.display = '';
221
+ } else if (this.disableAction=='disable') {
222
+ if (this.regionTextEl) {
223
+ this.regionTextEl.disabled = true;
224
+ }
225
+ this.regionSelectEl.disabled = false;
226
+ }
227
+ this.setMarkDisplay(this.regionSelectEl, true);
228
+ } else {
229
+ if (this.disableAction=='hide') {
230
+ if (this.regionTextEl) {
231
+ this.regionTextEl.style.display = '';
232
+ }
233
+ this.regionSelectEl.style.display = 'none';
234
+ Validation.reset(this.regionSelectEl);
235
+ } else if (this.disableAction=='disable') {
236
+ if (this.regionTextEl) {
237
+ this.regionTextEl.disabled = false;
238
+ }
239
+ this.regionSelectEl.disabled = true;
240
+ } else if (this.disableAction=='nullify') {
241
+ this.regionSelectEl.options.length = 1;
242
+ this.regionSelectEl.value = '';
243
+ this.regionSelectEl.selectedIndex = 0;
244
+ this.lastCountryId = '';
245
+ }
246
+ this.setMarkDisplay(this.regionSelectEl, false);
247
+ }
248
+
249
+ // Make Zip and its label required/optional
250
+ var zipUpdater = new ZipUpdater(this.countryEl.value, this.zipEl);
251
+ zipUpdater.update();
252
+ },
253
+
254
+ setMarkDisplay: function(elem, display){
255
+ elem = $(elem);
256
+ var labelElement = elem.up(0).down('label > span.required') ||
257
+ elem.up(1).down('label > span.required') ||
258
+ elem.up(0).down('label.required > em') ||
259
+ elem.up(1).down('label.required > em');
260
+ if(labelElement) {
261
+ inputElement = labelElement.up().next('input');
262
+ if (display) {
263
+ labelElement.show();
264
+ if (inputElement) {
265
+ inputElement.addClassName('required-entry');
266
+ }
267
+ } else {
268
+ labelElement.hide();
269
+ if (inputElement) {
270
+ inputElement.removeClassName('required-entry');
271
+ }
272
+ }
273
+ }
274
+ }
275
+ }
276
+
277
+ ZipUpdater = Class.create();
278
+ ZipUpdater.prototype = {
279
+ initialize: function(country, zipElement)
280
+ {
281
+ this.country = country;
282
+ this.zipElement = $(zipElement);
283
+ },
284
+
285
+ update: function()
286
+ {
287
+ // Country ISO 2-letter codes must be pre-defined
288
+ if (typeof optionalZipCountries == 'undefined') {
289
+ return false;
290
+ }
291
+
292
+ // Ajax-request and normal content load compatibility
293
+ if (this.zipElement != undefined) {
294
+ this._setPostcodeOptional();
295
+ } else {
296
+ Event.observe(window, "load", this._setPostcodeOptional.bind(this));
297
+ }
298
+ },
299
+
300
+ _setPostcodeOptional: function()
301
+ {
302
+ this.zipElement = $(this.zipElement);
303
+ if (this.zipElement == undefined) {
304
+ return false;
305
+ }
306
+
307
+ // find label
308
+ var label = $$('label[for="' + this.zipElement.id + '"]')[0];
309
+ if (label != undefined) {
310
+ var wildCard = label.down('em') || label.down('span.required');
311
+ }
312
+
313
+ // Make Zip and its label required/optional
314
+ if (optionalZipCountries.indexOf(this.country) != -1) {
315
+ while (this.zipElement.hasClassName('required-entry')) {
316
+ this.zipElement.removeClassName('required-entry');
317
+ }
318
+ if (wildCard != undefined) {
319
+ wildCard.hide();
320
+ }
321
+ } else {
322
+ this.zipElement.addClassName('required-entry');
323
+ if (wildCard != undefined) {
324
+ wildCard.show();
325
+ }
326
+ }
327
+ }
328
+ }
js/varien/iehover-fix.js ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Varien
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ function toggleMenu(el, over)
26
+ {
27
+ if (Element.childElements(el)) {
28
+ var uL = Element.childElements(el)[1];
29
+ var iS = true;
30
+ }
31
+ if (over) {
32
+ Element.addClassName(el, 'over');
33
+
34
+ if(iS){ uL.addClassName('shown-sub')};
35
+ }
36
+ else {
37
+ Element.removeClassName(el, 'over');
38
+ if(iS){ uL.removeClassName('shown-sub')};
39
+ }
40
+ }
41
+
42
+ ieHover = function() {
43
+ var items, iframe;
44
+ items = $$('#nav ul', '.truncated_full_value .item-options', '.tool-tip');
45
+ $$('#checkout-step-payment', '.tool-tip').each(function(el) {
46
+ el.show();
47
+ el.setStyle({'visibility':'hidden'})
48
+ })
49
+ for (var j=0; j<items.length; j++) {
50
+ iframe = document.createElement('IFRAME');
51
+ iframe.src = BLANK_URL;
52
+ iframe.scrolling = 'no';
53
+ iframe.frameBorder = 0;
54
+ iframe.className = 'hover-fix';
55
+ iframe.style.width = items[j].offsetWidth+"px";
56
+ iframe.style.height = items[j].offsetHeight+"px";
57
+ items[j].insertBefore(iframe, items[j].firstChild);
58
+ }
59
+ $$('.tool-tip', '#checkout-step-payment').each(function(el) {
60
+ el.hide();
61
+ el.setStyle({'visibility':'visible'})
62
+ })
63
+ }
64
+ Event.observe(window, 'load', ieHover);
js/varien/js.js ADDED
@@ -0,0 +1,682 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Varien
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ function popWin(url,win,para) {
26
+ var win = window.open(url,win,para);
27
+ win.focus();
28
+ }
29
+
30
+ function setLocation(url){
31
+ window.location.href = url;
32
+ }
33
+
34
+ function setPLocation(url, setFocus){
35
+ if( setFocus ) {
36
+ window.opener.focus();
37
+ }
38
+ window.opener.location.href = url;
39
+ }
40
+
41
+ function setLanguageCode(code, fromCode){
42
+ //TODO: javascript cookies have different domain and path than php cookies
43
+ var href = window.location.href;
44
+ var after = '', dash;
45
+ if (dash = href.match(/\#(.*)$/)) {
46
+ href = href.replace(/\#(.*)$/, '');
47
+ after = dash[0];
48
+ }
49
+
50
+ if (href.match(/[?]/)) {
51
+ var re = /([?&]store=)[a-z0-9_]*/;
52
+ if (href.match(re)) {
53
+ href = href.replace(re, '$1'+code);
54
+ } else {
55
+ href += '&store='+code;
56
+ }
57
+
58
+ var re = /([?&]from_store=)[a-z0-9_]*/;
59
+ if (href.match(re)) {
60
+ href = href.replace(re, '');
61
+ }
62
+ } else {
63
+ href += '?store='+code;
64
+ }
65
+ if (typeof(fromCode) != 'undefined') {
66
+ href += '&from_store='+fromCode;
67
+ }
68
+ href += after;
69
+
70
+ setLocation(href);
71
+ }
72
+
73
+ /**
74
+ * Add classes to specified elements.
75
+ * Supported classes are: 'odd', 'even', 'first', 'last'
76
+ *
77
+ * @param elements - array of elements to be decorated
78
+ * [@param decorateParams] - array of classes to be set. If omitted, all available will be used
79
+ */
80
+ function decorateGeneric(elements, decorateParams)
81
+ {
82
+ var allSupportedParams = ['odd', 'even', 'first', 'last'];
83
+ var _decorateParams = {};
84
+ var total = elements.length;
85
+
86
+ if (total) {
87
+ // determine params called
88
+ if (typeof(decorateParams) == 'undefined') {
89
+ decorateParams = allSupportedParams;
90
+ }
91
+ if (!decorateParams.length) {
92
+ return;
93
+ }
94
+ for (var k in allSupportedParams) {
95
+ _decorateParams[allSupportedParams[k]] = false;
96
+ }
97
+ for (var k in decorateParams) {
98
+ _decorateParams[decorateParams[k]] = true;
99
+ }
100
+
101
+ // decorate elements
102
+ // elements[0].addClassName('first'); // will cause bug in IE (#5587)
103
+ if (_decorateParams.first) {
104
+ Element.addClassName(elements[0], 'first');
105
+ }
106
+ if (_decorateParams.last) {
107
+ Element.addClassName(elements[total-1], 'last');
108
+ }
109
+ for (var i = 0; i < total; i++) {
110
+ if ((i + 1) % 2 == 0) {
111
+ if (_decorateParams.even) {
112
+ Element.addClassName(elements[i], 'even');
113
+ }
114
+ }
115
+ else {
116
+ if (_decorateParams.odd) {
117
+ Element.addClassName(elements[i], 'odd');
118
+ }
119
+ }
120
+ }
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Decorate table rows and cells, tbody etc
126
+ * @see decorateGeneric()
127
+ */
128
+ function decorateTable(table, options) {
129
+ var table = $(table);
130
+ if (table) {
131
+ // set default options
132
+ var _options = {
133
+ 'tbody' : false,
134
+ 'tbody tr' : ['odd', 'even', 'first', 'last'],
135
+ 'thead tr' : ['first', 'last'],
136
+ 'tfoot tr' : ['first', 'last'],
137
+ 'tr td' : ['last']
138
+ };
139
+ // overload options
140
+ if (typeof(options) != 'undefined') {
141
+ for (var k in options) {
142
+ _options[k] = options[k];
143
+ }
144
+ }
145
+ // decorate
146
+ if (_options['tbody']) {
147
+ decorateGeneric(table.select('tbody'), _options['tbody']);
148
+ }
149
+ if (_options['tbody tr']) {
150
+ decorateGeneric(table.select('tbody tr'), _options['tbody tr']);
151
+ }
152
+ if (_options['thead tr']) {
153
+ decorateGeneric(table.select('thead tr'), _options['thead tr']);
154
+ }
155
+ if (_options['tfoot tr']) {
156
+ decorateGeneric(table.select('tfoot tr'), _options['tfoot tr']);
157
+ }
158
+ if (_options['tr td']) {
159
+ var allRows = table.select('tr');
160
+ if (allRows.length) {
161
+ for (var i = 0; i < allRows.length; i++) {
162
+ decorateGeneric(allRows[i].getElementsByTagName('TD'), _options['tr td']);
163
+ }
164
+ }
165
+ }
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Set "odd", "even" and "last" CSS classes for list items
171
+ * @see decorateGeneric()
172
+ */
173
+ function decorateList(list, nonRecursive) {
174
+ if ($(list)) {
175
+ if (typeof(nonRecursive) == 'undefined') {
176
+ var items = $(list).select('li')
177
+ }
178
+ else {
179
+ var items = $(list).childElements();
180
+ }
181
+ decorateGeneric(items, ['odd', 'even', 'last']);
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Set "odd", "even" and "last" CSS classes for list items
187
+ * @see decorateGeneric()
188
+ */
189
+ function decorateDataList(list) {
190
+ list = $(list);
191
+ if (list) {
192
+ decorateGeneric(list.select('dt'), ['odd', 'even', 'last']);
193
+ decorateGeneric(list.select('dd'), ['odd', 'even', 'last']);
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Parse SID and produces the correct URL
199
+ */
200
+ function parseSidUrl(baseUrl, urlExt) {
201
+ var sidPos = baseUrl.indexOf('/?SID=');
202
+ var sid = '';
203
+ urlExt = (urlExt != undefined) ? urlExt : '';
204
+
205
+ if(sidPos > -1) {
206
+ sid = '?' + baseUrl.substring(sidPos + 2);
207
+ baseUrl = baseUrl.substring(0, sidPos + 1);
208
+ }
209
+
210
+ return baseUrl+urlExt+sid;
211
+ }
212
+
213
+ /**
214
+ * Formats currency using patern
215
+ * format - JSON (pattern, decimal, decimalsDelimeter, groupsDelimeter)
216
+ * showPlus - true (always show '+'or '-'),
217
+ * false (never show '-' even if number is negative)
218
+ * null (show '-' if number is negative)
219
+ */
220
+
221
+ function formatCurrency(price, format, showPlus){
222
+ var precision = isNaN(format.precision = Math.abs(format.precision)) ? 2 : format.precision;
223
+ var requiredPrecision = isNaN(format.requiredPrecision = Math.abs(format.requiredPrecision)) ? 2 : format.requiredPrecision;
224
+
225
+ //precision = (precision > requiredPrecision) ? precision : requiredPrecision;
226
+ //for now we don't need this difference so precision is requiredPrecision
227
+ precision = requiredPrecision;
228
+
229
+ var integerRequired = isNaN(format.integerRequired = Math.abs(format.integerRequired)) ? 1 : format.integerRequired;
230
+
231
+ var decimalSymbol = format.decimalSymbol == undefined ? "," : format.decimalSymbol;
232
+ var groupSymbol = format.groupSymbol == undefined ? "." : format.groupSymbol;
233
+ var groupLength = format.groupLength == undefined ? 3 : format.groupLength;
234
+
235
+ var s = '';
236
+
237
+ if (showPlus == undefined || showPlus == true) {
238
+ s = price < 0 ? "-" : ( showPlus ? "+" : "");
239
+ } else if (showPlus == false) {
240
+ s = '';
241
+ }
242
+
243
+ var i = parseInt(price = Math.abs(+price || 0).toFixed(precision)) + "";
244
+ var pad = (i.length < integerRequired) ? (integerRequired - i.length) : 0;
245
+ while (pad) { i = '0' + i; pad--; }
246
+ j = (j = i.length) > groupLength ? j % groupLength : 0;
247
+ re = new RegExp("(\\d{" + groupLength + "})(?=\\d)", "g");
248
+
249
+ /**
250
+ * replace(/-/, 0) is only for fixing Safari bug which appears
251
+ * when Math.abs(0).toFixed() executed on "0" number.
252
+ * Result is "0.-0" :(
253
+ */
254
+ var r = (j ? i.substr(0, j) + groupSymbol : "") + i.substr(j).replace(re, "$1" + groupSymbol) + (precision ? decimalSymbol + Math.abs(price - i).toFixed(precision).replace(/-/, 0).slice(2) : "")
255
+ var pattern = '';
256
+ if (format.pattern.indexOf('{sign}') == -1) {
257
+ pattern = s + format.pattern;
258
+ } else {
259
+ pattern = format.pattern.replace('{sign}', s);
260
+ }
261
+
262
+ return pattern.replace('%s', r).replace(/^\s\s*/, '').replace(/\s\s*$/, '');
263
+ };
264
+
265
+ function expandDetails(el, childClass) {
266
+ if (Element.hasClassName(el,'show-details')) {
267
+ $$(childClass).each(function(item){item.hide()});
268
+ Element.removeClassName(el,'show-details');
269
+ }
270
+ else {
271
+ $$(childClass).each(function(item){item.show()});
272
+ Element.addClassName(el,'show-details');
273
+ }
274
+ }
275
+
276
+ // Version 1.0
277
+ var isIE = navigator.appVersion.match(/MSIE/) == "MSIE";
278
+
279
+ if (!window.Varien)
280
+ var Varien = new Object();
281
+
282
+ Varien.showLoading = function(){
283
+ Element.show('loading-process');
284
+ }
285
+ Varien.hideLoading = function(){
286
+ Element.hide('loading-process');
287
+ }
288
+ Varien.GlobalHandlers = {
289
+ onCreate: function() {
290
+ Varien.showLoading();
291
+ },
292
+
293
+ onComplete: function() {
294
+ if(Ajax.activeRequestCount == 0) {
295
+ Varien.hideLoading();
296
+ }
297
+ }
298
+ };
299
+
300
+ Ajax.Responders.register(Varien.GlobalHandlers);
301
+
302
+ /**
303
+ * Quick Search form client model
304
+ */
305
+ Varien.searchForm = Class.create();
306
+ Varien.searchForm.prototype = {
307
+ initialize : function(form, field, emptyText){
308
+ this.form = $(form);
309
+ this.field = $(field);
310
+ this.emptyText = emptyText;
311
+
312
+ Event.observe(this.form, 'submit', this.submit.bind(this));
313
+ Event.observe(this.field, 'focus', this.focus.bind(this));
314
+ Event.observe(this.field, 'blur', this.blur.bind(this));
315
+ this.blur();
316
+ },
317
+
318
+ submit : function(event){
319
+ if (this.field.value == this.emptyText || this.field.value == ''){
320
+ Event.stop(event);
321
+ return false;
322
+ }
323
+ return true;
324
+ },
325
+
326
+ focus : function(event){
327
+ if(this.field.value==this.emptyText){
328
+ this.field.value='';
329
+ }
330
+
331
+ },
332
+
333
+ blur : function(event){
334
+ if(this.field.value==''){
335
+ this.field.value=this.emptyText;
336
+ }
337
+ },
338
+
339
+ initAutocomplete : function(url, destinationElement){
340
+ new Ajax.Autocompleter(
341
+ this.field,
342
+ destinationElement,
343
+ url,
344
+ {
345
+ paramName: this.field.name,
346
+ method: 'get',
347
+ minChars: 2,
348
+ updateElement: this._selectAutocompleteItem.bind(this),
349
+ onShow : function(element, update) {
350
+ if(!update.style.position || update.style.position=='absolute') {
351
+ update.style.position = 'absolute';
352
+ Position.clone(element, update, {
353
+ setHeight: false,
354
+ offsetTop: element.offsetHeight
355
+ });
356
+ }
357
+ Effect.Appear(update,{duration:0});
358
+ }
359
+
360
+ }
361
+ );
362
+ },
363
+
364
+ _selectAutocompleteItem : function(element){
365
+ if(element.title){
366
+ this.field.value = element.title;
367
+ }
368
+ this.form.submit();
369
+ }
370
+ }
371
+
372
+ Varien.Tabs = Class.create();
373
+ Varien.Tabs.prototype = {
374
+ initialize: function(selector) {
375
+ var self=this;
376
+ $$(selector+' a').each(this.initTab.bind(this));
377
+ },
378
+
379
+ initTab: function(el) {
380
+ el.href = 'javascript:void(0)';
381
+ if ($(el.parentNode).hasClassName('active')) {
382
+ this.showContent(el);
383
+ }
384
+ el.observe('click', this.showContent.bind(this, el));
385
+ },
386
+
387
+ showContent: function(a) {
388
+ var li = $(a.parentNode), ul = $(li.parentNode);
389
+ ul.getElementsBySelector('li', 'ol').each(function(el){
390
+ var contents = $(el.id+'_contents');
391
+ if (el==li) {
392
+ el.addClassName('active');
393
+ contents.show();
394
+ } else {
395
+ el.removeClassName('active');
396
+ contents.hide();
397
+ }
398
+ });
399
+ }
400
+ }
401
+
402
+ Varien.DateElement = Class.create();
403
+ Varien.DateElement.prototype = {
404
+ initialize: function(type, content, required, format) {
405
+ if (type == 'id') {
406
+ // id prefix
407
+ this.day = $(content + 'day');
408
+ this.month = $(content + 'month');
409
+ this.year = $(content + 'year');
410
+ this.full = $(content + 'full');
411
+ this.advice = $(content + 'date-advice');
412
+ } else if (type == 'container') {
413
+ // content must be container with data
414
+ this.day = content.day;
415
+ this.month = content.month;
416
+ this.year = content.year;
417
+ this.full = content.full;
418
+ this.advice = content.advice;
419
+ } else {
420
+ return;
421
+ }
422
+
423
+ this.required = required;
424
+ this.format = format;
425
+
426
+ this.day.addClassName('validate-custom');
427
+ this.day.validate = this.validate.bind(this);
428
+ this.month.addClassName('validate-custom');
429
+ this.month.validate = this.validate.bind(this);
430
+ this.year.addClassName('validate-custom');
431
+ this.year.validate = this.validate.bind(this);
432
+
433
+ this.setDateRange(false, false);
434
+ this.year.setAttribute('autocomplete','off');
435
+
436
+ this.advice.hide();
437
+ },
438
+ validate: function() {
439
+ var error = false,
440
+ day = parseInt(this.day.value.replace(/^0*/, '')) || 0,
441
+ month = parseInt(this.month.value.replace(/^0*/, '')) || 0,
442
+ year = parseInt(this.year.value) || 0;
443
+ if (!day && !month && !year) {
444
+ if (this.required) {
445
+ error = 'This date is a required value.';
446
+ } else {
447
+ this.full.value = '';
448
+ }
449
+ } else if (!day || !month || !year) {
450
+ error = 'Please enter a valid full date.';
451
+ } else {
452
+ var date = new Date, countDaysInMonth = 0, errorType = null;
453
+ date.setYear(year);date.setMonth(month-1);date.setDate(32);
454
+ countDaysInMonth = 32 - date.getDate();
455
+ if(!countDaysInMonth || countDaysInMonth>31) countDaysInMonth = 31;
456
+
457
+ if (day<1 || day>countDaysInMonth) {
458
+ errorType = 'day';
459
+ error = 'Please enter a valid day (1-%d).';
460
+ } else if (month<1 || month>12) {
461
+ errorType = 'month';
462
+ error = 'Please enter a valid month (1-12).';
463
+ } else {
464
+ if(day % 10 == day) this.day.value = '0'+day;
465
+ if(month % 10 == month) this.month.value = '0'+month;
466
+ this.full.value = this.format.replace(/%[mb]/i, this.month.value).replace(/%[de]/i, this.day.value).replace(/%y/i, this.year.value);
467
+ var testFull = this.month.value + '/' + this.day.value + '/'+ this.year.value;
468
+ var test = new Date(testFull);
469
+ if (isNaN(test)) {
470
+ error = 'Please enter a valid date.';
471
+ } else {
472
+ this.setFullDate(test);
473
+ }
474
+ }
475
+ var valueError = false;
476
+ if (!error && !this.validateData()){//(year<1900 || year>curyear) {
477
+ errorType = this.validateDataErrorType;//'year';
478
+ valueError = this.validateDataErrorText;//'Please enter a valid year (1900-%d).';
479
+ error = valueError;
480
+ }
481
+ }
482
+
483
+ if (error !== false) {
484
+ try {
485
+ error = Translator.translate(error);
486
+ }
487
+ catch (e) {}
488
+ if (!valueError) {
489
+ this.advice.innerHTML = error.replace('%d', countDaysInMonth);
490
+ } else {
491
+ this.advice.innerHTML = this.errorTextModifier(error);
492
+ }
493
+ this.advice.show();
494
+ return false;
495
+ }
496
+
497
+ // fixing elements class
498
+ this.day.removeClassName('validation-failed');
499
+ this.month.removeClassName('validation-failed');
500
+ this.year.removeClassName('validation-failed');
501
+
502
+ this.advice.hide();
503
+ return true;
504
+ },
505
+ validateData: function() {
506
+ var year = this.fullDate.getFullYear();
507
+ var date = new Date;
508
+ this.curyear = date.getFullYear();
509
+ return (year>=1900 && year<=this.curyear);
510
+ },
511
+ validateDataErrorType: 'year',
512
+ validateDataErrorText: 'Please enter a valid year (1900-%d).',
513
+ errorTextModifier: function(text) {
514
+ return text.replace('%d', this.curyear);
515
+ },
516
+ setDateRange: function(minDate, maxDate) {
517
+ this.minDate = minDate;
518
+ this.maxDate = maxDate;
519
+ },
520
+ setFullDate: function(date) {
521
+ this.fullDate = date;
522
+ }
523
+ };
524
+
525
+ Varien.DOB = Class.create();
526
+ Varien.DOB.prototype = {
527
+ initialize: function(selector, required, format) {
528
+ var el = $$(selector)[0];
529
+ var container = {};
530
+ container.day = Element.select(el, '.dob-day input')[0];
531
+ container.month = Element.select(el, '.dob-month input')[0];
532
+ container.year = Element.select(el, '.dob-year input')[0];
533
+ container.full = Element.select(el, '.dob-full input')[0];
534
+ container.advice = Element.select(el, '.validation-advice')[0];
535
+
536
+ new Varien.DateElement('container', container, required, format);
537
+ }
538
+ };
539
+
540
+ Varien.dateRangeDate = Class.create();
541
+ Varien.dateRangeDate.prototype = Object.extend(new Varien.DateElement(), {
542
+ validateData: function() {
543
+ var validate = true;
544
+ if (this.minDate || this.maxValue) {
545
+ if (this.minDate) {
546
+ this.minDate = new Date(this.minDate);
547
+ this.minDate.setHours(0);
548
+ if (isNaN(this.minDate)) {
549
+ this.minDate = new Date('1/1/1900');
550
+ }
551
+ validate = validate && (this.fullDate >= this.minDate)
552
+ }
553
+ if (this.maxDate) {
554
+ this.maxDate = new Date(this.maxDate)
555
+ this.minDate.setHours(0);
556
+ if (isNaN(this.maxDate)) {
557
+ this.maxDate = new Date();
558
+ }
559
+ validate = validate && (this.fullDate <= this.maxDate)
560
+ }
561
+ if (this.maxDate && this.minDate) {
562
+ this.validateDataErrorText = 'Please enter a valid date between %s and %s';
563
+ } else if (this.maxDate) {
564
+ this.validateDataErrorText = 'Please enter a valid date less than or equal to %s';
565
+ } else if (this.minDate) {
566
+ this.validateDataErrorText = 'Please enter a valid date equal to or greater than %s';
567
+ } else {
568
+ this.validateDataErrorText = '';
569
+ }
570
+ }
571
+ return validate;
572
+ },
573
+ validateDataErrorText: 'Date should be between %s and %s',
574
+ errorTextModifier: function(text) {
575
+ if (this.minDate) {
576
+ text = text.sub('%s', this.dateFormat(this.minDate));
577
+ }
578
+ if (this.maxDate) {
579
+ text = text.sub('%s', this.dateFormat(this.maxDate));
580
+ }
581
+ return text;
582
+ },
583
+ dateFormat: function(date) {
584
+ return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();
585
+ }
586
+ });
587
+
588
+ Varien.FileElement = Class.create();
589
+ Varien.FileElement.prototype = {
590
+ initialize: function (id) {
591
+ this.fileElement = $(id);
592
+ this.hiddenElement = $(id + '_value');
593
+
594
+ this.fileElement.observe('change', this.selectFile.bind(this));
595
+ },
596
+ selectFile: function(event) {
597
+ this.hiddenElement.value = this.fileElement.getValue();
598
+ }
599
+ };
600
+
601
+ Validation.addAllThese([
602
+ ['validate-custom', ' ', function(v,elm) {
603
+ return elm.validate();
604
+ }]
605
+ ]);
606
+
607
+ function truncateOptions() {
608
+ $$('.truncated').each(function(element){
609
+ Event.observe(element, 'mouseover', function(){
610
+ if (element.down('div.truncated_full_value')) {
611
+ element.down('div.truncated_full_value').addClassName('show')
612
+ }
613
+ });
614
+ Event.observe(element, 'mouseout', function(){
615
+ if (element.down('div.truncated_full_value')) {
616
+ element.down('div.truncated_full_value').removeClassName('show')
617
+ }
618
+ });
619
+
620
+ });
621
+ }
622
+ Event.observe(window, 'load', function(){
623
+ truncateOptions();
624
+ });
625
+
626
+ Element.addMethods({
627
+ getInnerText: function(element)
628
+ {
629
+ element = $(element);
630
+ if(element.innerText && !Prototype.Browser.Opera) {
631
+ return element.innerText
632
+ }
633
+ return element.innerHTML.stripScripts().unescapeHTML().replace(/[\n\r\s]+/g, ' ').strip();
634
+ }
635
+ });
636
+
637
+ if (!("console" in window) || !("firebug" in console))
638
+ {
639
+ var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
640
+ "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
641
+
642
+ window.console = {};
643
+ for (var i = 0; i < names.length; ++i)
644
+ window.console[names[i]] = function() {}
645
+ }
646
+
647
+ /**
648
+ * Executes event handler on the element. Works with event handlers attached by Prototype,
649
+ * in a browser-agnostic fashion.
650
+ * @param element The element object
651
+ * @param event Event name, like 'change'
652
+ *
653
+ * @example fireEvent($('my-input', 'click'));
654
+ */
655
+ function fireEvent(element, event){
656
+ if (document.createEventObject){
657
+ // dispatch for IE
658
+ var evt = document.createEventObject();
659
+ return element.fireEvent('on'+event,evt)
660
+ }
661
+ else{
662
+ // dispatch for firefox + others
663
+ var evt = document.createEvent("HTMLEvents");
664
+ evt.initEvent(event, true, true ); // event type,bubbling,cancelable
665
+ return !element.dispatchEvent(evt);
666
+ }
667
+ }
668
+
669
+ /**
670
+ * createContextualFragment is not supported in IE9. Adding its support.
671
+ */
672
+ if ((typeof Range != "undefined") && !Range.prototype.createContextualFragment)
673
+ {
674
+ Range.prototype.createContextualFragment = function(html)
675
+ {
676
+ var frag = document.createDocumentFragment(),
677
+ div = document.createElement("div");
678
+ frag.appendChild(div);
679
+ div.outerHTML = html;
680
+ return frag;
681
+ };
682
+ }
js/varien/menu.js ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Varien
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ /**
27
+ * @classDescription simple Navigation with replacing old handlers
28
+ * @param {String} id id of ul element with navigation lists
29
+ * @param {Object} settings object with settings
30
+ */
31
+ var mainNav = function() {
32
+
33
+ var main = {
34
+ obj_nav : $(arguments[0]) || $("nav"),
35
+
36
+ settings : {
37
+ show_delay : 0,
38
+ hide_delay : 0,
39
+ _ie6 : /MSIE 6.+Win/.test(navigator.userAgent),
40
+ _ie7 : /MSIE 7.+Win/.test(navigator.userAgent)
41
+ },
42
+
43
+ init : function(obj, level) {
44
+ obj.lists = obj.childElements();
45
+ obj.lists.each(function(el,ind){
46
+ main.handlNavElement(el);
47
+ if((main.settings._ie6 || main.settings._ie7) && level){
48
+ main.ieFixZIndex(el, ind, obj.lists.size());
49
+ }
50
+ });
51
+ if(main.settings._ie6 && !level){
52
+ document.execCommand("BackgroundImageCache", false, true);
53
+ }
54
+ },
55
+
56
+ handlNavElement : function(list) {
57
+ if(list !== undefined){
58
+ list.onmouseover = function(){
59
+ main.fireNavEvent(this,true);
60
+ };
61
+ list.onmouseout = function(){
62
+ main.fireNavEvent(this,false);
63
+ };
64
+ if(list.down("ul")){
65
+ main.init(list.down("ul"), true);
66
+ }
67
+ }
68
+ },
69
+
70
+ ieFixZIndex : function(el, i, l) {
71
+ if(el.tagName.toString().toLowerCase().indexOf("iframe") == -1){
72
+ el.style.zIndex = l - i;
73
+ } else {
74
+ el.onmouseover = "null";
75
+ el.onmouseout = "null";
76
+ }
77
+ },
78
+
79
+ fireNavEvent : function(elm,ev) {
80
+ if(ev){
81
+ elm.addClassName("over");
82
+ elm.down("a").addClassName("over");
83
+ if (elm.childElements()[1]) {
84
+ main.show(elm.childElements()[1]);
85
+ }
86
+ } else {
87
+ elm.removeClassName("over");
88
+ elm.down("a").removeClassName("over");
89
+ if (elm.childElements()[1]) {
90
+ main.hide(elm.childElements()[1]);
91
+ }
92
+ }
93
+ },
94
+
95
+ show : function (sub_elm) {
96
+ if (sub_elm.hide_time_id) {
97
+ clearTimeout(sub_elm.hide_time_id);
98
+ }
99
+ sub_elm.show_time_id = setTimeout(function() {
100
+ if (!sub_elm.hasClassName("shown-sub")) {
101
+ sub_elm.addClassName("shown-sub");
102
+ }
103
+ }, main.settings.show_delay);
104
+ },
105
+
106
+ hide : function (sub_elm) {
107
+ if (sub_elm.show_time_id) {
108
+ clearTimeout(sub_elm.show_time_id);
109
+ }
110
+ sub_elm.hide_time_id = setTimeout(function(){
111
+ if (sub_elm.hasClassName("shown-sub")) {
112
+ sub_elm.removeClassName("shown-sub");
113
+ }
114
+ }, main.settings.hide_delay);
115
+ }
116
+
117
+ };
118
+ if (arguments[1]) {
119
+ main.settings = Object.extend(main.settings, arguments[1]);
120
+ }
121
+ if (main.obj_nav) {
122
+ main.init(main.obj_nav, false);
123
+ }
124
+ };
125
+
126
+ document.observe("dom:loaded", function() {
127
+ //run navigation without delays and with default id="#nav"
128
+ //mainNav();
129
+
130
+ //run navigation with delays
131
+ mainNav("nav", {"show_delay":"100","hide_delay":"100"});
132
+ });
js/varien/payment.js ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Varien
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ var paymentForm = Class.create();
26
+ paymentForm.prototype = {
27
+ initialize: function(formId){
28
+ this.formId = formId;
29
+ this.validator = new Validation(this.formId);
30
+ var elements = Form.getElements(formId);
31
+
32
+ var method = null;
33
+ for (var i=0; i<elements.length; i++) {
34
+ if (elements[i].name=='payment[method]') {
35
+ if (elements[i].checked) {
36
+ method = elements[i].value;
37
+ }
38
+ } else {
39
+ if((elements[i].type) && ('submit' != elements[i].type.toLowerCase())) {
40
+ elements[i].disabled = true;
41
+ }
42
+ }
43
+ elements[i].setAttribute('autocomplete','off');
44
+ }
45
+ if (method) this.switchMethod(method);
46
+ },
47
+
48
+ switchMethod: function(method){
49
+ if (this.currentMethod && $('payment_form_'+this.currentMethod)) {
50
+ var form = $('payment_form_'+this.currentMethod);
51
+ form.style.display = 'none';
52
+ var elements = form.getElementsByTagName('input');
53
+ for (var i=0; i<elements.length; i++) elements[i].disabled = true;
54
+ var elements = form.getElementsByTagName('select');
55
+ for (var i=0; i<elements.length; i++) elements[i].disabled = true;
56
+
57
+ }
58
+ if ($('payment_form_'+method)){
59
+ var form = $('payment_form_'+method);
60
+ form.style.display = '';
61
+ var elements = form.getElementsByTagName('input');
62
+ for (var i=0; i<elements.length; i++) elements[i].disabled = false;
63
+ var elements = form.getElementsByTagName('select');
64
+ for (var i=0; i<elements.length; i++) elements[i].disabled = false;
65
+ this.currentMethod = method;
66
+ }
67
+ }
68
+ }
js/varien/product.js ADDED
@@ -0,0 +1,722 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Varien
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ if(typeof Product=='undefined') {
26
+ var Product = {};
27
+ }
28
+
29
+ /********************* IMAGE ZOOMER ***********************/
30
+
31
+ Product.Zoom = Class.create();
32
+ /**
33
+ * Image zoom control
34
+ *
35
+ * @author Magento Core Team <core@magentocommerce.com>
36
+ */
37
+ Product.Zoom.prototype = {
38
+ initialize: function(imageEl, trackEl, handleEl, zoomInEl, zoomOutEl, hintEl){
39
+ this.containerEl = $(imageEl).parentNode;
40
+ this.imageEl = $(imageEl);
41
+ this.handleEl = $(handleEl);
42
+ this.trackEl = $(trackEl);
43
+ this.hintEl = $(hintEl);
44
+
45
+ this.containerDim = Element.getDimensions(this.containerEl);
46
+ this.imageDim = Element.getDimensions(this.imageEl);
47
+
48
+ this.imageDim.ratio = this.imageDim.width/this.imageDim.height;
49
+
50
+ this.floorZoom = 1;
51
+
52
+ if (this.imageDim.width > this.imageDim.height) {
53
+ this.ceilingZoom = this.imageDim.width / this.containerDim.width;
54
+ } else {
55
+ this.ceilingZoom = this.imageDim.height / this.containerDim.height;
56
+ }
57
+
58
+ if (this.imageDim.width <= this.containerDim.width
59
+ && this.imageDim.height <= this.containerDim.height) {
60
+ this.trackEl.up().hide();
61
+ this.hintEl.hide();
62
+ this.containerEl.removeClassName('product-image-zoom');
63
+ return;
64
+ }
65
+
66
+ this.imageX = 0;
67
+ this.imageY = 0;
68
+ this.imageZoom = 1;
69
+
70
+ this.sliderSpeed = 0;
71
+ this.sliderAccel = 0;
72
+ this.zoomBtnPressed = false;
73
+
74
+ this.showFull = false;
75
+
76
+ this.selects = document.getElementsByTagName('select');
77
+
78
+ this.draggable = new Draggable(imageEl, {
79
+ starteffect:false,
80
+ reverteffect:false,
81
+ endeffect:false,
82
+ snap:this.contain.bind(this)
83
+ });
84
+
85
+ this.slider = new Control.Slider(handleEl, trackEl, {
86
+ axis:'horizontal',
87
+ minimum:0,
88
+ maximum:Element.getDimensions(this.trackEl).width,
89
+ alignX:0,
90
+ increment:1,
91
+ sliderValue:0,
92
+ onSlide:this.scale.bind(this),
93
+ onChange:this.scale.bind(this)
94
+ });
95
+
96
+ this.scale(0);
97
+
98
+ Event.observe(this.imageEl, 'dblclick', this.toggleFull.bind(this));
99
+
100
+ Event.observe($(zoomInEl), 'mousedown', this.startZoomIn.bind(this));
101
+ Event.observe($(zoomInEl), 'mouseup', this.stopZooming.bind(this));
102
+ Event.observe($(zoomInEl), 'mouseout', this.stopZooming.bind(this));
103
+
104
+ Event.observe($(zoomOutEl), 'mousedown', this.startZoomOut.bind(this));
105
+ Event.observe($(zoomOutEl), 'mouseup', this.stopZooming.bind(this));
106
+ Event.observe($(zoomOutEl), 'mouseout', this.stopZooming.bind(this));
107
+ },
108
+
109
+ toggleFull: function () {
110
+ this.showFull = !this.showFull;
111
+
112
+ //Hide selects for IE6 only
113
+ if (typeof document.body.style.maxHeight == "undefined") {
114
+ for (i=0; i<this.selects.length; i++) {
115
+ this.selects[i].style.visibility = this.showFull ? 'hidden' : 'visible';
116
+ }
117
+ }
118
+ val_scale = !this.showFull ? this.slider.value : 1;
119
+ this.scale(val_scale);
120
+
121
+ this.trackEl.style.visibility = this.showFull ? 'hidden' : 'visible';
122
+ this.containerEl.style.overflow = this.showFull ? 'visible' : 'hidden';
123
+ this.containerEl.style.zIndex = this.showFull ? '1000' : '9';
124
+
125
+ return this;
126
+ },
127
+
128
+ scale: function (v) {
129
+ var centerX = (this.containerDim.width*(1-this.imageZoom)/2-this.imageX)/this.imageZoom;
130
+ var centerY = (this.containerDim.height*(1-this.imageZoom)/2-this.imageY)/this.imageZoom;
131
+ var overSize = (this.imageDim.width > this.containerDim.width || this.imageDim.height > this.containerDim.height);
132
+
133
+ this.imageZoom = this.floorZoom+(v*(this.ceilingZoom-this.floorZoom));
134
+
135
+ if (overSize) {
136
+ if (this.imageDim.width > this.containerDim.width) {
137
+ this.imageEl.style.width = (this.imageZoom*this.containerDim.width)+'px';
138
+ } else if (this.imageDim.height > this.containerDim.height) {
139
+ this.imageEl.style.height = (this.imageZoom*this.containerDim.height)+'px';
140
+ }
141
+
142
+ if(this.containerDim.ratio){
143
+ this.imageEl.style.height = (this.imageZoom*this.containerDim.width*this.containerDim.ratio)+'px'; // for safari
144
+ }
145
+ } else {
146
+ this.slider.setDisabled();
147
+ }
148
+
149
+ this.imageX = this.containerDim.width*(1-this.imageZoom)/2-centerX*this.imageZoom;
150
+ this.imageY = this.containerDim.height*(1-this.imageZoom)/2-centerY*this.imageZoom;
151
+
152
+ this.contain(this.imageX, this.imageY, this.draggable);
153
+
154
+ return true;
155
+ },
156
+
157
+ startZoomIn: function()
158
+ {
159
+ if (!this.slider.disabled) {
160
+ this.zoomBtnPressed = true;
161
+ this.sliderAccel = .002;
162
+ this.periodicalZoom();
163
+ this.zoomer = new PeriodicalExecuter(this.periodicalZoom.bind(this), .05);
164
+ }
165
+ return this;
166
+ },
167
+
168
+ startZoomOut: function()
169
+ {
170
+ if (!this.slider.disabled) {
171
+ this.zoomBtnPressed = true;
172
+ this.sliderAccel = -.002;
173
+ this.periodicalZoom();
174
+ this.zoomer = new PeriodicalExecuter(this.periodicalZoom.bind(this), .05);
175
+ }
176
+ return this;
177
+ },
178
+
179
+ stopZooming: function()
180
+ {
181
+ if (!this.zoomer || this.sliderSpeed==0) {
182
+ return;
183
+ }
184
+ this.zoomBtnPressed = false;
185
+ this.sliderAccel = 0;
186
+ },
187
+
188
+ periodicalZoom: function()
189
+ {
190
+ if (!this.zoomer) {
191
+ return this;
192
+ }
193
+
194
+ if (this.zoomBtnPressed) {
195
+ this.sliderSpeed += this.sliderAccel;
196
+ } else {
197
+ this.sliderSpeed /= 1.5;
198
+ if (Math.abs(this.sliderSpeed)<.001) {
199
+ this.sliderSpeed = 0;
200
+ this.zoomer.stop();
201
+ this.zoomer = null;
202
+ }
203
+ }
204
+ this.slider.value += this.sliderSpeed;
205
+
206
+ this.slider.setValue(this.slider.value);
207
+ this.scale(this.slider.value);
208
+
209
+ return this;
210
+ },
211
+
212
+ contain: function (x,y,draggable) {
213
+
214
+ var dim = Element.getDimensions(draggable.element);
215
+
216
+ var xMin = 0, xMax = this.containerDim.width-dim.width;
217
+ var yMin = 0, yMax = this.containerDim.height-dim.height;
218
+
219
+ x = x>xMin ? xMin : x;
220
+ x = x<xMax ? xMax : x;
221
+ y = y>yMin ? yMin : y;
222
+ y = y<yMax ? yMax : y;
223
+
224
+ if (this.containerDim.width > dim.width) {
225
+ x = (this.containerDim.width/2) - (dim.width/2);
226
+ }
227
+
228
+ if (this.containerDim.height > dim.height) {
229
+ y = (this.containerDim.height/2) - (dim.height/2);
230
+ }
231
+
232
+ this.imageX = x;
233
+ this.imageY = y;
234
+
235
+ this.imageEl.style.left = this.imageX+'px';
236
+ this.imageEl.style.top = this.imageY+'px';
237
+
238
+ return [x,y];
239
+ }
240
+ }
241
+
242
+ /**************************** CONFIGURABLE PRODUCT **************************/
243
+ Product.Config = Class.create();
244
+ Product.Config.prototype = {
245
+ initialize: function(config){
246
+ this.config = config;
247
+ this.taxConfig = this.config.taxConfig;
248
+ this.settings = $$('.super-attribute-select');
249
+ this.state = new Hash();
250
+ this.priceTemplate = new Template(this.config.template);
251
+ this.prices = config.prices;
252
+
253
+ this.settings.each(function(element){
254
+ Event.observe(element, 'change', this.configure.bind(this))
255
+ }.bind(this));
256
+
257
+ // fill state
258
+ this.settings.each(function(element){
259
+ var attributeId = element.id.replace(/[a-z]*/, '');
260
+ if(attributeId && this.config.attributes[attributeId]) {
261
+ element.config = this.config.attributes[attributeId];
262
+ element.attributeId = attributeId;
263
+ this.state[attributeId] = false;
264
+ }
265
+ }.bind(this))
266
+
267
+ // Init settings dropdown
268
+ var childSettings = [];
269
+ for(var i=this.settings.length-1;i>=0;i--){
270
+ var prevSetting = this.settings[i-1] ? this.settings[i-1] : false;
271
+ var nextSetting = this.settings[i+1] ? this.settings[i+1] : false;
272
+ if(i==0){
273
+ this.fillSelect(this.settings[i])
274
+ }
275
+ else {
276
+ this.settings[i].disabled=true;
277
+ }
278
+ $(this.settings[i]).childSettings = childSettings.clone();
279
+ $(this.settings[i]).prevSetting = prevSetting;
280
+ $(this.settings[i]).nextSetting = nextSetting;
281
+ childSettings.push(this.settings[i]);
282
+ }
283
+
284
+ // Set default values - from config and overwrite them by url values
285
+ if (config.defaultValues) {
286
+ this.values = config.defaultValues;
287
+ }
288
+
289
+ var separatorIndex = window.location.href.indexOf('#');
290
+ if (separatorIndex != -1) {
291
+ var paramsStr = window.location.href.substr(separatorIndex+1);
292
+ var urlValues = paramsStr.toQueryParams();
293
+ if (!this.values) {
294
+ this.values = {};
295
+ }
296
+ for (var i in urlValues) {
297
+ this.values[i] = urlValues[i];
298
+ }
299
+ }
300
+
301
+ this.configureForValues();
302
+ document.observe("dom:loaded", this.configureForValues.bind(this));
303
+ },
304
+
305
+ configureForValues: function () {
306
+ if (this.values) {
307
+ this.settings.each(function(element){
308
+ var attributeId = element.attributeId;
309
+ element.value = (typeof(this.values[attributeId]) == 'undefined')? '' : this.values[attributeId];
310
+ this.configureElement(element);
311
+ }.bind(this));
312
+ }
313
+ },
314
+
315
+ configure: function(event){
316
+ var element = Event.element(event);
317
+ this.configureElement(element);
318
+ },
319
+
320
+ configureElement : function(element) {
321
+ this.reloadOptionLabels(element);
322
+ if(element.value){
323
+ this.state[element.config.id] = element.value;
324
+ if(element.nextSetting){
325
+ element.nextSetting.disabled = false;
326
+ this.fillSelect(element.nextSetting);
327
+ this.resetChildren(element.nextSetting);
328
+ }
329
+ }
330
+ else {
331
+ this.resetChildren(element);
332
+ }
333
+ this.reloadPrice();
334
+ // Calculator.updatePrice();
335
+ },
336
+
337
+ reloadOptionLabels: function(element){
338
+ var selectedPrice;
339
+ if(element.options[element.selectedIndex].config){
340
+ selectedPrice = parseFloat(element.options[element.selectedIndex].config.price)
341
+ }
342
+ else{
343
+ selectedPrice = 0;
344
+ }
345
+ for(var i=0;i<element.options.length;i++){
346
+ if(element.options[i].config){
347
+ element.options[i].text = this.getOptionLabel(element.options[i].config, element.options[i].config.price-selectedPrice);
348
+ }
349
+ }
350
+ },
351
+
352
+ resetChildren : function(element){
353
+ if(element.childSettings) {
354
+ for(var i=0;i<element.childSettings.length;i++){
355
+ element.childSettings[i].selectedIndex = 0;
356
+ element.childSettings[i].disabled = true;
357
+ if(element.config){
358
+ this.state[element.config.id] = false;
359
+ }
360
+ }
361
+ }
362
+ },
363
+
364
+ fillSelect: function(element){
365
+ var attributeId = element.id.replace(/[a-z]*/, '');
366
+ var options = this.getAttributeOptions(attributeId);
367
+ this.clearSelect(element);
368
+ element.options[0] = new Option(this.config.chooseText, '');
369
+
370
+ var prevConfig = false;
371
+ if(element.prevSetting){
372
+ prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex];
373
+ }
374
+
375
+ if(options) {
376
+ var index = 1;
377
+ for(var i=0;i<options.length;i++){
378
+ var allowedProducts = [];
379
+ if(prevConfig) {
380
+ for(var j=0;j<options[i].products.length;j++){
381
+ if(prevConfig.config.allowedProducts
382
+ && prevConfig.config.allowedProducts.indexOf(options[i].products[j])>-1){
383
+ allowedProducts.push(options[i].products[j]);
384
+ }
385
+ }
386
+ } else {
387
+ allowedProducts = options[i].products.clone();
388
+ }
389
+
390
+ if(allowedProducts.size()>0){
391
+ options[i].allowedProducts = allowedProducts;
392
+ element.options[index] = new Option(this.getOptionLabel(options[i], options[i].price), options[i].id);
393
+ element.options[index].config = options[i];
394
+ index++;
395
+ }
396
+ }
397
+ }
398
+ },
399
+
400
+ getOptionLabel: function(option, price){
401
+ var price = parseFloat(price);
402
+ if (this.taxConfig.includeTax) {
403
+ var tax = price / (100 + this.taxConfig.defaultTax) * this.taxConfig.defaultTax;
404
+ var excl = price - tax;
405
+ var incl = excl*(1+(this.taxConfig.currentTax/100));
406
+ } else {
407
+ var tax = price * (this.taxConfig.currentTax / 100);
408
+ var excl = price;
409
+ var incl = excl + tax;
410
+ }
411
+
412
+ if (this.taxConfig.showIncludeTax || this.taxConfig.showBothPrices) {
413
+ price = incl;
414
+ } else {
415
+ price = excl;
416
+ }
417
+
418
+ var str = option.label;
419
+ if(price){
420
+ if (this.taxConfig.showBothPrices) {
421
+ str+= ' ' + this.formatPrice(excl, true) + ' (' + this.formatPrice(price, true) + ' ' + this.taxConfig.inclTaxTitle + ')';
422
+ } else {
423
+ str+= ' ' + this.formatPrice(price, true);
424
+ }
425
+ }
426
+ return str;
427
+ },
428
+
429
+ formatPrice: function(price, showSign){
430
+ var str = '';
431
+ price = parseFloat(price);
432
+ if(showSign){
433
+ if(price<0){
434
+ str+= '-';
435
+ price = -price;
436
+ }
437
+ else{
438
+ str+= '+';
439
+ }
440
+ }
441
+
442
+ var roundedPrice = (Math.round(price*100)/100).toString();
443
+
444
+ if (this.prices && this.prices[roundedPrice]) {
445
+ str+= this.prices[roundedPrice];
446
+ }
447
+ else {
448
+ str+= this.priceTemplate.evaluate({price:price.toFixed(2)});
449
+ }
450
+ return str;
451
+ },
452
+
453
+ clearSelect: function(element){
454
+ for(var i=element.options.length-1;i>=0;i--){
455
+ element.remove(i);
456
+ }
457
+ },
458
+
459
+ getAttributeOptions: function(attributeId){
460
+ if(this.config.attributes[attributeId]){
461
+ return this.config.attributes[attributeId].options;
462
+ }
463
+ },
464
+
465
+ reloadPrice: function(){
466
+ var price = 0;
467
+ var oldPrice = 0;
468
+ for(var i=this.settings.length-1;i>=0;i--){
469
+ var selected = this.settings[i].options[this.settings[i].selectedIndex];
470
+ if(selected.config){
471
+ price += parseFloat(selected.config.price);
472
+ oldPrice += parseFloat(selected.config.oldPrice);
473
+ }
474
+ }
475
+
476
+ optionsPrice.changePrice('config', {'price': price, 'oldPrice': oldPrice});
477
+ optionsPrice.reload();
478
+
479
+ return price;
480
+
481
+ if($('product-price-'+this.config.productId)){
482
+ $('product-price-'+this.config.productId).innerHTML = price;
483
+ }
484
+ this.reloadOldPrice();
485
+ },
486
+
487
+ reloadOldPrice: function(){
488
+ if ($('old-price-'+this.config.productId)) {
489
+
490
+ var price = parseFloat(this.config.oldPrice);
491
+ for(var i=this.settings.length-1;i>=0;i--){
492
+ var selected = this.settings[i].options[this.settings[i].selectedIndex];
493
+ if(selected.config){
494
+ price+= parseFloat(selected.config.price);
495
+ }
496
+ }
497
+ if (price < 0)
498
+ price = 0;
499
+ price = this.formatPrice(price);
500
+
501
+ if($('old-price-'+this.config.productId)){
502
+ $('old-price-'+this.config.productId).innerHTML = price;
503
+ }
504
+
505
+ }
506
+ }
507
+ }
508
+
509
+
510
+ /**************************** SUPER PRODUCTS ********************************/
511
+
512
+ Product.Super = {};
513
+ Product.Super.Configurable = Class.create();
514
+
515
+ Product.Super.Configurable.prototype = {
516
+ initialize: function(container, observeCss, updateUrl, updatePriceUrl, priceContainerId) {
517
+ this.container = $(container);
518
+ this.observeCss = observeCss;
519
+ this.updateUrl = updateUrl;
520
+ this.updatePriceUrl = updatePriceUrl;
521
+ this.priceContainerId = priceContainerId;
522
+ this.registerObservers();
523
+ },
524
+ registerObservers: function() {
525
+ var elements = this.container.getElementsByClassName(this.observeCss);
526
+ elements.each(function(element){
527
+ Event.observe(element, 'change', this.update.bindAsEventListener(this));
528
+ }.bind(this));
529
+ return this;
530
+ },
531
+ update: function(event) {
532
+ var elements = this.container.getElementsByClassName(this.observeCss);
533
+ var parameters = Form.serializeElements(elements, true);
534
+
535
+ new Ajax.Updater(this.container, this.updateUrl + '?ajax=1', {
536
+ parameters:parameters,
537
+ onComplete:this.registerObservers.bind(this)
538
+ });
539
+ var priceContainer = $(this.priceContainerId);
540
+ if(priceContainer) {
541
+ new Ajax.Updater(priceContainer, this.updatePriceUrl + '?ajax=1', {
542
+ parameters:parameters
543
+ });
544
+ }
545
+ }
546
+ }
547
+
548
+ /**************************** PRICE RELOADER ********************************/
549
+ Product.OptionsPrice = Class.create();
550
+ Product.OptionsPrice.prototype = {
551
+ initialize: function(config) {
552
+ this.productId = config.productId;
553
+ this.priceFormat = config.priceFormat;
554
+ this.includeTax = config.includeTax;
555
+ this.defaultTax = config.defaultTax;
556
+ this.currentTax = config.currentTax;
557
+ this.productPrice = config.productPrice;
558
+ this.showIncludeTax = config.showIncludeTax;
559
+ this.showBothPrices = config.showBothPrices;
560
+ this.productOldPrice = config.productOldPrice;
561
+ this.priceInclTax = config.priceInclTax;
562
+ this.priceExclTax = config.priceExclTax;
563
+ this.skipCalculate = config.skipCalculate;//@deprecated after 1.5.1.0
564
+ this.duplicateIdSuffix = config.idSuffix;
565
+ this.specialTaxPrice = config.specialTaxPrice;
566
+
567
+ this.oldPlusDisposition = config.oldPlusDisposition;
568
+ this.plusDisposition = config.plusDisposition;
569
+
570
+ this.oldMinusDisposition = config.oldMinusDisposition;
571
+ this.minusDisposition = config.minusDisposition;
572
+
573
+ this.optionPrices = {};
574
+ this.containers = {};
575
+
576
+ this.displayZeroPrice = true;
577
+
578
+ this.initPrices();
579
+ },
580
+
581
+ setDuplicateIdSuffix: function(idSuffix) {
582
+ this.duplicateIdSuffix = idSuffix;
583
+ },
584
+
585
+ initPrices: function() {
586
+ this.containers[0] = 'product-price-' + this.productId;
587
+ this.containers[1] = 'bundle-price-' + this.productId;
588
+ this.containers[2] = 'price-including-tax-' + this.productId;
589
+ this.containers[3] = 'price-excluding-tax-' + this.productId;
590
+ this.containers[4] = 'old-price-' + this.productId;
591
+ },
592
+
593
+ changePrice: function(key, price) {
594
+ this.optionPrices[key] = price;
595
+ },
596
+
597
+ getOptionPrices: function() {
598
+ var price = 0;
599
+ var nonTaxable = 0;
600
+ var oldPrice = 0;
601
+ var priceInclTax = 0;
602
+ var currentTax = this.currentTax;
603
+ $H(this.optionPrices).each(function(pair) {
604
+ if ('undefined' != typeof(pair.value.price) && 'undefined' != typeof(pair.value.oldPrice)) {
605
+ price += parseFloat(pair.value.price);
606
+ oldPrice += parseFloat(pair.value.oldPrice);
607
+ } else if (pair.key == 'nontaxable') {
608
+ nonTaxable = pair.value;
609
+ } else if (pair.key == 'priceInclTax') {
610
+ priceInclTax += pair.value;
611
+ } else if (pair.key == 'optionsPriceInclTax') {
612
+ priceInclTax += pair.value * (100 + currentTax) / 100;
613
+ } else {
614
+ price += parseFloat(pair.value);
615
+ oldPrice += parseFloat(pair.value);
616
+ }
617
+ });
618
+ var result = [price, nonTaxable, oldPrice, priceInclTax];
619
+ return result;
620
+ },
621
+
622
+ reload: function() {
623
+ var price;
624
+ var formattedPrice;
625
+ var optionPrices = this.getOptionPrices();
626
+ var nonTaxable = optionPrices[1];
627
+ var optionOldPrice = optionPrices[2];
628
+ var priceInclTax = optionPrices[3];
629
+ optionPrices = optionPrices[0];
630
+
631
+ $H(this.containers).each(function(pair) {
632
+ var _productPrice;
633
+ var _plusDisposition;
634
+ var _minusDisposition;
635
+ if ($(pair.value)) {
636
+ if (pair.value == 'old-price-'+this.productId && this.productOldPrice != this.productPrice) {
637
+ _productPrice = this.productOldPrice;
638
+ _plusDisposition = this.oldPlusDisposition;
639
+ _minusDisposition = this.oldMinusDisposition;
640
+ } else {
641
+ _productPrice = this.productPrice;
642
+ _plusDisposition = this.plusDisposition;
643
+ _minusDisposition = this.minusDisposition;
644
+ }
645
+
646
+ if (pair.value == 'old-price-'+this.productId && optionOldPrice !== undefined) {
647
+ price = optionOldPrice+parseFloat(_productPrice);
648
+ } else if (this.specialTaxPrice == 'true' && this.priceInclTax !== undefined && this.priceExclTax !== undefined) {
649
+ price = optionPrices+parseFloat(this.priceExclTax);
650
+ priceInclTax += this.priceInclTax;
651
+ } else {
652
+ price = optionPrices+parseFloat(_productPrice);
653
+ priceInclTax += parseFloat(_productPrice) * (100 + this.currentTax) / 100;
654
+ }
655
+
656
+ if (this.specialTaxPrice == 'true') {
657
+ var excl = price;
658
+ var incl = priceInclTax;
659
+ } else if (this.includeTax == 'true') {
660
+ // tax = tax included into product price by admin
661
+ var tax = price / (100 + this.defaultTax) * this.defaultTax;
662
+ var excl = price - tax;
663
+ var incl = excl*(1+(this.currentTax/100));
664
+ } else {
665
+ var tax = price * (this.currentTax / 100);
666
+ var excl = price;
667
+ var incl = excl + tax;
668
+ }
669
+
670
+ excl += parseFloat(_plusDisposition);
671
+ incl += parseFloat(_plusDisposition);
672
+ excl -= parseFloat(_minusDisposition);
673
+ incl -= parseFloat(_minusDisposition);
674
+
675
+ //adding nontaxlable part of options
676
+ excl += parseFloat(nonTaxable);
677
+ incl += parseFloat(nonTaxable);
678
+
679
+ if (pair.value == 'price-including-tax-'+this.productId) {
680
+ price = incl;
681
+ } else if (pair.value == 'price-excluding-tax-'+this.productId) {
682
+ price = excl;
683
+ } else if (pair.value == 'old-price-'+this.productId) {
684
+ if (this.showIncludeTax || this.showBothPrices) {
685
+ price = incl;
686
+ } else {
687
+ price = excl;
688
+ }
689
+ } else {
690
+ if (this.showIncludeTax) {
691
+ price = incl;
692
+ } else {
693
+ price = excl;
694
+ }
695
+ }
696
+
697
+ if (price < 0) price = 0;
698
+
699
+ if (price > 0 || this.displayZeroPrice) {
700
+ formattedPrice = this.formatPrice(price);
701
+ } else {
702
+ formattedPrice = '';
703
+ }
704
+
705
+ if ($(pair.value).select('.price')[0]) {
706
+ $(pair.value).select('.price')[0].innerHTML = formattedPrice;
707
+ if ($(pair.value+this.duplicateIdSuffix) && $(pair.value+this.duplicateIdSuffix).select('.price')[0]) {
708
+ $(pair.value+this.duplicateIdSuffix).select('.price')[0].innerHTML = formattedPrice;
709
+ }
710
+ } else {
711
+ $(pair.value).innerHTML = formattedPrice;
712
+ if ($(pair.value+this.duplicateIdSuffix)) {
713
+ $(pair.value+this.duplicateIdSuffix).innerHTML = formattedPrice;
714
+ }
715
+ }
716
+ };
717
+ }.bind(this));
718
+ },
719
+ formatPrice: function(price) {
720
+ return formatCurrency(price, this.priceFormat);
721
+ }
722
+ }
js/varien/telephone.js ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Varien
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+ var telephoneElem = Class.create();
26
+
27
+ telephoneElem.prototype = {
28
+ initialize : function(fval,f1,f2,f3,f4){
29
+ this.valField = fval;
30
+ this.f1 = f1;
31
+ this.f2 = f2;
32
+ this.f3 = f3;
33
+ this.f4 = f4;
34
+ this.last = f3;
35
+
36
+ this.eventKeyPress = this.keyPress.bindAsEventListener(this);
37
+ this.eventKeyUp = this.keyUp.bindAsEventListener(this);
38
+
39
+ Event.observe(this.f1, "keyup", this.eventKeyUp);
40
+ Event.observe(this.f2, "keyup", this.eventKeyUp);
41
+ Event.observe(this.f3, "keyup", this.eventKeyUp);
42
+
43
+ Event.observe(this.f1, "keypress", this.eventKeyPress);
44
+ Event.observe(this.f2, "keypress", this.eventKeyPress);
45
+ Event.observe(this.f3, "keypress", this.eventKeyPress);
46
+
47
+ if (this.f4)
48
+ {
49
+ Event.observe(this.f4, "keyup", this.eventKeyUp);
50
+ Event.observe(this.f4, "keypress", this.eventKeyPress);
51
+ this.last = f4;
52
+ }
53
+ this.loadValues();
54
+ },
55
+
56
+ keyPress: function(event){
57
+ var code = event.keyCode;
58
+ /* if ((event.keyCode < 48 || event.keyCode > 57) && event.keyCode != Event.KEY_BACKSPACE && event.keyCode != Event.KEY_DELETE && event.keyCode != Event.KEY_LEFT && event.keyCode != Event.KEY_RIGHT)
59
+ {
60
+ Event.stop(event);
61
+ }*/
62
+ },
63
+
64
+ keyUp: function(event){
65
+ var element = Event.element(event);
66
+ var code = event.keyCode;
67
+ if (element.id != this.last && code != Event.KEY_TAB && code != 16 && code != Event.KEY_BACKSPACE && code != Event.KEY_DELETE && code != Event.KEY_LEFT && code != Event.KEY_RIGHT)
68
+ {
69
+ var size = element.size;
70
+ if (element.value.length == size)
71
+ {
72
+ if (nextElem = this.getNextElement(element.id))
73
+ {
74
+ Field.activate(nextElem);
75
+ }
76
+ }
77
+ }
78
+ this.setValField();
79
+ },
80
+
81
+ getNextElement: function(curent_id){
82
+ if (curent_id == this.last)
83
+ {
84
+ return false;
85
+ }
86
+
87
+ if (curent_id == this.f1)
88
+ {
89
+ return this.f2;
90
+ }
91
+ if (curent_id == this.f2)
92
+ {
93
+ return this.f3;
94
+ }
95
+ if (curent_id == this.f3)
96
+ {
97
+ return this.f4;
98
+ }
99
+
100
+ return false;
101
+ },
102
+
103
+ setValField: function(){
104
+ cur_value = '';
105
+ if($F(this.f1)) cur_value += '(' + $F(this.f1) + ') ';
106
+ if($F(this.f2)) cur_value += $F(this.f2);
107
+ if($F(this.f3)) cur_value += '-' + $F(this.f3);
108
+ if (this.f4) cur_value += $F(this.f4) ? '-' + $F(this.f4) : '';
109
+
110
+ $(this.valField).value = cur_value;
111
+ },
112
+
113
+ loadValues: function(){
114
+ var val = $F(this.valField);
115
+ if (val && val.length)
116
+ {
117
+ re = /^[\(]?(\d{3})[\)]?[-|\s]?(\d{3})[-|\s](\d{4})[-|\s]?(\d{0,4})?$/;
118
+ if (re.test(val))
119
+ {
120
+ arrVal = re.exec(val);
121
+ $(this.f1).value = arrVal[1];
122
+ $(this.f2).value = arrVal[2];
123
+ $(this.f3).value = arrVal[3];
124
+ if (this.f4 && arrVal[4])
125
+ {
126
+ $(this.f4).value = arrVal[4];
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }
js/varien/weee.js ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @category Varien
21
+ * @package js
22
+ * @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
23
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
24
+ */
25
+
26
+ /**************************** WEEE STUFF ********************************/
27
+ function taxToggle(details, switcher, expandedClassName)
28
+ {
29
+ if ($(details).style.display == 'none') {
30
+ $(details).show();
31
+ $(switcher).addClassName(expandedClassName);
32
+ } else {
33
+ $(details).hide();
34
+ $(switcher).removeClassName(expandedClassName);
35
+ }
36
+ }
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Lib_Js_Mage</name>
4
+ <version>1.6.0.0</version>
5
+ <stability>stable</stability>
6
+ <license>Mixed</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Javascript Libraries for Magento</summary>
10
+ <description>Javascript Libraries for Magento</description>
11
+ <notes>1.6.0.0</notes>
12
+ <authors><author><name>Magento Core Team</name><user>core</user><email>core@magentocommerce.com</email></author></authors>
13
+ <date>2011-08-18</date>
14
+ <time>08:29:36</time>
15
+ <contents><target name="mageweb"><dir name="js"><dir name="lib"><file name="FABridge.js" hash="64244d8d58abd42bd71f0ee3309767ad"/><file name="boxover.js" hash="a5ade77452e8d5066cb84dcac3d34ed5"/><file name="ccard.js" hash="d3e849be0977d53de4af933b40293ff6"/><file name="dropdown.js" hash="b47a46ecc0ffaa60c7ef3b60bad27bf3"/><file name="ds-sleight.js" hash="85af457d444865d1587bfe4875bd4fc6"/><file name="flex.js" hash="59191d36c041897d4ea86671671f7b65"/></dir><dir name="mage"><dir name="adminhtml"><file name="accordion.js" hash="6f0269f9d5060cfe42a0cb806d4657c5"/><file name="browser.js" hash="6433918dff8f6797553005a543a194dd"/><file name="events.js" hash="e63e761d3feb5a176bf9517ed8c13af9"/><file name="flexuploader.js" hash="3b84b6c22da29211474453a055750128"/><file name="form.js" hash="d427e4b296cc5823900b54195207a474"/><file name="giftmessage.js" hash="742b0a1178f509e77794be3bfdbe3701"/><dir name="giftoptions"><file name="tooltip.js" hash="693608acf4d65958c91765260c1c8434"/></dir><file name="grid.js" hash="02daffe0a45c27aef2b589e7f0ab862d"/><file name="hash.js" hash="5be791a6cd26ff7ab09ac9df5a9fdc9b"/><file name="image.js" hash="5721f1141f99e350bb5efb32dd004067"/><file name="loader.js" hash="f96ba03feef42b1335b94b294a0a991c"/><file name="magento-all.js" hash="23677c90ebc09dac2179476715be9e3b"/><dir name="product"><dir name="composite"><file name="configure.js" hash="f23f502c62f0656148b705dd0f6815bb"/></dir></dir><file name="product.js" hash="81d8065e9cee57a5e30ef2622f3a4506"/><file name="rules.js" hash="ef09be8d19fd77c7d91eae6a2d6573fc"/><dir name="sales"><file name="packaging.js" hash="1ab04d26b4b9281149486bdcadcc85d8"/></dir><file name="sales.js" hash="a4296235ba7ad200dd042fa5200c11b0"/><file name="scrollbar.js" hash="bee8e4ad54a830e5bd054f2ab2ce3dd1"/><file name="tabs.js" hash="562a6244e92532be0bdea8b7efab5638"/><file name="tools.js" hash="d7f5a1c048db67c081d94ee27e53b8bb"/><file name="uploader.js" hash="41d67dcd00f3b0d98ddd572c5f9bbeb4"/><file name="variables.js" hash="8d2261b60d2f8b9a16fc287c1409c94c"/><dir name="wysiwyg"><dir name="tiny_mce"><dir name="plugins"><dir name="magentovariable"><file name="editor_plugin.js" hash="5c2745eb128c45d2d1991c063a5583b5"/><dir name="img"><file name="icon.gif" hash="682b29a0e734f952cb2edabede6a25d1"/></dir></dir><dir name="magentowidget"><file name="editor_plugin.js" hash="60fdac7be7bbc4872ff27f2f15f6f8de"/><dir name="img"><file name="icon.gif" hash="532c141286373f098f1f4362e001c7f8"/></dir></dir></dir><file name="setup.js" hash="01a0c5b901bfd934e83c27a3a5a15eb3"/><dir name="themes"><dir name="advanced"><dir name="skins"><dir name="default"><file name="content.css" hash="39d109d661ea96af47d6a19c8c938d1e"/><file name="dialog.css" hash="97841661b61720b5ec4c9abf5e2e2abc"/></dir></dir></dir></dir></dir><file name="widget.js" hash="720586f7c4dda7674fa32d41c3e1c43b"/></dir></dir><file name="centinel.js" hash="41e4e3934681ef033860851ee2b7aba1"/><file name="cookies.js" hash="27b928501b43734c92b079ce19cba820"/><file name="directpost.js" hash="753e0c8f8d41cd7f3130b380ab5f6172"/><file name="translate.js" hash="ad862170f3baf5d16aa2c6c61ae232af"/><file name="translate_inline.css" hash="ecc986ee6878c40889d99f0f1964f625"/><file name="translate_inline.js" hash="219437ece6900633563e3cdee1f9d147"/></dir><dir name="varien"><file name="accordion.js" hash="70dde90999d61bf0ead8fbb24853c57a"/><file name="configurable.js" hash="10ecc0453a2acb613f1e9230c0e4f0bf"/><file name="form.js" hash="a470621a37d8c0fd1fd29c1aa5ee8670"/><file name="iehover-fix.js" hash="e5222683d48a9d4e1c9dbd3869d272e5"/><file name="js.js" hash="bcebae57a13302f0f9a8a1d71c7e49c9"/><file name="menu.js" hash="d3769730462205cd5a4096f5846faf3a"/><file name="payment.js" hash="2af70aefbfe63f09a96eb44aad61cd1a"/><file name="product.js" hash="aac185eadbc519df073dd25d2bafabe2"/><file name="telephone.js" hash="8b1b8c13882e07d210b2a89116c2d6bd"/><file name="weee.js" hash="bf921d6da47bdf79dcf0b7ce483caa1c"/></dir><file name="blank.html" hash="d41d8cd98f00b204e9800998ecf8427e"/><file name="index.php" hash="9a76023de59c1958cac0473ef31efa26"/><file name="spacer.gif" hash="df3e567d6f16d040326c7a0ea29a4f41"/><dir name="flash"><file name="AC_RunActiveContent.js" hash="3e038cea960c1b650442b85cea237053"/></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php><package><name>Lib_Js_Prototype</name><channel>community</channel><min>1.7.0.0</min><max>1.7.1.0</max></package></required></dependencies>
18
+ </package>