modular_view.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020
  1. /**********************************************************************************
  2. * modular_view.js
  3. *
  4. * Modular 프레임워크의 뷰 관련된 부분이 포함되어 있는 스크립트 파일
  5. * 'Modular.view' 라는 네임스페이스를 사용하고 있음
  6. *
  7. * @author 김선엽(sunyoupk@udapsoft.co.kr)
  8. **********************************************************************************/
  9. /*=============================================================
  10. *
  11. * SearchView 구현
  12. *
  13. =============================================================*/
  14. Modular.view.SearchView = function () {
  15. };
  16. Modular.view.SearchView.initConditions = function (searchId) {
  17. var searchCondition = Modular.model.PageContext.getSearchCondition(searchId);
  18. jQuery.each(searchCondition.conditions, function (p, v) {
  19. jQuery("#" + p).val(v.value);
  20. });
  21. };
  22. Modular.view.SearchView.setAllConditions = function (searchId) {
  23. var searchCondition = Modular.model.PageContext.getSearchCondition(searchId);
  24. var flag = true;
  25. jQuery.each(searchCondition.conditions, function (p, v) {
  26. switch (v.type) {
  27. case "range" :
  28. var fValue = jQuery("#" + v.fKey);
  29. if (fValue.size() <= 0) {
  30. // alert("조회조건 '<modular:key id=\"" + v.key + "\" fromKey=\"" + v.fKey + "\">'에 해당하는 폼 엘리먼트가 정의되지 않았습니다.");
  31. flag = false;
  32. } else {
  33. v.fValue = fValue.val();
  34. }//end if
  35. var tValue = jQuery("#" + v.tKey);
  36. if (tValue.size() <= 0) {
  37. // alert("조회조건 '<modular:key id=\"" + v.key + "\" toKey=\"" + v.tKey + "\">'에 해당하는 폼 엘리먼트가 정의되지 않았습니다.");
  38. flag = false;
  39. } else {
  40. v.tValue = tValue.val();
  41. }//end if
  42. break;
  43. case "multi" :
  44. var checkObj = jQuery("input[name='"+p+"']");
  45. var selObj = jQuery("#" + p);
  46. if (checkObj.size() <= 0 && selObj.size() <= 0) {
  47. //alert("조회조건 '<modular:key id=\"" + v.key + "\">'에 해당하는 폼 엘리먼트가 정의되지 않았습니다.");
  48. flag = false;
  49. }
  50. else if(checkObj.size() > 0){//CheckBox 엘리멘트 사용하는 경우
  51. var checkedValues = [];
  52. checkObj.each(function(i){
  53. if( this.checked ) {
  54. checkedValues.push(jQuery(this).val());
  55. }
  56. });
  57. v.value = checkedValues;
  58. }
  59. else if(selObj.size() > 0){//Select 엘리멘트 사용하는 경우
  60. var checkedValues = [];
  61. for(var i=0; i<selObj[0].options.length; i++){
  62. if (selObj[0].options[i].selected) {
  63. checkedValues.push(selObj[0].options[i].value);
  64. }
  65. }
  66. v.value = checkedValues;
  67. }
  68. else {
  69. flag = false;
  70. }
  71. break;
  72. default :
  73. /*
  74. * 원래 jQuery("#" + p); 형태로 바인딩했었으나 이럴 경우 아이디값은 무조건 유일해야하며
  75. * 서버측에서 request.getParameterrValues와 같은 형태로 받고자 하는건 불가능하게 됨
  76. * 따라서 각 HTML 요소에 따라 name으로 조회를 해서 단일과 멀티로 나누어 모두 동작하게 수정함
  77. * 2009.05.26 - gloom
  78. * form input 가능 요소 : input, select, textarea
  79. */
  80. var inputObj = jQuery("input[name='"+p+"']");
  81. var selObj = jQuery("select[name='"+p+"']");
  82. var taObj = jQuery("textarea[name='"+p+"']");
  83. if (inputObj.size() <= 0 && selObj.size() <= 0 && taObj.size() <= 0) {
  84. // alert("조회조건 '<modular:key id=\"" + v.key + "\">'에 해당하는 폼 엘리먼트가 정의되지 않았습니다.");
  85. flag = false;
  86. }
  87. else if(inputObj.size() > 0) {//input 요소인 경우
  88. var inputType = inputObj.attr("type");
  89. switch (inputType) {
  90. case "checkbox" :
  91. var inputValues = [];
  92. inputObj.each(function(i){
  93. if( this.checked ) {
  94. inputValues.push(jQuery(this).val());
  95. }
  96. });
  97. v.value = inputValues;
  98. break;
  99. case "radio" :
  100. v.value = jQuery("input[name='"+p+"']:checked").val();
  101. break;
  102. default :
  103. if(inputObj.size() == 1) {
  104. v.value = inputObj.val();
  105. }
  106. else {
  107. var inputValues = [];
  108. inputObj.each(function(i){
  109. if(Modular.Utils.hasText(jQuery(this).val())) {
  110. inputValues.push(jQuery(this).val());
  111. }
  112. });
  113. if(inputValues.length > 0) {
  114. v.value = inputValues;
  115. }
  116. }
  117. }//end switch case
  118. }
  119. else if(selObj.size() > 0) {//select 요소인 경우
  120. v.value = selObj.val();
  121. }
  122. else if(taObj.size() > 0) {//textarea 요소인 경우
  123. v.value = taObj.val();
  124. }
  125. else {
  126. flag = false;
  127. }
  128. }//end switch case
  129. });
  130. return flag;
  131. };
  132. /*=============================================================
  133. *
  134. * Form Validation 구현
  135. *
  136. =============================================================*/
  137. Modular.view.Form = {
  138. setClientType : function(formElem, clientType) {
  139. var target = jQuery(formElem);
  140. var conditionForm;
  141. var temp = jQuery("input[name='modular.web.clientType']", target);
  142. if (temp.size() > 0) {
  143. conditionForm = temp;
  144. } else {
  145. conditionForm = jQuery("<input type=\"hidden\" name=\"modular.web.clientType\" />");
  146. target.append(conditionForm);
  147. }
  148. conditionForm.val(clientType);
  149. },
  150. display : function () {
  151. jQuery(":text,:password,input[type='hidden'],:file").each(function () {
  152. var target = jQuery(this);
  153. var id = target.attr("id");
  154. var name = target.attr("name");
  155. /*
  156. * id나 name 둘 중 하나만 있는 경우, 동일한 값으로 채워준다.
  157. * 둘 다 있거나, 둘 다 없는 경우는 무시.
  158. */
  159. if (!Modular.Utils.hasText(id) && Modular.Utils.hasText(name)) {
  160. target.attr("id", name);
  161. } else if (Modular.Utils.hasText(id) && !Modular.Utils.hasText(name)) {
  162. target.attr("name", id);
  163. }//end if else
  164. var type = target.attr(Modular.view.FormAttribute.TYPE);
  165. var format = target.attr(Modular.view.FormAttribute.FORMAT);
  166. var mask = target.attr(Modular.view.FormAttribute.MASK);
  167. var maskChars = target.attr(Modular.view.FormAttribute.MASKCHARS);
  168. var event = target.attr(Modular.view.FormAttribute.EVENT) || "button";
  169. var required = target.attr(Modular.view.FormAttribute.REQUIRED) || "false";
  170. var message = target.attr(Modular.view.FormAttribute.MESSAGE);
  171. var defaultValue = target.attr(Modular.view.FormAttribute.DEFAULTVALUE);
  172. var validator = target.attr(Modular.view.FormAttribute.VALIDATOR);
  173. var min = target.attr(Modular.view.FormAttribute.MIN);
  174. var max = target.attr(Modular.view.FormAttribute.MAX);
  175. //modular:required 지정시
  176. if ("true" == required) {
  177. var msg = message || "필수 입력 항목 입니다.";
  178. target.addClass("required");
  179. Modular.view.Form.makeValidator({
  180. target : target,
  181. msg : msg,
  182. useMask : false,
  183. mask : mask,
  184. v : function (v) {
  185. if (v.trim() == "") {
  186. return false;
  187. } else {
  188. return true;
  189. }//end if
  190. }
  191. });
  192. }//end if
  193. //modular:type 지정시
  194. switch (type) {
  195. case "date" :
  196. var o = {
  197. changeMonth: true,
  198. changeYear: true,
  199. showButtonPanel: true,
  200. "dateFormat" : "yy-mm-dd",
  201. "showButtonPanel" : false,
  202. "onSelect" : function() {
  203. $(this).change();
  204. },
  205. showOn: "both",
  206. buttonImage: Modular.model.PageContext.WEB_RESOURCE_ROOT + "/css/app/theme/default/img/button/icon_calendar.gif",
  207. buttonImageOnly: true
  208. };
  209. if (format) {
  210. o.dateFormat = format;
  211. }
  212. var convertDate = function (s) {
  213. s = s.split("-");
  214. return new Date(parseInt(s[0]), parseInt(s[1]) - 1, parseInt(s[2]));
  215. };
  216. if (min) {
  217. o.minDate = convertDate(min);
  218. }//end if
  219. if (max) {
  220. o.maxDate = convertDate(max);
  221. }//end if
  222. if (format == 'yy-mm') {
  223. o.showButtonPanel = true;
  224. o.onClose = function(dateText, inst) {
  225. var month = $("#ui-datepicker-div .ui-datepicker-month :selected").val();
  226. var year = $("#ui-datepicker-div .ui-datepicker-year :selected").val();
  227. target.datepicker('setDate', new Date(year, month, 1));
  228. };
  229. o.beforeShow = function(input, inst) {
  230. jQuery('#ui-datepicker-div .ui-datepicker-calendar').hide();
  231. };
  232. o.isMonthly = true;
  233. } else {
  234. o.showButtonPanel = false;
  235. o.beforeShow = function(input, inst) {
  236. jQuery('#ui-datepicker-div .ui-datepicker-calendar').show();
  237. };
  238. o.isMonthly = false;
  239. }
  240. /*
  241. * 선택된 언어환경에 맞는 달력 표시언어 설정
  242. */
  243. var calendarLocalization = (hUser.lang).toLowerCase();
  244. try{
  245. $.datepicker.setDefaults($.datepicker.regional[calendarLocalization]);
  246. target.datepicker(o);
  247. }
  248. catch (e) {
  249. // pass exception object to error handler
  250. }
  251. if (format == 'yy-mm') {
  252. target.focus(function () {
  253. $(".ui-datepicker-calendar").hide();
  254. });
  255. }
  256. break;
  257. case "number" :
  258. target.addClass("number");
  259. /*
  260. * 숫자일 경우, mask가 설정될때와 안될때를 구분해 처리하도록 로직 수정
  261. * 2009.08.28 - gloom
  262. */
  263. if (mask) {
  264. var o = {};
  265. o["mask"] = mask;
  266. o["textAlign"] = false;
  267. /*
  268. * 숫자의 경우 mask가 역순으로 적용되므로 실제 입력할 때에는 정상적으로 입력하더라도
  269. * 프레임워크 내부에서 처리할 때 역순으로 변환되도록 처리함.
  270. * 2009.02.18 - Helexis
  271. * 2009.08.28 - gloom 보완
  272. */
  273. o["type"] = "reverse";
  274. var temp = o["mask"].split("").reverse();
  275. o["mask"] = temp.join("");
  276. if(maskChars) {//masking 기준자가 별도로 있는 경우 옵션 추가
  277. o["fixedChars"] = maskChars;
  278. }
  279. target.setMask(o);
  280. }
  281. else {
  282. target.numeric();//숫자입력만받게함
  283. }
  284. break;
  285. default :
  286. if (mask) {
  287. target.css({
  288. "ime-mode" : "disabled"
  289. });
  290. var o = {};
  291. o["mask"] = mask;
  292. if(maskChars) {//masking 기준자가 별도로 있는 경우 옵션 추가
  293. o["fixedChars"] = maskChars;
  294. }
  295. target.setMask(o);
  296. }//end if
  297. }//switch case
  298. if (defaultValue == Modular.view.FormDefaultValue.CURRENTDATE) {
  299. target.val(hcommon.getDate());
  300. }
  301. /*
  302. * validation 기본 전제는,
  303. * 필수 입력 체크가 아니므로, 값이 없을 경우에는
  304. * validation 하지 않는다.
  305. *
  306. * 2009.01.08 - Helexis
  307. */
  308. if (validator) {
  309. /*
  310. * built-in validator : 사용자정의 validator
  311. */
  312. validator = Modular.view.Form.validator[validator] || eval(validator);
  313. var msg = message || "입력 값이 잘 못 되었습니다.";
  314. Modular.view.Form.makeValidator({
  315. target : target,
  316. msg : msg,
  317. useMask : true,
  318. mask : mask,
  319. v : function (v, target) {
  320. if (!v || v.trim().length == 0) {
  321. return true;
  322. }//end if
  323. return validator.call(this, v, target);
  324. }
  325. });
  326. } else if (min && max && type != "date") {
  327. var msg = message || "입력 값은 최소 '" + min + "' 이상, 최대 '" + max + "' 이하만 가능합니다.";
  328. Modular.view.Form.makeValidator({
  329. target : target,
  330. msg : msg,
  331. useMask : true,
  332. mask : mask,
  333. v : function (v) {
  334. if (!v || v.trim().length == 0) {
  335. return true;
  336. }//end if
  337. v = type == "number" ? parseInt(v) : v;
  338. if (v < min || v > max) {
  339. return false;
  340. } else {
  341. return true;
  342. }//end if
  343. }
  344. });
  345. } else if (min && type != "date") {
  346. var msg = message || "입력 값은 '" + min + "' 이상만 가능합니다.";
  347. Modular.view.Form.makeValidator({
  348. target : target,
  349. msg : msg,
  350. useMask : true,
  351. mask : mask,
  352. v : function (v) {
  353. if (!v || v.trim().length == 0) {
  354. return true;
  355. }//end if
  356. v = type == "number" ? parseInt(v) : v;
  357. if (v < min) {
  358. return false;
  359. } else {
  360. return true;
  361. }//end if
  362. }
  363. });
  364. } else if (max && type != "date") {
  365. var msg = message || "입력 값은 '" + max + "' 이하만 가능합니다.";
  366. Modular.view.Form.makeValidator({
  367. target : target,
  368. msg : msg,
  369. useMask : true,
  370. mask : mask,
  371. v : function (v) {
  372. if (!v || v.trim().length == 0) {
  373. return true;
  374. }//end if
  375. v = type == "number" ? parseInt(v) : v;
  376. if (v > max) {
  377. return false;
  378. } else {
  379. return true;
  380. }//end if
  381. }
  382. });
  383. }//end if else
  384. });
  385. jQuery("textarea").each(function () {
  386. var target = jQuery(this);
  387. var id = target.attr("id");
  388. var name = target.attr("name");
  389. /*
  390. * id나 name 둘 중 하나만 있는 경우, 동일한 값으로 채워준다.
  391. * 둘 다 있거나, 둘 다 없는 경우는 무시.
  392. */
  393. if (!Modular.Utils.hasText(id) && Modular.Utils.hasText(name)) {
  394. target.attr("id", name);
  395. } else if (Modular.Utils.hasText(id) && !Modular.Utils.hasText(name)) {
  396. target.attr("name", id);
  397. }//end if else
  398. var required = target.attr(Modular.view.FormAttribute.REQUIRED) || "false";
  399. var message = target.attr(Modular.view.FormAttribute.MESSAGE);
  400. var validator = target.attr(Modular.view.FormAttribute.VALIDATOR);
  401. //modular:required 지정시
  402. if ("true" == required) {
  403. var msg = message || "필수 입력 항목 입니다.";
  404. target.addClass("required");
  405. Modular.view.Form.makeValidator({
  406. target : target,
  407. msg : msg,
  408. v : function (v) {
  409. if (v.trim() == "") {
  410. return false;
  411. } else {
  412. return true;
  413. }//end if
  414. }
  415. });
  416. }//end if
  417. /*
  418. * validation 기본 전제는,필수 입력 체크가 아니므로, 값이 없을 경우에는validation 하지 않는다.
  419. */
  420. if (validator) {
  421. /*
  422. * built-in validator : 사용자정의 validator
  423. */
  424. validator = Modular.view.Form.validator[validator] || eval(validator);
  425. var msg = message || "입력 값이 잘 못 되었습니다.";
  426. Modular.view.Form.makeValidator({
  427. target : target,
  428. msg : msg,
  429. v : function (v, target) {
  430. if (!v || v.trim().length == 0) {
  431. return true;
  432. }//end if
  433. return validator.call(this, v, target);
  434. }
  435. });
  436. }
  437. });
  438. /*
  439. * radio, checkbox 에 대한 Validation 처리.
  440. *
  441. * modular:list에 의한 radio, checkbox 는 감싸고 있는 span 태그를 target으로 한다.
  442. */
  443. jQuery("span.required").each(function(){
  444. var target = jQuery(this);
  445. var id = target.attr("id");
  446. //alert(id);
  447. var required = target.attr(Modular.view.FormAttribute.REQUIRED) || "false";
  448. var message = target.attr(Modular.view.FormAttribute.MESSAGE);
  449. //var validator = target.attr(Modular.view.FormAttribute.VALIDATOR);
  450. //modular:required 지정시
  451. if ("true" == required) {
  452. var msg = message || "필수 선택 항목 입니다.";
  453. target.addClass("required");
  454. Modular.view.Form.makeValidator({
  455. target : target,
  456. msg : msg,
  457. v : function (v) {
  458. var len = jQuery("input:checked", target).length;
  459. if (len <= 0) {
  460. return false;
  461. } else {
  462. return true;
  463. }//end if else
  464. }
  465. });
  466. }//end if
  467. });
  468. jQuery("select").each(function () {
  469. var target = jQuery(this);
  470. var id = target.attr("id");
  471. var name = target.attr("name");
  472. /*
  473. * id나 name 둘 중 하나만 있는 경우, 동일한 값으로 채워준다.
  474. * 둘 다 있거나, 둘 다 없는 경우는 무시.
  475. */
  476. if (!Modular.Utils.hasText(id) && Modular.Utils.hasText(name)) {
  477. target.attr("id", name);
  478. } else if (Modular.Utils.hasText(id) && !Modular.Utils.hasText(name)) {
  479. target.attr("name", id);
  480. }//end if else
  481. var required = target.attr(Modular.view.FormAttribute.REQUIRED) || "false";
  482. var message = target.attr(Modular.view.FormAttribute.MESSAGE);
  483. var validator = target.attr(Modular.view.FormAttribute.VALIDATOR);
  484. //modular:required 지정시
  485. if ("true" == required) {
  486. var msg = message || "필수 선택 항목 입니다.";
  487. target.addClass("required");
  488. Modular.view.Form.makeValidator({
  489. target : target,
  490. msg : msg,
  491. v : function (v) {
  492. var val = jQuery("option:selected", target).attr("value");
  493. if (val.trim() == "") {
  494. return false;
  495. } else {
  496. return true;
  497. }//end if
  498. }
  499. });
  500. }//end if
  501. if (validator) {
  502. /*
  503. * built-in validator : 사용자정의 validator
  504. */
  505. validator = Modular.view.Form.validator[validator] || eval(validator);
  506. var msg = message || "입력 값이 잘 못 되었습니다.";
  507. Modular.view.Form.makeValidator({
  508. target : target,
  509. msg : msg,
  510. v : function (v, target) {
  511. if (!v || v.trim().length == 0) {
  512. return true;
  513. }//end if
  514. return validator.call(this, v, target);
  515. }
  516. });
  517. }
  518. });
  519. /*
  520. * Form Submit에 대한 이벤트 캡처 및 validation 로직 추가
  521. */
  522. jQuery("form").submit(function (e) {
  523. //재검사를 위해 기존 invalid 표시는 제거한다.
  524. jQuery(".invalid",this).removeClass("invalid");
  525. var vs = Modular.model.PageContext.validators;
  526. for (var i = 0; i < vs.length; i++) {
  527. vs[i].call(this);
  528. }//end for
  529. if (jQuery(".invalid",this).length > 0) {
  530. jQuery(".invalid:first",this).focus();
  531. e.stopImmediatePropagation();
  532. return false;
  533. }//end if
  534. jQuery(":text", this).each(function () {
  535. var target = jQuery(this);
  536. if (target.attr(Modular.view.FormAttribute.MASK)) {
  537. target.val(target.unmaskedVal(target.attr(Modular.view.FormAttribute.MASKCHARS)));
  538. }//end if
  539. });
  540. Modular.view.Form.bindSearchParameters(this);
  541. return true;
  542. });
  543. },
  544. /**
  545. * 검색조건으로 지정된 데이터들을 JSON형태로 만들어
  546. * 검색조건 파라미터(modular.web.bind.condition)에 설정한다.
  547. */
  548. bindSearchParameters : function (formElem) {
  549. var target = jQuery(formElem);
  550. var type = target.attr(Modular.view.FormAttribute.TYPE);
  551. if (type == "search") {
  552. var id = target.attr("id");
  553. if (Modular.model.PageContext.popSearchForm) {
  554. Modular.view.SearchView.setAllConditions(id);
  555. var conditions = [];
  556. jQuery.each(Modular.model.PageContext.getSearchCondition(id).conditions, function (key, value) {
  557. conditions.push(value);
  558. });
  559. var conditionForm = this.findSearchParametersObj(target);
  560. conditionForm.val(Modular.Utils.toJSON(conditions));
  561. }//end if
  562. }//end if
  563. },
  564. /**
  565. * 검색조건으로 지정된 데이터들을 JSON형태로 만들어
  566. * 검색조건 파라미터(modular.web.bind.condition)에 설정한다.
  567. */
  568. findSearchParametersObj : function (formObj) {
  569. var conditionForm;
  570. var temp = jQuery("input[name='modular.web.bind.condition']", formObj);
  571. if (temp.size() > 0) {
  572. conditionForm = temp;
  573. } else {
  574. conditionForm = jQuery("<input type=\"hidden\" name=\"modular.web.bind.condition\" />");
  575. formObj.append(conditionForm);
  576. }//end if else
  577. return conditionForm;
  578. },
  579. /**
  580. * Form에 대한 built-in validator 확장지점.
  581. * 추후 구현하려면, 이 지점에 구현합니다.
  582. */
  583. validator : {
  584. /**
  585. * 사용자정의 built-in e-mail validator
  586. *
  587. * @param value validation 대상 값
  588. * @return 검증 성공 여부
  589. */
  590. email : function (value) {
  591. return /^.+@.+\..+$/.test(value);
  592. }
  593. },
  594. /**
  595. * 경고 메시지와 관련된 툴팁을 생성하여 리턴함.
  596. *
  597. * @param msg {String} 툴팁에 사용할 메시지
  598. * @param tag {String} 경고 메시지 이미지를 감쌀 태그
  599. * @return {Object} 생성된 툴팁 객체
  600. */
  601. makeExclamation : function (msg, tag) {
  602. tag = tag || "span";
  603. var exclamation = jQuery("<br/><" + tag + " class=\"error\" > " + msg + " </" + tag + ">");
  604. exclamation.hide();
  605. return exclamation;
  606. },
  607. /**
  608. * validator를 생성하여 주어진 target에 설정함.
  609. *
  610. * validation 로직 및 display에 따른 로직의 중복을 피하기 위해서
  611. * 중복이 되는 코드를 별도의 메소드로 분리하고,
  612. * 핵심 비즈니스 로직을 전략에 따라 변경 가능하도록
  613. * strategy-pattern을 적용하였음.
  614. *
  615. * 옵션 파라미터 객체는 다음과 같은 속성을 포함할 수 있음.
  616. *
  617. * - target {Object} validator 적용 대상 객체
  618. * - title {String} 툴팁의 타이틀 (modular2.0 부터 사용안함)
  619. * - msg {String} 툴팁의 메시지
  620. * - useMask {boolean} 마스크 사용여부
  621. * - m {String} 마스크
  622. * - v {Function} validator 함수
  623. *
  624. * @param p {Object} validator에 필요한 옵션 객체
  625. */
  626. makeValidator : function (p) {
  627. p = jQuery.extend({
  628. useMask : true
  629. }, p || {});
  630. var t = p.target;
  631. //var exclamation = Modular.view.Form.makeExclamation(p.title + "|" + p.msg);
  632. var exclamation = Modular.view.Form.makeExclamation(p.msg, "label");
  633. t.parent().append(exclamation);
  634. var validator = function () {
  635. var val = p.useMask ? ((p.mask) ? t.unmaskedVal(t.attr(Modular.view.FormAttribute.MASKCHARS)) : t.val()) : t.val();
  636. /*
  637. * custom validator 사용시 인자를 넘길수 없는 불편 해소를 위해
  638. * 타겟 Object도 함께 전달해주는 방식으로 변경함
  639. * 2009.07.02 - 김윤수
  640. */
  641. if(!t.hasClass("invalid")) {//이미 invalid 체킹된 엘리멘트의 경우 Sklp
  642. if (!p.v.call(this, val, t[0]) && t.css("display") != 'none') {
  643. t.addClass("invalid");
  644. exclamation.show();
  645. /*
  646. * IE에서 focus 변경 이벤트 시 blur 이벤트가 동시에 발생하여
  647. * invalid할 경우, form 사이를 계속 focus 반복하는 무한루프에 빠짐.
  648. * 따라서, focus를 제거함.
  649. *
  650. * 2009.01.05 - Helexis
  651. */
  652. // t.focus();
  653. } else {
  654. t.removeClass("invalid");
  655. exclamation.hide();
  656. }//end if else
  657. }
  658. };
  659. Modular.model.PageContext.validators.push(validator);
  660. /*
  661. * blur 이벤트에만 vaalidator 체크가 들어있는 경우
  662. * 팝업등을 통해 데이터가 채워지는 경우 invalid 스타일이 사라지지 않는 문제 발생
  663. * 우선 submit시에만 validator 체크하는것으로 변경함
  664. * 2009.05.26 - gloom
  665. */
  666. //t.bind("blur", validator);
  667. return validator;
  668. },
  669. isValid : function(formObj) {
  670. //재검사를 위해 기존 invalid 표시는 제거한다.
  671. jQuery(".invalid",formObj).removeClass("invalid");
  672. var vs = Modular.model.PageContext.validators;
  673. for (var i = 0; i < vs.length; i++) {
  674. vs[i].call(formObj);
  675. }//end for
  676. if (jQuery(".invalid",formObj).length > 0) {
  677. jQuery(".invalid:first",formObj).focus();
  678. //e.stopImmediatePropagation();
  679. return false;
  680. }//end if
  681. jQuery(":text", formObj).each(function () {
  682. var target = jQuery(formObj);
  683. if (target.attr(Modular.view.FormAttribute.MASK)) {
  684. target.val(target.unmaskedVal(target.attr(Modular.view.FormAttribute.MASKCHARS)));
  685. }//end if
  686. });
  687. this.bindSearchParameters(formObj);
  688. return true;
  689. }
  690. };
  691. /**
  692. * Form Validation에 사용되는 사용자 정의 속성을 기술한 상수 모음 클래스
  693. */
  694. Modular.view.FormAttribute = {
  695. TYPE : "modular:type",
  696. FORMAT : "modular:format",
  697. MASK : "modular:mask",
  698. MASKCHARS : "modular:maskChars",
  699. EVENT : "modular:event",
  700. REQUIRED : "modular:required",
  701. MESSAGE : "modular:message",
  702. VALIDATOR : "modular:validator",
  703. MIN : "modular:min",
  704. MAX : "modular:max",
  705. DEFAULTVALUE : "modular:defaultValue"
  706. };
  707. /**
  708. * Form 태그 속성 확장: modular:defaultValue
  709. * 2013.02.07 김선엽 추가
  710. */
  711. Modular.view.FormDefaultValue = {
  712. CURRENTDATE : "getDate"
  713. };
  714. /*=============================================================
  715. *
  716. * List Display 구현
  717. *
  718. =============================================================*/
  719. /**
  720. * Form에서 List 타입인 combobox, checkbox, radio 유형의 목록을
  721. * display 하기 위해 사용되는 클래스
  722. */
  723. Modular.view.Form.List = {
  724. display : function (p) {
  725. p = jQuery.extend({
  726. displayType : "select",
  727. events : [],
  728. separator : ","
  729. }, p || {});
  730. switch (p.displayType) {
  731. case "radio" :
  732. var t = jQuery("#" + p.id + "_div");//span tag
  733. jQuery.each(p.events, function (idx, evt) {
  734. jQuery("input[type=radio]",t).each(function(){
  735. jQuery(this).bind(evt.eventType, evt.eventHandler);
  736. });
  737. });
  738. jQuery.each(p.attr, function() {
  739. var key = this.key;
  740. var value = this.value;
  741. jQuery("input[type=radio]",t).each(function(){
  742. jQuery(this).attr(key, value);
  743. });
  744. });
  745. if (p.required) {
  746. t.attr("modular:required", "true").addClass("required");
  747. }//end if
  748. // id 를 유닉하게 명시
  749. jQuery("input[type=radio]",t).each(function(index){
  750. jQuery(this).attr("id", p.id+"_"+index);
  751. });
  752. break;
  753. case "checkbox" :
  754. var t = jQuery("#" + p.id + "_div");//span tag
  755. jQuery.each(p.events, function (idx, evt) {
  756. jQuery("input[type=checkbox]",t).each(function(){
  757. jQuery(this).bind(evt.eventType, evt.eventHandler);
  758. });
  759. });
  760. jQuery.each(p.attr, function() {
  761. var key = this.key;
  762. var value = this.value;
  763. jQuery("input[type=checkbox]",t).each(function(){
  764. jQuery(this).attr(key, value);
  765. });
  766. });
  767. if (p.required) {
  768. t.attr("modular:required", "true").addClass("required");
  769. }//end if
  770. // id를 유닉하게 명시.
  771. jQuery("input[type=checkbox]",t).each(function(index){
  772. jQuery(this).attr("id", p.id+"_"+index);
  773. });
  774. break;
  775. default :
  776. var select = jQuery("#" + p.id);
  777. jQuery.each(p.attr, function() {
  778. //alert("key:"+this.key+" value:"+this.value);
  779. select.attr(this.key, this.value);
  780. });
  781. if (p.css) {
  782. select.addClass(p.css);
  783. }//end if
  784. if (p.required) {
  785. select.attr(Modular.view.FormAttribute.REQUIRED, "true");
  786. }//end if
  787. if (p.message) {
  788. select.attr(Modular.view.FormAttribute.MESSAGE, p.message);
  789. }//end if
  790. jQuery.each(p.events, function (idx, evt) {
  791. select.bind(evt.eventType, evt.eventHandler);
  792. });
  793. break;
  794. }//end switch case
  795. }
  796. };
  797. /*=============================================================
  798. *
  799. * Modal-Dialog 구현을 위해 사용된 API
  800. * 이 부분은 기존의 구현을 위치만 이동하였음.
  801. *
  802. =============================================================*/
  803. /**
  804. * Dialog를 사용하기 위한 클래스
  805. */
  806. Modular.view.Dialog = {
  807. /**
  808. * 윈도우창을 띄움
  809. */
  810. openWindow : function(url, target, attrs, id, openEventCheck, expiredays ) {
  811. if ( openEventCheck == true ) {
  812. if ( Modular.Utils.getCookie( "openevent_" + id ) == "check" ) {
  813. return;
  814. }
  815. }
  816. window.open(url, target, attrs);
  817. },
  818. /**
  819. * 윈도우 모달창을 띄움
  820. */
  821. openModalWindow: function(url, title, params, width_px, height_px, scroll, returnHandler, id, openEventCheck, expiredays ) {
  822. if ( openEventCheck == true ) {
  823. if ( Modular.Utils.getCookie( "openevent_" + id ) == "check" ) {
  824. return;
  825. }
  826. }
  827. if (window.showModalDialog) {
  828. var args = new Array();
  829. args["_url"] = url;
  830. args["_title"] = title;
  831. args["_params"] = params;
  832. args["_scroll"] = scroll;
  833. args["_id"] = id;
  834. args["_openEventCheck"] = openEventCheck;
  835. args["_expiredays"] = expiredays;
  836. if(window.dialogArguments){ //상위가 modal인 경우
  837. args["_parent"] = window.dialogArguments[2]; //상위 window 전달(window 객체는 항상 최상위를 유지)
  838. }else{
  839. args["_parent"] = window;
  840. }
  841. //TODO : 창 위치 조정 기능 추가할것.
  842. var features = "dialogHeight:"+height_px+"px;dialogWidth:"+width_px+"px;";
  843. var retValue = window.showModalDialog( Modular.model.PageContext.WEB_RESOURCE_ROOT + "/js/modular/modal.html", args, features);
  844. if ( returnHandler ) {
  845. returnHandler.call( this, retValue );
  846. }
  847. else {
  848. return retValue;
  849. }
  850. } else {
  851. attrs = 'width=' + width_px + ',height=' + height_px + ',toolbar=no,directories=no,status=no,menubar=no,scrollbars=' + scroll + ',resizable=no,modal=yes';
  852. Modular.view.Dialog.openWindow(url, "_blank", attrs, id, openEventCheck, expiredays );
  853. }
  854. }
  855. };
  856. /*=============================================================
  857. *
  858. * Key Event 구현
  859. *
  860. =============================================================*/
  861. /**
  862. * 화면의 Key 이벤트에 대한 Key-Code를 나타내는 상수 클래스
  863. */
  864. Modular.view.Key = {
  865. /**
  866. * 탭 키 코드
  867. */
  868. TAB : 9,
  869. /**
  870. * 엔터 키 코드
  871. */
  872. ENTER : 13,
  873. /**
  874. * ESC 키 코드
  875. */
  876. ESC : 27
  877. };
  878. /*=============================================================
  879. *
  880. * 메세지
  881. *
  882. =============================================================*/
  883. /**
  884. * 화면내의 메세지 정의 상수 클래스
  885. */
  886. Modular.Message = {
  887. /**
  888. * Validation 오류 메세지 (Dialog 타이틀용)
  889. */
  890. VALIDATION_DIALOG : "입력오류입니다"
  891. };
  892. /*=============================================================
  893. *
  894. * Form 전체 파라미터를 디버깅 하기위한 함수.
  895. * - Modular.model 과 Modular.view 네임스페이스에 의존관계가 있어서 이곳에 정의.
  896. =============================================================*/
  897. Modular.debugSubmit = function(formId){
  898. if(Modular.Debugger.enabled && formId != ""){
  899. var params = "------ All Parameters ["+formId+"] ------<br>" + decodeURIComponent(jQuery("#"+formId).serialize());
  900. Modular.view.SearchView.setAllConditions(formId);
  901. var conditions = [];
  902. jQuery.each(Modular.model.PageContext.getSearchCondition(formId).conditions, function (key, value) {
  903. conditions.push(value);
  904. });
  905. params = params + "&modular.web.bind.condition=" +Modular.Utils.toJSON(conditions);
  906. Modular.debug(params);
  907. }
  908. };