<commit_before>/*jslint unparam: true */
/*global window, $ */
$(function () {
	'use strict';
	// Change this to the location of your server-side upload handler:
	$('#file_select_file').fileupload({
		url: get_file_upload_post_uri('file'),
		dataType: 'text',
		formData: {},
		start: function (e) {
			$('#progress_file .progress-bar').css('width', 0);
		},
		done: function (e, data) {
			$('#files_file').append(data['result']).fadeIn('fast');
		},
		progressall: function (e, data) {
			var progress = parseInt(data.loaded / data.total * 100, 10);
			$('#progress_file .progress-bar').css(
				'width',
				progress + '%'
			);
		}
	}).prop('disabled', !$.support.fileInput)
		.parent().addClass($.support.fileInput ? undefined : 'disabled');

	$('#file_select_img').fileupload({
		url: $('#post_uri').val() ? get_url($('#post_uri').val()) : get_file_upload_post_uri('img'),
		dataType: 'text',
		formData: {
			thumbnail_size: $('#thumbnail_size').val(),
			insert_target: $('#insert_target').val()
		},
		start: function (e) {
			$('#progress_img .progress-bar').css('width', 0);
		},
		done: function (e, data) {
			$('#btn_timeline').removeAttr('disabled');
			$('#form_button').removeAttr('disabled');
			$('#files_img').append(data['result']).fadeIn('fast');
		},
		progressall: function (e, data) {
			$('#btn_timeline').attr('disabled', 'disabled');
			$('#form_button').attr('disabled', 'disabled');
			var progress = parseInt(data.loaded / data.total * 100, 10);
			$('#progress_img .progress-bar').css(
				'width',
				progress + '%'
			);
		}
	}).prop('disabled', !$.support.fileInput)
		.parent().addClass($.support.fileInput ? undefined : 'disabled');

	$(document).on('click','.delete_file_tmp', function(){
		var file_id   = $(this).data('id') ? parseInt($(this).data('id')) : 0;
		var upload_type = $(this).data('type') ? $(this).data('type') : 'file_tmp';
		var file_type = $(this).data('file_type') ? $(this).data('file_type') : 'img';
		var model = $(this).data('model') ? $(this).data('model') : 'album';

		if (model.length > 0 && model != 'album' && model != 'news') model = 'album';

		var delete_uri = '';
		if (check_is_admin()) delete_uri += 'admin/';
		if (upload_type == 'file_tmp' || upload_type == 'image_tmp') {
			delete_uri += 'filetmp/api/upload';
			if (file_type == 'file') delete_uri += '/file';
		} else {
			delete_uri += model;
			delete_uri += (file_type == 'file') ? '/file' : '/image';
			delete_uri += '/api/delete';
		}
		delete_uri += '.json';

		delete_item(delete_uri, file_id, '#' + upload_type);
		return false;
	});
});
$('.btn_disp_file_select').click(function() {
	$('#btn_disp_file_select_' + $(this).data('type')).remove();
	$('#upload_files_' + $(this).data('type')).removeClass('hidden');
});

function load_file_tmp(get_url, file_name, parent_attr) {
	var parentDomElement = $(parent_attr);

	var get_data = {};
	get_data['file'] = file_name;

	$.ajax({
		url : get_url,
		type : 'GET',
		dataType : 'text',
		data : get_data,
		timeout: get_config('default_ajax_timeout'),
		beforeSend: function(xhr, settings) {
			$(parentDomElement).html(get_loading_image_tag(true));
		},
		complete: function(xhr, textStatus) {
		},
		success: function(result) {
			$(parentDomElement).children('.loading_image').remove();
			$(parentDomElement).append(result).fadeIn('fast');
		},
		error: function(result) {
			$.jGrowl(get_error_message(result['status'], '読み込みに失敗しました。'));
		}
	});
}

function get_file_upload_post_uri(type) {
	var uri = (type == 'file') ? 'filetmp/api/upload/file.html' : 'filetmp/api/upload.html';
	if (check_is_admin()) uri = 'admin/' + uri;
	return get_url(uri);
}
<commit_msg>Bug fixed to disabled to delete file at upload form<commit_after>/*jslint unparam: true */
/*global window, $ */
$(function () {
	'use strict';
	// Change this to the location of your server-side upload handler:
	$('#file_select_file').fileupload({
		url: get_file_upload_post_uri('file'),
		dataType: 'text',
		formData: {},
		start: function (e) {
			$('#progress_file .progress-bar').css('width', 0);
		},
		done: function (e, data) {
			$('#files_file').append(data['result']).fadeIn('fast');
		},
		progressall: function (e, data) {
			var progress = parseInt(data.loaded / data.total * 100, 10);
			$('#progress_file .progress-bar').css(
				'width',
				progress + '%'
			);
		}
	}).prop('disabled', !$.support.fileInput)
		.parent().addClass($.support.fileInput ? undefined : 'disabled');

	$('#file_select_img').fileupload({
		url: $('#post_uri').val() ? get_url($('#post_uri').val()) : get_file_upload_post_uri('img'),
		dataType: 'text',
		formData: {
			thumbnail_size: $('#thumbnail_size').val(),
			insert_target: $('#insert_target').val()
		},
		start: function (e) {
			$('#progress_img .progress-bar').css('width', 0);
		},
		done: function (e, data) {
			$('#btn_timeline').removeAttr('disabled');
			$('#form_button').removeAttr('disabled');
			$('#files_img').append(data['result']).fadeIn('fast');
		},
		progressall: function (e, data) {
			$('#btn_timeline').attr('disabled', 'disabled');
			$('#form_button').attr('disabled', 'disabled');
			var progress = parseInt(data.loaded / data.total * 100, 10);
			$('#progress_img .progress-bar').css(
				'width',
				progress + '%'
			);
		}
	}).prop('disabled', !$.support.fileInput)
		.parent().addClass($.support.fileInput ? undefined : 'disabled');

	$(document).on('click','.delete_file_tmp', function(){
		var file_id   = $(this).data('id') ? parseInt($(this).data('id')) : 0;
		var upload_type = $(this).data('type') ? $(this).data('type') : 'file_tmp';
		var file_type = $(this).data('file_type') ? $(this).data('file_type') : 'img';
		var model = $(this).data('model') ? $(this).data('model') : 'album';
		var parentSelector = '#' + upload_type + '_' + file_id;

		if (model.length > 0 && model != 'album' && model != 'news') model = 'album';

		var delete_uri = '';
		if (check_is_admin()) delete_uri += 'admin/';
		if (upload_type == 'file_tmp' || upload_type == 'image_tmp') {
			delete_uri += 'filetmp/api/upload';
			if (file_type == 'file') delete_uri += '/file';
		} else {
			delete_uri += model;
			delete_uri += (file_type == 'file') ? '/file' : '/image';
			delete_uri += '/api/delete';
		}
		delete_uri += '.json';

		delete_item(delete_uri, parentSelector, file_id);
		return false;
	});
});
$('.btn_disp_file_select').click(function() {
	$('#btn_disp_file_select_' + $(this).data('type')).remove();
	$('#upload_files_' + $(this).data('type')).removeClass('hidden');
});

function load_file_tmp(get_url, file_name, parent_attr) {
	var parentDomElement = $(parent_attr);

	var get_data = {};
	get_data['file'] = file_name;

	$.ajax({
		url : get_url,
		type : 'GET',
		dataType : 'text',
		data : get_data,
		timeout: get_config('default_ajax_timeout'),
		beforeSend: function(xhr, settings) {
			$(parentDomElement).html(get_loading_image_tag(true));
		},
		complete: function(xhr, textStatus) {
		},
		success: function(result) {
			$(parentDomElement).children('.loading_image').remove();
			$(parentDomElement).append(result).fadeIn('fast');
		},
		error: function(result) {
			$.jGrowl(get_error_message(result['status'], '読み込みに失敗しました。'));
		}
	});
}

function get_file_upload_post_uri(type) {
	var uri = (type == 'file') ? 'filetmp/api/upload/file.html' : 'filetmp/api/upload.html';
	if (check_is_admin()) uri = 'admin/' + uri;
	return get_url(uri);
}
<|endoftext|>


<commit_before>/**
 * @(#)yobi.user.Setting.js 2013.05.16
 *
 * Copyright NHN Corporation.
 * Released under the MIT license
 *
 * http://yobi.dev.naver.com/license
 */
(function(ns){

    var oNS = $yobi.createNamespace(ns);
    oNS.container[oNS.name] = function(htOptions){

        var htVar = {};
        var htElement = {};

        /**
         * initialize
         *
         * @param {Hash Table} htOptions
         */
        function _init(htOptions){
            _initElement();
            _attachEvent();

            _initFormValidator();
        }

        /**
         * 엘리먼트 변수 초기화
         * initialize elements
         */
        function _initElement(){
            // 기본
            htElement.welFormBasic = $("#frmBasic");

            // 아바타
            htElement.welFormAvatar = $("#frmAvatar");
            htElement.welAvatarWrap = $("#avatarWrap");
            htElement.welAvatarImage = htElement.welAvatarWrap.find("img");
            htElement.welAvatarProgress = htElement.welAvatarWrap.find(".progress");
            htVar.nProgressHeight = htElement.welAvatarWrap.height();

            htElement.welBtnUploadFile = $("#btnUploadFile");
            htElement.welBtnSubmitCrop = $("#btnSubmitCrop");
            htElement.welImgCrop = $("#avatarImgCrop");

            // 비밀번호 변경
            htElement.welFormPswd = $("#frmPassword");
            htElement.welInputOldPassword  = $('#oldPassword');
            htElement.welInputPassword  = $('#password');
            htElement.welInputRetypedPassword = $('#retypedPassword');

            // 알림 설정
            htElement.welChkNotiSwtich = $(".notiUpdate");
        }

        /**
         * 이벤트 초기화
         * attach event
         */
        function _attachEvent(){
            // 비밀번호 설정
            htElement.welInputOldPassword.focusout(_onBlurInputPassword);
            htElement.welInputPassword.focusout(_onBlurInputPassword);
            htElement.welInputRetypedPassword.focusout(_onBlurInputPassword);

            // 아바타 업로드 설정
            yobi.Files.attach({
                "beforeUpload"  : _onAvatarBeforeUpload,
                "successUpload" : _onAvatarUploaded,
                "errorUpload"   : _onAvatarUploadError,
                "uploadProgress": _onAvatarUploading
            });
            yobi.Files.getUploader(".avatar-frm");

            // 알림 설정 변경
            htElement.welChkNotiSwtich.change(_onChangeNotiSwitch);
        }

        /**
         * 아바타 이미지 업로드 전 타입/확장자 검사
         * false 를 반환하면 업로드 하지 않는다
         *
         * @param {Hash Table} htData
         * @param {File} htData.oFile 업로드 파일
         * @return {Boolean}
         */
        function _onAvatarBeforeUpload(htData){
            if($yobi.isImageFile(htData.oFile) === false){
                _onAvatarUploadError(Messages("user.avatar.onlyImage"));
                return false;
            }
        }
        /**
         * 알림 On/Off 스위치 변경
         */
        function _onChangeNotiSwitch(){
            var welTarget  = $(this);
            var bChecked   = welTarget.prop("checked");
            var url        = $(this).attr("data-href");

            $.ajax(url, {
                "method" : "post",
                "success": function(data){
                    welTarget.prop("checked", bChecked);
                },
                "error"  : function(oRes){
                    welTarget.prop("checked", !bChecked);
                    $yobi.alert(Messages("error.failedTo",
                                Messages("userinfo.changeNotifications"),
                                oRes.status, oRes.statusText));
                }
            })
        }

        /**
         * 아바타 이미지 업로드가 완료된 후
         * ajaxForm 의 success 이벤트 핸들러
         *
         * @param {Hash Table} htData 업로드 된 파일의 정보
         */
        function _onAvatarUploaded(htData){
            var oRes = htData.oRes;

            // 업로드 완료한 파일이 이미지가 아니면 오류 처리하고 삭제
            if(oRes.mimeType.indexOf("image/") !== 0){
                _onAvatarUploadError(Messages("user.avatar.onlyImage"));
                yobi.Files.deleteFile({"sURL": oRes.url});
                return false;
            }

            htElement.welAvatarImage.attr("src", oRes.url);

            // 설정 폼에 avatarId 설정
            var welAvatarId = htElement.welFormAvatar.find("input[name=avatarId]");
            if(welAvatarId.length === 0){ // 없으면 새로 설정하고
                welAvatarId = htElement.welFormAvatar.append($("<input>").attr({
                    "type": "hidden",
                    "name": "avatarId",
                    "value": oRes.id
                }));
            } else { // 이미 있으면 값만 수정
                welAvatarId.attr("value", oRes.id);
            }

            _setAvatarProgressBar(100);

            // Crop 후에 업로드 인지, 처음 업로드인지 구분
            if(!htVar.oJcrop){
                _setJcrop(oRes); // jCrop 설정
            } else {
                htElement.welFormAvatar.submit();
            }
        }

        /**
         * jCrop 설정
         *
         * @param {Object} oRes 파일 정보
         */
        function _setJcrop(oRes){
            htElement.welImgCrop.on("load", function(){
                htVar.oJcrop = null;

                htElement.welImgCrop.Jcrop({
                    "aspectRatio": 1,
                    "minSize"  : [128, 128],
                    "bgColor"  : "#fff",
                    "setSelect": [0, 0, 128, 128],
                    "onSelect" : _onAvatarImageCrop,
                    "onChange" : _onAvatarImageCrop,
                    "onRelease": _onAvatarImageCropCancel
                }, function(){
                    htVar.oJcrop = this;
                });
            });
            htElement.welImgCrop.show();
            htElement.welImgCrop.attr("src", oRes.url);

            // 파일 업로드 버튼은 감추고, 크롭 이미지 전송 버튼 활성화

            htElement.welBtnUploadFile.hide();
            htElement.welBtnSubmitCrop.show();
            htElement.welBtnSubmitCrop.click(_sendCroppedImage);
        }

        /**
         * jCrop 커스텀 이벤트 핸들러
         * 잘라내기 된 이미지를 미리보기 해주는 역할
         *
         * @param {Hash Table} htData
         */
        function _onAvatarImageCrop(htData){
            if(htData.w <= 0){
                return;
            }
            var nRx = 128 / htData.w;
            var nRy = 128 / htData.h;

            var nWidth = htElement.welImgCrop.width();
            var nHeight = htElement.welImgCrop.height();

            // 미리보기 표시
            htElement.welAvatarImage.css({
                "width"     : Math.round(nRx * nWidth) + "px",
                "height"    : Math.round(nRy * nHeight) + "px",
                "marginLeft": "-" + Math.round(nRx * htData.x) + "px",
                "marginTop" : "-" + Math.round(nRy * htData.y) + "px"
            });

            htVar.htLastCrop = htData;
        }

        /**
         * jCrop 취소시 이벤트 핸들러
         * 완전하게 취소할 수 없고 늘 128x128 이상의 이미지 영역을 갖도록
         */
        function _onAvatarImageCropCancel(){
            if(htVar.oJcrop){
                htVar.oJcrop.setSelect([0, 0, 128, 128]);
            } else {
                htVar.htLastCrop = null;
            }
        }

        /**
         * jCrop 의 결과와 canvas 를 이용해서
         * 잘라낸 이미지를 서버에 전송하는 함수
         * #btnSubmitCrop 버튼을 클릭했을 때 실행된다
         */
        function _sendCroppedImage(){
            var elImage = new Image();
            var sTmpImageURL = htElement.welImgCrop.attr("src");

            // 원본 이미지 크기를 알아내기 위해 새 객체로 불러온다
            // 브라우저 캐시를 사용하므로 네트워크 호출 없음
            elImage.onload = function(){
                // 실제 이미지 크기와 jCrop 영역의 비율 계산
                var htData = htVar.htLastCrop;
                var nWidth = htElement.welImgCrop.width();
                var nRealWidth  = elImage.width;
                var nRw = nRealWidth / nWidth;
                var htCropData = {
                    "x": (htData.x * nRw),
                    "y": (htData.y * nRw),
                    "w": (htData.w * nRw),
                    "h": (htData.h * nRw)
                };

                var htEnv = yobi.Files.getEnv();

                // blob 전송이 가능한 환경이면
                if(htEnv.bXHR2){
                    // 임시 업로드 상태의 현재 파일은 삭제
                    yobi.Files.deleteFile({"sURL": sTmpImageURL});

                    // 캔버스를 이용해 Crop 이미지 데이터로 업로드
                    var elCanvas = document.getElementById("avatarCrop"); // canvas
                    var oContext = elCanvas.getContext("2d");
                    oContext.drawImage(elImage, htCropData.x, htCropData.y, htCropData.w, htCropData.h, 0, 0, 128, 128);

                    // canvas-to-blob.js
                    elCanvas.toBlob(function(oFile){
                        yobi.Files.uploadFile(oFile);
                    }, 'image/jpeg', 100);
                } else {
                    // TODO: 아니면 서버에 Crop 데이터만 전송한다 (for IE)
                    htElement.welFormAvatar.submit();
                }
            };
            elImage.src = sTmpImageURL;
        }

        /**
         * 아바타 이미지 업로드에 실패한 경우.
         * 일반적으로 서버 연결에 실패했을 때 이 상황이 발생한다.
         * ajaxForm 의 error 이벤트 핸들러.
         */
        function _onAvatarUploadError(sMessage){
            $yobi.alert(sMessage || Messages("user.avatar.uploadError"));
            _setAvatarProgressBar(0);
        }

        /**
         * 아바타 이미지 업로드 진행 상태
         * ajaxForm 의 uploadProgress 이벤트 핸들러
         *
         * @param {Wrapped Event} weEvt
         * @param {Number} nPosition
         * @param {Number}
         */
        function _onAvatarUploading(weEvt, nPosition, nTotal, nPercent){
            _setAvatarProgressBar(nPercent);
            htElement.welAvatarProgress.css("opacity", 1);
        }

        /**
         * 아바타 이미지 업로드 진행 상태 표시 함수
         *
         * @param {Number} nPercent
         */
        function _setAvatarProgressBar(nPercent){
            nPercent = parseInt(nPercent, 10);
            var nHeight = parseInt(htVar.nProgressHeight * (nPercent / 100), 10);
            htElement.welAvatarProgress.height(nHeight);

            // 꽉 차면 보이지 않게 하고 다시 0으로 되돌림
            if(nPercent === 100){
                htElement.welAvatarProgress.css("opacity", 0);

                setTimeout(function(){
                    //htElement.welFormBasic.submit();
                    _setAvatarProgressBar(0);
                }, 1000);
            }
        }

        /**
         * 비밀번호 확인 입력란 벗어날 때 이벤트 핸들러
         * 마지막 입력란이므로 전체 폼 유효성 검사
         */
        function _onBlurInputPassword(){
            htVar.oValidator._validateForm();
        }

        /**
         * initialize FormValidator
         * @require validate.js
         */
        function _initFormValidator(){
            var aRules = [
                {"name": 'oldPassword',     "rules": 'required'},
                {"name": 'password',        "rules": 'required|min_length[4]'},
                {"name": 'retypedPassword', "rules": 'required|matches[password]'}
            ];

            htVar.oValidator = new FormValidator('frmPassword', aRules, _onFormValidate);

            htVar.oValidator.setMessage('required',   Messages("validation.required"));
            htVar.oValidator.setMessage('min_length', Messages("validation.tooShortPassword"));
            htVar.oValidator.setMessage('matches',    Messages("validation.passwordMismatch"));
        }
        /**
         * on validate form
         *
         * @param {Array} aErrors
         */
        function _onFormValidate(aErrors){
            _clearPopovers();

            // to avoid bootstrap bug
            if (aErrors.length <= 0) {
                return _clearTooltips();
            }

            var welTarget;
            aErrors.forEach(function(htError){
                welTarget = htElement.welFormPswd.find("input[name=" + htError.name + "]");

                if(welTarget){
                    _showPopover(welTarget, htError.message);
                }
            });
        }

        /**
         * Bootstrap toolTip function has some limitation.
         * In this case, toolTip doesn't provide easy way to change title and contents.
         * So, unfortunately I had to change data value in directly.
         *
         * @param {Wrapped Element} welInput
         * @param {String} sMessage
         */
        function _showPopover(welInput, sMessage){
            welInput.popover({"trigger": "manual", "placement": "right"});

            var oPopover = welInput.data('popover');
            oPopover.options.placement = 'right';
            oPopover.options.trigger   = 'manual';
            oPopover.options.content   = sMessage;

            welInput.popover('show');
        }

        /**
         * 폼 영역에 있는 jquery.tooltip 모두 제거하는 함수
         */
        function _clearPopovers(){
            try {
                htElement.welFormPswd.find("input").each(function(i, v){
                    $(v).popover("destroy");
                });
            } catch(e){} // to avoid bootstrap bug
        }

        _init(htOptions || {});
    };
})("yobi.user.Setting");
<commit_msg>UserSettings: fix javascript error<commit_after>/**
 * @(#)yobi.user.Setting.js 2013.05.16
 *
 * Copyright NHN Corporation.
 * Released under the MIT license
 *
 * http://yobi.dev.naver.com/license
 */
(function(ns){

    var oNS = $yobi.createNamespace(ns);
    oNS.container[oNS.name] = function(htOptions){

        var htVar = {};
        var htElement = {};

        /**
         * initialize
         *
         * @param {Hash Table} htOptions
         */
        function _init(htOptions){
            _initElement();
            _attachEvent();

            _initFormValidator();
        }

        /**
         * 엘리먼트 변수 초기화
         * initialize elements
         */
        function _initElement(){
            // 기본
            htElement.welFormBasic = $("#frmBasic");

            // 아바타
            htElement.welFormAvatar = $("#frmAvatar");
            htElement.welAvatarWrap = $("#avatarWrap");
            htElement.welAvatarImage = htElement.welAvatarWrap.find("img");
            htElement.welAvatarProgress = htElement.welAvatarWrap.find(".progress");
            htVar.nProgressHeight = htElement.welAvatarWrap.height();

            htElement.welBtnUploadFile = $("#btnUploadFile");
            htElement.welBtnSubmitCrop = $("#btnSubmitCrop");
            htElement.welImgCrop = $("#avatarImgCrop");

            // 비밀번호 변경
            htElement.welFormPswd = $("#frmPassword");
            htElement.welInputOldPassword  = $('#oldPassword');
            htElement.welInputPassword  = $('#password');
            htElement.welInputRetypedPassword = $('#retypedPassword');

            // 알림 설정
            htElement.welChkNotiSwtich = $(".notiUpdate");
        }

        /**
         * 이벤트 초기화
         * attach event
         */
        function _attachEvent(){
            // 비밀번호 설정
            htElement.welInputOldPassword.focusout(_onBlurInputPassword);
            htElement.welInputPassword.focusout(_onBlurInputPassword);
            htElement.welInputRetypedPassword.focusout(_onBlurInputPassword);

            // 아바타 업로드 설정
            yobi.Files.attach({
                "beforeUpload"  : _onAvatarBeforeUpload,
                "successUpload" : _onAvatarUploaded,
                "errorUpload"   : _onAvatarUploadError,
                "uploadProgress": _onAvatarUploading
            });
            yobi.Files.getUploader(".avatar-frm");

            // 알림 설정 변경
            htElement.welChkNotiSwtich.change(_onChangeNotiSwitch);
        }

        /**
         * 아바타 이미지 업로드 전 타입/확장자 검사
         * false 를 반환하면 업로드 하지 않는다
         *
         * @param {Hash Table} htData
         * @param {File} htData.oFile 업로드 파일
         * @return {Boolean}
         */
        function _onAvatarBeforeUpload(htData){
            if($yobi.isImageFile(htData.oFile) === false){
                _onAvatarUploadError(Messages("user.avatar.onlyImage"));
                return false;
            }
        }
        /**
         * 알림 On/Off 스위치 변경
         */
        function _onChangeNotiSwitch(){
            var welTarget  = $(this);
            var bChecked   = welTarget.prop("checked");
            var url        = $(this).attr("data-href");

            $.ajax(url, {
                "method" : "post",
                "success": function(data){
                    welTarget.prop("checked", bChecked);
                },
                "error"  : function(oRes){
                    welTarget.prop("checked", !bChecked);
                    $yobi.alert(Messages("error.failedTo",
                                Messages("userinfo.changeNotifications"),
                                oRes.status, oRes.statusText));
                }
            })
        }

        /**
         * 아바타 이미지 업로드가 완료된 후
         * ajaxForm 의 success 이벤트 핸들러
         *
         * @param {Hash Table} htData 업로드 된 파일의 정보
         */
        function _onAvatarUploaded(htData){
            var oRes = htData.oRes;

            // 업로드 완료한 파일이 이미지가 아니면 오류 처리하고 삭제
            if(oRes.mimeType.indexOf("image/") !== 0){
                _onAvatarUploadError(Messages("user.avatar.onlyImage"));
                yobi.Files.deleteFile({"sURL": oRes.url});
                return false;
            }

            htElement.welAvatarImage.attr("src", oRes.url);

            // 설정 폼에 avatarId 설정
            var welAvatarId = htElement.welFormAvatar.find("input[name=avatarId]");
            if(welAvatarId.length === 0){ // 없으면 새로 설정하고
                welAvatarId = htElement.welFormAvatar.append($("<input>").attr({
                    "type": "hidden",
                    "name": "avatarId",
                    "value": oRes.id
                }));
            } else { // 이미 있으면 값만 수정
                welAvatarId.attr("value", oRes.id);
            }

            _setAvatarProgressBar(100);

            // Crop 후에 업로드 인지, 처음 업로드인지 구분
            if(!htVar.oJcrop){
                _setJcrop(oRes); // jCrop 설정
            } else {
                htElement.welFormAvatar.submit();
            }
        }

        /**
         * jCrop 설정
         *
         * @param {Object} oRes 파일 정보
         */
        function _setJcrop(oRes){
            htElement.welImgCrop.on("load", function(){
                htVar.oJcrop = null;

                htElement.welImgCrop.Jcrop({
                    "aspectRatio": 1,
                    "minSize"  : [128, 128],
                    "bgColor"  : "#fff",
                    "setSelect": [0, 0, 128, 128],
                    "onSelect" : _onAvatarImageCrop,
                    "onChange" : _onAvatarImageCrop,
                    "onRelease": _onAvatarImageCropCancel
                }, function(){
                    htVar.oJcrop = this;
                });
            });
            htElement.welImgCrop.show();
            htElement.welImgCrop.attr("src", oRes.url);

            // 파일 업로드 버튼은 감추고, 크롭 이미지 전송 버튼 활성화

            htElement.welBtnUploadFile.hide();
            htElement.welBtnSubmitCrop.show();
            htElement.welBtnSubmitCrop.click(_sendCroppedImage);
        }

        /**
         * jCrop 커스텀 이벤트 핸들러
         * 잘라내기 된 이미지를 미리보기 해주는 역할
         *
         * @param {Hash Table} htData
         */
        function _onAvatarImageCrop(htData){
            if(htData.w <= 0){
                return;
            }
            var nRx = 128 / htData.w;
            var nRy = 128 / htData.h;

            var nWidth = htElement.welImgCrop.width();
            var nHeight = htElement.welImgCrop.height();

            // 미리보기 표시
            htElement.welAvatarImage.css({
                "width"     : Math.round(nRx * nWidth) + "px",
                "height"    : Math.round(nRy * nHeight) + "px",
                "marginLeft": "-" + Math.round(nRx * htData.x) + "px",
                "marginTop" : "-" + Math.round(nRy * htData.y) + "px"
            });

            htVar.htLastCrop = htData;
        }

        /**
         * jCrop 취소시 이벤트 핸들러
         * 완전하게 취소할 수 없고 늘 128x128 이상의 이미지 영역을 갖도록
         */
        function _onAvatarImageCropCancel(){
            if(htVar.oJcrop){
                htVar.oJcrop.setSelect([0, 0, 128, 128]);
            } else {
                htVar.htLastCrop = null;
            }
        }

        /**
         * jCrop 의 결과와 canvas 를 이용해서
         * 잘라낸 이미지를 서버에 전송하는 함수
         * #btnSubmitCrop 버튼을 클릭했을 때 실행된다
         */
        function _sendCroppedImage(){
            var elImage = new Image();
            var sTmpImageURL = htElement.welImgCrop.attr("src");

            // 원본 이미지 크기를 알아내기 위해 새 객체로 불러온다
            // 브라우저 캐시를 사용하므로 네트워크 호출 없음
            elImage.onload = function(){
                // 실제 이미지 크기와 jCrop 영역의 비율 계산
                var htData = htVar.htLastCrop;
                var nWidth = htElement.welImgCrop.width();
                var nRealWidth  = elImage.width;
                var nRw = nRealWidth / nWidth;
                var htCropData = {
                    "x": (htData.x * nRw),
                    "y": (htData.y * nRw),
                    "w": (htData.w * nRw),
                    "h": (htData.h * nRw)
                };

                var htEnv = yobi.Files.getEnv();

                // blob 전송이 가능한 환경이면
                if(htEnv.bXHR2){
                    // 임시 업로드 상태의 현재 파일은 삭제
                    yobi.Files.deleteFile({"sURL": sTmpImageURL});

                    // 캔버스를 이용해 Crop 이미지 데이터로 업로드
                    var elCanvas = document.getElementById("avatarCrop"); // canvas
                    var oContext = elCanvas.getContext("2d");
                    oContext.drawImage(elImage, htCropData.x, htCropData.y, htCropData.w, htCropData.h, 0, 0, 128, 128);

                    // canvas-to-blob.js
                    elCanvas.toBlob(function(oFile){
                        yobi.Files.uploadFile(oFile);
                    }, 'image/jpeg', 100);
                } else {
                    // TODO: 아니면 서버에 Crop 데이터만 전송한다 (for IE)
                    htElement.welFormAvatar.submit();
                }
            };
            elImage.src = sTmpImageURL;
        }

        /**
         * 아바타 이미지 업로드에 실패한 경우.
         * 일반적으로 서버 연결에 실패했을 때 이 상황이 발생한다.
         * ajaxForm 의 error 이벤트 핸들러.
         */
        function _onAvatarUploadError(sMessage){
            $yobi.alert(sMessage || Messages("user.avatar.uploadError"));
            _setAvatarProgressBar(0);
        }

        /**
         * 아바타 이미지 업로드 진행 상태
         * ajaxForm 의 uploadProgress 이벤트 핸들러
         *
         * @param {Wrapped Event} weEvt
         * @param {Number} nPosition
         * @param {Number}
         */
        function _onAvatarUploading(weEvt, nPosition, nTotal, nPercent){
            _setAvatarProgressBar(nPercent);
            htElement.welAvatarProgress.css("opacity", 1);
        }

        /**
         * 아바타 이미지 업로드 진행 상태 표시 함수
         *
         * @param {Number} nPercent
         */
        function _setAvatarProgressBar(nPercent){
            nPercent = parseInt(nPercent, 10);
            var nHeight = parseInt(htVar.nProgressHeight * (nPercent / 100), 10);
            htElement.welAvatarProgress.height(nHeight);

            // 꽉 차면 보이지 않게 하고 다시 0으로 되돌림
            if(nPercent === 100){
                htElement.welAvatarProgress.css("opacity", 0);

                setTimeout(function(){
                    //htElement.welFormBasic.submit();
                    _setAvatarProgressBar(0);
                }, 1000);
            }
        }

        /**
         * 비밀번호 확인 입력란 벗어날 때 이벤트 핸들러
         * 마지막 입력란이므로 전체 폼 유효성 검사
         */
        function _onBlurInputPassword(){
            htVar.oValidator._validateForm();
        }

        /**
         * initialize FormValidator
         * @require validate.js
         */
        function _initFormValidator(){
            var aRules = [
                {"name": 'oldPassword',     "rules": 'required'},
                {"name": 'password',        "rules": 'required|min_length[4]'},
                {"name": 'retypedPassword', "rules": 'required|matches[password]'}
            ];

            htVar.oValidator = new FormValidator('frmPassword', aRules, _onFormValidate);

            htVar.oValidator.setMessage('required',   Messages("validation.required"));
            htVar.oValidator.setMessage('min_length', Messages("validation.tooShortPassword"));
            htVar.oValidator.setMessage('matches',    Messages("validation.passwordMismatch"));
        }
        /**
         * on validate form
         *
         * @param {Array} aErrors
         */
        function _onFormValidate(aErrors){
            _clearPopovers();

            // to avoid bootstrap bug
            if (aErrors.length <= 0) {
                return _clearPopovers();
            }

            var welTarget;
            aErrors.forEach(function(htError){
                welTarget = htElement.welFormPswd.find("input[name=" + htError.name + "]");

                if(welTarget){
                    _showPopover(welTarget, htError.message);
                }
            });
        }

        /**
         * Bootstrap toolTip function has some limitation.
         * In this case, toolTip doesn't provide easy way to change title and contents.
         * So, unfortunately I had to change data value in directly.
         *
         * @param {Wrapped Element} welInput
         * @param {String} sMessage
         */
        function _showPopover(welInput, sMessage){
            welInput.popover({"trigger": "manual", "placement": "right"});

            var oPopover = welInput.data('popover');
            oPopover.options.placement = 'right';
            oPopover.options.trigger   = 'manual';
            oPopover.options.content   = sMessage;

            welInput.popover('show');
        }

        /**
         * 폼 영역에 있는 jquery.tooltip 모두 제거하는 함수
         */
        function _clearPopovers(){
            try {
                htElement.welFormPswd.find("input").each(function(i, v){
                    $(v).popover("destroy");
                });
            } catch(e){} // to avoid bootstrap bug
        }

        _init(htOptions || {});
    };
})("yobi.user.Setting");
<|endoftext|>


<commit_before>function splitSubMenu(columns) {
	jQuery("div.sub").each(function (i) {
		var items = jQuery(this).find('ul');
		var blockCount = columns;
		for (var i = 0; i < items.length; i += blockCount) {
			var slice = items.slice(i, i + blockCount);
			slice.wrapAll("

");
		}
	});
}

jQuery(document).ready(function () {

	// calculate height of top level menu and set top style for menu placement
	jQuery('ul.megamenu li .sub').css('top', jQuery('ul.megamenu > li').height());

	// set hover class to parent item
	jQuery('li.level0 div').mouseover(function () {
		jQuery(this).closest('li.level0').find('a.level0').addClass("megahover")
	}).mouseout(function () {
	    jQuery(this).closest('li.level0').find('a.level0').removeClass("megahover")
	});

	function megaHoverOver() {
		jQuery(this).find(".sub").stop().fadeTo('slow', 1).show();

		// calculate width of all ul's
		(function (jQuery) {
			jQuery.fn.calcSubWidth = function () {
				rowWidth = 0;
				//Calculate row
				$(this).find("ul").each(function () {
					rowWidth += $(this).width();
				});
			};
		})(jQuery);

		if (jQuery(this).find(".row").length > 0) {
            // if row exists...
			var biggestRow = 0;
			// calculate each row
			jQuery(this).find(".row").each(function () {
				jQuery(this).calcSubWidth();
				// find biggest row
				if (rowWidth > biggestRow) {
					biggestRow = rowWidth;
				}
			});
			// set width
			jQuery(this).find(".sub").css({ 'width': biggestRow });
			jQuery(this).find(".row:last").css({ 'margin': '0' });
		}
        else {
            // if row does not exist...
			jQuery(this).calcSubWidth();
			// set width
			jQuery(this).find(".sub").css({ 'width': rowWidth });
		}
	}

	function megaHoverOut() {
		jQuery(this).find(".sub").stop().fadeTo('slow', 0, function () {
			jQuery(this).hide();
		});
	}

	var config = {
		sensitivity: 2, // number = sensitivity threshold (must be 1 or higher)
		interval: 100, // number = milliseconds for onMouseOver polling interval
		over: megaHoverOver, // function = onMouseOver callback (REQUIRED)
		timeout: 100, // number = milliseconds delay before onMouseOut
		out: megaHoverOut // function = onMouseOut callback (REQUIRED)
	};

	jQuery("ul.megamenu li .sub").css({ 'opacity': '0' });
	jQuery("ul.megamenu li").hoverIntent(config);
});
<commit_msg>Use more specific div.sub selector<commit_after>function splitSubMenu(columns) {
	jQuery("ul.megamenu div.sub").each(function (i) {
		var items = jQuery(this).find('ul');
		var blockCount = columns;
		for (var i = 0; i < items.length; i += blockCount) {
			var slice = items.slice(i, i + blockCount);
			slice.wrapAll("

");
		}
	});
}

jQuery(document).ready(function () {

	// calculate height of top level menu and set top style for menu placement
	jQuery('ul.megamenu li .sub').css('top', jQuery('ul.megamenu > li').height());

	// set hover class to parent item
	jQuery('li.level0 div').mouseover(function () {
		jQuery(this).closest('li.level0').find('a.level0').addClass("megahover")
	}).mouseout(function () {
	    jQuery(this).closest('li.level0').find('a.level0').removeClass("megahover")
	});

	function megaHoverOver() {
		jQuery(this).find(".sub").stop().fadeTo('slow', 1).show();

		// calculate width of all ul's
		(function (jQuery) {
			jQuery.fn.calcSubWidth = function () {
				rowWidth = 0;
				//Calculate row
				$(this).find("ul").each(function () {
					rowWidth += $(this).width();
				});
			};
		})(jQuery);

		if (jQuery(this).find(".row").length > 0) {
            // if row exists...
			var biggestRow = 0;
			// calculate each row
			jQuery(this).find(".row").each(function () {
				jQuery(this).calcSubWidth();
				// find biggest row
				if (rowWidth > biggestRow) {
					biggestRow = rowWidth;
				}
			});
			// set width
			jQuery(this).find(".sub").css({ 'width': biggestRow });
			jQuery(this).find(".row:last").css({ 'margin': '0' });
		}
        else {
            // if row does not exist...
			jQuery(this).calcSubWidth();
			// set width
			jQuery(this).find(".sub").css({ 'width': rowWidth });
		}
	}

	function megaHoverOut() {
		jQuery(this).find(".sub").stop().fadeTo('slow', 0, function () {
			jQuery(this).hide();
		});
	}

	var config = {
		sensitivity: 2, // number = sensitivity threshold (must be 1 or higher)
		interval: 100, // number = milliseconds for onMouseOver polling interval
		over: megaHoverOver, // function = onMouseOver callback (REQUIRED)
		timeout: 100, // number = milliseconds delay before onMouseOut
		out: megaHoverOut // function = onMouseOut callback (REQUIRED)
	};

	jQuery("ul.megamenu li .sub").css({ 'opacity': '0' });
	jQuery("ul.megamenu li").hoverIntent(config);
});
<|endoftext|>


<commit_before>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	$C = require('collection.js'),
	fs = require('fs-extra-promise'),
	path = require('path'),
	hasha = require('hasha');

const
	{resolve, entries, block} = require('@pzlr/build-core'),
	{args, output, assetsJSON, buildCache} = include('build/build.webpack'),
	{normalizeSep} = include('build/helpers');

const
	IN_PROCESS = 3;

/**
 * Tree of dependencies
 * @type {Promise<{entry, processes, dependencies}>}
 */
module.exports = (async () => {
	const mkdirp = (src) => {
		if (!fs.existsSync(src)) {
			fs.mkdirpSync(src);
		}
	};

	let
		cacheFile;

	if (Number(process.env.FROM_CACHE)) {
		mkdirp(buildCache);
		cacheFile = path.join(buildCache, 'graph.json');

		if (fs.existsSync(cacheFile)) {
			return fs.readJSONSync(cacheFile);
		}
	}

	const
		tmpEntries = path.join(resolve.entry(), 'tmp');

	mkdirp(tmpEntries);
	mkdirp(path.dirname(output));

	let
		entriesFilter;

	if (typeof args.build === 'string') {
		entriesFilter = $C(args.build.split(',')).reduce((map, el) => (map[el] = true, map), {});
		entriesFilter.index = true;
	}

	const
		buildConfig = (await entries.getBuildConfig()).filter((el, key) => entriesFilter ? entriesFilter[key] : true),
		blockMap = await block.getAll(),
		graph = await buildConfig.getUnionEntryPoints({cache: blockMap});

	$C(graph.dependencies).forEach((el, key, data) => {
		if (key !== 'index' && !el.has('index')) {
			data[key] = new Set(['index', ...el]);
		}

		el.add(key);

		const
			content = `ModuleDependencies.add("${key}", ${JSON.stringify([...el])});`,
			name = `${key}.dependencies`;

		const src = output
			.replace(/\[name]/g, `${name}.js`)
			.replace(/\[hash:?(\d*)]/, (str, length) => {
				const res = hasha(content, {algorithm: 'md5'});
				return length ? res.substr(0, Number(length)) : res;
			});

		fs.writeFileSync(src, content);

		let fd;
		try {
			fd = fs.openSync(assetsJSON, 'r+');

		} catch (_) {
			fd = fs.openSync(assetsJSON, 'w+');
		}

		const
			file = fs.readFileSync(fd, 'utf-8'),
			assets = file ? JSON.parse(file) : {};

		assets[name] = {js: src};
		fs.writeFileSync(fd, JSON.stringify(assets));
		fs.closeSync(fd);
	});

	/**
	 * Returns an url relative to the entry folder
	 */
	function getUrl(url) {
		if (resolve.isNodeModule(url)) {
			return normalizeSep(url);
		}

		return normalizeSep(path.relative(tmpEntries, url));
	}

	const processes = [
		{}
	];

	const entry = await $C(graph.entry)
		.parallel()
		.to({})
		.reduce(async (entry, list, name) => {
			// JS / TS

			const
				blackName = /^[iv]-/,
				logicTaskName = `${name}.js`,
				logicFile = path.join(tmpEntries, logicTaskName);

			fs.writeFileSync(logicFile, await $C(list).async.to('').reduce(async (str, {name}) => {
				const
					block = blockMap.get(name),
					logic = block && await block.logic;

				if (block) {
					$C(block.libs).forEach((el) => str += `require('${el}');\n`);
				}

				if (!block || logic) {
					const url = logic ? logic : resolve.isNodeModule(name) ? name : path.resolve(tmpEntries, '../', name);
					str += `require('${getUrl(url)}');\n`;
				}

				return str;
			}));

			entry[logicTaskName] = logicFile;
			processes[0][logicTaskName] = logicFile;

			// CSS

			const
				styleTaskName = `${name}$style`,
				styleFile = path.join(tmpEntries, `${name}.styl`);

			fs.writeFileSync(styleFile, await $C(list).async.to('').reduce(async (str, {name, isParent}) => {
				const
					block = blockMap.get(name),
					style = block && await block.styles;

				if (!isParent && style && style.length && !blackName.test(name)) {
					$C(style).forEach((url) => {
						str += `@import "${getUrl(url)}"\n`;
					});

					if (/^[bp]-/.test(name)) {
						str +=
							`
	.${name}
		extends($${name.camelize(name, false)})

	`;
					}
				}

				return str;
			}));

			let union = processes[processes.length - 1];
			if (processes.length === 1 || $C(union).length() > IN_PROCESS) {
				processes.push(union = {});
			}

			entry[styleTaskName] = union[styleTaskName] = styleFile;

			// TEMPLATES

			const
				tplTaskName = `${name}_tpl.js`,
				tplFile = path.join(tmpEntries, `${name}.ss${!args.fast ? '.js' : ''}`);

			fs.writeFileSync(tplFile, await $C(list)
				.async
				.to(args.fast ? '' : 'window.TPLS = window.TPLS || Object.create(null);\n')
				.reduce(async (str, {name, isParent}) => {
					const
						block = blockMap.get(name),
						tpl = block && await block.tpl;

					if (!isParent && tpl && !blackName.test(name)) {
						const url = getUrl(tpl);
						str += args.fast ? `- include '${url}'\n` : `Object.assign(TPLS, require('./${url}'));\n`;
					}

					return str;
				})
			);

			if (args.fast) {
				const
					tplRequireFileUrl = path.join(tmpEntries, tplTaskName);

				fs.writeFileSync(
					tplRequireFileUrl,
					`Object.assign(window.TPLS = window.TPLS || Object.create(null), require('./${getUrl(tplFile)}'));\n`
				);

				entry[tplTaskName] = union[tplTaskName] = tplRequireFileUrl;

			} else {
				entry[tplTaskName] = union[tplTaskName] = tplFile;
			}

			// HTML

			const
				htmlTaskName = `${name}_view`,
				htmlFile = path.join(tmpEntries, `${htmlTaskName}.html.js`);

			fs.writeFileSync(htmlFile, await $C(list).async.to('').reduce(async (str, {name}) => {
				const
					block = blockMap.get(name),
					html = block && await block.etpl;

				if (html && !blackName.test(name)) {
					str += `require('./${getUrl(html)}');\n`;
				}

				return str;
			}));

			entry[htmlTaskName] = union[htmlTaskName] = htmlFile;
			return entry;
		});

	const res = {
		entry,
		processes,
		dependencies: graph.dependencies
	};

	if (cacheFile) {
		fs.writeFileSync(cacheFile, JSON.stringify(res, null, 2));
		process.env.FROM_CACHE = true;
	}

	return res;
})();
<commit_msg>:wrench:<commit_after>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	$C = require('collection.js'),
	fs = require('fs-extra-promise'),
	path = require('path'),
	hasha = require('hasha');

const
	{resolve, entries, block} = require('@pzlr/build-core'),
	{args, output, assetsJSON, buildCache} = include('build/build.webpack'),
	{normalizeSep} = include('build/helpers');

const
	IN_PROCESS = 3;

/**
 * Tree of dependencies
 * @type {Promise<{entry, processes, dependencies}>}
 */
module.exports = (async () => {
	const mkdirp = (src) => {
		if (!fs.existsSync(src)) {
			fs.mkdirpSync(src);
		}
	};

	let
		cacheFile;

	if (Number(process.env.FROM_CACHE)) {
		mkdirp(buildCache);
		cacheFile = path.join(buildCache, 'graph.json');

		if (fs.existsSync(cacheFile)) {
			return fs.readJSONSync(cacheFile);
		}
	}

	const
		tmpEntries = path.join(resolve.entry(), 'tmp');

	mkdirp(tmpEntries);
	mkdirp(path.dirname(output));

	let
		entriesFilter;

	if (typeof args.build === 'string') {
		entriesFilter = $C(args.build.split(',')).reduce((map, el) => (map[el] = true, map), {});
		entriesFilter.index = true;
	}

	const
		buildConfig = (await entries.getBuildConfig()).filter((el, key) => entriesFilter ? entriesFilter[key] : true),
		blockMap = await block.getAll(),
		graph = await buildConfig.getUnionEntryPoints({cache: blockMap});

	$C(graph.dependencies).forEach((el, key, data) => {
		if (key !== 'index' && !el.has('index')) {
			data[key] = new Set(['index', ...el]);
		}

		el.add(key);

		const
			content = `ModuleDependencies.add("${key}", ${JSON.stringify([...el])});`,
			name = `${key}.dependencies`;

		const src = output
			.replace(/\[name]/g, `${name}.js`)
			.replace(/\[hash:?(\d*)]/, (str, length) => {
				const res = hasha(content, {algorithm: 'md5'});
				return length ? res.substr(0, Number(length)) : res;
			});

		fs.writeFileSync(src, content);

		let fd;
		try {
			fd = fs.openSync(assetsJSON, 'r+');

		} catch (_) {
			fd = fs.openSync(assetsJSON, 'w+');
		}

		const
			file = fs.readFileSync(fd, 'utf-8'),
			assets = file ? JSON.parse(file) : {};

		assets[name] = {js: src};
		fs.writeFileSync(fd, JSON.stringify(assets));
		fs.closeSync(fd);
	});

	/**
	 * Returns an url relative to the entry folder
	 */
	function getUrl(url) {
		if (resolve.isNodeModule(url)) {
			return normalizeSep(url);
		}

		return normalizeSep(path.relative(tmpEntries, url));
	}

	const processes = [
		{}
	];

	const entry = await $C(graph.entry)
		.parallel()
		.to({})
		.reduce(async (entry, list, name) => {
			// JS / TS

			const
				blackName = /^[iv]-/,
				logicTaskName = `${name}.js`,
				logicFile = path.join(tmpEntries, logicTaskName);

			fs.writeFileSync(logicFile, await $C(list).async.to('').reduce(async (str, {name}) => {
				const
					block = blockMap.get(name),
					logic = block && await block.logic;

				if (block) {
					$C(block.libs).forEach((el) => str += `require('${el}');\n`);
				}

				if (!block || logic) {
					const url = logic ? logic : resolve.isNodeModule(name) ? name : path.resolve(tmpEntries, '../', name);
					str += `require('${getUrl(url)}');\n`;
				}

				return str;
			}));

			entry[logicTaskName] = logicFile;
			processes[0][logicTaskName] = logicFile;

			// CSS

			const
				styleTaskName = `${name}$style`,
				styleFile = path.join(tmpEntries, `${name}.styl`);

			fs.writeFileSync(styleFile, await $C(list).async.to('').reduce(async (str, {name, isParent}) => {
				const
					block = blockMap.get(name),
					style = block && await block.styles;

				if (!isParent && style && style.length && !blackName.test(name)) {
					$C(style).forEach((url) => {
						str += `@import "${getUrl(url)}"\n`;
					});

					if (/^[bp]-/.test(name)) {
						str +=
							`
.${name}
	extends($${name.camelize(name, false)})

`;
					}
				}

				return str;
			}));

			let union = processes[processes.length - 1];
			if (processes.length === 1 || $C(union).length() > IN_PROCESS) {
				processes.push(union = {});
			}

			entry[styleTaskName] = union[styleTaskName] = styleFile;

			// TEMPLATES

			const
				tplTaskName = `${name}_tpl.js`,
				tplFile = path.join(tmpEntries, `${name}.ss${!args.fast ? '.js' : ''}`);

			fs.writeFileSync(tplFile, await $C(list)
				.async
				.to(args.fast ? '' : 'window.TPLS = window.TPLS || Object.create(null);\n')
				.reduce(async (str, {name, isParent}) => {
					const
						block = blockMap.get(name),
						tpl = block && await block.tpl;

					if (!isParent && tpl && !blackName.test(name)) {
						const url = getUrl(tpl);
						str += args.fast ? `- include '${url}'\n` : `Object.assign(TPLS, require('./${url}'));\n`;
					}

					return str;
				})
			);

			if (args.fast) {
				const
					tplRequireFileUrl = path.join(tmpEntries, tplTaskName);

				fs.writeFileSync(
					tplRequireFileUrl,
					`Object.assign(window.TPLS = window.TPLS || Object.create(null), require('./${getUrl(tplFile)}'));\n`
				);

				entry[tplTaskName] = union[tplTaskName] = tplRequireFileUrl;

			} else {
				entry[tplTaskName] = union[tplTaskName] = tplFile;
			}

			// HTML

			const
				htmlTaskName = `${name}_view`,
				htmlFile = path.join(tmpEntries, `${htmlTaskName}.html.js`);

			fs.writeFileSync(htmlFile, await $C(list).async.to('').reduce(async (str, {name}) => {
				const
					block = blockMap.get(name),
					html = block && await block.etpl;

				if (html && !blackName.test(name)) {
					str += `require('./${getUrl(html)}');\n`;
				}

				return str;
			}));

			entry[htmlTaskName] = union[htmlTaskName] = htmlFile;
			return entry;
		});

	const res = {
		entry,
		processes,
		dependencies: graph.dependencies
	};

	if (cacheFile) {
		fs.writeFileSync(cacheFile, JSON.stringify(res, null, 2));
		process.env.FROM_CACHE = true;
	}

	return res;
})();
<|endoftext|>


<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

const gulp = require('gulp');
const filter = require('gulp-filter');
const es = require('event-stream');
const gulptslint = require('gulp-tslint');
const gulpeslint = require('gulp-eslint');
const tsfmt = require('typescript-formatter');
const tslint = require('tslint');
const VinylFile = require('vinyl');
const vfs = require('vinyl-fs');
const path = require('path');
const fs = require('fs');
const pall = require('p-all');

/**
 * Hygiene works by creating cascading subsets of all our files and
 * passing them through a sequence of checks. Here are the current subsets,
 * named according to the checks performed on them. Each subset contains
 * the following one, as described in mathematical notation:
 *
 * all ⊃ eol ⊇ indentation ⊃ copyright ⊃ typescript
 */

const all = [
	'*',
	'build/**/*',
	'extensions/**/*',
	'scripts/**/*',
	'src/**/*',
	'test/**/*',
	'!**/node_modules/**'
];

const indentationFilter = [
	'**',

	// except specific files
	'!ThirdPartyNotices.txt',
	'!LICENSE.txt',
	'!src/vs/nls.js',
	'!src/vs/css.js',
	'!src/vs/loader.js',
	'!src/vs/base/common/marked/raw.marked.js',
	'!src/vs/base/common/winjs.base.raw.js',
	'!src/vs/base/node/terminateProcess.sh',
	'!src/vs/base/node/ps-win.ps1',
	'!test/assert.js',

	// except specific folders
	'!test/smoke/out/**',
	'!extensions/vscode-api-tests/testWorkspace/**',
	'!extensions/vscode-api-tests/testWorkspace2/**',
	'!build/monaco/**',
	'!build/win32/**',

	// except multiple specific files
	'!**/package.json',
	'!**/yarn.lock',

	// except multiple specific folders
	'!**/octicons/**',
	'!**/fixtures/**',
	'!**/lib/**',
	'!extensions/**/out/**',
	'!extensions/**/snippets/**',
	'!extensions/**/syntaxes/**',
	'!extensions/**/themes/**',
	'!extensions/**/colorize-fixtures/**',

	// except specific file types
	'!src/vs/*/**/*.d.ts',
	'!src/typings/**/*.d.ts',
	'!extensions/**/*.d.ts',
	'!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,template,yaml,yml,d.ts.recipe}',
	'!build/{lib,tslintRules}/**/*.js',
	'!build/**/*.sh',
	'!build/tfs/**/*.js',
	'!**/Dockerfile'
];

const copyrightFilter = [
	'**',
	'!**/*.desktop',
	'!**/*.json',
	'!**/*.html',
	'!**/*.template',
	'!**/*.md',
	'!**/*.bat',
	'!**/*.cmd',
	'!**/*.xml',
	'!**/*.sh',
	'!**/*.txt',
	'!**/*.xpm',
	'!**/*.opts',
	'!**/*.disabled',
	'!**/*.code-workspace',
	'!build/**/*.init',
	'!resources/linux/snap/snapcraft.yaml',
	'!resources/win32/bin/code.js',
	'!extensions/markdown/media/tomorrow.css',
	'!extensions/html/server/src/modes/typescript/*'
];

const eslintFilter = [
	'src/**/*.js',
	'build/gulpfile.*.js',
	'!src/vs/loader.js',
	'!src/vs/css.js',
	'!src/vs/nls.js',
	'!src/vs/css.build.js',
	'!src/vs/nls.build.js',
	'!src/**/winjs.base.raw.js',
	'!src/**/raw.marked.js',
	'!**/test/**'
];

const tslintFilter = [
	'src/**/*.ts',
	'test/**/*.ts',
	'extensions/**/*.ts',
	'!**/fixtures/**',
	'!**/typings/**',
	'!**/node_modules/**',
	'!extensions/typescript/test/colorize-fixtures/**',
	'!extensions/vscode-api-tests/testWorkspace/**',
	'!extensions/vscode-api-tests/testWorkspace2/**',
	'!extensions/**/*.test.ts',
	'!extensions/html/server/lib/jquery.d.ts'
];

const copyrightHeaderLines = [
	'/*---------------------------------------------------------------------------------------------',
	' *  Copyright (c) Microsoft Corporation. All rights reserved.',
	' *  Licensed under the MIT License. See License.txt in the project root for license information.',
	' *--------------------------------------------------------------------------------------------*/'
];

gulp.task('eslint', () => {
	return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
		.pipe(filter(eslintFilter))
		.pipe(gulpeslint('src/.eslintrc'))
		.pipe(gulpeslint.formatEach('compact'))
		.pipe(gulpeslint.failAfterError());
});

gulp.task('tslint', () => {
	const options = { emitError: true };

	return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
		.pipe(filter(tslintFilter))
		.pipe(gulptslint.default({ rulesDirectory: 'build/lib/tslint' }))
		.pipe(gulptslint.default.report(options));
});

function hygiene(some) {
	let errorCount = 0;

	const indentation = es.through(function (file) {
		const lines = file.contents.toString('utf8').split(/\r\n|\r|\n/);
		file.__lines = lines;

		lines
			.forEach((line, i) => {
				if (/^\s*$/.test(line)) {
					// empty or whitespace lines are OK
				} else if (/^[\t]*[^\s]/.test(line)) {
					// good indent
				} else if (/^[\t]* \*/.test(line)) {
					// block comment using an extra space
				} else {
					console.error(file.relative + '(' + (i + 1) + ',1): Bad whitespace indentation');
					errorCount++;
				}
			});

		this.emit('data', file);
	});

	const copyrights = es.through(function (file) {
		const lines = file.__lines;

		for (let i = 0; i < copyrightHeaderLines.length; i++) {
			if (lines[i] !== copyrightHeaderLines[i]) {
				console.error(file.relative + ': Missing or bad copyright statement');
				errorCount++;
				break;
			}
		}

		this.emit('data', file);
	});

	const formatting = es.map(function (file, cb) {
		tsfmt.processString(file.path, file.contents.toString('utf8'), {
			verify: true,
			tsfmt: true,
			// verbose: true
			// keep checkJS happy
			editorconfig: undefined,
			replace: undefined,
			tsconfig: undefined,
			tslint: undefined
		}).then(result => {
			if (result.error) {
				fs.writeFileSync('C:\\Users\\joao\\Desktop\\src.txt', result.src);
				fs.writeFileSync('C:\\Users\\joao\\Desktop\\dest.txt', result.dest);

				console.error(result.src, result.message);
				errorCount++;
			}
			cb(null, file);

		}, err => {
			cb(err);
		});
	});

	const tslintConfiguration = tslint.Configuration.findConfiguration('tslint.json', '.');
	const tslintOptions = { fix: false, formatter: 'json' };
	const tsLinter = new tslint.Linter(tslintOptions);

	const tsl = es.through(function (file) {
		const contents = file.contents.toString('utf8');
		tsLinter.lint(file.relative, contents, tslintConfiguration.results);
		this.emit('data', file);
	});

	let input;

	if (Array.isArray(some) || typeof some === 'string' || !some) {
		input = vfs.src(some || all, { base: '.', follow: true, allowEmpty: true });
	} else {
		input = some;
	}

	const result = input
		.pipe(filter(f => !f.stat.isDirectory()))
		.pipe(filter(indentationFilter))
		.pipe(indentation)
		.pipe(filter(copyrightFilter))
		.pipe(copyrights);

	const typescript = result
		.pipe(filter(tslintFilter))
		.pipe(formatting)
		.pipe(tsl);

	const javascript = result
		.pipe(filter(eslintFilter))
		.pipe(gulpeslint('src/.eslintrc'))
		.pipe(gulpeslint.formatEach('compact'))
		.pipe(gulpeslint.failAfterError());

	let count = 0;
	return es.merge(typescript, javascript)
		.pipe(es.through(function (data) {
			count++;
			if (process.env['TRAVIS'] && count % 10 === 0) {
				process.stdout.write('.');
			}
			this.emit('data', data);
		}, function () {
			process.stdout.write('\n');

			const tslintResult = tsLinter.getResult();
			if (tslintResult.failures.length > 0) {
				for (const failure of tslintResult.failures) {
					const name = failure.getFileName();
					const position = failure.getStartPosition();
					const line = position.getLineAndCharacter().line;
					const character = position.getLineAndCharacter().character;

					console.error(`${name}:${line + 1}:${character + 1}:${failure.getFailure()}`);
				}
				errorCount += tslintResult.failures.length;
			}

			if (errorCount > 0) {
				this.emit('error', 'Hygiene failed with ' + errorCount + ' errors. Check \'build/gulpfile.hygiene.js\'.');
			} else {
				this.emit('end');
			}
		}));
}

function createGitIndexVinyls(paths) {
	const cp = require('child_process');
	const repositoryPath = process.cwd();

	const fns = paths.map(relativePath => () => new Promise((c, e) => {
		const fullPath = path.join(repositoryPath, relativePath);

		fs.stat(fullPath, (err, stat) => {
			if (err && err.code === 'ENOENT') { // ignore deletions
				return c(null);
			} else if (err) {
				return e(err);
			}

			cp.exec(`git show :${relativePath}`, { maxBuffer: 2000 * 1024, encoding: 'buffer' }, (err, out) => {
				if (err) {
					return e(err);
				}

				c(new VinylFile({
					path: fullPath,
					base: repositoryPath,
					contents: out,
					stat
				}));
			});
		});
	}));

	return pall(fns, { concurrency: 4 })
		.then(r => r.filter(p => !!p));
}

gulp.task('hygiene', () => hygiene());

// this allows us to run hygiene as a git pre-commit hook
if (require.main === module) {
	const cp = require('child_process');

	process.on('unhandledRejection', (reason, p) => {
		console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
		process.exit(1);
	});

	if (process.argv.length > 2) {
		hygiene(process.argv.slice(2)).on('error', err => {
			console.error();
			console.error(err);
			process.exit(1);
		});
	} else {
		cp.exec('git diff --cached --name-only', { maxBuffer: 2000 * 1024 }, (err, out) => {
			if (err) {
				console.error();
				console.error(err);
				process.exit(1);
				return;
			}

			const some = out
				.split(/\r?\n/)
				.filter(l => !!l);

			if (some.length > 0) {
				console.log('Reading git index versions...');

				createGitIndexVinyls(some)
					.then(vinyls => new Promise((c, e) => hygiene(es.readArray(vinyls))
						.on('end', () => c())
						.on('error', e)))
					.catch(err => {
						console.error();
						console.error(err);
						process.exit(1);
					});
			}
		});
	}
}
<commit_msg>fix hygiene<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

const gulp = require('gulp');
const filter = require('gulp-filter');
const es = require('event-stream');
const gulptslint = require('gulp-tslint');
const gulpeslint = require('gulp-eslint');
const tsfmt = require('typescript-formatter');
const tslint = require('tslint');
const VinylFile = require('vinyl');
const vfs = require('vinyl-fs');
const path = require('path');
const fs = require('fs');
const pall = require('p-all');

/**
 * Hygiene works by creating cascading subsets of all our files and
 * passing them through a sequence of checks. Here are the current subsets,
 * named according to the checks performed on them. Each subset contains
 * the following one, as described in mathematical notation:
 *
 * all ⊃ eol ⊇ indentation ⊃ copyright ⊃ typescript
 */

const all = [
	'*',
	'build/**/*',
	'extensions/**/*',
	'scripts/**/*',
	'src/**/*',
	'test/**/*',
	'!**/node_modules/**'
];

const indentationFilter = [
	'**',

	// except specific files
	'!ThirdPartyNotices.txt',
	'!LICENSE.txt',
	'!src/vs/nls.js',
	'!src/vs/css.js',
	'!src/vs/loader.js',
	'!src/vs/base/common/marked/raw.marked.js',
	'!src/vs/base/common/winjs.base.raw.js',
	'!src/vs/base/node/terminateProcess.sh',
	'!src/vs/base/node/ps-win.ps1',
	'!test/assert.js',

	// except specific folders
	'!test/smoke/out/**',
	'!extensions/vscode-api-tests/testWorkspace/**',
	'!extensions/vscode-api-tests/testWorkspace2/**',
	'!build/monaco/**',
	'!build/win32/**',

	// except multiple specific files
	'!**/package.json',
	'!**/yarn.lock',

	// except multiple specific folders
	'!**/octicons/**',
	'!**/fixtures/**',
	'!**/lib/**',
	'!extensions/**/out/**',
	'!extensions/**/snippets/**',
	'!extensions/**/syntaxes/**',
	'!extensions/**/themes/**',
	'!extensions/**/colorize-fixtures/**',

	// except specific file types
	'!src/vs/*/**/*.d.ts',
	'!src/typings/**/*.d.ts',
	'!extensions/**/*.d.ts',
	'!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,template,yaml,yml,d.ts.recipe}',
	'!build/{lib,tslintRules}/**/*.js',
	'!build/**/*.sh',
	'!build/tfs/**/*.js',
	'!**/Dockerfile'
];

const copyrightFilter = [
	'**',
	'!**/*.desktop',
	'!**/*.json',
	'!**/*.html',
	'!**/*.template',
	'!**/*.md',
	'!**/*.bat',
	'!**/*.cmd',
	'!**/*.xml',
	'!**/*.sh',
	'!**/*.txt',
	'!**/*.xpm',
	'!**/*.opts',
	'!**/*.disabled',
	'!**/*.code-workspace',
	'!build/**/*.init',
	'!resources/linux/snap/snapcraft.yaml',
	'!resources/win32/bin/code.js',
	'!extensions/markdown/media/tomorrow.css',
	'!extensions/html/server/src/modes/typescript/*'
];

const eslintFilter = [
	'src/**/*.js',
	'build/gulpfile.*.js',
	'!src/vs/loader.js',
	'!src/vs/css.js',
	'!src/vs/nls.js',
	'!src/vs/css.build.js',
	'!src/vs/nls.build.js',
	'!src/**/winjs.base.raw.js',
	'!src/**/raw.marked.js',
	'!**/test/**'
];

const tslintFilter = [
	'src/**/*.ts',
	'test/**/*.ts',
	'extensions/**/*.ts',
	'!**/fixtures/**',
	'!**/typings/**',
	'!**/node_modules/**',
	'!extensions/typescript/test/colorize-fixtures/**',
	'!extensions/vscode-api-tests/testWorkspace/**',
	'!extensions/vscode-api-tests/testWorkspace2/**',
	'!extensions/**/*.test.ts',
	'!extensions/html/server/lib/jquery.d.ts'
];

const copyrightHeaderLines = [
	'/*---------------------------------------------------------------------------------------------',
	' *  Copyright (c) Microsoft Corporation. All rights reserved.',
	' *  Licensed under the MIT License. See License.txt in the project root for license information.',
	' *--------------------------------------------------------------------------------------------*/'
];

gulp.task('eslint', () => {
	return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
		.pipe(filter(eslintFilter))
		.pipe(gulpeslint('src/.eslintrc'))
		.pipe(gulpeslint.formatEach('compact'))
		.pipe(gulpeslint.failAfterError());
});

gulp.task('tslint', () => {
	const options = { emitError: true };

	return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
		.pipe(filter(tslintFilter))
		.pipe(gulptslint.default({ rulesDirectory: 'build/lib/tslint' }))
		.pipe(gulptslint.default.report(options));
});

function hygiene(some) {
	let errorCount = 0;

	const indentation = es.through(function (file) {
		const lines = file.contents.toString('utf8').split(/\r\n|\r|\n/);
		file.__lines = lines;

		lines
			.forEach((line, i) => {
				if (/^\s*$/.test(line)) {
					// empty or whitespace lines are OK
				} else if (/^[\t]*[^\s]/.test(line)) {
					// good indent
				} else if (/^[\t]* \*/.test(line)) {
					// block comment using an extra space
				} else {
					console.error(file.relative + '(' + (i + 1) + ',1): Bad whitespace indentation');
					errorCount++;
				}
			});

		this.emit('data', file);
	});

	const copyrights = es.through(function (file) {
		const lines = file.__lines;

		for (let i = 0; i < copyrightHeaderLines.length; i++) {
			if (lines[i] !== copyrightHeaderLines[i]) {
				console.error(file.relative + ': Missing or bad copyright statement');
				errorCount++;
				break;
			}
		}

		this.emit('data', file);
	});

	const formatting = es.map(function (file, cb) {
		tsfmt.processString(file.path, file.contents.toString('utf8'), {
			verify: true,
			tsfmt: true,
			// verbose: true
			// keep checkJS happy
			editorconfig: undefined,
			replace: undefined,
			tsconfig: undefined,
			tslint: undefined
		}).then(result => {
			if (result.error) {
				console.error(result.message);
				errorCount++;
			}
			cb(null, file);

		}, err => {
			cb(err);
		});
	});

	const tslintConfiguration = tslint.Configuration.findConfiguration('tslint.json', '.');
	const tslintOptions = { fix: false, formatter: 'json' };
	const tsLinter = new tslint.Linter(tslintOptions);

	const tsl = es.through(function (file) {
		const contents = file.contents.toString('utf8');
		tsLinter.lint(file.relative, contents, tslintConfiguration.results);
		this.emit('data', file);
	});

	let input;

	if (Array.isArray(some) || typeof some === 'string' || !some) {
		input = vfs.src(some || all, { base: '.', follow: true, allowEmpty: true });
	} else {
		input = some;
	}

	const result = input
		.pipe(filter(f => !f.stat.isDirectory()))
		.pipe(filter(indentationFilter))
		.pipe(indentation)
		.pipe(filter(copyrightFilter))
		.pipe(copyrights);

	const typescript = result
		.pipe(filter(tslintFilter))
		.pipe(formatting)
		.pipe(tsl);

	const javascript = result
		.pipe(filter(eslintFilter))
		.pipe(gulpeslint('src/.eslintrc'))
		.pipe(gulpeslint.formatEach('compact'))
		.pipe(gulpeslint.failAfterError());

	let count = 0;
	return es.merge(typescript, javascript)
		.pipe(es.through(function (data) {
			count++;
			if (process.env['TRAVIS'] && count % 10 === 0) {
				process.stdout.write('.');
			}
			this.emit('data', data);
		}, function () {
			process.stdout.write('\n');

			const tslintResult = tsLinter.getResult();
			if (tslintResult.failures.length > 0) {
				for (const failure of tslintResult.failures) {
					const name = failure.getFileName();
					const position = failure.getStartPosition();
					const line = position.getLineAndCharacter().line;
					const character = position.getLineAndCharacter().character;

					console.error(`${name}:${line + 1}:${character + 1}:${failure.getFailure()}`);
				}
				errorCount += tslintResult.failures.length;
			}

			if (errorCount > 0) {
				this.emit('error', 'Hygiene failed with ' + errorCount + ' errors. Check \'build/gulpfile.hygiene.js\'.');
			} else {
				this.emit('end');
			}
		}));
}

function createGitIndexVinyls(paths) {
	const cp = require('child_process');
	const repositoryPath = process.cwd();

	const fns = paths.map(relativePath => () => new Promise((c, e) => {
		const fullPath = path.join(repositoryPath, relativePath);

		fs.stat(fullPath, (err, stat) => {
			if (err && err.code === 'ENOENT') { // ignore deletions
				return c(null);
			} else if (err) {
				return e(err);
			}

			cp.exec(`git show :${relativePath}`, { maxBuffer: 2000 * 1024, encoding: 'buffer' }, (err, out) => {
				if (err) {
					return e(err);
				}

				c(new VinylFile({
					path: fullPath,
					base: repositoryPath,
					contents: out,
					stat
				}));
			});
		});
	}));

	return pall(fns, { concurrency: 4 })
		.then(r => r.filter(p => !!p));
}

gulp.task('hygiene', () => hygiene());

// this allows us to run hygiene as a git pre-commit hook
if (require.main === module) {
	const cp = require('child_process');

	process.on('unhandledRejection', (reason, p) => {
		console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
		process.exit(1);
	});

	if (process.argv.length > 2) {
		hygiene(process.argv.slice(2)).on('error', err => {
			console.error();
			console.error(err);
			process.exit(1);
		});
	} else {
		cp.exec('git diff --cached --name-only', { maxBuffer: 2000 * 1024 }, (err, out) => {
			if (err) {
				console.error();
				console.error(err);
				process.exit(1);
				return;
			}

			const some = out
				.split(/\r?\n/)
				.filter(l => !!l);

			if (some.length > 0) {
				console.log('Reading git index versions...');

				createGitIndexVinyls(some)
					.then(vinyls => new Promise((c, e) => hygiene(es.readArray(vinyls))
						.on('end', () => c())
						.on('error', e)))
					.catch(err => {
						console.error();
						console.error(err);
						process.exit(1);
					});
			}
		});
	}
}
<|endoftext|>


<commit_before>(function(module, angular, undefined) {
"use strict";

module.provider('Raven', function() {
  var _development = null;

  this.development = function(config) {
    _development = config || _development;
    return this;
  }

  this.$get = ['$window', '$log', function($window, $log) {
    var service = {
      VERSION: $window.Raven.VERSION,
      TraceKit: $window.Raven.TraceKit,
      captureException: function captureException(exception, cause) {
        if (_development) {
          $log.error('Raven: Exception ', exception, cause);
        } else {
          $window.Raven.captureException(exception, cause);
        }
      },
      captureMessage: function captureMessage(message, data) {
        if (_development) {
          $log.error('Raven: Message ', message, data);
        } else {
          $window.Raven.captureMessage(message, data);
        }
      },
      context: function context(func) {
        try {
          func();
        } catch(event) {
          _captureException(event);
        }
      },
      setUser: function setUser(user) {
        if (_development) {
          $log.error('Raven: User ', user);
        } else {
          $window.Raven.setUser(user);
        }
      },
      lastException: function lastException() {
        if (_development) {
          $log.error('Raven: Last Exception');
        } else {
          $window.Raven.lastException();
        }
      },
      context: function(options, func, args) {
        var RavenService = this;

        if (isFunction(options)) {
          args = func || [];
          func = options;
          options = undefined;
        }

        return RavenService.wrap(options, func).apply(this, args);
      },
      }

    };

    return service;
  }]; // end $get
}); // end provider

module.factory('$exceptionHandler', ['Raven', function(Raven) {
  return function(exception, cause) {
    Raven.captureException(exception, cause);
  };
}]);

}(angular.module('ngRaven', []), angular));
<commit_msg>add raven wrap<commit_after>(function(module, angular, undefined) {
"use strict";

module.provider('Raven', function() {
  var _development = null;

  this.development = function(config) {
    _development = config || _development;
    return this;
  }

  this.$get = ['$window', '$log', function($window, $log) {
    var service = {
      VERSION: $window.Raven.VERSION,
      TraceKit: $window.Raven.TraceKit,
      captureException: function captureException(exception, cause) {
        if (_development) {
          $log.error('Raven: Exception ', exception, cause);
        } else {
          $window.Raven.captureException(exception, cause);
        }
      },
      captureMessage: function captureMessage(message, data) {
        if (_development) {
          $log.error('Raven: Message ', message, data);
        } else {
          $window.Raven.captureMessage(message, data);
        }
      },
      context: function context(func) {
        try {
          func();
        } catch(event) {
          _captureException(event);
        }
      },
      setUser: function setUser(user) {
        if (_development) {
          $log.error('Raven: User ', user);
        } else {
          $window.Raven.setUser(user);
        }
      },
      lastException: function lastException() {
        if (_development) {
          $log.error('Raven: Last Exception');
        } else {
          $window.Raven.lastException();
        }
      },
      context: function(options, func, args) {
        var RavenService = this;

        if (isFunction(options)) {
          args = func || [];
          func = options;
          options = undefined;
        }

        return RavenService.wrap(options, func).apply(this, args);
      },
      wrap: function(options, func) {
        var RavenService = this;

        if (isUndefined(func) && !isFunction(options)) {
          return options;
        }

        if (isFunction(options)) {
          func = options;
          options = undefined;
        }

        if (!isFunction(func)) {
          return func;
        }

        if (func.__raven__) {
          return func;
        }

        function wrapped() {
          var args = [], i = arguments.length;
          while(i--) args[i] = Raven.wrap(options, arguments[i]);
          try {
            return func.apply(this, args);
          } catch(e) {
            RavenService.captureException(e, options);
          }
        }

        for (var property in func) {
          if (func.hasOwnProperty(property)) {
            wrapped[property] = func[property];
          }
        }
        wrapped.__raven__ = true;
        return wrapped;
      }

    };

    return service;
  }]; // end $get
}); // end provider

module.factory('$exceptionHandler', ['Raven', function(Raven) {
  return function(exception, cause) {
    Raven.captureException(exception, cause);
  };
}]);

}(angular.module('ngRaven', []), angular));
<|endoftext|>


<commit_before><commit_msg>updates homepage tiles to top visited profiles over the last 30 days<commit_after><|endoftext|>