PageRenderTime 22ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/js/varien/form.js

https://bitbucket.org/sevenly/magento-ce
JavaScript | 392 lines | 328 code | 34 blank | 30 comment | 96 complexity | c16ed6f82b78d8f3bc07de6f5ebd8eb6 MD5 | raw file
  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) 2012 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. submit : function(url){
  51. if(this.validator && this.validator.validate()){
  52. this.form.submit();
  53. }
  54. return false;
  55. },
  56. bindElements:function (){
  57. var elements = Form.getElements(this.form);
  58. for (var row in elements) {
  59. if (elements[row].id) {
  60. Event.observe(elements[row],'focus',this.elementFocus);
  61. Event.observe(elements[row],'blur',this.elementBlur);
  62. }
  63. }
  64. },
  65. elementOnFocus: function(event){
  66. var element = Event.findElement(event, 'fieldset');
  67. if(element){
  68. Element.addClassName(element, this.highlightClass);
  69. }
  70. },
  71. elementOnBlur: function(event){
  72. var element = Event.findElement(event, 'fieldset');
  73. if(element){
  74. Element.removeClassName(element, this.highlightClass);
  75. }
  76. },
  77. setElementsRelation: function(parent, child, dataUrl, first){
  78. if (parent=$(parent)) {
  79. // TODO: array of relation and caching
  80. if (!this.cache[parent.id]){
  81. this.cache[parent.id] = $A();
  82. this.cache[parent.id]['child'] = child;
  83. this.cache[parent.id]['dataUrl'] = dataUrl;
  84. this.cache[parent.id]['data'] = $A();
  85. this.cache[parent.id]['first'] = first || false;
  86. }
  87. Event.observe(parent,'change',this.childLoader);
  88. }
  89. },
  90. onChangeChildLoad: function(event){
  91. element = Event.element(event);
  92. this.elementChildLoad(element);
  93. },
  94. elementChildLoad: function(element, callback){
  95. this.callback = callback || false;
  96. if (element.value) {
  97. this.currLoader = element.id;
  98. this.currDataIndex = element.value;
  99. if (this.cache[element.id]['data'][element.value]) {
  100. this.setDataToChild(this.cache[element.id]['data'][element.value]);
  101. }
  102. else{
  103. new Ajax.Request(this.cache[this.currLoader]['dataUrl'],{
  104. method: 'post',
  105. parameters: {"parent":element.value},
  106. onComplete: this.reloadChildren.bind(this)
  107. });
  108. }
  109. }
  110. },
  111. reloadChildren: function(transport){
  112. var data = eval('(' + transport.responseText + ')');
  113. this.cache[this.currLoader]['data'][this.currDataIndex] = data;
  114. this.setDataToChild(data);
  115. },
  116. setDataToChild: function(data){
  117. if (data.length) {
  118. var child = $(this.cache[this.currLoader]['child']);
  119. if (child){
  120. var html = '<select name="'+child.name+'" id="'+child.id+'" class="'+child.className+'" title="'+child.title+'" '+this.extraChildParams+'>';
  121. if(this.cache[this.currLoader]['first']){
  122. html+= '<option value="">'+this.cache[this.currLoader]['first']+'</option>';
  123. }
  124. for (var i in data){
  125. if(data[i].value) {
  126. html+= '<option value="'+data[i].value+'"';
  127. if(child.value && (child.value == data[i].value || child.value == data[i].label)){
  128. html+= ' selected';
  129. }
  130. html+='>'+data[i].label+'</option>';
  131. }
  132. }
  133. html+= '</select>';
  134. Element.insert(child, {before: html});
  135. Element.remove(child);
  136. }
  137. }
  138. else{
  139. var child = $(this.cache[this.currLoader]['child']);
  140. if (child){
  141. var html = '<input type="text" name="'+child.name+'" id="'+child.id+'" class="'+child.className+'" title="'+child.title+'" '+this.extraChildParams+'>';
  142. Element.insert(child, {before: html});
  143. Element.remove(child);
  144. }
  145. }
  146. this.bindElements();
  147. if (this.callback) {
  148. this.callback();
  149. }
  150. }
  151. }
  152. RegionUpdater = Class.create();
  153. RegionUpdater.prototype = {
  154. initialize: function (countryEl, regionTextEl, regionSelectEl, regions, disableAction, zipEl)
  155. {
  156. this.countryEl = $(countryEl);
  157. this.regionTextEl = $(regionTextEl);
  158. this.regionSelectEl = $(regionSelectEl);
  159. this.zipEl = $(zipEl);
  160. this.config = regions['config'];
  161. delete regions.config;
  162. this.regions = regions;
  163. this.disableAction = (typeof disableAction=='undefined') ? 'hide' : disableAction;
  164. this.zipOptions = (typeof zipOptions=='undefined') ? false : zipOptions;
  165. if (this.regionSelectEl.options.length<=1) {
  166. this.update();
  167. }
  168. Event.observe(this.countryEl, 'change', this.update.bind(this));
  169. },
  170. _checkRegionRequired: function()
  171. {
  172. var label, wildCard;
  173. var elements = [this.regionTextEl, this.regionSelectEl];
  174. var that = this;
  175. if (typeof this.config == 'undefined') {
  176. return;
  177. }
  178. var regionRequired = this.config.regions_required.indexOf(this.countryEl.value) >= 0;
  179. elements.each(function(currentElement) {
  180. Validation.reset(currentElement);
  181. label = $$('label[for="' + currentElement.id + '"]')[0];
  182. if (label) {
  183. wildCard = label.down('em') || label.down('span.required');
  184. if (!that.config.show_all_regions) {
  185. if (regionRequired) {
  186. label.up().show();
  187. } else {
  188. label.up().hide();
  189. }
  190. }
  191. }
  192. if (label && wildCard) {
  193. if (!regionRequired) {
  194. wildCard.hide();
  195. if (label.hasClassName('required')) {
  196. label.removeClassName('required');
  197. }
  198. } else if (regionRequired) {
  199. wildCard.show();
  200. if (!label.hasClassName('required')) {
  201. label.addClassName('required')
  202. }
  203. }
  204. }
  205. if (!regionRequired) {
  206. if (currentElement.hasClassName('required-entry')) {
  207. currentElement.removeClassName('required-entry');
  208. }
  209. if ('select' == currentElement.tagName.toLowerCase() &&
  210. currentElement.hasClassName('validate-select')) {
  211. currentElement.removeClassName('validate-select');
  212. }
  213. } else {
  214. if (!currentElement.hasClassName('required-entry')) {
  215. currentElement.addClassName('required-entry');
  216. }
  217. if ('select' == currentElement.tagName.toLowerCase() &&
  218. !currentElement.hasClassName('validate-select')) {
  219. currentElement.addClassName('validate-select');
  220. }
  221. }
  222. });
  223. },
  224. update: function()
  225. {
  226. if (this.regions[this.countryEl.value]) {
  227. var i, option, region, def;
  228. def = this.regionSelectEl.getAttribute('defaultValue');
  229. if (this.regionTextEl) {
  230. if (!def) {
  231. def = this.regionTextEl.value.toLowerCase();
  232. }
  233. this.regionTextEl.value = '';
  234. }
  235. this.regionSelectEl.options.length = 1;
  236. for (regionId in this.regions[this.countryEl.value]) {
  237. region = this.regions[this.countryEl.value][regionId];
  238. option = document.createElement('OPTION');
  239. option.value = regionId;
  240. option.text = region.name.stripTags();
  241. option.title = region.name;
  242. if (this.regionSelectEl.options.add) {
  243. this.regionSelectEl.options.add(option);
  244. } else {
  245. this.regionSelectEl.appendChild(option);
  246. }
  247. if (regionId==def || (region.name && region.name.toLowerCase()==def) ||
  248. (region.name && region.code.toLowerCase()==def)
  249. ) {
  250. this.regionSelectEl.value = regionId;
  251. }
  252. }
  253. if (this.disableAction=='hide') {
  254. if (this.regionTextEl) {
  255. this.regionTextEl.style.display = 'none';
  256. }
  257. this.regionSelectEl.style.display = '';
  258. } else if (this.disableAction=='disable') {
  259. if (this.regionTextEl) {
  260. this.regionTextEl.disabled = true;
  261. }
  262. this.regionSelectEl.disabled = false;
  263. }
  264. this.setMarkDisplay(this.regionSelectEl, true);
  265. } else {
  266. if (this.disableAction=='hide') {
  267. if (this.regionTextEl) {
  268. this.regionTextEl.style.display = '';
  269. }
  270. this.regionSelectEl.style.display = 'none';
  271. Validation.reset(this.regionSelectEl);
  272. } else if (this.disableAction=='disable') {
  273. if (this.regionTextEl) {
  274. this.regionTextEl.disabled = false;
  275. }
  276. this.regionSelectEl.disabled = true;
  277. } else if (this.disableAction=='nullify') {
  278. this.regionSelectEl.options.length = 1;
  279. this.regionSelectEl.value = '';
  280. this.regionSelectEl.selectedIndex = 0;
  281. this.lastCountryId = '';
  282. }
  283. this.setMarkDisplay(this.regionSelectEl, false);
  284. }
  285. this._checkRegionRequired();
  286. // Make Zip and its label required/optional
  287. var zipUpdater = new ZipUpdater(this.countryEl.value, this.zipEl);
  288. zipUpdater.update();
  289. },
  290. setMarkDisplay: function(elem, display){
  291. elem = $(elem);
  292. var labelElement = elem.up(0).down('label > span.required') ||
  293. elem.up(1).down('label > span.required') ||
  294. elem.up(0).down('label.required > em') ||
  295. elem.up(1).down('label.required > em');
  296. if(labelElement) {
  297. inputElement = labelElement.up().next('input');
  298. if (display) {
  299. labelElement.show();
  300. if (inputElement) {
  301. inputElement.addClassName('required-entry');
  302. }
  303. } else {
  304. labelElement.hide();
  305. if (inputElement) {
  306. inputElement.removeClassName('required-entry');
  307. }
  308. }
  309. }
  310. }
  311. }
  312. ZipUpdater = Class.create();
  313. ZipUpdater.prototype = {
  314. initialize: function(country, zipElement)
  315. {
  316. this.country = country;
  317. this.zipElement = $(zipElement);
  318. },
  319. update: function()
  320. {
  321. // Country ISO 2-letter codes must be pre-defined
  322. if (typeof optionalZipCountries == 'undefined') {
  323. return false;
  324. }
  325. // Ajax-request and normal content load compatibility
  326. if (this.zipElement != undefined) {
  327. this._setPostcodeOptional();
  328. } else {
  329. Event.observe(window, "load", this._setPostcodeOptional.bind(this));
  330. }
  331. },
  332. _setPostcodeOptional: function()
  333. {
  334. this.zipElement = $(this.zipElement);
  335. if (this.zipElement == undefined) {
  336. return false;
  337. }
  338. // find label
  339. var label = $$('label[for="' + this.zipElement.id + '"]')[0];
  340. if (label != undefined) {
  341. var wildCard = label.down('em') || label.down('span.required');
  342. }
  343. // Make Zip and its label required/optional
  344. if (optionalZipCountries.indexOf(this.country) != -1) {
  345. while (this.zipElement.hasClassName('required-entry')) {
  346. this.zipElement.removeClassName('required-entry');
  347. }
  348. if (wildCard != undefined) {
  349. wildCard.hide();
  350. }
  351. } else {
  352. this.zipElement.addClassName('required-entry');
  353. if (wildCard != undefined) {
  354. wildCard.show();
  355. }
  356. }
  357. }
  358. }