1 /* 2 SG framework 3 */ 4 5 /** 6 * @fileOverview 웹 콘텐츠제작용 프레임워크 7 * @version 1.0 8 * @author taejin (drumtj@gmail.com) 9 */ 10 11 /** 12 * @see (http://jquery.com/). 13 * @name jQuery 14 * @class 15 * See the jQuery Library (http://jquery.com/) for full details. This just 16 * documents the function and classes that are added to jQuery by this plug-in. 17 */ 18 19 20 /** 21 * @see (http://jquery.com/) 22 * @name fn 23 * @class 24 * See the jQuery Library (http://jquery.com/) for full details. This just 25 * documents the function and classes that are added to jQuery by this plug-in. 26 * @memberOf jQuery 27 */ 28 29 (function(){ 30 31 if( !("jQuery" in window) ){ 32 throw new Error("sg framework is require jQuery"); 33 } 34 35 var toString = {}.toString 36 , slice = [].slice; 37 38 var //readyCallbackList = [] 39 initCallbackList = [] 40 , customTagList = {} 41 , customAttrList = {} 42 , setStageFunc 43 , setScaleModeFunc 44 , progressImg; 45 46 //private 47 var version = "1.0" 48 , scaleMode = "none" 49 , scaleX = 0 50 , scaleY = 0 51 , stageWidth = 0 52 , stageHeight = 0 53 , $stage = null 54 , $content = null 55 , $body = null 56 , $window = $( window ); 57 58 //support 59 if( !("forEach" in Array.prototype) ){ 60 Array.prototype.forEach = function ( callback ){ 61 for( var i=0; i<this.length; i++ ){ 62 callback.call( window, this[ i ] ); 63 } 64 } 65 } 66 67 /** 68 * change cursor 69 * @example 70 * $( element ).pointer(); 71 * @example 72 * $( element ).pointer( false ); 73 * @param {boolean} bool 74 * @returns jQuery object 75 * @type jQuery Object 76 */ 77 jQuery.fn.pointer = function(){ 78 return $( this ).css( "cursor", arguments[0] == false ? "auto" : "pointer" ); 79 }; 80 81 /** 82 * Returns the numeric value of the css 83 * @example 84 * $( element ).cssVal( "margin-top" ); 85 * @param {string} cssName 86 * @returns remove the "px" character number 87 * @type number 88 */ 89 jQuery.fn.cssVal = function( cssName ){ 90 var val = $( this ).css( cssName ); 91 if( val ) num = parseFloat( val.replace( "px", "") ); 92 else num = 0; 93 94 return isNaN( num ) ? 0 : num; 95 }; 96 97 /** 98 * get custom tag 99 * @example 100 * $( 'p' ).getCustomTag( "sg-btn-hide" ); 101 * @param {string} tagName 102 * @returns jQuery object 103 * @type jQuery Object 104 */ 105 jQuery.fn.getCustomTag = function( tagName ){ 106 var isRoot = (this == $); 107 for( var o in customTagList ){ 108 if( tagName == o ){ 109 if( isRoot ) return $( "[" + customTagList[ o ].identifier + "]" ); 110 else return $( this ).children( "[" + customTagList[ o ].identifier + "]" ); 111 } 112 } 113 return $; 114 }; 115 116 /** 117 * get custom tag 118 * @function 119 * @memberOf jQuery 120 * @example 121 * $.getCustomTag( "sg-btn-hide" ); 122 * @param {string} tagName 123 * @returns jQuery object 124 * @type jQuery Object 125 */ 126 jQuery.getCustomTag = jQuery.fn.getCustomTag; 127 128 129 130 function swapTag( obj, findTagName, swapTagName, identifier ) { 131 if ( document.querySelector( findTagName ) ) { 132 identifier = identifier ? ' ' + identifier + ' ' : ''; 133 obj.html = obj.html 134 .replace( new RegExp( '<' + findTagName, 'g' ), '<' + swapTagName + identifier ) 135 .replace( new RegExp( '</' + findTagName + '>', 'g' ), '</' + swapTagName + '>' ); 136 }else{ 137 customTagList[ findTagName ].nothing = true; 138 } 139 } 140 141 function replaceTagList(){ 142 var obj = { html: document.body.innerHTML } 143 , customTagName 144 , customAttrName 145 , ctInfo, caInfo; 146 147 //customTagList.forEach(function(o) { 148 for( customTagName in customTagList ){ 149 ctInfo = customTagList[ customTagName ]; 150 swapTag(obj, customTagName, ctInfo.originTag, ctInfo.identifier); 151 }; 152 153 //add custom attribute prefix : data- 154 var sgAttrNameReg = /\ssg([\-][\w]*){1,5}(\s)?=/gi, 155 s1 = obj.html.split('<'), 156 s2, matchArr, r2 = [], 157 i; 158 159 for ( i = 0; i < s1.length; i++ ) { 160 s2 = s1[ i ].split( '>' ); 161 for ( var j = 0; j < s2.length; j++ ) { 162 if ( j % 2 == 0 ) { 163 matchArr = s2[ j ].match( sgAttrNameReg ); 164 if ( matchArr ) { 165 for ( var k = 0; k < matchArr.length; k++ ) { 166 s2[ j ] = s2[ j ].replace( matchArr[ k ], " data-" + matchArr[ k ].substr( 1 ) ); 167 } 168 } 169 } 170 } 171 r2.push( s2.join( '>' ) ); 172 } 173 174 obj.html = r2.join( '<' ); 175 document.body.innerHTML = obj.html; 176 177 //support placeholder bug 178 $( "[placeholder]" ).each(function(i,e){ 179 $( this ).text("").attr( "placeholder", $( this ).attr("placeholder") ); 180 }); 181 182 //function apply 183 var $customTag; 184 for( customTagName in customTagList ){ 185 ctInfo = customTagList[ customTagName ]; 186 if( ctInfo.nothing ) continue; 187 188 $customTag = $.getCustomTag( customTagName );//$( "[" + ctInfo.identifier + "]" ); 189 190 if( sg.isFunction( ctInfo[ "initFunc" ] ) ){ 191 ctInfo[ "initFunc" ].call( sg ); 192 } 193 194 //execute to init function of custom attribute for each custom tag 195 $customTag.each(function(index, element) { 196 $( element ).data( "_customTagName", customTagName ); 197 sg.setOption( element ); 198 if( /^sg-btn-/.test( customTagName ) ) $( element ).pointer(); 199 if( sg.isFunction( ctInfo[ "eachInitFunc" ] ) ){ 200 ctInfo[ "eachInitFunc" ].call( element, element ); 201 } 202 sg.initAttr( element ); 203 }); 204 205 //execute to action function of custom attribute when called event handle 206 if( ctInfo[ "eventName" ] ){//sg.isFunction( ctInfo[ "eventFunc" ] ) 207 $customTag.bind( ctInfo[ "eventName" ], function( e ){ 208 var ctname = $( this ).data( "_customTagName" ); 209 if ( !$( this ).data( "options" ).enabled ) return; 210 if( sg.isFunction( customTagList[ ctname ][ "eventFunc" ] ) ) customTagList[ ctname ][ "eventFunc" ].call( this, this, e ); 211 sg.actionAttr( this ); 212 }); 213 }; 214 $customTag = null; 215 }; 216 217 //apply custom attribute for all tag 218 for( customAttrName in customAttrList ){ 219 caInfo = customAttrList[ customAttrName ]; 220 if( caInfo.isForEveryTags ){ 221 if( caInfo && sg.isFunction( caInfo[ "init" ] ) ){ 222 $( "[data-" + customAttrName + "]" ).each(function( i, element ){ 223 sg.setOption( element ); 224 caInfo[ "init" ].call( element, element, element.getAttribute( "data-" + customAttrName ) ); 225 }); 226 } 227 } 228 } 229 } 230 231 232 function applyScaleMode(){ 233 var ww = $window.width(); 234 var hh = $window.height(); 235 var ch = $content.height(); 236 ch += $content.cssVal( "border-top-width" ) + $content.cssVal( "border-bottom-width" ); 237 ch += $content.cssVal( "margin-top" ) + $content.cssVal( "margin-bottom" ); 238 ch += $content.cssVal( "padding-top" ) + $content.cssVal( "padding-bottom" ); 239 240 switch( scaleMode ){ 241 case "showall": 242 var msc = Math.min(ww / stageWidth, hh / stageHeight); 243 if(ch - stageHeight <= 1){ 244 if(ch * msc > hh){ 245 //console.log("top 0, overflow:visible"); 246 $stage.css({ 247 "transform" : "scale(" + msc + ")", 248 "transform-origin" : "0 0", 249 "left" : ((ww - stageWidth * msc) * 0.5) + "px", 250 "top" : 0 251 }); 252 253 $stage.parent().css({ 254 "overflow-y" : "visible" 255 }); 256 }else{ 257 //console.log("top center, overflow:hidden"); 258 $stage.css({ 259 "transform" : "scale(" + msc + ")", 260 "transform-origin" : "0 0", 261 "left" : ((ww - stageWidth * msc) * 0.5) + "px", 262 "top" : ((hh - ch * msc) * 0.5) + "px" 263 }); 264 265 $stage.parent().css({ 266 "overflow-y" : "hidden" 267 }); 268 } 269 }else{ 270 //console.log("top center, overflow:auto"); 271 $stage.css({ 272 "transform" : "scale(" + msc + ")", 273 "transform-origin" : "0 0", 274 "left" : ((ww - stageWidth * msc) * 0.5) + "px", 275 "top" : ((hh - stageHeight * msc) * 0.5) + "px" 276 }); 277 278 $stage.parent().css({ 279 "overflow-y" : "auto" 280 }); 281 } 282 scaleX = scaleY = msc; 283 break; 284 285 case "noscale": 286 scaleX = scaleY = 0; 287 break; 288 289 case "exactfit": 290 var mscx = ww / stageWidth; 291 var mscy = hh / stageHeight; 292 $stage.css({ 293 "transform" : "scale(" + mscx + ", " + mscy + ")", 294 "transform-origin" : "0 0" 295 }); 296 scaleX = mscx 297 scaleY = mscy; 298 break; 299 } 300 } 301 302 303 /** 304 * @namespace 웹 콘텐츠제작용 프레임 워크 305 * @author taejin (drumtj@gmail.com) 306 * @name sg 307 * @version 1.0 308 * @since 2014.09.22 309 * @description 310 * jQuery를 필요로 하는 library입니다.<br> 311 * - stage scale control<br> 312 * - custom attribute and custom tag<br> 313 */ 314 var sg = { 315 //Variables defined for codehint 316 /** 317 * [Read Only] sg framework의 버전정보. 318 * @name version 319 * @memberOf sg 320 * @type string 321 */ 322 get version() { return version }, 323 324 /** 325 * [Read Only] stage의 scaleMode값. sg.setScaleMode 함수로 설정되며 "showall", "exactfit", "none"의 값이 설정될 수 있다. 326 * @name scaleMode 327 * @memberOf sg 328 * @type string 329 */ 330 get scaleMode() { return scaleMode }, 331 332 /** 333 *[Read Only] stage의 X축 scale값. sg.setScaleMode 함수로 scaleMode가 설정되면 값이 계산된다. 이 비율은 stage의 width를 기준으로 계산된다. 334 * @name scaleX 335 * @memberOf sg 336 * @type number 0.0 ~ 1.0 337 */ 338 get scaleX() { return scaleX }, 339 340 /** 341 * [Read Only] stage의 Y축 scale값. sg.setScaleMode 함수로 scaleMode가 설정되면 값이 계산된다. 이 비율은 stage의 height를 기준으로 계산된다. 342 * @name scaleY 343 * @memberOf sg 344 * @type number 0.0 ~ 1.0 345 */ 346 get scaleY() { return scaleY }, 347 348 /** 349 * [Read Only] stage의 width값. setStage함수로 stage설정시 설정된 stage의 width값을 읽어온다. 350 * @name stageWidth 351 * @memberOf sg 352 * @type number 353 */ 354 get stageWidth() { return stageWidth }, 355 356 /** 357 * [Read Only] stage의 height값. setStage함수로 stage설정시 설정된 stage의 height값을 읽어온다. 358 * @name stageHeight 359 * @memberOf sg 360 * @type number 361 */ 362 get stageHeight() { return stageHeight }, 363 364 /** 365 * [Read Only] 스테이지로 설정된 엘리먼트. sg.setStage함수로 설정된다. 366 * @name $stage 367 * @memberOf sg 368 * @type jQuery Object 369 */ 370 get $stage() { return $stage }, 371 372 /** 373 * [Read Only] stage의 자식요소들을 감싼 컨테이너. $stage가 설정될 때 설정된다. 374 * @name $content 375 * @memberOf sg 376 * @type jQuery Object 377 */ 378 get $content() { return $content }, 379 380 /** 381 * [Read Only] $("body")의 참조 382 * @name $body 383 * @memberOf sg 384 * @type jQuery Object 385 */ 386 get $body() { return $body }, 387 388 /** 389 * [Read Only] jQuery Object of window object. 390 * @name $window 391 * @memberOf sg 392 * @type jQuery Object 393 */ 394 get $window() { return $window }, 395 396 /** 397 * [Read Only] sg에 새로운 함수를 추가하거나 기존 함수에 덮어쓰거나 함수를 상속받아 확장한다. 398 * @function 399 * @name extend 400 * @memberOf sg 401 * @example 402 * sg.extend({ 403 * myfunc: function( ){ 404 * //TO DO 405 * } 406 * }); 407 * @param {object} property sg에 추가할 함수를 가진 Object 408 */ 409 extend: function( prop ){ 410 if(typeof prop !== "object"){ throw new Error("sg.extend arguments is not Object!"); } 411 412 for( var name in prop ){ 413 //sg.hasOwnProperty( name ) 414 if( name in sg ) prop[ name ]._super = sg[ name ]; 415 sg[ name ] = prop[ name ]; 416 } 417 }, 418 419 /** 420 * sg.extend를 통해 확장한 함수에서 원래 함수를 호출할 때 사용 421 * @function 422 * @name super 423 * @memberOf sg 424 * @example 425 * sg.extend({ 426 * myfunc: function( str ){ 427 * return '(' + str + ')'; 428 * } 429 * }); 430 * 431 * sg.myfunc( 'abc' ); //return "(abc)" 432 * 433 * sg.extend({ 434 * myfunc: function( str ){ 435 * return sg.super( str.toUpperCase() ); 436 * } 437 * }); 438 * 439 * sg.myfunc( 'abc' ); //return "(ABC)" 440 * @param {object} arguments 원래 함수의 arguments. 441 * @return {*} 원래 함수의 반환 값. 442 * @type * 443 */ 444 super: function(){ 445 var _super = arguments.callee.caller._super; 446 return sg.isFunction( _super ) ? _super.apply( this, arguments ) : null; 447 } 448 }; 449 450 451 sg.extend({ 452 /** 453 * 대상이 함수인지 확인. jQuery의 isFunction 함수를 사용. 454 * @function 455 * @name isFunction 456 * @memberOf sg 457 * @param {object} object 458 * @returns true or false 459 * @type boolean 460 */ 461 isFunction: $.isFunction, 462 463 /** 464 * 대상이 배열인지 확인. jQuery의 isArray 함수를 사용. 465 * @function 466 * @name isArray 467 * @memberOf sg 468 * @param {object} object 469 * @returns true or false 470 * @type boolean 471 */ 472 isArray: $.isArray, 473 474 /** 475 * 대상이 window객체인지 확인. jQuery의 isWindow 함수를 사용. 476 * @function 477 * @name isWindow 478 * @memberOf sg 479 * @param {object} object 480 * @returns true or false 481 * @type boolean 482 */ 483 isWindow: $.isWindow, 484 485 /** 486 * 대상이 숫자인지 확인. jQuery의 isNumeric 함수를 사용. 487 * @function 488 * @name isNumeric 489 * @memberOf sg 490 * @param {object} object 491 * @returns true or false 492 * @type boolean 493 */ 494 isNumeric: $.isNumeric, 495 496 /** 497 * 대상이 빈 오브젝트인지 확인. jQuery의 isEmptyObject 함수를 사용. 498 * @function 499 * @name isEmptyObject 500 * @memberOf sg 501 * @param {object} object 502 * @returns true or false 503 * @type boolean 504 */ 505 isEmptyObject: $.isEmptyObject, 506 507 /** 508 * 대상이 배열에 포함되어 있는지 확인. jQuery의 inArray 함수를 사용. 509 * @function 510 * @name inArray 511 * @memberOf sg 512 * @param {object} element 513 * @param {array} array 514 * @param {number} index 515 * @returns true or false 516 * @type string 517 */ 518 inArray: $.inArray, 519 520 /** 521 * 대상의 data type을 반환. jQuery의 type 함수를 사용. 522 * @function 523 * @name type 524 * @memberOf sg 525 * @param {object} 526 * @returns true or false 527 * @type string 528 */ 529 type: $.type 530 }); 531 532 533 534 sg.extend({ 535 536 /** 537 * 초기실행 callback함수를 추가한다. 이렇게 추가된 callback함수들은 초기 실행과정 진행 후에 실행된다. 538 * @function 539 * @name addInit 540 * @memberOf sg 541 * @example 542 * sg.addInit( function(){} ); 543 * @param {function} callback 544 */ 545 addInit: function( callback ){ 546 initCallbackList.push( callback ); 547 }, 548 549 /** 550 * progress image의 경로를 설정한다. 설정된 image는 page loading하는 동안 화면에 나타난다. 551 * @function 552 * @name setLoadingImage 553 * @memberOf sg 554 * @example 555 * sg.setLoadingImage( '../common/img/progress.gif' ); 556 * @param {string} path 557 */ 558 setLoadingImage: function( path ){ 559 progressImg = new Image(); 560 progressImg.setAttribute("data-sg-id", "progressImg"); 561 progressImg["onload"] = function( e ){ 562 this.style.left = (((window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) - this.width) * 0.5) + "px"; 563 this.style.top = (((window.innerHeight || document.documentElement.clientWidth || document.body.clientWidth) - this.height) * 0.5) + "px"; 564 if( !sg.isReady ) document.body.appendChild( progressImg ); 565 else delete progressImg; 566 }; 567 progressImg.src = path; 568 progressImg.style.position = "fixed"; 569 progressImg.style.visibility = "visible"; 570 }, 571 572 /** 573 * stage를 설정한다. 설정된 stage는 sg.$stage로 접근 할 수 있다. stage는 scale조절의 기준이 된다. 574 * @function 575 * @name setStage 576 * @memberOf sg 577 * @example 578 * sg.setStage( "#stage" ); 579 * @param {object} elementOrSelector 580 */ 581 setStage: function( elementOrSelector ){ 582 setStageFunc = function(){ 583 var $temp = $( elementOrSelector ); 584 if( $temp.length == 0 ) throw new Error( "setStage : $stage is not select. (selector : " + elementOrSelector + ")" ); 585 586 $temp.attr( "data-sg-id", "stage" ); 587 $content = $( "<div data-sg-id='content'></div>" ); 588 $temp.contents().each(function( i, e ){ 589 $content.append( this ); 590 }); 591 592 $temp.append( $content ).css( "position", "absolute" ); 593 $temp.parent().css( "overflow-x", "hidden" ); 594 595 //border가 없으면, 때로는 크기가 잘 못 계산되기 때문에 596 if( $temp.cssVal( "border-top-width" ) == 0 ){ 597 $temp.css( "border", "solid 1px rgba(255,255,255,0)" ); 598 } 599 600 stageWidth = $temp.width(); 601 stageHeight = $temp.height(); 602 603 $content.css({ 604 "min-height": stageHeight, 605 "visibility": "hidden" 606 }); 607 608 $stage = $temp; 609 610 //apply scaleMode 611 if( setScaleModeFunc ){ 612 setScaleModeFunc.apply( sg ); 613 setScaleModeFunc = null; 614 } 615 } 616 617 if( sg.isReady ){ 618 setStageFunc.apply( sg ); 619 setStageFunc = null; 620 } 621 }, 622 623 /** 624 * scaleMode를 설정한다. stage가 설정되어야 기능이 작동하며, "showall", "exactfit", "none"의 모드가 있다. 625 * @function 626 * @name setScaleMode 627 * @memberOf sg 628 * @example 629 * sg.setStage( "#stage" ); 630 * sg.setScaleMode( "showall" ); 631 * @example 632 * sg.setStage( "#stage" ); 633 * sg.setScaleMode( "exactfit" ); 634 * @param {string} scaleMode 635 */ 636 setScaleMode: function( _scaleMode ){ 637 scaleMode = _scaleMode; 638 setScaleModeFunc = function(){ 639 $window.bind( "resize" , function(){ 640 applyScaleMode(); 641 }); 642 applyScaleMode(); 643 } 644 645 if( $stage ){ 646 setScaleModeFunc.apply( this ); 647 setScaleModeFunc = null; 648 } 649 }, 650 651 //options setting for custom tags 652 /** 653 * $(target).data("options")에 Custom tag 처리시 사용할 값을 저장한다. 654 * @function 655 * @name setOption 656 * @memberOf sg 657 * @example 658 * sg.setOption( element ); 659 * @example 660 * sg.setOption( element , {myClicked: false} ); 661 * @param {object} elementOrSelector element나 jQuery selector 662 * @param {object} options options값이 전달되지 않았다면 기본값을 넣는다. 663 */ 664 setOption: function ( target, options ){ 665 var op = { enabled: true }; 666 for( var o in options ) op[ o ] = options[ o ]; 667 $( target ).data( "options", op ); 668 }, 669 670 /** 671 * register custom attribute.<br> 672 * @function 673 * @name addCustomAttr 674 * @memberOf sg 675 * @param {string} option.name name of custom attribute. 676 * @param {function} option.init initialize function. 초기 설정 시점에 실행 677 * @param {function} option.action action function. 이 커스텀 속성을 사용하는 커스텀 태그의 이벤트 처리시 실행 678 * @param {boolean} option.applyAll 모든 기본 태그에서도 이 속성의 기능을 적용 할 것인지 여부. true or false 679 * @example 680 * sg.addCustomAttr({ 681 * //attribute name 682 * name: "sg-attrname", 683 * //initialize 684 * init: function( element, attrValue ){}, 685 * //action 686 * action: function( element, attrValue ){}, 687 * //apply to every tag - default value : true 688 * applyAll: false 689 * }); 690 * @example 691 * sg.addCustomAttr({ 692 * name: "sg-color", 693 * init: function( element, attrValue ){ 694 * $( element ).css( "color", attrValue ); 695 * }, 696 * }); 697 * @example 698 * sg.addCustomAttr({ 699 * name: "sg-alert", 700 * action: function( element, attrValue ){ 701 * if( attrValue ) alert( attrValue ); 702 * } 703 * }); 704 */ 705 addCustomAttr: function( obj ){ 706 customAttrList[ obj.name ] = { 707 init: obj.init, 708 action: obj.action, 709 isForEveryTags: obj.applyAll 710 } 711 }, 712 713 /** 714 * register custom tag.<br> 715 * custom tag를 select 하려면 $.getCustomTag( custom tag name )을 사용한다. 716 * @function 717 * @name addCustomTag 718 * @memberOf sg 719 * @param {string} option.name name of custom tag. 720 * @param {string} option.originTag 교체할 진짜 태그의 이름. 기본값은 'div' 721 * @param {string} option.id custom tag의 식별자로 특수한 경우가 아니면 기본값을 사용. 기본값은 "[data-sg-id='name of custom tag']" 722 * @param {array} option.attr custom tag에서 사용 될 custom attribute 이름을 나열한 배열 723 * @param {function} option.init 초기설정 때 실행 될 내용이 있다면 이곳에 함수를 정의한다. 724 * @param {function} option.tagInit 초기설정 때 각 태그마다 실행 될 내용이 있다면 이곳에 함수를 정의한다. 725 * @param {string} option.event 특정 이벤트로 동작한다면 이벤트 이름을 넣는다. 726 * @param {function} option.eventHandle 이벤트의 처리 함수를 정의한다. 727 * @example 728 * sg.addCustomTag({ 729 * //tag name 730 * name: "sg-tagname", 731 * //swap tag name (default tag) - default value : "div" 732 * originTag: "div", 733 * //identifier - default value : "data-sg-id=__custom tag name__" 734 * id: "data-myid='ID'", 735 * //used attributes 736 * attr: [ "sg-color" ], 737 * //initialize 738 * init: function(){}, 739 * //init each tag 740 * tagInit: function( element ){}, 741 * //event 742 * event: "eventName", 743 * //handle 744 * eventHandle: function( element, event ){} 745 * }); 746 * @example 747 * sg.addCustomTag({ 748 * name: "sg-h1", 749 * attr: [ "sg-color", "sg-alert" ], 750 * tagInit: function( element ){ 751 * $( element ).css( "font-size", "40pt" ); 752 * }, 753 * event: "click", 754 * eventHandle: function( element ){ 755 * $( element ).animate( {"font-size": "80pt"} ); 756 * } 757 * }); 758 */ 759 addCustomTag: function( obj ){ 760 customTagList[ obj.name ] = { 761 originTag: obj.originTag ? obj.originTag : "div", 762 identifier: obj.id ? obj.id : "data-sg-id='" + obj.name + "'", 763 eventName: obj.event, 764 attrList: (function( list ){ 765 if( !list ) return null; 766 else list = slice.call( list );//copy array 767 var i=0, attrName; 768 list.forEach( function(attrName){ 769 if( !(attrName in customAttrList) ) list.splice( i, 1 ); 770 else i++; 771 }); 772 return list; 773 })( obj.attr ), 774 initFunc: obj.init, 775 eachInitFunc: obj.tagInit, 776 eventFunc: obj.eventHandle 777 } 778 }, 779 780 //initialize about custom attribute in custom tag 781 /** 782 * 커스텀 태그 정의시 설정한, 사용되는 속성에 대한 초기화 함수. 783 * @function 784 * @name initAttr 785 * @memberOf sg 786 * @example sg.initAttr( element ); 787 * @param {object} element 788 */ 789 initAttr: function( element ){ 790 //console.log( element, arguments.callee ); 791 var customTagName = $( element ).data( "_customTagName" ) 792 , attrList, attr, attrValue; 793 794 if( customTagName ){ 795 attrList = customTagList[ customTagName ].attrList; 796 if( attrList ){ 797 attrList.forEach(function( attrName ){ 798 attr = customAttrList[ attrName ]; 799 attrValue = element.getAttribute( "data-" + attrName ); 800 if( attr && attr[ "init" ] && !attr.isForEveryTags ){ 801 attr[ "init" ].call( element, element, attrValue ); 802 } 803 }); 804 } 805 } 806 }, 807 808 //execute function about custom attribute in custom tag 809 /** 810 * 커스텀 태그 정의시 설정한, 사용되는 커스텀 속성에 대한 기능실행 함수. 811 * @function 812 * @name actionAttr 813 * @memberOf sg 814 * @example sg.actionAttr( element ); 815 * @param {object} element 816 */ 817 actionAttr: function( element ){ 818 var customTagName = $( element ).data( "_customTagName" ) 819 , attrList, attr, attrValue; 820 821 if( customTagName ){ 822 attrList = customTagList[ customTagName ].attrList; 823 if( attrList ){ 824 attrList.forEach(function( attrName ){ 825 attr = customAttrList[ attrName ]; 826 attrValue = element.getAttribute( "data-" + attrName ); 827 if( attr && attr[ "action" ] ){ 828 attr[ "action" ].call( element, element, attrValue ); 829 } 830 }); 831 } 832 } 833 }, 834 835 836 837 /** 838 * jQuery.hide 839 * @function 840 * @name hide 841 * @memberOf sg 842 * @example 843 * sg.hide( 'p' ); //$( 'p' ).hide(); 844 * sg.hide( this ); //$( this ).hide(); 845 * @param {object} elementOrSelector 846 */ 847 hide: function( elementOrSelector ){ 848 $( elementOrSelector ).hide(); 849 }, 850 851 /** 852 * jQuery.show 853 * @function 854 * @name show 855 * @memberOf sg 856 * @example 857 * sg.show( 'p' ); //$( 'p' ).show(); 858 * sg.show( this ); //$( this ).show(); 859 * @param {object} elementOrSelector 860 */ 861 show: function( elementOrSelector ){ 862 $( elementOrSelector ).show(); 863 }, 864 865 /** 866 * jQuery.fadeIn("slow") 867 * @function 868 * @name fadeIn 869 * @memberOf sg 870 * @example 871 * sg.fadeIn( 'p' ); //$( 'p' ).fadeIn( 'slow' ); 872 * sg.fadeIn( this ); //$( this ).fadeIn( 'slow' ); 873 * @param {object} elementOrSelector 874 */ 875 fadeIn: function( elementOrSelector ){ 876 $( elementOrSelector ).fadeIn("slow"); 877 }, 878 879 /** 880 * jQuery.fadeOut("slow") 881 * @function 882 * @name fadeOut 883 * @memberOf sg 884 * @example 885 * sg.fadeOut( 'p' ); //$( 'p' ).fadeOut( 'slow' ); 886 * sg.fadeOut( this ); //$( this ).fadeOut( 'slow' ); 887 * @param {object} elementOrSelector 888 */ 889 fadeOut: function( elementOrSelector ){ 890 $( elementOrSelector ).fadeOut("slow"); 891 }, 892 893 /** 894 * 커스텀 태그가 이벤트에 동작하도록 허용하고 cursor를 pointer로 설정. 895 * @function 896 * @name enabled 897 * @memberOf sg 898 * @example 899 * sg.enabled( this ); 900 * sg.enabled( '#myButton' ); 901 * sg.enabled( $.getCustomTag( 'sg-btn-hide' ) ); 902 * @param {object} elementOrSelector 903 * @returns jQuery Object 904 * @type jQuery Object 905 */ 906 enabled: function ( elementOrSelector ){ 907 return $(elementOrSelector).each(function(i,e){ 908 var $this = $(this); 909 $this.css("cursor","pointer"); 910 var options = $this.data("options") || {}; 911 options.enabled = true; 912 $this.data("options", options); 913 }); 914 }, 915 916 /** 917 * 커스텀 태그가 이벤트에 동작하지 않도록 하고 cursor를 default로 설정. 918 * @function 919 * @name disabled 920 * @memberOf sg 921 * @example 922 * sg.disabled( this ); 923 * sg.disabled( '#myButton' ); 924 * sg.disabled( $.getCustomTag( 'sg-btn-hide' ) ); 925 * @param {object} elementOrSelector 926 * @returns jQuery Object 927 * @type jQuery Object 928 */ 929 disabled: function ( elementOrSelector ){ 930 return $(elementOrSelector).each(function(i,e){ 931 var $this = $(this); 932 $this.css("cursor","default"); 933 var options = $this.data("options") || {}; 934 options.enabled = false; 935 $this.data("options", options); 936 }); 937 } 938 }); 939 940 sg.extend({ 941 /** 942 * 초기 실행 함수. parameter로 callback함수가 전달 된다면 초기 설정 진행 후에 callback함수 실행. 943 * @function 944 * @name init 945 * @memberOf sg 946 * @example 947 * sg.setStage( "#stage" ); 948 * sg.setScaleMode( "showall" ); 949 * sg.init(); 950 * @example 951 * sg.setStage( "#stage" ); 952 * sg.setScaleMode( "showall" ); 953 * sg.init( function(){} ); 954 * @param {function} callback 955 */ 956 init: function ( callback ) { 957 function _init(){ 958 //////setting 959 //console.log("setting"); 960 $body = $( document.body ); 961 962 replaceTagList(); 963 964 if( setStageFunc ){ 965 setStageFunc.apply( sg ); 966 setStageFunc = null; 967 } 968 969 ///compatibility for old versions 970 if( "init" in window && sg.isFunction( window[ "init" ] ) ){ 971 window[ "init" ].apply( window ); 972 } 973 974 if( "initList" in window ){ 975 initCallbackList = initCallbackList.concat( window[ "initList" ] ); 976 } 977 /// 978 979 initCallbackList.forEach( function( initFunc ){ 980 if( sg.isFunction( initFunc ) ) initFunc.apply( window ); 981 }); 982 983 984 $("[data-sg-id='progressImg']").remove(); 985 $content = $("[data-sg-id='content']").css( "visibility", "visible" ); 986 $stage = $("[data-sg-id='stage']"); 987 sg.isReady = true; 988 989 setTimeout(function(){ 990 $window.trigger("resize"); 991 }, 0); 992 } 993 994 if( $.isReady ){ 995 _init.apply( window ); 996 if( sg.isFunction( callback ) ) callback.apply( window ); 997 }else{ 998 $( document ).ready(function(e) { 999 _init.apply( window ); 1000 if( sg.isFunction( callback ) ) callback.apply( window ); 1001 }); 1002 } 1003 } 1004 }); 1005 1006 window.sg = sg; 1007 1008 return sg; 1009 })();