jquery plugin - jquery.pager.js

현재 주소 복사
트랙백 주소 복사
방실이님의 글 (2/9/2012 7:36:15 PM) Viewing : 4079

이번 플러그인은 pager 입니다.

http://www.j-dee.com/2008/12/22/jquery-pager-plugin/

이 pager의 각 단위는 span 으로 렌더링 됩니다. 그래서 디자인 하기가 편합니다..^^;;

그런데 이 pager는 페이징 방식이...다이얼방식(표현이 맞나 모르겠네요..@.@) 입니다.

즉 현재 활성화된 페이지가 가운데 오는 방식이죠...외국 사이트에서는 이러한 방식을 많이 쓰고 있습니다만..

우리의 고객들은....싫어 하더군요..ㅡ.ㅡ;

그래서 전통적인 방식의 기능도 추가 하였습니다.

사용법은 아래와 같습니다.

var initializePager = function(){ 
 if(parseInt($('#totalCnt').val()) >= 0 ){
  var cur = $.getUrlVars()['pageCnt'];
  var rowCount = parseInt($('#rowCnt').val());
  
  $('#pager').pager({
   pagerType : 'classic',
   pagenumber : rowCount==0?1:(cur==null?1:cur),
   pagecount : rowCount==0?1:parseInt($('#totalCnt').val())%parseInt($('#rowCnt').val())==0?parseInt($('#totalCnt').val())/parseInt($('#rowCnt').val()):parseInt($('#totalCnt').val())/parseInt($('#rowCnt').val()) + 1,
   buttonClickCallback: pagerCallback
  });
 }
};

// 페이저를 클릭 했을 경우
function pagerCallback(pageClickNumber){
 var pageCnt = $.getUrlVars()['pageCnt'];
    
 if(pageCnt == null){
  if(location.href.indexOf('?') > 0 && $.getUrlVars().length > 0){
   location.href = location.href+'&pageCnt='+pageClickNumber;
  }else{
   location.href = location.href+'?pageCnt='+pageClickNumber;
  }
 }
 else{
  var reg = /pageCnt=(\d+)/gi;
  location.href = location.href.replace(reg, 'pageCnt='+pageClickNumber);
 }
 return false; 
}

공통 js 파일에 위와 같이 선언해 놓고..

pager가 필요한 페이지에서만 위 함수를 콜하면 되겠습니다...

pager.js 의 전체 코드는 아래와 같습니다.

/*
* jQuery pager plugin
* Version 1.0 (12/22/2008)
* @requires jQuery v1.2.6 or later
*
* Example at: http://jonpauldavies.github.com/JQuery/Pager/PagerDemo.html
*
* Copyright (c) 2008-2009 Jon Paul Davies
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
* 
* Read the related blog post and contact the author at http://www.j-dee.com/2008/12/22/jquery-pager-plugin/
*
* This version is far from perfect and doesn't manage it's own state, therefore contributions are more than welcome!
*
* Usage: .pager({ pagenumber: 1, pagecount: 15, buttonClickCallback: PagerClickTest });
*
* Where pagenumber is the visible page number
*       pagecount is the total number of pages to display
*       buttonClickCallback is the method to fire when a pager button is clicked.
*
* buttonClickCallback signiture is PagerClickTest = function(pageclickednumber) 
* Where pageclickednumber is the number of the page clicked in the control.
*
* The included Pager.CSS file is a dependancy but can obviously tweaked to your wishes
* Tested in IE6 IE7 Firefox & Safari. Any browser strangeness, please report.
*/
(function ($) {

    var pagerType = 'classic';
    $.fn.pager = function (options) {

        var opts = $.extend({}, $.fn.pager.defaults, options);
        pagerType = opts.pagerType;

        return this.each(function () {

            // empty out the destination element and then render out the pager
            // with the supplied options
            $(this).empty().append(renderpager(parseInt(options.pagenumber), parseInt(options.pagecount), options.buttonClickCallback));

            // specify correct cursor activity
            $('.pages span').mouseover(function () {
                document.body.style.cursor = "pointer";
            }).mouseout(function () {
                document.body.style.cursor = "auto";
            });
        });
    };

    // render and return the pager with the supplied options
    function renderpager(pagenumber, pagecount, buttonClickCallback) {

        // setup $pager to hold render
        var $pager = $('<div class="pages"></div>');

        // add in the previous and next buttons
        $pager.append(renderButton('first', pagenumber, pagecount, buttonClickCallback)).append(renderButton('prev', pagenumber, pagecount, buttonClickCallback));

        // pager currently only handles 10 viewable pages ( could be easily
        // parameterized, maybe in next version ) so handle edge cases
        var startPoint = 1;
        var endPoint = 9;

        if (pagerType == 'classic') {
            endPoint = 10;
            startPoint = parseInt((pagenumber - 1) / 10) * 10 + 1;
            endPoint = parseInt((pagenumber - 1) / 10) * 10 + 10;

            if (endPoint > pagecount) {
                endPoint = pagecount;
                startPoint = parseInt(pagecount / 10) * 10 + 1;
            }
        } else {
            if (pagenumber > 4) {
                startPoint = pagenumber - 4;
                endPoint = pagenumber + 4;
            }

            if (endPoint > pagecount) {
                startPoint = pagecount - 8;
                endPoint = pagecount;
            }
        }

        if (startPoint < 1) {
            startPoint = 1;
        }

        // loop thru visible pages and render buttons
        for (var page = startPoint; page <= endPoint; page++) {

            var currentButton = $('<span class="page-number">' + (page) + '</span>');

            page == pagenumber ? currentButton.addClass('pgCurrent') : currentButton.click(function () {
                buttonClickCallback(this.firstChild.data);
            });
            currentButton.appendTo($pager);
        }

        // render in the next and last buttons before returning the whole
        // rendered control back.
        $pager.append(renderButton('next', pagenumber, pagecount, buttonClickCallback)).append(renderButton('last', pagenumber, pagecount, buttonClickCallback));

        return $pager;
    }

    // renders and returns a 'specialized' button, ie 'next', 'previous' etc.
    // rather than a page number button
    function renderButton(buttonLabel, pagenumber, pagecount, buttonClickCallback) {
        var $Button = $('<span class="pgNext">&nbsp;</span>');

        var destPage = 1;

        // work out destination page for required button type
        switch (buttonLabel) {
            case "first":
                destPage = 1;
                $Button.addClass('first');
                break;
            case "prev":
                if (pagerType == 'classic') {
                    if (pagenumber < 10) {
                        destPage = 1;
                    } else {
                        destPage = parseInt((pagenumber - 1) / 10) * 10;
                        if (destPage == 0) {
                            destPage = 1;
                        }
                    }
                } else {
                    destPage = pagenumber - 1;
                }
                $Button.addClass('pre');
                break;
            case "next":
                if (pagerType == 'classic') {
                    destPage = parseInt((pagenumber - 1) / 10) * 10 + 10 + 1;

                    if (destPage > pagecount) {
                        destPage = parseInt(pagecount / 10) * 10 + 1;
                    }
                } else {
                    destPage = pagenumber + 1;
                }
                $Button.addClass('next');
                break;
            case "last":
                destPage = pagecount;
                $Button.addClass('last');
                break;
        }

        // disable and 'grey' out buttons if not needed.
        if (buttonLabel == "first" || buttonLabel == "prev") {
            pagenumber <= 1 ? $Button.addClass('pgEmpty') : $Button.click(function () {
                buttonClickCallback(destPage);
            });
        } else if (buttonLabel == "next") {
            if (pagerType == 'classic') {
                parseInt((pagenumber - 1) / 10) * 10 + 10 >= pagecount ? $Button.addClass('pgEmpty') : $Button.click(function () {
                    buttonClickCallback(destPage);
                });
            } else {
                pagenumber >= pagecount ? $Button.addClass('pgEmpty') : $Button.click(function () {
                    buttonClickCallback(destPage);
                });
            }
        } else {
            pagenumber >= pagecount ? $Button.addClass('pgEmpty') : $Button.click(function () {
                buttonClickCallback(destPage);
            });
        }

        return $Button;
    }

    // pager defaults. hardly worth bothering with in this case but used as
    // placeholder for expansion in the next version
    $.fn.pager.defaults = {
        pagenumber: 1,
        pagecount: 1
    };

})(jQuery);

마지막 업데이트 : (4/24/2012 11:28:56 AM)




첨부 파일 보기 (1)
Trackback 보기 (0)
댓글 보기 (0)
댓글 쓰기

jquery plugin - jquery.limitCharWidth.js

현재 주소 복사
트랙백 주소 복사
방실이님의 글 (2/9/2012 7:23:48 PM) Viewing : 1949

종종 혹은 자주..애용하는 jquery plugin을 정리 해 보려 합니다..

http://archive.plugins.jquery.com/project/limitCharWidth

이 플러그인은..이제 배포가 중단된듯 합니다..ㅡ.ㅡ;;

이 플러그인은

table 의 td 에서 내용의 글자가 너무 길면 ... 으로 바꿔 주는 플러그인입니다.

td의 width를 지정하였으나 내용이 길어 td의 width가 넘어서는 경우가 있다면..

넘는 만큼 잘라서 ... 으로 보여 주고

그 대신 title 어트리뷰트에 전체 데이터를 보여 주는 방식입니다...

기존 배포본이 작동을 안해서...손 좀 봤습니다..ㅡ.ㅡ;

사용법은 위 링크에 나온 것 처럼..사용하시면 됩니다.

<div class='hide_overflow' style='width:50px'>
    Text that expected to be shown in one line
</div>

$('div.hide_overflow').limitCharWidth();

그러면 결과는 아래 처럼 나옵니다.

<div class='hide_overflow' style='width:50px'>
    Text that expec...
</div>

 

아래는 js파일 내용입니다.

/**
* limitCharWidth 0.6 - Limit inner text to adjust to container width
*
* history
* : 2009-04-05 ver0.6 - Bugfix: previouse version hasn't work on IE.
* : 2009-04-05 ver0.5 - Spaces at the end of collapsed string is trimed
Some code improvement
* : 2009-03-04 ver0.4 - Now the container needs not necessarily to be set
whiteSpace to nowrap
* : 2009-02-27 ver0.3 - Fixed a bug that occured when the target isn't a block
* : 2009-02-01 ver0.2 - Fixed a bug that this didn't work on IE6 without width
parameter.
* : 2009-01-28 ver0.1 - Initial release
*
* Copyright (c) 2008 Sugama Keita (http://jamadam.com/blog/)
*
* Dual licensed under the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
*/
; (function($) {
    $.fn.extend({

        unlimitCharWidth: function() {

            return $(this).each(function() {

                $(this).text($.data(this, 'limitCharWidth'));
            });
        },

        limitCharWidth: function(args) {

            args =
    $.extend({
        alternative: '...',
        width: null,
        set_title: true
    }, args || {});

            return $(this).each(function() {
                var current = $(this).text();

                // Set original content to title
                if (!this.title && args.set_title) {
                    this.title = $.trim(current);
                }

                // Save original data
                if (!$.data(this, 'limitCharWidth')) {
                    $.data(this, 'limitCharWidth', current);
                }

                var org = $.data(this, 'limitCharWidth');

                var width = args.width;

                if (!width) {
                    if ($(this).css('display') == 'block') {
                        width = $(this).text('').width();
                    } else {
                        return $(this);
                    }
                }

                $(this).text(org);

                var oldWhiteSpaceSetting = $(this).css('whiteSpace');
                $(this).css({ whiteSpace: 'nowrap' });

                var dummyspan = $(this).wrapInner('<span></span>').find('span');

                /*
                dummyspan.css({
                fontSize        : $(this).css('fontSize'),
                fontWeight      : $(this).css('fontWeight'),
                fontFamily      : $(this).css('fontFamily'),
                wordSpacing     : $(this).css('wordSpacing'),
                textIndent      : $(this).css('textIndent'),
                textTransform   : $(this).css('textTransform'),
                letterSpacing   : $(this).css('letterSpacing'),
                whiteSpace      : $(this).css('whiteSpace')
                });
                */

                if (dummyspan.width() > width) {
                    dummyspan.text(dummyspan.text() + args.alternative);
                }

                while (dummyspan.width() > width) {

                    var newcontent = dummyspan.text().slice(0, -1 * (args.alternative.length + 1));

                    newcontent = $.trim(newcontent);

                    if (newcontent) {
                        dummyspan.text(newcontent + args.alternative);
                    } else {
                        dummyspan.text('');
                        break;
                    }
                }

                $(this).css({ whiteSpace: oldWhiteSpaceSetting });

                // remove dummy span
                $(this).text(dummyspan.text());
            });
        }
    });
})(jQuery);


마지막 업데이트 : (2/9/2012 7:23:48 PM)




첨부 파일 보기 (1)
Trackback 보기 (0)
댓글 보기 (0)
댓글 쓰기

ASP.NET 에서 가장(Impersonate) 기능 사용하기

현재 주소 복사
트랙백 주소 복사
방실이님의 글 (10/19/2011 1:01:25 PM) Viewing : 3758

프로젝트 진행중에 네트워크 드라이브에 엑셀파일을 업로드를 하고 그 파일을 열어서 Formula 를 읽어서 수식 계산 후에 클라이언트로 내려 주는 기능이 필요 하게 되었습니다.

먼저 네트워크 드라이브는 연결을 하게 되면 기본적으로 아이디 패스워드만 맞춰 주면 업로드 다운로드는 가능 하더군요..

그러나 파일을 오픈 하게 되면 엑세스 오류를 던집니다.

이런 경우 웹계정을 윈도우즈 계정으로 가장 하여 실행을 할 수 있습니다.

쉽게 말해 서버 운영체제에 있는 계정으로 로그인을 하여 그 권한을 획득 하는 것이죠..

기본적인 사항은  MSDN문서를 참고 하시면 되겠습니다.

위 문서중에 모든 연결에 대하여 가장을 하는 경우 

즉 web.config에서 라고 설정을 하면..특정 어셈블리를 로드 하지 못한다는 런타임 오류를 던지더군요...ㅡ.ㅠ;;

이거 아마도 추측 하기에 웹계정이 윈도우계정으로 가장되어서 윈도우계정이 웹권한이 없기 때문이 아닐까....생각해 봅니다..ㅡ.ㅡ;;

가장을 사용하기 위해서는...

서버에 계정과 비밀번호를 할당 합니다.

이 계정에는 기본적으로 제일 적은 권한인 Guests Role을 주고 나머지 Role은 제거 하는게 좋을 듯 싶습니다.

네트워크 서버에는 이 계정과 비밀번호가 같은 계정을 생성하여 공유하고자 하는 폴더를 공유 합니다.

이 절차가 끝나면 서버에서 윈도우즈 탐색기를 통해 위 계정으로 네트워크 서버에 접속이 가능하여야 합니다.

어쨋든..저는 코드에서 구현 하는 것으로 사용 하였습니다.

public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;

WindowsImpersonationContext impersonationContext; 

[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName, 
	String lpszDomain,
	String lpszPassword,
	int dwLogonType, 
	int dwLogonProvider,
	ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int DuplicateToken(IntPtr hToken, 
	int impersonationLevel,  
	ref IntPtr hNewToken);
                          
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern  bool CloseHandle(IntPtr handle);

public void Page_Load(Object s, EventArgs e)
{
	if(impersonateValidUser("username", "domain", "password"))
	{
		//Insert your code that runs under the security context of a specific user here.
		undoImpersonation();
	}
	else
	{
		//Your impersonation failed. Therefore, include a fail-safe mechanism here.
	}
}

private bool impersonateValidUser(String userName, String domain, String password)
{
	WindowsIdentity tempWindowsIdentity;
	IntPtr token = IntPtr.Zero;
	IntPtr tokenDuplicate = IntPtr.Zero;

	if(RevertToSelf())
	{
		if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, 
			LOGON32_PROVIDER_DEFAULT, ref token) != 0)
		{
			if(DuplicateToken(token, 2, ref tokenDuplicate) != 0) 
			{
				tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
				impersonationContext = tempWindowsIdentity.Impersonate();
				if (impersonationContext != null)
				{
					CloseHandle(token);
					CloseHandle(tokenDuplicate);
					return true;
				}
			}
		} 
	}
	if(token!= IntPtr.Zero)
		CloseHandle(token);
	if(tokenDuplicate!=IntPtr.Zero)
		CloseHandle(tokenDuplicate);
	return false;
}

private void undoImpersonation()
{
	impersonationContext.Undo();
}

참고로 AD가 구현 되어 있지 않았다면 domain은 빈값을 넣어 주면 되겠습니다.

그러나..서버에 배포시 문제가 생겼습니다.

로컬 및 테스트 서버에서는 잘 작동 하였는데..서버에 배포를 하니..로그인 실패가 뜨는 것입니다.

LogonUserA 메서드가 false를 던지는 것이죠.

일반적으로 운영 서버의 경우 보안의 제약 사항이 많기 때문에 많은 제약 사항 중에 해당 되는 것을 찾아야 했습니다.

음.

결론은 로컬보안정책 > 사용자 권한 할당 > 로컬 로그온 허용 에 해당 계정을 넣어주면 되었습니다.

완전..개고생 했네요..

 

PS . 네트워크 서버의 경로는 코드 상에 UNC 경로로 입력 하여야 합니다.


마지막 업데이트 : (10/19/2011 1:03:55 PM)

TAG : 가장 



Trackback 보기 (0)
댓글 보기 (2)
kevin님의 글 (10/19/2011 1:41:26 PM)
한가지 궁금한 것이 생겼는데요. ^^

LogonUser 에 LOGON32_LOGON_INTERACTIVE 옵션을 준 경우라서 아마 그런 제약이 걸린 것이 아닐까 싶습니다. 그거 말고, LOGON32_LOGON_NETWORK_CLEARTEXT 를 주었다면... 아마 괜찮지 않았을까 싶은데요. (참고로, 해보지 않고 던지는 의문입니다. ^^)



방실이님의 글 (10/24/2011 11:15:16 AM)
성태씨 글 보고..일단 MSDN을 뒤져 보았습니다.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa378184(v=vs.85).aspx
요런 링크에 해당 메서드에 대한 설명이 있네요..
logontype 부분의 설명을 보면 성태씨 의견 처럼 LOGON32_LOGON_NETWORK_CLEARTEXT가 맞을 것 같아요..
그래서 일단 적용을 해보았습니다.
다른 것은 건들지 않고 LOGONTYPE 파라메터의 값만 LOGON32_LOGON_NETWORK_CLEARTEXT으로 바꾸어 보았는데..
false가 떨어지네요..
참고로 저 값의 int 형 값은 8 입니다.
http://pinvoke.net/default.aspx/advapi32.LogonUser
위 링크를 참고 하면 되고요..
일단 테스트 결과는 그렇게 되었네요..
이거.... 참.....



댓글 쓰기

HTML5 Forms with ASP.NET MVC and MvcContrib.FluentHtml

현재 주소 복사
트랙백 주소 복사
방실이님의 글 (10/11/2011 9:02:24 AM) Viewing : 1743

메일링으로 온 내용중에 관심 있는 부분이라 포스팅 합니다.

fluent 라는 단어가 곧잘..보이네요...^^;

http://userinexperience.com/?p=692

asp.net mvc 에도 편리한 addin 어셈블리들이 나오네요..좋군요..^^;

써 봐야 겠어요.


마지막 업데이트 : (10/11/2011 9:02:24 AM)

TAG : MVC 



Trackback 보기 (0)
댓글 보기 (0)
댓글 쓰기

Facebook API의 &quot;Error validating verification code&quot; 라는 에러.

현재 주소 복사
트랙백 주소 복사
방실이님의 글 (9/23/2011 3:42:26 PM) Viewing : 2589

페이스북을 연동할 일이 있어 API를 살펴 보았습니다..

그런데 로그인후 access_token을 받아야 하는 부분에서 .... 계속 오류가 나는 것입니다..ㅡ.ㅠ;

{
   "error": {
      "message": "Error validating verification code.",
      "type": "OAuthException"
   }
}

위와 같이 말이죠..

엄청 나게 구글을 뒤졌지만 원인을 찾지 못 하였습니다.

그러다가..찾은 결론이..황당하게도..

redirect_uri 가 틀렸는데.

http://test.com:50050 -> http://test.com:50050/

왼쪽이 틀린 것이고 오른쪽이 맞는 것입니다..

헐헐헐헐...슬러시 하나 때문에..도대체 몇 시간을...ㅡ.ㅠ;


마지막 업데이트 : (9/23/2011 3:42:26 PM)

TAG : Facebook 



Trackback 보기 (0)
댓글 보기 (0)
댓글 쓰기



<< < 1 2 3 4 5 6 7 8 9 10 > >>