Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5e8de47a6e | |||
| 39465b38d9 | |||
| 47a1dc5843 | |||
| 00b173573d | |||
| e77ec978eb | |||
| 92ad098351 |
@@ -1,4 +1,4 @@
|
||||
DATABASE_URL="postgresql://momo_app:qlalfqjsgh11@121.156.99.3:5432/distribution"
|
||||
DATABASE_URL="postgresql://momo_app:qlalfqjsgh11@183.99.177.40:5432/distribution"
|
||||
NEXTAUTH_URL="http://localhost:3000"
|
||||
NEXTAUTH_SECRET="2b1f94cca798f49ff62822b01617503b019d118df9d249ee61f835a7dca1946e"
|
||||
NEXT_PUBLIC_APP_NAME="유통관리 ERP"
|
||||
@@ -17,3 +17,11 @@ SMTP_FROM=모모유통 <chpark@coa-soft.com>
|
||||
MOMO_BANK_ACCOUNT=기업은행 434-115361-01-016
|
||||
MOMO_PHONE=010-6624-5315
|
||||
DEPLOY_WEBHOOK_TOKEN=momo-deploy-2026-secure
|
||||
|
||||
# 카카오 OAuth (개발) — 카카오 디벨로퍼스에서 발급 후 채워넣기
|
||||
# https://developers.kakao.com/console/app → 앱 키 → REST API 키
|
||||
# 카카오 로그인 → 활성화 ON, Redirect URI 등록 필수
|
||||
# 동의항목: 이메일(필수 동의), 닉네임(기본)
|
||||
KAKAO_REST_API_KEY=1e7825e926c4e8de575ee73ecbd02398
|
||||
KAKAO_CLIENT_SECRET=jva60F8UfxZtDFIYqZsbECeHl8fcz6e6
|
||||
KAKAO_REDIRECT_URI=http://localhost:3000/api/auth/kakao/callback
|
||||
|
||||
@@ -17,10 +17,3 @@ SMTP_FROM=모모유통 <momo8443@daum.net>
|
||||
# ============ 거래명세표에 표시될 공급자 정보 ============
|
||||
MOMO_BANK_ACCOUNT=기업은행 434-115361-01-016
|
||||
MOMO_PHONE=010-6624-5315
|
||||
|
||||
# ============ 웹 푸시(PWA 알림) ============
|
||||
# 미설정 시 코드 하드코딩 기본 VAPID 키 사용. 운영에서 키를 교체하려면 아래 지정.
|
||||
# 생성: npx web-push generate-vapid-keys
|
||||
# VAPID_PUBLIC_KEY=__public__
|
||||
# VAPID_PRIVATE_KEY=__private__
|
||||
# VAPID_SUBJECT=mailto:admin@momotogether.com
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
name: Deploy momo-erp
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install sshpass
|
||||
run: |
|
||||
apt-get update -qq && apt-get install -y -qq sshpass openssh-client || \
|
||||
sudo apt-get update -qq && sudo apt-get install -y -qq sshpass openssh-client
|
||||
|
||||
- name: Deploy via SSH (password auth)
|
||||
run: |
|
||||
set +e # 배포 단계 실패해도 워크플로우 성공 처리 (실제 결과는 헬스체크가 판단)
|
||||
export SSHPASS='qlalfqjsgh11'
|
||||
mkdir -p ~/.ssh
|
||||
ssh-keyscan -H 183.99.177.40 >> ~/.ssh/known_hosts 2>/dev/null || true
|
||||
|
||||
sshpass -e ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
|
||||
chpark@183.99.177.40 'bash -s' <<'REMOTE_SCRIPT'
|
||||
set +e
|
||||
DEPLOY_DIR="$HOME/momo-erp/source"
|
||||
mkdir -p "$HOME/momo-erp"
|
||||
|
||||
if [ -d "$DEPLOY_DIR/.git" ]; then
|
||||
cd "$DEPLOY_DIR"
|
||||
git fetch origin
|
||||
git reset --hard origin/main
|
||||
else
|
||||
git clone https://git.junggomoa.com/chpark/distribution_erp.git "$DEPLOY_DIR"
|
||||
cd "$DEPLOY_DIR"
|
||||
fi
|
||||
|
||||
# .env.production 갱신 (SMTP/MOMO 포함)
|
||||
cat > .env.production <<'ENVEOF'
|
||||
DATABASE_URL=postgresql://momo_app:qlalfqjsgh11@183.99.177.40:5432/distribution
|
||||
NEXTAUTH_URL=https://momotogether.com
|
||||
NEXTAUTH_SECRET=2b1f94cca798f49ff62822b01617503b019d118df9d249ee61f835a7dca1946e
|
||||
NEXT_PUBLIC_APP_NAME=유통관리 ERP
|
||||
NEXT_PUBLIC_COMPANY_NAME=모모유통
|
||||
MASTER_PWD=qlalfqjsgh11
|
||||
AES_KEY=ILJIAESSECRETKEY
|
||||
FILE_STORAGE_PATH=/data_storage
|
||||
LOG_LEVEL=info
|
||||
SMTP_HOST=mail.coa-soft.com
|
||||
SMTP_PORT=465
|
||||
SMTP_USER=chpark@coa-soft.com
|
||||
SMTP_PASS=1321Qkrckd!!!!!!
|
||||
SMTP_FROM=모모유통 <chpark@coa-soft.com>
|
||||
MOMO_BANK_ACCOUNT=기업은행 434-115361-01-016
|
||||
MOMO_PHONE=010-6624-5315
|
||||
DEPLOY_WEBHOOK_TOKEN=momo-deploy-2026-secure
|
||||
ENVEOF
|
||||
|
||||
docker compose -f docker-compose.prod.yml up -d --build
|
||||
|
||||
# 마이그레이션 (idempotent)
|
||||
docker compose -f docker-compose.prod.yml exec -T momo-erp npm run migrate:momo || \
|
||||
echo "::warning::migration skipped"
|
||||
|
||||
docker compose -f docker-compose.prod.yml ps
|
||||
echo "✔ 배포 완료"
|
||||
REMOTE_SCRIPT
|
||||
|
||||
- name: Healthcheck (실제 배포 성공 판정)
|
||||
run: |
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
sleep 10
|
||||
CODE=$(curl -s -o /tmp/p.html -w "%{http_code}" -L https://momotogether.com/ || echo 000)
|
||||
HAS_NEW=$(grep -q "WORKFLOW\|매입 발주\|SCREEN PREVIEW" /tmp/p.html && echo yes || echo no)
|
||||
echo " ${i}/10: HTTP $CODE / 신버전=$HAS_NEW"
|
||||
if [ "$CODE" = "200" ] && [ "$HAS_NEW" = "yes" ]; then
|
||||
echo "::notice::✔ 운영 정상 + 신버전 코드 확인"
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
echo "::error::헬스체크 실패: 신버전 코드가 운영에 반영되지 않음"
|
||||
exit 1
|
||||
@@ -24,13 +24,6 @@
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# 안드로이드 서명 키/번들 — 절대 커밋 금지 (Play Store 서명 키 노출 = 앱 도용 위험)
|
||||
*.keystore
|
||||
*.jks
|
||||
*.aab
|
||||
*.apk
|
||||
signing-key-info.txt
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
@@ -49,11 +42,3 @@ yarn-error.log*
|
||||
next-env.d.ts
|
||||
|
||||
/src/generated/prisma
|
||||
|
||||
# Android TWA build artifacts / keystore (절대 커밋 금지)
|
||||
android/*.keystore
|
||||
android/*.jks
|
||||
android/*.aab
|
||||
android/*.apk
|
||||
android/app/
|
||||
android/.gradle/
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## 개요
|
||||
|
||||
`.gitea/workflows/deploy.yml` 워크플로가 `main` 브랜치 푸시 시 자동으로
|
||||
배포 서버(121.156.99.3)에 SSH 접속 → `docker compose up -d --build` 실행합니다.
|
||||
배포 서버(183.99.177.40)에 SSH 접속 → `docker compose up -d --build` 실행합니다.
|
||||
|
||||
## Gitea 시크릿 등록
|
||||
|
||||
@@ -11,10 +11,10 @@ Gitea 저장소 → **Settings → Actions → Secrets** 에 다음 시크릿을
|
||||
|
||||
| 시크릿 이름 | 값 (예시) |
|
||||
|-------------|----------|
|
||||
| `DEPLOY_HOST` | `121.156.99.3` |
|
||||
| `DEPLOY_HOST` | `183.99.177.40` |
|
||||
| `DEPLOY_USER` | `chpark` |
|
||||
| `DEPLOY_SSH_KEY` | SSH 개인키 전체 (BEGIN/END 포함) |
|
||||
| `DATABASE_URL` | `postgresql://momo_app:qlalfqjsgh11@121.156.99.3:5432/distribution` |
|
||||
| `DATABASE_URL` | `postgresql://postgres:qlalfqjsgh11@183.99.177.40:5432/distribution` |
|
||||
| `NEXTAUTH_URL` | `https://momotogether.com` |
|
||||
| `NEXTAUTH_SECRET` | 임의의 32바이트 hex (현재 .env.production 값 재사용 가능) |
|
||||
| `MASTER_PWD` | `qlalfqjsgh11` |
|
||||
@@ -26,7 +26,7 @@ Gitea 저장소 → **Settings → Actions → Secrets** 에 다음 시크릿을
|
||||
```bash
|
||||
ssh-keygen -t ed25519 -C "gitea-deploy" -f ~/.ssh/momo_deploy -N ""
|
||||
# 공개키를 배포 서버에 등록
|
||||
ssh-copy-id -i ~/.ssh/momo_deploy.pub chpark@121.156.99.3
|
||||
ssh-copy-id -i ~/.ssh/momo_deploy.pub chpark@183.99.177.40
|
||||
# 개인키를 Gitea Secret `DEPLOY_SSH_KEY` 에 붙여넣기
|
||||
cat ~/.ssh/momo_deploy
|
||||
```
|
||||
@@ -41,7 +41,7 @@ cat ~/.ssh/momo_deploy
|
||||
|
||||
긴급 시:
|
||||
```bash
|
||||
ssh chpark@121.156.99.3
|
||||
ssh chpark@183.99.177.40
|
||||
cd ~/momo-erp/source
|
||||
git pull
|
||||
docker compose -f docker-compose.prod.yml up -d --build
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
## 기술 스택
|
||||
- **Frontend**: Next.js 15 (App Router), React 19, TypeScript, Tailwind CSS
|
||||
- **Backend**: Next.js API Routes (Node.js)
|
||||
- **Database**: PostgreSQL (외부 공용 서버 `121.156.99.3:5432/distribution`, raw SQL via `pg`)
|
||||
- **Database**: PostgreSQL (외부 공용 서버 `211.115.91.141:11140/fito`, raw SQL via `pg`)
|
||||
- **인증**: JWT (jose) + Cookie 기반 세션
|
||||
- **상태관리**: Zustand
|
||||
- **UI**: SweetAlert2, Lucide Icons, Custom DataGrid (TanStack React Table)
|
||||
@@ -76,4 +76,4 @@ npm run dev # 개발 서버 (localhost:3000)
|
||||
|
||||
- Docker Compose dev/prod 분리
|
||||
- Traefik 리버스 프록시 + `fito.wace.me` 서브도메인
|
||||
- DB는 외부 `121.156.99.3:5432/distribution` 공유 (컨테이너 내부 DB 없음)
|
||||
- DB는 외부 `211.115.91.141:11140/fito` 공유 (컨테이너 내부 DB 없음)
|
||||
|
||||
@@ -26,16 +26,9 @@ ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ENV PORT=3000
|
||||
ENV HOSTNAME=0.0.0.0
|
||||
|
||||
# webhook 자기재배포에 필요한 CLI: git (소스 동기), docker + compose (이미지 빌드/swap)
|
||||
# docker socket 은 docker-compose.prod.yml 에서 host 의 /var/run/docker.sock 으로 마운트됨
|
||||
RUN apk add --no-cache git docker-cli docker-cli-compose
|
||||
|
||||
# 비루트 사용자 (보안)
|
||||
RUN addgroup --system --gid 1001 nodejs && \
|
||||
adduser --system --uid 1001 nextjs && \
|
||||
# docker socket 접근 권한: 운영 호스트 /var/run/docker.sock 의 GID(988) 와 동일한 그룹 생성 후 nextjs 가입
|
||||
addgroup -g 988 dockerhost && \
|
||||
addgroup nextjs dockerhost
|
||||
adduser --system --uid 1001 nextjs
|
||||
|
||||
# standalone 번들 복사
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
|
||||
@@ -1,320 +0,0 @@
|
||||
# 인프라 이관 가이드 (집 PC → IDC)
|
||||
|
||||
> 작성: 2026-05-12 / 대상 호스트: `chparkserver` (183.99.177.40)
|
||||
> 목적: 운영 중인 서비스 전부 IDC 서버로 옮길 때 필요한 정보와 절차 정리
|
||||
|
||||
---
|
||||
|
||||
## 1. 현재 호스트 사양 / 환경
|
||||
|
||||
| 항목 | 값 |
|
||||
|---|---|
|
||||
| Hostname | `chparkserver` |
|
||||
| OS | Ubuntu 24.04.4 LTS (kernel 6.8) |
|
||||
| Docker | 29.1.3 |
|
||||
| K3s | v1.34.6+k3s1 |
|
||||
| 디스크 | `/` 116G / `/data` 916G (사용 121G) |
|
||||
| 외부 IP | 183.99.177.40 |
|
||||
| 접속 | SSH (chpark@) |
|
||||
|
||||
**디스크 사용량 분포 (`/data`)**:
|
||||
```
|
||||
51G containerd (K3s container runtime)
|
||||
31G docker (docker engine data-root)
|
||||
56G opt (docker compose 운영 파일들)
|
||||
544M transfer
|
||||
490M dumps
|
||||
303M k3s
|
||||
90M mailu
|
||||
87M backups ← 이번 사고 대응으로 만든 백업
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 운영 중인 서비스 전체 목록
|
||||
|
||||
### 2.1 Docker Compose 기반 (직접 운영)
|
||||
|
||||
| Project | 경로 | 도메인/포트 | 비고 |
|
||||
|---|---|---|---|
|
||||
| **traefik** | `/data/opt/docker/traefik/` | 80, 443 | HTTPS reverse proxy (Let's Encrypt). 모든 도메인 입구 |
|
||||
| **mailufinal** | `/data/mailu/` | mail.coa-soft.com (25/110/143/465/587/993/995) | Mailu 메일 서버 9개 컨테이너 |
|
||||
| **nextcloudfinal** | `/home/chpark/nextcloud/` | cloud.junggomoa.com | Nextcloud + MariaDB 11.8 + Redis |
|
||||
| **gitea2** | `/data/opt/docker/gitea/` | git.junggomoa.com / 2222 (SSH) | Gitea + PostgreSQL |
|
||||
| **mattermost2** | `/data/opt/docker/mattermost/` | 8065 | Mattermost + PostgreSQL |
|
||||
| **registry2** | `/data/opt/docker/registry/` | localhost:5000 | Docker registry (K3s 가 image pull 용) |
|
||||
| **source** | `/home/chpark/momo-erp/source/` | momotogether.com | momo-erp |
|
||||
| **tradeing2** | `/home/chpark/tradeing/` | (도메인 확인) | Tradeing 서비스 + PostgreSQL |
|
||||
| **portainer** | `/data/opt/docker/portainer/` | 9000 (관리 UI) | Docker 관리 UI |
|
||||
|
||||
> ⚠️ **stopped 상태로 남은 옛 프로젝트**: `gitea`, `mailu`, `mattermost`, `nextcloud`, `registry`, `tradeing` — 이전 버전. **이관 시 무시**.
|
||||
|
||||
### 2.2 K3s 위에서 운영 (kubectl 로 관리)
|
||||
|
||||
| Namespace | 서비스 | 도메인 |
|
||||
|---|---|---|
|
||||
| `invyone` | frontend / backend-spring / backend-node | www.invyone.com / solution.invyone.com |
|
||||
| `invyone-homepage` | homepage | (invyone homepage) |
|
||||
| `insurance` | api / web / postgres-0 | (insurance 도메인) |
|
||||
| `kubernetes-dashboard` | dashboard / metrics-scraper | (관리용) |
|
||||
| `portainer` | portainer-agent | (관리용) |
|
||||
| `kube-system` | coredns / metrics-server / local-path-provisioner | (인프라) |
|
||||
|
||||
> K3s manifests: `/data/k8s-manifests/` 또는 Gitea 의 repo 확인.
|
||||
|
||||
---
|
||||
|
||||
## 3. 데이터 볼륨 (이관 시 반드시 옮길 것)
|
||||
|
||||
### 3.1 Docker Named Volumes
|
||||
```
|
||||
nextcloud_nextcloud_db ← Nextcloud DB (MariaDB 11.8)
|
||||
nextcloud_nextcloud_data ← Nextcloud 사용자 파일
|
||||
insurance_postgres_data ← Insurance K3s PostgreSQL
|
||||
insurance_uploads ← Insurance 업로드 파일
|
||||
invyone-db-data ← Invyone PostgreSQL
|
||||
source_momo_data_storage ← Momo ERP 데이터
|
||||
```
|
||||
호스트 경로: `/data/docker/volumes/<volume_name>/_data/`
|
||||
|
||||
### 3.2 Bind Mount 경로
|
||||
```
|
||||
/data/mailu/ ← Mailu compose + env + 인증서
|
||||
/mailu/ ← Mailu data (메일함 실제 저장 위치, /mailu/data)
|
||||
/data/opt/docker/ ← 각 서비스의 compose 디렉토리
|
||||
/home/chpark/nextcloud/ ← Nextcloud compose
|
||||
/home/chpark/momo-erp/ ← Momo ERP compose + source
|
||||
/home/chpark/tradeing/ ← Tradeing compose
|
||||
```
|
||||
|
||||
### 3.3 K3s/containerd
|
||||
```
|
||||
/data/containerd/ ← K3s container runtime data (이관 비추, K3s 새로 설치 + manifest 재배포 권장)
|
||||
/data/k3s/ ← K3s state
|
||||
/data/k8s-manifests/ ← K8s manifest 파일들 (직접 이관)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 외부 노출 포트 (방화벽 규칙)
|
||||
|
||||
| 포트 | 프로토콜 | 용도 |
|
||||
|---|---|---|
|
||||
| 80, 443 | TCP | Traefik (HTTPS 리버스 프록시) |
|
||||
| 25 | TCP | SMTP (메일 수신) |
|
||||
| 465 | TCP | SMTPS (메일 송신 TLS) |
|
||||
| 587 | TCP | SMTP Submission |
|
||||
| 993 | TCP | IMAPS |
|
||||
| 995 | TCP | POP3S |
|
||||
| 110, 143 | TCP | POP3/IMAP plain (보안상 disable 권장) |
|
||||
| 2222 | TCP | Gitea SSH |
|
||||
| 8065 | TCP | Mattermost |
|
||||
| 5432 | TCP | **⚠️ invyone-db PostgreSQL 외부 노출** — IDC 이관 시 내부 IP 만 허용하도록 변경 권장 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 운영 중 적용된 Hotfix 내역 (이관 시 그대로 가져가야 함)
|
||||
|
||||
이관 시 단순히 compose 파일만 복사하면 안 됨. 아래는 컨테이너/네트워크 quirk 대응으로 추가한 패치.
|
||||
|
||||
### 5.1 Mailu (`/data/mailu/docker-compose.yml`)
|
||||
- **admin / front / antispam** 의 `entrypoint` override:
|
||||
```yaml
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
echo "nameserver 127.0.0.11" > /etc/resolv.conf
|
||||
echo "nameserver 192.168.203.2" >> /etc/resolv.conf
|
||||
echo "search ." >> /etc/resolv.conf
|
||||
echo "options edns0 trust-ad ndots:0" >> /etc/resolv.conf
|
||||
exec /start.py
|
||||
```
|
||||
- **admin / front / antispam** 에 `extra_hosts` (mailu 내부 service IP 직접 박음):
|
||||
```yaml
|
||||
extra_hosts:
|
||||
- "redis:192.168.203.4"
|
||||
- "imap:192.168.203.9"
|
||||
- "smtp:192.168.203.6"
|
||||
- "antispam:192.168.203.8"
|
||||
- "webmail:192.168.203.10"
|
||||
- "front:192.168.203.3"
|
||||
- "resolver:192.168.203.2"
|
||||
```
|
||||
> 이유: docker user-defined bridge network 에서 admin 만 DNSSEC AD flag 강제. embedded DNS(127.0.0.11) 가 DNSSEC 안 함 → admin 시작 실패. mailu unbound resolver(192.168.203.2) 가 DNSSEC capable 이라 그쪽으로 박았고, internal service hostname 은 `extra_hosts` 로 박아 NXDOMAIN 방지.
|
||||
|
||||
- **resolver** service 의 `ipv4_address: 192.168.203.254` **제거됨** (자동 할당).
|
||||
> 이유: 192.168.203.254 IP 가 packet drop 되는 docker bridge quirk 발견. 자동 할당으로 .2 받음.
|
||||
|
||||
- **`/data/mailu/mailu.env`** 에 추가:
|
||||
```
|
||||
WEBROOT_REDIRECT=/webmail/
|
||||
```
|
||||
> 이유: 로그인 후 admin 계정이라 가끔 admin UI 로 redirect 됨. 항상 webmail 로 일관시킴.
|
||||
|
||||
### 5.2 Nextcloud (`/home/chpark/nextcloud/docker-compose.yml`)
|
||||
- DB 컨테이너 image: `mariadb:10.5` → **`mariadb:11.8`** (원본 데이터 버전 일치)
|
||||
- `command:` 라인 중복 제거 (이전엔 두 줄이라 첫 번째가 덮어써짐)
|
||||
- 백업 위치: `/data/backups/nextcloud_db_20260512_080401.tgz` (87MB)
|
||||
- 추가 mariadb-dump: `/data/backups/nc_db_*.sql`
|
||||
|
||||
### 5.3 Docker daemon (`/etc/docker/daemon.json`)
|
||||
- 사용자가 이전에 추가한 `"dns": ["8.8.8.8", "1.1.1.1"]` 가 모든 컨테이너 dns 옵션과 합쳐져 충돌. **이관 시 daemon.json 의 dns 키는 빼는 게 안전** (Mailu 가 의존하는 docker embedded DNS 만 사용하도록).
|
||||
|
||||
### 5.4 cron
|
||||
```
|
||||
*/5 * * * * /mailu/sync-certs.sh
|
||||
0 4 * * * /usr/bin/docker builder prune -af --filter until=72h
|
||||
5 4 * * * /usr/bin/docker image prune -af --filter until=168h
|
||||
```
|
||||
이관 시 root crontab 그대로 복사. `sync-certs.sh` 는 traefik 발급 인증서를 Mailu 형식으로 변환하는 스크립트.
|
||||
|
||||
---
|
||||
|
||||
## 6. 이관 절차 (체크리스트)
|
||||
|
||||
### Phase 1 — 신규 IDC 호스트 준비
|
||||
- [ ] Ubuntu 24.04 LTS 설치 (현재와 동일 버전 권장)
|
||||
- [ ] Docker 29.x + Docker Compose v2 설치
|
||||
- [ ] K3s 설치 (`curl -sfL https://get.k3s.io | sh -`)
|
||||
- [ ] 디스크 파티션: `/` (시스템) + `/data` (운영 데이터, **916G 이상 권장**)
|
||||
- [ ] systemd: `docker`, `k3s`, `containerd` 자동 시작 enable
|
||||
|
||||
### Phase 2 — 데이터 백업 (현재 호스트)
|
||||
```bash
|
||||
# 1. 모든 docker compose 정지 (downtime 시작)
|
||||
for proj in mailufinal nextcloudfinal gitea2 mattermost2 registry2 source tradeing2 traefik portainer; do
|
||||
docker compose -p $proj down
|
||||
done
|
||||
|
||||
# 2. K3s 도 정지 (시작 시 컨테이너 자동 stop)
|
||||
sudo systemctl stop k3s
|
||||
|
||||
# 3. volume + 운영 디렉토리 통째로 백업
|
||||
sudo tar -czf /data/backups/all_volumes_$(date +%Y%m%d).tgz \
|
||||
/data/docker/volumes \
|
||||
/data/mailu \
|
||||
/data/opt \
|
||||
/data/k8s-manifests \
|
||||
/home/chpark/nextcloud \
|
||||
/home/chpark/momo-erp \
|
||||
/home/chpark/tradeing \
|
||||
/mailu
|
||||
|
||||
# 4. crontab 백업
|
||||
sudo crontab -l > /data/backups/root_crontab.txt
|
||||
|
||||
# 5. daemon.json 백업
|
||||
sudo cp /etc/docker/daemon.json /data/backups/daemon.json
|
||||
```
|
||||
|
||||
### Phase 3 — IDC 로 전송
|
||||
```bash
|
||||
# rsync 권장 (재시도 가능)
|
||||
rsync -avzP --partial --append-verify \
|
||||
/data/backups/all_volumes_*.tgz \
|
||||
user@idc-host:/data/backups/
|
||||
```
|
||||
|
||||
### Phase 4 — IDC 에서 복원
|
||||
```bash
|
||||
cd /
|
||||
sudo tar -xzf /data/backups/all_volumes_*.tgz
|
||||
|
||||
# crontab 복원
|
||||
sudo crontab /data/backups/root_crontab.txt
|
||||
|
||||
# 각 서비스 기동
|
||||
for path in /data/opt/docker/traefik /data/mailu /home/chpark/nextcloud /data/opt/docker/gitea /data/opt/docker/mattermost /data/opt/docker/registry /home/chpark/momo-erp/source /home/chpark/tradeing /data/opt/docker/portainer; do
|
||||
cd "$path" && docker compose up -d
|
||||
done
|
||||
|
||||
# K3s manifest 재적용
|
||||
kubectl apply -f /data/k8s-manifests/
|
||||
```
|
||||
|
||||
### Phase 5 — DNS 변경
|
||||
- 도메인 A 레코드를 새 IDC IP 로 변경 (TTL 짧게 미리 줄여놓으면 좋음)
|
||||
- `mail.coa-soft.com`
|
||||
- `cloud.junggomoa.com`
|
||||
- `git.junggomoa.com`
|
||||
- `momotogether.com`
|
||||
- `www.invyone.com` / `solution.invyone.com`
|
||||
- 기타
|
||||
- Mailu MX 레코드도 새 IP 로
|
||||
|
||||
### Phase 6 — 검증
|
||||
```bash
|
||||
# 컨테이너 상태
|
||||
docker ps --filter "name=mailufinal\|nextcloud\|traefik\|gitea" --format "{{.Names}} {{.Status}}"
|
||||
|
||||
# HTTP 확인
|
||||
for url in https://mail.coa-soft.com/ https://cloud.junggomoa.com/ https://git.junggomoa.com/ https://momotogether.com/; do
|
||||
curl -ksS -o /dev/null -w "$url -> %{http_code}\n" "$url"
|
||||
done
|
||||
|
||||
# SMTP banner
|
||||
echo "QUIT" | nc -w 3 새IDC_IP 25
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 이관 후 정리할 것 (선택)
|
||||
|
||||
- [ ] 옛 compose project (gitea/mailu/mattermost/nextcloud/registry/tradeing) 삭제 — `docker compose -p <이름> down --remove-orphans`
|
||||
- [ ] dangling image 정리 — 이미 cron 으로 자동화됨
|
||||
- [ ] `/data/backups/` 의 오래된 tarball 정리
|
||||
- [ ] `daemon.json` 의 `"dns"` 키 제거 (Mailu admin DNS 충돌 방지)
|
||||
- [ ] Mailu admin/front/antispam 의 entrypoint override 가 더 이상 필요한지 재확인 (IDC 의 docker network 환경에서는 안 필요할 수도)
|
||||
|
||||
---
|
||||
|
||||
## 8. 핵심 비밀번호 / 인증 정보
|
||||
|
||||
> ⚠️ 이 문서에는 비밀번호 직접 안 박는다. 아래 위치에서 확인:
|
||||
|
||||
- Mailu 계정: `/data/mailu/mailu.env` (SECRET_KEY, DB_PW 등)
|
||||
- Nextcloud DB: `/home/chpark/nextcloud/docker-compose.yml` (MYSQL_ROOT_PASSWORD)
|
||||
- 각 서비스 admin 계정: 해당 compose 의 environment 또는 env_file
|
||||
- Traefik basic auth: `/data/opt/docker/traefik/` 안 설정
|
||||
- SSH 비밀번호: 운영 PC 관리자가 보관
|
||||
|
||||
이관 시 새 IDC 에서 비밀번호 **모두 회전(rotation) 권장**.
|
||||
|
||||
---
|
||||
|
||||
## 9. 알려진 이슈 / 주의사항
|
||||
|
||||
1. **Mailu resolver 192.168.203.254 IP 회피**: 이번 사고에서 .254 IP 가 packet drop 되는 docker bridge quirk 발견. IDC 에서도 발생할 수 있으니 resolver 는 자동 할당으로 두는 게 안전.
|
||||
|
||||
2. **MariaDB 버전 일치**: Nextcloud DB 는 11.8.x. 이관 시 절대 다운그레이드 금지 (이번에 10.5 로 갔다가 plugin load fail 로 사고남).
|
||||
|
||||
3. **K3s 와 docker 의 iptables/nftables 공존**: K3s 의 kube-router 가 FORWARD chain 에 끼어들어서 docker bridge 통신에 영향을 줄 수 있음. mailu 의 192.168.203.0/24 subnet 이 다른 서비스의 K3s pod CIDR 와 안 겹치는지 확인.
|
||||
|
||||
4. **메일 데이터 위치**: 사용자 메일함 파일은 `/mailu/data/` (호스트 root). `/data/mailu/` 와 다른 위치. 이관 시 둘 다 옮겨야 함.
|
||||
|
||||
5. **인증서**: Let's Encrypt 인증서는 Traefik 이 자동 발급. 이관 후 도메인 가리키면 자동 재발급. 단 rate limit 주의 (도메인당 주 5건).
|
||||
|
||||
---
|
||||
|
||||
## 10. 빠른 참조 — 자주 쓰는 명령
|
||||
|
||||
```bash
|
||||
# 전체 컨테이너 상태
|
||||
docker ps --format "{{.Names}}\t{{.Status}}" | sort
|
||||
|
||||
# 특정 서비스 로그
|
||||
docker logs --tail 50 mailufinal-admin-1
|
||||
|
||||
# 한 서비스만 재기동
|
||||
cd /data/mailu && docker compose up -d --force-recreate admin
|
||||
|
||||
# Mailu 계정 추가 (admin 컨테이너 안)
|
||||
docker exec mailufinal-admin-1 flask mailu user $USER $DOMAIN $PASSWORD
|
||||
|
||||
# Nextcloud occ
|
||||
docker exec -u www-data nextcloud-app-new php occ status
|
||||
|
||||
# K3s pod 상태
|
||||
kubectl get pods -A
|
||||
```
|
||||
@@ -1,178 +1,70 @@
|
||||
# 모모유통 ERP (Distribution ERP)
|
||||
# FITO — (주)피토 PLM (Next.js)
|
||||
|
||||
식자재/도소매 **유통·물류 업무 통합 관리 시스템**.
|
||||
거래처가 발주를 넣고, 본사가 출고·정산하고, 매입·입고·재고·세금계산서까지 한 화면에서 처리한다.
|
||||
기존 Java/Spring MVC + JSP + MyBatis 기반 FITO PLM을 Next.js 15 + Node.js로 컨버전한 시스템.
|
||||
|
||||
- 운영 도메인: **https://momotogether.com**
|
||||
- Android 앱: **`com.momotogether.app`** (TWA, Play 스토어 등록용 AAB / 사이드로드 APK)
|
||||
- 코드 저장소(원격): `git.junggomoa.com/chpark/distribution_erp`
|
||||
- 사용자: (주)모모유통 본사·김포지사 + 계약 거래처 전용 — 일반 소비자용 아님
|
||||
- 원본: [/Users/jhj/FITO](../FITO) (Java 7 + Spring 3.2.4 + MyBatis 3.2.3 + JSP)
|
||||
- DB: 외부 PostgreSQL `211.115.91.141:11140/fito` (기존 스키마 그대로 사용)
|
||||
- 이전 이력: `woosung-nextjs`에서 피벗. 스냅샷 태그 `woosung-v1-snapshot`.
|
||||
|
||||
---
|
||||
|
||||
## 주요 기능
|
||||
|
||||
### 거래처(구매자) 화면
|
||||
- **출고 요청** — 재고 있는 품목 선택 → 장바구니 → 발주 요청. 택배전용·용차비·환불 라인 자동/수동 추가. 상시판매·기간한정 품목 분리.
|
||||
- **내 출고 이력** — 본인 발주 진행상태 추적.
|
||||
- **푸시 알림 토글** — PWA 설치 후 새 상품 등록 시 알림 수신.
|
||||
- **회원정보 수정** — 본인 정보·기준 명세표 변경.
|
||||
|
||||
### 본사/지사 운영
|
||||
- **출고 처리** — 발주 검토 → 거래명세표 자동 생성(이미지/엑셀/메일 발송) → 재고 자동 차감.
|
||||
- **입금 관리** — 출고 후 미수금 추적·입금 등록.
|
||||
- **계산서·전자세금계산서** — 과세/면세 자동 분리. 국세청 ESERO 연동 어댑터(현재는 DB 기록).
|
||||
- **매입 발주** — 공급업체별 발주서 작성·메일 발송. 발주지사(HQ/KIMPO) 선택.
|
||||
- **매입 입금관리** — 진행상태와 결재상태(입금완료/미입금)를 **분리 관리**. 부분입고 시 입고금액 기준 입금 처리.
|
||||
- **입고 처리** — 정상/불량 분리 입고, 유통기한·물류팀 최종완료자 체크리스트.
|
||||
- **재고 관리** — 창고별 실시간 재고, 입출고 이력, 창고 간 이동, 유통기한 임박 알림.
|
||||
|
||||
### 마스터·통계·관리
|
||||
- **품목 마스터** — 가격·원가·과세/면세·택배전용·1회 발주한도·판매기간(또는 상시판매) + 일괄 적용.
|
||||
- **공급업체/거래처/창고/계산서 기준정보** 관리.
|
||||
- **푸시알림 게시판** — 관리자가 공지(이미지+본문)를 작성하고 선택한 구독자에게 푸시 발송. 사용자가 알림 탭하면 공지 페이지로 이동.
|
||||
- **통계** — 대시보드, 월간/일자별 매출, 원가·마진, 거래처×일자 매출, 지사 수수료, 창고 이동 통계.
|
||||
|
||||
---
|
||||
|
||||
## 기술 스택
|
||||
|
||||
- **풀스택 단일 Next.js 프로젝트** — 프론트(React 19, App Router) + 백엔드(API Routes, Node.js) 한 저장소.
|
||||
- **TypeScript** strict mode, **Tailwind CSS**.
|
||||
- **DB**: 외부 PostgreSQL `121.156.99.3:5432/distribution` — raw SQL(`pg`).
|
||||
- **인증**: JWT(jose) + HTTP Cookie 세션 + AES-128-ECB(비밀번호).
|
||||
- **PWA**: `manifest.json` + Service Worker(`public/sw.js`) — 푸시 핸들러·알림 위임(badge·icon).
|
||||
- **푸시**: `web-push`(VAPID) — `momo_push_subscriptions` 에 endpoint 저장, 발송은 `lib/push.ts`.
|
||||
- **거래명세표 캡처**: `html-to-image` (이미지 공유/저장).
|
||||
- **상태관리**: Zustand (auth/menu/theme).
|
||||
|
||||
---
|
||||
|
||||
## 디렉토리 구조
|
||||
|
||||
```
|
||||
src/
|
||||
├── app/
|
||||
│ ├── (auth)/login 로그인
|
||||
│ ├── (main)/
|
||||
│ │ ├── m/orders/new 거래처 — 출고요청
|
||||
│ │ ├── m/orders 거래처 — 내 출고이력
|
||||
│ │ ├── m/notices/[id] 공지 도달 페이지 (푸시 클릭 시)
|
||||
│ │ ├── m/admin/orders 출고 처리
|
||||
│ │ ├── m/admin/payments 입금 관리
|
||||
│ │ ├── m/admin/invoices 계산서 발행
|
||||
│ │ ├── m/admin/einvoices 전자세금계산서
|
||||
│ │ ├── m/admin/procurements매입 발주서
|
||||
│ │ ├── m/admin/proc-payments 매입 입금관리
|
||||
│ │ ├── m/admin/inbounds 입고 처리
|
||||
│ │ ├── m/admin/inventory 재고 관리
|
||||
│ │ ├── m/admin/items 품목 마스터
|
||||
│ │ ├── m/admin/notices 푸시알림 게시판
|
||||
│ │ ├── m/admin/vendors 공급업체 관리
|
||||
│ │ ├── m/admin/warehouses 창고 관리
|
||||
│ │ ├── m/admin/statistics 통계 대시보드
|
||||
│ │ └── profile 회원정보 수정
|
||||
│ └── api/m/ 업무 API (orders/items/inbounds/push/notices …)
|
||||
├── lib/
|
||||
│ ├── db.ts PostgreSQL Pool (queryRows/queryOne/execute)
|
||||
│ ├── auth.ts 인증 + 세션
|
||||
│ ├── push.ts web-push 발송 + 구독 관리
|
||||
│ ├── notices.ts 공지 테이블 자동 생성
|
||||
│ ├── momo-proc.ts 매입 진행/결재 분리 마이그레이션
|
||||
│ └── capture-share.ts 이미지 캡처/공유
|
||||
├── components/
|
||||
│ ├── layout/ Header / Sidebar
|
||||
│ ├── grid/ DataGrid (TanStack Table)
|
||||
│ ├── ui/ 버튼/입력/SearchableSelect 등
|
||||
│ └── push-optin.tsx 푸시 알림 켜기/끄기 토글 (localStorage 영속)
|
||||
└── store/ Zustand (auth/menu/theme)
|
||||
|
||||
public/
|
||||
├── sw.js Service Worker — fetch 캐시 + push/notificationclick
|
||||
├── manifest.json PWA 매니페스트
|
||||
├── icon-{192,512}.png PWA 아이콘 (모모 로고)
|
||||
├── badge-96.png 알림 상태바 단색 배지
|
||||
└── .well-known/assetlinks.json TWA Digital Asset Links
|
||||
|
||||
android/
|
||||
├── twa-manifest.json Bubblewrap TWA 빌드 설정 (notification delegation ON)
|
||||
└── README.md APK/AAB 빌드 가이드 (PWABuilder / Bubblewrap)
|
||||
```
|
||||
|
||||
각 디렉토리별 상세는 `*/CLAUDE.md` 참고.
|
||||
|
||||
---
|
||||
|
||||
## 로컬 개발
|
||||
## 개발 시작
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev # http://localhost:3000
|
||||
npm run build # 운영 빌드 검증
|
||||
npm run lint
|
||||
npm run dev # http://localhost:3000
|
||||
```
|
||||
|
||||
### 환경변수 (`.env.development`)
|
||||
## 환경변수
|
||||
|
||||
| 키 | 설명 |
|
||||
|---|---|
|
||||
| `DATABASE_URL` | PostgreSQL 접속 (예: `postgresql://momo_app:****@121.156.99.3:5432/distribution`) |
|
||||
| `NEXTAUTH_URL` | 로컬: `http://localhost:3000` |
|
||||
| `NEXTAUTH_SECRET` | JWT 서명 시크릿 |
|
||||
| `AES_KEY` | 16바이트 — 비밀번호 AES 키 (기존 데이터 호환 필요) |
|
||||
| `MASTER_PWD` | 마스터 비밀번호 (개발 편의) |
|
||||
| `SMTP_HOST/USER/PASS/FROM` | 거래명세표·계산서 메일 발송 |
|
||||
| `MOMO_BANK_ACCOUNT`, `MOMO_PHONE` | 거래명세표 공급자 정보 (기준명세표 미설정 폴백) |
|
||||
| `VAPID_PUBLIC_KEY` / `VAPID_PRIVATE_KEY` | (선택) 웹푸시 VAPID — 미설정 시 `lib/push.ts` 의 기본키 사용 |
|
||||
`.env.development`의 DB 접속 정보를 확인. 필수 키:
|
||||
|
||||
`.env.momo.example` 참고.
|
||||
- `DATABASE_URL` — 외부 PostgreSQL 접속
|
||||
- `NEXTAUTH_SECRET` — JWT 서명 키
|
||||
- `MASTER_PWD` — 마스터 비밀번호 (개발 편의용)
|
||||
- `AES_KEY` — 비밀번호 AES 암호화 키 (기존 Java 호환)
|
||||
|
||||
---
|
||||
## 배포 표준
|
||||
|
||||
## 배포 — Gitea Actions 자동 배포
|
||||
- Docker Compose (dev/prod 분리) — 기존 FITO(Java) 배포환경 재사용
|
||||
- Traefik 리버스 프록시 + `fito.wace.me` 도메인 (entrypoints: web, websecure / certresolver: le)
|
||||
- 외부 네트워크 `toktork_server_default`
|
||||
- DB는 외부 서버 공유 (`211.115.91.141:11140/fito`) — 컨테이너 내부 DB 없음
|
||||
|
||||
`main` 브랜치에 push 하면 [`.gitea/workflows/deploy.yml`](.gitea/workflows/deploy.yml) 이 자동 실행되어 운영 서버에서 `git pull → docker compose build → up -d` 까지 수행.
|
||||
### `start.sh` 배포 스크립트 (권장)
|
||||
|
||||
- 운영 서버: `121.156.99.3` (SSH, chpark)
|
||||
- Compose 파일: [`docker-compose.prod.yml`](docker-compose.prod.yml)
|
||||
- 컨테이너명: `momo-erp` / 이미지: `momo-erp:latest`
|
||||
- 리버스 프록시: Traefik (`traefik-net` 외부 네트워크, Let's Encrypt 자동발급)
|
||||
- 호스트: `momotogether.com`, `www.momotogether.com`
|
||||
- 영구 스토리지: named volume `momo_data_storage` ↔ `/data_storage` (업로드 이미지)
|
||||
- DB: 외부 공유 — 컨테이너 내부 DB 없음
|
||||
```bash
|
||||
# 첫 배포 (서버에서)
|
||||
cp .env.production.example .env.production
|
||||
vi .env.production # DATABASE_URL, NEXTAUTH_SECRET, AES_KEY 등 입력
|
||||
|
||||
> ⚠️ **수동 SSH 빌드 금지** — 자동 워크플로우와 충돌. 배포 검증은 `build-sha.txt` 또는 `docker logs momo-erp` 로 확인.
|
||||
./start.sh prod # git pull → build → 기동 → Traefik 라우팅 확인
|
||||
|
||||
---
|
||||
# 이후 배포 (git commit 후)
|
||||
./start.sh prod # 자동 git pull + 재빌드
|
||||
|
||||
## Android 앱 (TWA)
|
||||
# 기타 운영
|
||||
./start.sh logs prod # 실시간 로그
|
||||
./start.sh restart prod # 재시작 (git pull 포함)
|
||||
./start.sh stop prod # 중지
|
||||
./start.sh status prod # 컨테이너 상태
|
||||
./start.sh build prod # no-cache 재빌드
|
||||
./start.sh clean prod # 전체 삭제 (확인 필요)
|
||||
```
|
||||
|
||||
`com.momotogether.app` — `momotogether.com` 을 감싸는 Trusted Web Activity.
|
||||
스크립트는 start.sh 자체가 업데이트되면 새 버전으로 **자동 재실행**하므로 안전합니다.
|
||||
|
||||
- **알림 위임(notification delegation) ON** — 웹 푸시가 "삼성 인터넷" 등 브라우저가 아니라 **모모유통 앱 이름·아이콘**으로 표시됨.
|
||||
- **AAB**: Play 스토어 업로드용
|
||||
- **APK**: 사이드로드(직접 설치) 테스트용
|
||||
- 빌드 가이드: [`android/README.md`](android/README.md) (PWABuilder 또는 Bubblewrap)
|
||||
- ⚠️ 기존 서명키 재사용 필수 — 키가 바뀌면 `assetlinks.json` 지문이 안 맞아 위임 깨짐.
|
||||
### 로컬 개발
|
||||
|
||||
서비스워커 갱신 / 페이지 콘텐츠 변경은 **APK 재빌드 불필요** — 서버 배포만으로 앱에도 반영됨.
|
||||
```bash
|
||||
./start.sh # docker 기반 (localhost:3643, hot reload)
|
||||
npm run dev # docker 없이 Node 직접 (localhost:3000)
|
||||
```
|
||||
|
||||
---
|
||||
### 인프라 정보
|
||||
|
||||
## 코딩 컨벤션
|
||||
- 컨테이너명: `plm-fito-next` (prod) / `plm-fito-next-dev` (dev)
|
||||
- 도메인: `https://fito.wace.me`
|
||||
- 내부 포트: 3000 (Traefik이 외부 80/443 → 3000)
|
||||
- 파일 저장: 호스트 `./data_storage` (레포 상대경로) ↔ 컨테이너 `/data_storage`
|
||||
- 이미지: Next.js `output: "standalone"` 기반 multi-stage build
|
||||
|
||||
상세 규칙은 [`.claude/rules/`](.claude/rules/) 와 디렉토리별 `CLAUDE.md` 참고.
|
||||
|
||||
- **SQL alias 대문자 유지**: `SELECT col AS "OBJID"` (큰따옴표 필수, 없으면 PG 가 소문자 반환)
|
||||
- **삭제 플래그**: `COALESCE(is_del,'N') != 'Y'`
|
||||
- **objid 타입 변환**: `objid::text AS "OBJID"`
|
||||
- **API 응답**: 목록 `{ RESULTLIST, TOTAL_CNT }`, 단건 `{ success, data }`, 저장 `{ success, objId? }`, 오류 `{ success:false, message }` + 적절한 status code
|
||||
- **인증 가드**: 모든 API 라우트 첫 줄에 `getSession()` / `requireMomoAdmin()` / `requireMomoUser()`
|
||||
- **신규 컬럼**: `ensureColumns` 패턴으로 라우트 첫 호출 시 자동 ALTER (운영 무중단)
|
||||
- **푸시 알림 대상**: 일반 발송은 모든 구독자 / 거래처 전용은 `sendPush(payload, undefined, { generalOnly: true })`
|
||||
|
||||
---
|
||||
|
||||
## 라이선스
|
||||
|
||||
내부용. 외부 배포·재사용 금지.
|
||||
상세 구성은 [CLAUDE.md](CLAUDE.md) 참고.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Class-Path:
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="ko" xml:lang="ko">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>네이버 :: Smart Editor 2 ™</title>
|
||||
<script type="text/javascript" src="./js/HuskyEZCreator.js" charset="utf-8"></script>
|
||||
</head>
|
||||
<body>
|
||||
<form action="sample.php" method="post">
|
||||
<textarea name="ir1" id="ir1" rows="10" cols="100" style="width:766px; height:412px; display:none;"></textarea>
|
||||
<!--textarea name="ir1" id="ir1" rows="10" cols="100" style="width:100%; height:412px; min-width:610px; display:none;"></textarea-->
|
||||
<p>
|
||||
<input type="button" onclick="pasteHTML();" value="본문에 내용 넣기" />
|
||||
<input type="button" onclick="showHTML();" value="본문 내용 가져오기" />
|
||||
<input type="button" onclick="submitContents(this);" value="서버로 내용 전송" />
|
||||
<input type="button" onclick="setDefaultFont();" value="기본 폰트 지정하기 (궁서_24)" />
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<script type="text/javascript">
|
||||
var oEditors = [];
|
||||
|
||||
// 추가 글꼴 목록
|
||||
//var aAdditionalFontSet = [["MS UI Gothic", "MS UI Gothic"], ["Comic Sans MS", "Comic Sans MS"],["TEST","TEST"]];
|
||||
|
||||
nhn.husky.EZCreator.createInIFrame({
|
||||
oAppRef: oEditors,
|
||||
elPlaceHolder: "ir1",
|
||||
sSkinURI: "SmartEditor2Skin.html",
|
||||
htParams : {
|
||||
bUseToolbar : true, // 툴바 사용 여부 (true:사용/ false:사용하지 않음)
|
||||
bUseVerticalResizer : true, // 입력창 크기 조절바 사용 여부 (true:사용/ false:사용하지 않음)
|
||||
bUseModeChanger : true, // 모드 탭(Editor | HTML | TEXT) 사용 여부 (true:사용/ false:사용하지 않음)
|
||||
//aAdditionalFontList : aAdditionalFontSet, // 추가 글꼴 목록
|
||||
fOnBeforeUnload : function(){
|
||||
//alert("완료!");
|
||||
}
|
||||
}, //boolean
|
||||
fOnAppLoad : function(){
|
||||
//예제 코드
|
||||
//oEditors.getById["ir1"].exec("PASTE_HTML", ["로딩이 완료된 후에 본문에 삽입되는 text입니다."]);
|
||||
},
|
||||
fCreator: "createSEditor2"
|
||||
});
|
||||
|
||||
function pasteHTML() {
|
||||
var sHTML = "<span style='color:#FF0000;'>이미지도 같은 방식으로 삽입합니다.<\/span>";
|
||||
oEditors.getById["ir1"].exec("PASTE_HTML", [sHTML]);
|
||||
}
|
||||
|
||||
function showHTML() {
|
||||
var sHTML = oEditors.getById["ir1"].getIR();
|
||||
alert(sHTML);
|
||||
}
|
||||
|
||||
function submitContents(elClickedObj) {
|
||||
oEditors.getById["ir1"].exec("UPDATE_CONTENTS_FIELD", []); // 에디터의 내용이 textarea에 적용됩니다.
|
||||
|
||||
// 에디터의 내용에 대한 값 검증은 이곳에서 document.getElementById("ir1").value를 이용해서 처리하면 됩니다.
|
||||
|
||||
try {
|
||||
elClickedObj.form.submit();
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
function setDefaultFont() {
|
||||
var sDefaultFont = '궁서';
|
||||
var nFontSize = 24;
|
||||
oEditors.getById["ir1"].setDefaultFont(sDefaultFont, nFontSize);
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,175 @@
|
||||
@charset "UTF-8";
|
||||
/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */
|
||||
/* COMMON */
|
||||
body,#smart_editor2,#smart_editor2 p,#smart_editor2 h1,#smart_editor2 h2,#smart_editor2 h3,#smart_editor2 h4,#smart_editor2 h5,#smart_editor2 h6,#smart_editor2 ul,#smart_editor2 ol,#smart_editor2 li,#smart_editor2 dl,#smart_editor2 dt,#smart_editor2 dd,#smart_editor2 table,#smart_editor2 th,#smart_editor2 td,#smart_editor2 form,#smart_editor2 fieldset,#smart_editor2 legend,#smart_editor2 input,#smart_editor2 textarea,#smart_editor2 button,#smart_editor2 select{margin:0;padding:0}
|
||||
#smart_editor2,#smart_editor2 h1,#smart_editor2 h2,#smart_editor2 h3,#smart_editor2 h4,#smart_editor2 h5,#smart_editor2 h6,#smart_editor2 input,#smart_editor2 textarea,#smart_editor2 select,#smart_editor2 table,#smart_editor2 button{font-family:'돋움',Dotum,Helvetica,sans-serif;font-size:12px;color:#666}
|
||||
#smart_editor2 span,#smart_editor2 em{font-size:12px}
|
||||
#smart_editor2 em,#smart_editor2 address{font-style:normal}
|
||||
#smart_editor2 img,#smart_editor2 fieldset{border:0}
|
||||
#smart_editor2 hr{display:none}
|
||||
#smart_editor2 ol,#smart_editor2 ul{list-style:none}
|
||||
#smart_editor2 button{border:0;background:none;font-size:11px;vertical-align:top;cursor:pointer}
|
||||
#smart_editor2 button span,#smart_editor2 button em{visibility:hidden;overflow:hidden;position:absolute;top:0;font-size:0;line-height:0}
|
||||
#smart_editor2 legend,#smart_editor2 .blind{visibility:hidden;overflow:hidden;position:absolute;width:0;height:0;font-size:0;line-height:0}
|
||||
#smart_editor2 .input_ty1{height:14px;margin:0;padding:4px 2px 0 4px;border:1px solid #c7c7c7;font-size:11px;color:#666}
|
||||
#smart_editor2 a:link,#smart_editor2 a:visited,#smart_editor2 a:active,#smart_editor2 a:focus{color:#666;text-decoration:none}
|
||||
#smart_editor2 a:hover{color:#666;text-decoration:underline}
|
||||
/* LAYOUT */
|
||||
#smart_editor2 .se2_header{margin:10px 0 29px 0}
|
||||
#smart_editor2 .se2_bi{float:left;width:93px;height:20px;margin:0;padding:0;background:url("../img/ko_KR/btn_set.png?130306") -343px -358px no-repeat;font-size:0;line-height:0;text-indent:-10000px;vertical-align:middle}
|
||||
#smart_editor2 .se2_allhelp{display:inline-block;width:18px;height:18px;padding:0;background:url("../img/ko_KR/btn_set.png?130306") -437px -358px no-repeat;font-size:0;line-height:0;text-indent:-10000px;vertical-align:middle}
|
||||
#smart_editor2 #smart_editor2_content{border:1px solid #b5b5b5}
|
||||
#smart_editor2 .se2_tool{overflow:visible;position:relative;z-index:25}
|
||||
/* EDITINGAREA */
|
||||
#smart_editor2 .se2_input_area{position:relative;z-index:22;height:400px;margin:0;padding:0;*zoom:1}
|
||||
#smart_editor2 .se2_input_wysiwyg,#smart_editor2 .se2_input_syntax{display:block;overflow:auto;width:100%;height:100%;margin:0;*margin:-1px 0 0 0;border:0}
|
||||
/* EDITINGMODE */
|
||||
#smart_editor2 .se2_conversion_mode{position:relative;height:15px;padding-top:1px;border-top:1px solid #b5b5b5;background:url("../img/icon_set.gif") 0 -896px repeat-x}
|
||||
#smart_editor2 .se2_inputarea_controller{display:block;clear:both;position:relative;width:100%;height:15px;text-align:center;cursor:n-resize}
|
||||
#smart_editor2 .se2_inputarea_controller span,#smart_editor2 .controller_on span{background:url("../img/ico_extend.png") no-repeat}
|
||||
#smart_editor2 .se2_inputarea_controller span{position:static;display:inline-block;visibility:visible;overflow:hidden;height:15px;padding-left:11px;background-position:0 2px;color:#888;font-size:11px;letter-spacing:-1px;line-height:16px;white-space:nowrap}
|
||||
* + html #smart_editor2 .se2_inputarea_controller span{line-height:14px}
|
||||
#smart_editor2 .controller_on span{background-position:0 -21px;color:#249c04}
|
||||
#smart_editor2 .ly_controller{display:block;position:absolute;bottom:2px;left:50%;width:287px;margin-left:-148px;padding:8px 0 7px 9px;border:1px solid #827f7c;background:#fffdef}
|
||||
#smart_editor2 .ly_controller p{color:#666;font-size:11px;letter-spacing:-1px;line-height:11px}
|
||||
#smart_editor2 .ly_controller .bt_clse,#smart_editor2 .ly_controller .ic_arr{position:absolute;background:url("../img/ico_extend.png") no-repeat}
|
||||
#smart_editor2 .ly_controller .bt_clse{top:5px;right:4px;width:14px;height:15px;background-position:1px -43px}
|
||||
#smart_editor2 .ly_controller .ic_arr{top:25px;left:50%;width:10px;height:6px;margin-left:-5px;background-position:0 -65px}
|
||||
#smart_editor2 .se2_converter{float:left;position:absolute;top:-1px;right:3px;z-index:20}
|
||||
#smart_editor2 .se2_converter li{float:left}
|
||||
#smart_editor2 .se2_converter .se2_to_editor{width:59px;height:15px;background:url("../img/ko_KR/btn_set.png?130306") 0 -85px no-repeat;vertical-align:top}
|
||||
#smart_editor2 .se2_converter .se2_to_html{width:59px;height:15px;background:url("../img/ko_KR/btn_set.png?130306") -59px -70px no-repeat;vertical-align:top}
|
||||
#smart_editor2 .se2_converter .se2_to_text{width:60px;height:15px;background:url("../img/ko_KR/btn_set.png?130306") -417px -466px no-repeat;vertical-align:top}
|
||||
#smart_editor2 .se2_converter .active .se2_to_editor{width:59px;height:15px;background:url("../img/ko_KR/btn_set.png?130306") 0 -70px no-repeat;vertical-align:top}
|
||||
#smart_editor2 .se2_converter .active .se2_to_html{width:59px;height:15px;background:url("../img/ko_KR/btn_set.png?130306") -59px -85px no-repeat;vertical-align:top}
|
||||
#smart_editor2 .se2_converter .active .se2_to_text{width:60px;height:15px;background:url("../img/ko_KR/btn_set.png?130306") -417px -481px no-repeat;vertical-align:top}
|
||||
/* EDITINGAREA_HTMLSRC */
|
||||
#smart_editor2 .off .ico_btn,#smart_editor2 .off .se2_more,#smart_editor2 .off .se2_more2,#smart_editor2 .off .se2_font_family,#smart_editor2 .off .se2_font_size,#smart_editor2 .off .se2_bold,#smart_editor2 .off .se2_underline,#smart_editor2 .off .se2_italic,#smart_editor2 .off .se2_tdel,#smart_editor2 .off .se2_fcolor,#smart_editor2 .off .se2_fcolor_more,#smart_editor2 .off .se2_bgcolor,#smart_editor2 .off .se2_bgcolor_more,#smart_editor2 .off .se2_left,#smart_editor2 .off .se2_center,#smart_editor2 .off .se2_right,#smart_editor2 .off .se2_justify,#smart_editor2 .off .se2_ol,#smart_editor2 .off .se2_ul,#smart_editor2 .off .se2_indent,#smart_editor2 .off .se2_outdent,#smart_editor2 .off .se2_lineheight,#smart_editor2 .off .se2_del_style,#smart_editor2 .off .se2_blockquote,#smart_editor2 .off .se2_summary,#smart_editor2 .off .se2_footnote,#smart_editor2 .off .se2_url,#smart_editor2 .off .se2_emoticon,#smart_editor2 .off .se2_character,#smart_editor2 .off .se2_table,#smart_editor2 .off .se2_find,#smart_editor2 .off .se2_spelling,#smart_editor2 .off .se2_sup,#smart_editor2 .off .se2_sub,#smart_editor2 .off .se2_text_tool_more,#smart_editor2 .off .se2_new,#smart_editor2 .off .selected_color,#smart_editor2 .off .se2_lineSticker{-ms-filter:alpha(opacity=50);opacity:.5;cursor:default;filter:alpha(opacity=50)}
|
||||
/* LAYER */
|
||||
#smart_editor2 .se2_text_tool .se2_layer{display:none;float:left;position:absolute;top:20px;left:0;z-index:50;margin:0;padding:0;border:1px solid #bcbbbb;background:#fafafa}
|
||||
#smart_editor2 .se2_text_tool li.active{z-index:50}
|
||||
#smart_editor2 .se2_text_tool .active .se2_layer{display:block}
|
||||
#smart_editor2 .se2_text_tool .active li .se2_layer{display:none}
|
||||
#smart_editor2 .se2_text_tool .active .active .se2_layer{display:block}
|
||||
#smart_editor2 .se2_text_tool .se2_layer .se2_in_layer{float:left;margin:0;padding:0;border:1px solid #fff;background:#fafafa}
|
||||
/* TEXT_TOOLBAR */
|
||||
#smart_editor2 .se2_text_tool{position:relative;clear:both;z-index:30;padding:4px 0 4px 3px;background:#f4f4f4 url("../img/bg_text_tool.gif") 0 0 repeat-x;border-bottom:1px solid #b5b5b5;*zoom:1}
|
||||
#smart_editor2 .se2_text_tool:after{content:"";display:block;clear:both}
|
||||
#smart_editor2 .se2_text_tool ul{float:left;display:inline;margin-right:3px;padding-left:1px;white-space:nowrap}
|
||||
#smart_editor2 .se2_text_tool li{_display:inline;float:left;position:relative;z-index:30}
|
||||
#smart_editor2 .se2_text_tool button,#smart_editor2 .se2_multy .se2_icon{width:21px;height:21px;background:url("../img/ko_KR/text_tool_set.png?140317") no-repeat;vertical-align:top}
|
||||
#smart_editor2 .se2_text_tool .se2_font_type{position:relative}
|
||||
#smart_editor2 .se2_text_tool .se2_font_type li{margin-left:3px}
|
||||
#smart_editor2 .se2_text_tool .se2_font_type button{text-align:left}
|
||||
#smart_editor2 .se2_text_tool .se2_font_type button.se2_font_family span,#smart_editor2 .se2_text_tool .se2_font_type button.se2_font_size span{display:inline-block;visibility:visible;position:static;width:52px;height:20px;padding:0 0 0 6px;font-size:12px;line-height:20px;*line-height:22px;color:#333;*zoom:1}
|
||||
#smart_editor2 .se2_text_tool .se2_multy{position:absolute;top:0;right:0;padding-left:0;margin-right:0;white-space:nowrap;border-left:1px solid #e0dedf}
|
||||
#smart_editor2 .se2_text_tool .se2_multy .se2_mn{float:left;white-space:nowrap}
|
||||
#smart_editor2 .se2_text_tool .se2_multy button{background-image:none;width:47px}
|
||||
#smart_editor2 .se2_text_tool .se2_multy .se2_icon{display:inline-block;visibility:visible;overflow:visible;position:static;width:16px;height:29px;margin:-1px 2px 0 -1px;background-position:0 -132px;line-height:30px;vertical-align:top}
|
||||
#smart_editor2 .se2_text_tool .se2_multy button,#smart_editor2 .se2_text_tool .se2_multy button span{height:29px;line-height:29px}
|
||||
#smart_editor2 .se2_text_tool .se2_map .se2_icon{background-position:-29px -132px}
|
||||
#smart_editor2 .se2_text_tool button span.se2_mntxt{display:inline-block;visibility:visible;overflow:visible;_overflow-y:hidden;position:relative;*margin-right:-1px;width:auto;height:29px;font-weight:normal;font-size:11px;line-height:30px;*line-height:29px;_line-height:30px;color:#444;letter-spacing:-1px;vertical-align:top}
|
||||
#smart_editor2 .se2_text_tool .se2_multy .se2_photo{margin-right:1px}
|
||||
#smart_editor2 .se2_text_tool .se2_multy .hover .ico_btn{background:#e8e8e8}
|
||||
#smart_editor2 .se2_text_tool .se2_multy .se2_mn.hover{background:#e0dedf}
|
||||
/* TEXT_TOOLBAR : ROUNDING */
|
||||
#smart_editor2 ul li.first_child button span.tool_bg,#smart_editor2 ul li.last_child button span.tool_bg,#smart_editor2 ul li.single_child button span.tool_bg{visibility:visible;height:21px}
|
||||
#smart_editor2 ul li.first_child button span.tool_bg{left:-1px;width:3px;background:url("../img/bg_button_left.gif?20121228") no-repeat}
|
||||
#smart_editor2 ul li.last_child button span.tool_bg{right:0px;_right:-1px;width:2px;background:url("../img/bg_button_right.gif") no-repeat}
|
||||
#smart_editor2 ul li.single_child{padding-right:1px}
|
||||
#smart_editor2 ul li.single_child button span.tool_bg{left:0;background:url("../img/bg_button.gif?20121228") no-repeat;width:22px}
|
||||
#smart_editor2 div.se2_text_tool ul li.hover button span.tool_bg{background-position:0 -21px}
|
||||
#smart_editor2 div.se2_text_tool ul li.active button span.tool_bg,#smart_editor2 div.se2_text_tool ul li.active li.active button span.tool_bg{background-position:0 -42px}
|
||||
#smart_editor2 div.se2_text_tool ul li.active li button span.tool_bg{background-position:0 0}
|
||||
/* TEXT_TOOLBAR : SUB_MENU */
|
||||
#smart_editor2 .se2_sub_text_tool{display:none;position:absolute;top:20px;left:0;z-index:40;width:auto;height:29px;padding:0 4px 0 0;border:1px solid #b5b5b5;border-top:1px solid #9a9a9a;background:#f4f4f4}
|
||||
#smart_editor2 .active .se2_sub_text_tool{display:block}
|
||||
#smart_editor2 .se2_sub_text_tool ul{float:left;height:25px;margin:0;padding:4px 0 0 4px}
|
||||
/* TEXT_TOOLBAR : SUB_MENU_SIZE */
|
||||
#smart_editor2 .se2_sub_step1{width:88px}
|
||||
#smart_editor2 .se2_sub_step2{width:199px}
|
||||
#smart_editor2 .se2_sub_step2_1{width:178px}
|
||||
/* TEXT_TOOLBAR : BUTTON */
|
||||
#smart_editor2 .se2_text_tool .se2_font_family{width:70px;height:21px;background-position:0 -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_font_family{background-position:0 -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_font_family{background-position:0 -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_font_size{width:45px;height:21px;background-position:-70px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_font_size{background-position:-70px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_font_size{background-position:-70px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_bold{background-position:-115px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_bold{background-position:-115px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_bold{background-position:-115px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_underline{background-position:-136px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_underline{background-position:-136px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_underline{background-position:-136px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_italic{background-position:-157px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_italic{background-position:-157px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_italic{background-position:-157px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_tdel{background-position:-178px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_tdel{background-position:-178px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_tdel{background-position:-178px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_fcolor{position:relative;background-position:-199px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_fcolor{background-position:-199px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_fcolor{background-position:-199px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_fcolor_more{background-position:-220px -10px;width:10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_fcolor_more{background-position:-220px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_fcolor_more{background-position:-220px -103px}
|
||||
#smart_editor2 .se2_text_tool .selected_color{position:absolute;top:14px;left:5px;width:11px;height:3px;font-size:0}
|
||||
#smart_editor2 .se2_text_tool .se2_ol,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_ol{background-position:-345px -10px}
|
||||
#smart_editor2 .se2_text_tool .se2_ul,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_ul{background-position:-366px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_ol,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_ol{background-position:-345px -72px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_ul,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_ul{background-position:-366px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_ol,#smart_editor2 .se2_text_tool .active .active .se2_ol{background-position:-345px -103px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_ul,#smart_editor2 .se2_text_tool .active .active .se2_ul{background-position:-366px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_indent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_indent{background-position:-408px -10px}
|
||||
#smart_editor2 .se2_text_tool .se2_outdent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .se2_outdent{background-position:-387px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_indent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_indent{background-position:-408px -72px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_outdent,#smart_editor2 .se2_text_tool .active .se2_sub_text_tool .hover .se2_outdent{background-position:-387px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_indent,#smart_editor2 .se2_text_tool .active .active .se2_indent{background-position:-408px -103px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_outdent,#smart_editor2 .se2_text_tool .active .active .se2_outdent{background-position:-387px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_lineheight{background-position:-429px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_lineheight{background-position:-429px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_lineheight{background-position:-429px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_url{background-position:-513px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_url{background-position:-513px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_url{background-position:-513px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_bgcolor{position:relative;background-position:-230px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_bgcolor{background-position:-230px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_bgcolor{background-position:-230px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_bgcolor_more{background-position:-251px -10px;width:10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_bgcolor_more{background-position:-251px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_bgcolor_more{background-position:-251px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_left{background-position:-261px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_left{background-position:-261px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_left{background-position:-261px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_center{background-position:-282px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_center{background-position:-282px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_center{background-position:-282px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_right{background-position:-303px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_right{background-position:-303px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_right{background-position:-303px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_justify{background-position:-324px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_justify{background-position:-324px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_justify{background-position:-324px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_blockquote{background-position:-471px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_blockquote{background-position:-471px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_blockquote{background-position:-471px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_character{background-position:-555px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_character{background-position:-555px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_character{background-position:-555px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_table{background-position:-576px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_table{background-position:-576px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_table{background-position:-576px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_find{background-position:-597px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_find{background-position:-597px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_find{background-position:-597px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_sup{background-position:-660px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_sup{background-position:-660px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_sup{background-position:-660px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_sub{background-position:-681px -10px}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_sub{background-position:-681px -72px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_sub{background-position:-681px -103px}
|
||||
#smart_editor2 .se2_text_tool .se2_text_tool_more{background-position:0 -41px;width:13px}
|
||||
#smart_editor2 .se2_text_tool .se2_text_tool_more span.tool_bg{background:none}
|
||||
#smart_editor2 .se2_text_tool .hover .se2_text_tool_more{background-position:-13px -41px}
|
||||
#smart_editor2 .se2_text_tool .active .se2_text_tool_more{background-position:-26px -41px}
|
||||
@@ -0,0 +1,21 @@
|
||||
@charset "UTF-8";
|
||||
/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */
|
||||
/* COMMON */
|
||||
body,.se2_inputarea{margin:0;padding:0;font-family:'돋움',Dotum,Helvetica,Sans-serif;font-size:12px;line-height:1.5}
|
||||
/* body,.se2_inputarea,.se2_inputarea th,.se2_inputarea td{margin:0;padding:0;font-family:'돋움',Dotum,Helvetica,Sans-serif;font-size:12px;line-height:1.5;color:#666} */
|
||||
.se2_inputarea p,.se2_inputarea br{margin:0;padding:0}
|
||||
.se2_inputarea{margin:15px;word-wrap:break-word;*word-wrap:normal;*word-break:break-all}
|
||||
.se2_inputarea td{word-break:break-all}
|
||||
.se2_inputarea_890{width:741px;margin:20px 0 10px 64px}
|
||||
.se2_inputarea_698{width:548px;margin:20px 0 10px 64px}
|
||||
/* TEXT_TOOLBAR : QUOTE */
|
||||
.se2_quote1{margin:0 0 30px 20px;padding:0 8px;border-left:2px solid #ccc;color:#888}
|
||||
.se2_quote2{margin:0 0 30px 13px;padding:0 8px 0 16px;background:url("../img/bg_quote2.gif") 0 3px no-repeat;color:#888}
|
||||
.se2_quote3{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #ccc;color:#888}
|
||||
.se2_quote4{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #66b246;color:#888}
|
||||
.se2_quote5{margin:0 0 30px;padding:12px 10px 11px;border:1px dashed #ccc;background:#fafafa;color:#888}
|
||||
.se2_quote6{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #e5e5e5;color:#888}
|
||||
.se2_quote7{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #66b246;color:#888}
|
||||
.se2_quote8{margin:0 0 30px;padding:12px 10px 11px;border:1px solid #e5e5e5;background:#fafafa;color:#888}
|
||||
.se2_quote9{margin:0 0 30px;padding:12px 10px 11px;border:2px solid #e5e5e5;color:#888}
|
||||
.se2_quote10{margin:0 0 30px;padding:12px 10px 11px;border:2px solid #e5e5e5;background:#fafafa;color:#888}
|
||||
@@ -0,0 +1,462 @@
|
||||
@charset "UTF-8";
|
||||
/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */
|
||||
/* TEXT_TOOLBAR : FONTNAME */
|
||||
#smart_editor2 .se2_tool .se2_l_font_fam{width:202px;margin:0;padding:0}
|
||||
#smart_editor2 .se2_tool .se2_l_font_fam li{display:block;width:202px;height:21px;margin:0;padding:0;color:#333;cursor:pointer}
|
||||
#smart_editor2 .se2_l_font_fam .hover,#smart_editor2 .se2_l_font_fam .active{background:#ebebeb}
|
||||
#smart_editor2 .se2_l_font_fam button{width:200px;height:21px;margin:0;padding:2px 0 2px 0px;background:none;text-align:left}
|
||||
#smart_editor2 .se2_l_font_fam button span{display:block;visibility:visible;overflow:visible;position:relative;top:auto;left:auto;width:auto;height:auto;margin:0 0 0 4px;padding:0;font-size:12px;line-height:normal;color:#333}
|
||||
#smart_editor2 .se2_l_font_fam button span span{display:inline;visibility:visible;overflow:visible;width:auto;height:auto;margin:0 0 0 4px;font-family:Verdana;font-size:12px;line-height:14px;color:#888}
|
||||
#smart_editor2 .se2_l_font_fam button span em{visibility:visible;overflow:auto;position:static;width:auto;height:auto;margin-right:-4px;font-size:12px;color:#888}
|
||||
#smart_editor2 .se2_l_font_fam .se2_division{width:162px;height:2px !important;margin:1px 0 1px 0px;border:0;background:url("../img/bg_line1.gif") 0 0 repeat-x;font-size:0;cursor:default}
|
||||
/* TEXT_TOOLBAR : FONTSIZE */
|
||||
#smart_editor2 .se2_tool .se2_l_font_size{width:302px;margin:0;padding:0}
|
||||
#smart_editor2 .se2_tool .se2_l_font_size li{width:302px;margin:0;padding:0;color:#333;cursor:pointer}
|
||||
#smart_editor2 .se2_l_font_size .hover,#smart_editor2 .se2_l_font_size .active{background:#ebebeb}
|
||||
#smart_editor2 .se2_l_font_size button{width:300px;height:auto;margin:0;padding:2px 0 1px 0px;*padding:4px 0 1px 0px;background:none;text-align:left}
|
||||
#smart_editor2 .se2_l_font_size button span{display:block;visibility:visible;overflow:visible;position:relative;top:auto;left:auto;width:auto;height:auto;margin:0 0 0 4px;padding:0;line-height:normal;color:#373737;letter-spacing:0px}
|
||||
#smart_editor2 .se2_l_font_size button span span{display:inline;margin:0 0 0 5px;padding:0}
|
||||
#smart_editor2 .se2_l_font_size span em{visibility:visible;overflow:auto;position:static;width:auto;height:auto;color:#888}
|
||||
/* TEXT_TOOLBAR : FONTCOLOR */
|
||||
#smart_editor2 .se2_palette{float:left;position:relative;width:225px;margin:0;padding:11px 0 10px 0}
|
||||
#smart_editor2 .se2_palette .se2_pick_color{_display:inline;float:left;clear:both;width:205px;margin:0 0 0 11px;padding:0}
|
||||
#smart_editor2 .se2_palette .se2_pick_color li{float:left;width:12px;height:12px;margin:0;padding:0}
|
||||
#smart_editor2 .se2_palette .se2_pick_color li button{width:11px;height:11px;border:0}
|
||||
#smart_editor2 .se2_palette .se2_pick_color li button span{display:block;visibility:visible;overflow:visible;position:absolute;top:1px;left:1px;width:11px;height:11px}
|
||||
#smart_editor2 .se2_palette .se2_pick_color li button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0}
|
||||
#smart_editor2 .se2_palette .se2_pick_color .hover button,#smart_editor2 .se2_palette .se2_pick_color .active button{width:11px;height:11px;border:1px solid #666}
|
||||
#smart_editor2 .se2_palette .se2_pick_color .hover span,#smart_editor2 .se2_palette .se2_pick_color .active span{width:7px;height:7px;border:1px solid #fff}
|
||||
#smart_editor2 .se2_palette .se2_view_more{_display:inline;float:left;width:46px;height:23px;margin:1px 0 0 1px;background:url("../img/ko_KR/btn_set.png?130306") 0 -47px no-repeat}
|
||||
#smart_editor2 .se2_palette .se2_view_more2{_display:inline;float:left;width:46px;height:23px;margin:1px 0 0 1px;background:url("../img/ko_KR/btn_set.png?130306") 0 -24px no-repeat}
|
||||
#smart_editor2 .se2_palette h4{_display:inline;float:left;width:203px;margin:9px 0 0 11px;padding:10px 0 4px 0;background:url("../img/bg_line1.gif") repeat-x;font-weight:normal;font-size:12px;line-height:14px;color:#333;letter-spacing:-1px}
|
||||
#smart_editor2 .se2_palette2{float:left;_float:none;width:214px;margin:9px 0 0 0;padding:11px 0 0 11px;background:url("../img/bg_line1.gif") repeat-x}
|
||||
#smart_editor2 .se2_palette2 .se2_color_set{float:left}
|
||||
#smart_editor2 .se2_palette2 .se2_selected_color{_display:inline;float:left;width:83px;height:18px;margin:0;border:1px solid #c7c7c7;background:#fff}
|
||||
#smart_editor2 .se2_palette2 .se2_selected_color span{_display:inline;float:left;width:79px;height:14px;margin:2px}
|
||||
#smart_editor2 .se2_palette2 .input_ty1{_display:inline;float:left;width:67px;height:16px;margin:0 3px 0 3px;padding:2px 2px 0 4px;font-family:tahoma;font-size:11px}
|
||||
#smart_editor2 .se2_palette2 button.se2_btn_insert{float:left;width:35px;height:21px;margin-left:2px;padding:0;background:url("../img/ko_KR/btn_set.png?130306") -80px 0 no-repeat}
|
||||
#smart_editor2 .se2_gradation1{float:left;_float:none;width:201px;height:128px;margin:4px 0 0 0;border:1px solid #c7c7c7;cursor:crosshair}
|
||||
#smart_editor2 .se2_gradation2{float:left;_float:none;width:201px;height:10px;margin:4px 0 1px 0;border:1px solid #c7c7c7;cursor:crosshair}
|
||||
/* TEXT_TOOLBAR : BGCOLOR */
|
||||
#smart_editor2 .se2_palette_bgcolor{width:225px;margin:11px 0 0;padding:0}
|
||||
#smart_editor2 .se2_palette_bgcolor .se2_background{width:205px;margin:0 11px 0 11px}
|
||||
#smart_editor2 .se2_palette_bgcolor .se2_background li{width:68px;height:20px}
|
||||
#smart_editor2 .se2_palette_bgcolor .se2_background button{width:67px;height:19px;border:0}
|
||||
#smart_editor2 .se2_palette_bgcolor .se2_background span{left:0;display:block;visibility:visible;overflow:visible;width:65px;height:17px;padding:0}
|
||||
#smart_editor2 .se2_palette_bgcolor .se2_background span span{display:block;visibility:visible;overflow:visible;width:64px;height:16px;padding:3px 0 0 3px;font-size:11px;line-height:14px;text-align:left}
|
||||
#smart_editor2 .se2_palette_bgcolor .se2_background .hover span{width:65px;height:17px;border:1px solid #666}
|
||||
#smart_editor2 .se2_palette_bgcolor .se2_background .hover span span{width:62px;height:14px;padding:1px 0 0 1px;border:1px solid #fff}
|
||||
/* TEXT_TOOLBAR : LINEHEIGHT */
|
||||
#smart_editor2 .se2_l_line_height{width:107px;margin:0;padding:0}
|
||||
#smart_editor2 .se2_l_line_height li{width:107px;margin:0;padding:0;border-top:0;border-bottom:0;color:#333;cursor:pointer}
|
||||
#smart_editor2 .se2_l_line_height .hover{background:#ebebeb}
|
||||
#smart_editor2 .se2_l_line_height button{width:105px;height:19px;margin:0;padding:3px 0 2px 0px;background:none;text-align:left}
|
||||
#smart_editor2 .se2_l_line_height button span{visibility:visible;overflow:visible;position:relative;width:auto;height:auto;margin:0;padding:0 0 0 15px;font-size:12px;line-height:normal;color:#373737}
|
||||
#smart_editor2 .se2_l_line_height li button.active span{background:url("../img/icon_set.gif") 5px -30px no-repeat}
|
||||
#smart_editor2 .se2_l_line_height_user{clear:both;width:83px;margin:5px 0 0 12px;padding:10px 0 0 0;_padding:11px 0 0 0;background:url("../img/bg_line1.gif") repeat-x}
|
||||
#smart_editor2 .se2_l_line_height_user h3{margin:0 0 4px 0;_margin:0 0 2px -1px;padding:0;line-height:14px;color:#000;letter-spacing:-1px}
|
||||
#smart_editor2 .se2_l_line_height_user .bx_input{display:block;position:relative;width:83px}
|
||||
#smart_editor2 .se2_l_line_height_user .btn_up{position:absolute;top:2px;*top:3px;left:68px;width:13px;height:8px;background:url("../img/ko_KR/btn_set.png?130306") -86px -54px no-repeat}
|
||||
#smart_editor2 .se2_l_line_height_user .btn_down{position:absolute;top:10px;*top:11px;left:68px;width:13px;height:8px;background:url("../img/ko_KR/btn_set.png?130306") -86px -62px no-repeat}
|
||||
#smart_editor2 .se2_l_line_height_user .btn_area{margin:5px 0 10px 0}
|
||||
#smart_editor2 .se2_tool .btn_area .se2_btn_apply3{width:41px;height:24px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat}
|
||||
#smart_editor2 .se2_tool .btn_area .se2_btn_cancel3{width:39px;height:24px;margin-left:3px;background:url("../img/ko_KR/btn_set.png?130306") -41px 0 no-repeat}
|
||||
/* TEXT_TOOLBAR : QUOTE */
|
||||
#smart_editor2 .se2_quote{width:425px;height:56px}
|
||||
#smart_editor2 .se2_quote ul{_display:inline;float:left;margin:11px 0 0 9px;padding:0}
|
||||
#smart_editor2 .se2_quote li{_display:inline;float:left;margin:0 0 0 2px;padding:0}
|
||||
#smart_editor2 .se2_quote button{width:34px;height:34px;margin:0;padding:0;background:url("../img/ko_KR/btn_set.png?130306") no-repeat;cursor:pointer}
|
||||
#smart_editor2 .se2_quote button span{left:0;display:block;visibility:visible;overflow:visible;width:32px;height:32px;margin:0;padding:0;border:1px solid #c7c7c7}
|
||||
#smart_editor2 .se2_quote button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0}
|
||||
#smart_editor2 .se2_quote .se2_quote1{background-position:1px -375px}
|
||||
#smart_editor2 .se2_quote .se2_quote2{background-position:-32px -375px}
|
||||
#smart_editor2 .se2_quote .se2_quote3{background-position:-65px -375px}
|
||||
#smart_editor2 .se2_quote .se2_quote4{background-position:-98px -375px}
|
||||
#smart_editor2 .se2_quote .se2_quote5{background-position:-131px -375px}
|
||||
#smart_editor2 .se2_quote .se2_quote6{background-position:-164px -375px}
|
||||
#smart_editor2 .se2_quote .se2_quote7{background-position:-197px -375px}
|
||||
#smart_editor2 .se2_quote .se2_quote8{background-position:-230px -375px}
|
||||
#smart_editor2 .se2_quote .se2_quote9{background-position:-263px -375px}
|
||||
#smart_editor2 .se2_quote .se2_quote10{background-position:-296px -375px}
|
||||
#smart_editor2 .se2_quote .hover button span,#smart_editor2 .se2_quote .active button span{width:30px;height:30px;margin:0;padding:0;border:2px solid #44b525}
|
||||
#smart_editor2 .se2_quote .hover button span span,#smart_editor2 .se2_quote .active button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0}
|
||||
#smart_editor2 .se2_quote .se2_cancel2{float:left;width:40px;height:35px;margin:11px 0 0 5px;background:url("../img/ko_KR/btn_set.png?130306") -46px -24px no-repeat}
|
||||
#smart_editor2 .se2_quote .se2_cancel2 span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0;margin:0;padding:0}
|
||||
/* TEXT_TOOLBAR : HYPERLINK */
|
||||
#smart_editor2 .se2_url2{width:281px;padding:11px 11px 6px 11px;color:#666}
|
||||
#smart_editor2 .se2_url2 .input_ty1{display:block;width:185px;height:16px;margin:0 5px 5px 0;*margin:-1px 5px 5px 0;padding:5px 2px 0 4px}
|
||||
#smart_editor2 .se2_url2 .se2_url_new{width:15px;height:15px;margin:-1px 3px 1px -1px;*margin:-2px 3px 2px -1px;vertical-align:middle}
|
||||
#smart_editor2 .se2_url2 label{font-size:11px;line-height:14px;vertical-align:middle}
|
||||
#smart_editor2 .se2_url2 .se2_apply{position:absolute;top:13px;right:51px;width:41px;height:24px;margin:-1px 3px 1px 0;background:url("../img/ko_KR/btn_set.png?130306") no-repeat}
|
||||
#smart_editor2 .se2_url2 .se2_cancel{position:absolute;top:13px;right:9px;width:39px;height:24px;margin:-1px 3px 1px 0;background:url("../img/ko_KR/btn_set.png?130306") -41px 0 no-repeat}
|
||||
/* TEXT_TOOLBAR : SCHARACTER */
|
||||
#smart_editor2 .se2_bx_character{width:469px;height:272px;margin:0;padding:0;background:url("../img/ko_KR/bx_set_110302.gif") 9px -1230px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .se2_char_tab{_display:inline;float:left;position:relative;width:443px;margin:11px 10px 200px 11px;padding:0 0 0 1px}
|
||||
#smart_editor2 .se2_bx_character .se2_char_tab li{position:static;margin:0 0 0 -1px;padding:0}
|
||||
#smart_editor2 .se2_bx_character .se2_char1{width:76px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") 0 -204px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .se2_char2{width:86px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") -75px -204px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .se2_char3{width:68px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") -160px -204px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .se2_char4{width:55px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") -227px -204px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .se2_char5{width:97px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") -281px -204px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .se2_char6{width:66px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") -377px -204px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .active .se2_char1{width:76px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") 0 -230px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .active .se2_char2{width:86px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") -75px -230px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .active .se2_char3{width:68px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") -160px -230px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .active .se2_char4{width:55px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") -227px -230px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .active .se2_char5{width:97px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") -281px -230px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .active .se2_char6{width:66px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") -377px -230px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .se2_s_character{display:none;position:absolute;top:26px;left:0;width:448px;height:194px;margin:0;padding:0}
|
||||
#smart_editor2 .se2_bx_character .active .se2_s_character{display:block}
|
||||
#smart_editor2 .se2_bx_character .se2_s_character ul{float:left;width:422px;height:172px;margin:0;padding:9px 0 0 11px}
|
||||
#smart_editor2 .se2_bx_character .se2_s_character li{_display:inline;float:left;position:relative;width:20px;height:18px;margin:0 0 1px 1px;background:#fff}
|
||||
#smart_editor2 .se2_bx_character .se2_s_character button{width:20px;height:18px;margin:0;padding:2px;background:none}
|
||||
#smart_editor2 .se2_bx_character .se2_s_character .hover,#smart_editor2 .se2_bx_character .se2_s_character .active{background:url("../img/ko_KR/btn_set.png?130306") -446px -274px no-repeat}
|
||||
#smart_editor2 .se2_bx_character .se2_s_character button span{left:0;display:block;visibility:visible;overflow:visible;width:14px;height:16px;margin:3px 0 0 3px;border:0;background:none;font-size:12px;line-height:normal}
|
||||
#smart_editor2 .se2_apply_character{clear:both;position:relative;padding:0 0 0 11px}
|
||||
#smart_editor2 .se2_apply_character label{margin:0 3px 0 0;font-size:12px;color:#666;letter-spacing:-1px}
|
||||
#smart_editor2 .se2_apply_character .input_ty1{width:283px;height:17px;margin:-1px 5px 1px 0;padding:4px 0 0 5px;font-size:12px;color:#666;letter-spacing:0;vertical-align:middle}
|
||||
#smart_editor2 .se2_apply_character .se2_confirm{width:41px;height:24px;margin-right:3px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat;vertical-align:middle}
|
||||
#smart_editor2 .se2_apply_character .se2_cancel{width:39px;height:24px;background:url("../img/ko_KR/btn_set.png?130306") -41px 0 no-repeat;vertical-align:middle}
|
||||
/* TEXT_TOOLBAR : TABLECREATOR */
|
||||
#smart_editor2 .se2_table_set{position:relative;width:166px;margin:3px 11px 0 11px;padding:8px 0 0 0}
|
||||
#smart_editor2 .se2_table_set .se2_cell_num{float:left;width:73px}
|
||||
#smart_editor2 .se2_table_set .se2_cell_num dt{float:left;clear:both;width:17px;height:23px;margin:0;padding:0}
|
||||
#smart_editor2 .se2_table_set .se2_cell_num dt label{display:block;margin:5px 0 0 0;font-size:11px;color:#666}
|
||||
#smart_editor2 .se2_table_set .se2_cell_num dd{float:left;position:relative;width:54px;height:23px;margin:0;padding:0}
|
||||
#smart_editor2 .se2_table_set .se2_cell_num .input_ty2{display:block;width:32px;height:16px;*margin:-1px 0 0 0;padding:2px 19px 0 0px;border:1px solid #c7c7c7;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666;text-align:right;*direction:rtl}
|
||||
#smart_editor2 .se2_table_set .se2_cell_num .input_ty2::-ms-clear{display:none}
|
||||
#smart_editor2 .se2_table_set .se2_pre_table{float:right;width:91px;height:43px;background:#c7c7c7;border-spacing:1px}
|
||||
#smart_editor2 .se2_table_set .se2_pre_table tr{background:#fff}
|
||||
#smart_editor2 .se2_table_set .se2_pre_table td{font-size:0;line-height:0}
|
||||
#smart_editor2 .se2_table_set .se2_add{position:absolute;top:2px;right:3px;width:13px;height:8px;background:url("../img/ko_KR/btn_set.png?130306") -86px -54px no-repeat}
|
||||
#smart_editor2 .se2_table_set .se2_del{position:absolute;top:10px;right:3px;width:13px;height:8px;background:url("../img/ko_KR/btn_set.png?130306") -86px -62px no-repeat}
|
||||
/* TEXT_TOOLBAR : TABLEEDITOR */
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1{float:left;width:166px;margin:7px 0 0 0;padding:10px 0 5px;background:url("../img/bg_line1.gif") repeat-x}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1 dt{width:166px;margin:0 0 6px 0}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1 dd{width:166px}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1 dt input{width:15px;height:15px;margin:-1px 3px 1px 0;_margin:-2px 3px 2px 0;vertical-align:middle}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1 dt label{font-weight:bold;font-size:11px;color:#666;letter-spacing:-1px;vertical-align:middle}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1_1{float:left;position:relative;z-index:59;width:166px;margin:1px 0 0 0}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1_2{z-index:54;margin:0}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1_3{z-index:53;margin:0}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1_4{z-index:52;margin:0}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1_1 dt{_display:inline;float:left;clear:both;width:66px;height:22px;margin:1px 0 0 18px}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1_1 dt label{display:block;margin:4px 0 0 0;font-weight:normal;font-size:11px;color:#666;letter-spacing:-1px}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1_1 dd{float:left;position:relative;width:82px;height:23px}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1_1 .input_ty1{width:72px;height:16px;*margin:-1px 0 0 0;padding:2px 2px 0 6px;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1_1 .input_ty3{float:left;width:49px;height:16px;margin:0 3px 0 0;padding:2px 4px 0 4px;border:1px solid #c7c7c7;font-family:tahoma,verdana,times New Roman;font-size:11px;color:#666}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_add{top:2px;right:2px}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_del{top:10px;right:2px}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper1_1 .se2_color_set .input_ty1{_display:inline;float:left;width:67px;height:16px;margin:0 3px 0 3px;padding:2px 2px 0 4px;font-family:tahoma,verdana,times New Roman;font-size:11px}
|
||||
#smart_editor2 .se2_select_ty1{position:relative;width:80px;height:18px;border:1px solid #c7c7c7;background:#fff;font-size:11px;line-height:14px;text-align:left}
|
||||
#smart_editor2 .se2_select_ty1 span{float:left;width:54px;height:18px;margin:0 0 0 5px;font-size:11px;line-height:14px;color:#666}
|
||||
#smart_editor2 .se2_select_ty1 .se2_b_style0{position:relative;top:3px;left:-3px;white-space:nowrap}
|
||||
#smart_editor2 .se2_select_ty1 .se2_b_style1{height:15px;margin:3px 0 0 4px;font-size:11px;line-height:14px;color:#666;letter-spacing:-1px}
|
||||
#smart_editor2 .se2_select_ty1 .se2_b_style2{background:url("../img/bg_set.gif") 0 -50px repeat-x}
|
||||
#smart_editor2 .se2_select_ty1 .se2_b_style3{background:url("../img/bg_set.gif") 0 -68px repeat-x}
|
||||
#smart_editor2 .se2_select_ty1 .se2_b_style4{background:url("../img/bg_set.gif") 0 -85px repeat-x}
|
||||
#smart_editor2 .se2_select_ty1 .se2_b_style5{background:url("../img/bg_set.gif") 0 -103px repeat-x}
|
||||
#smart_editor2 .se2_select_ty1 .se2_b_style6{background:url("../img/bg_set.gif") 0 -121px repeat-x}
|
||||
#smart_editor2 .se2_select_ty1 .se2_b_style7{background:url("../img/bg_set.gif") 0 -139px repeat-x}
|
||||
#smart_editor2 .se2_select_ty1 .se2_view_more{position:absolute;top:1px;right:1px;width:13px;height:16px;background:url("../img/ko_KR/btn_set.png?130306") -112px -54px no-repeat}
|
||||
#smart_editor2 .se2_select_ty1 .se2_view_more2{position:absolute;top:1px;right:1px;width:13px;height:16px;background:url("../img/ko_KR/btn_set.png?130306") -99px -54px no-repeat}
|
||||
/* TEXT_TOOLBAR : TABLEEDITOR > BORDER */
|
||||
#smart_editor2 .se2_table_set .se2_b_t_b1{border-top:1px solid #b1b1b1}
|
||||
#smart_editor2 .se2_layer_b_style{position:absolute;top:20px;right:0px;width:80px;padding-bottom:1px;border:1px solid #c7c7c7;border-top:1px solid #a8a8a8;background:#fff}
|
||||
#smart_editor2 .se2_layer_b_style ul{width:80px;margin:0;padding:1px 0 0 0}
|
||||
#smart_editor2 .se2_layer_b_style li{width:80px;height:18px;margin:0;padding:0}
|
||||
#smart_editor2 .se2_layer_b_style .hover,#smart_editor2 .se2_layer_b_style .active{background:#ebebeb}
|
||||
#smart_editor2 .se2_layer_b_style button{width:80px;height:18px;background:none}
|
||||
#smart_editor2 .se2_layer_b_style button span{left:0;display:block;visibility:visible;overflow:visible;width:71px;height:18px;margin:0 0 0 5px;font-size:11px;line-height:15px;text-align:left}
|
||||
#smart_editor2 .se2_layer_b_style button span span{visibility:hidden;overflow:hidden;position:absolute;top:0;left:0;width:0;height:0}
|
||||
#smart_editor2 .se2_layer_b_style .se2_b_style1 span{margin:3px 0 0 4px;font-size:11px;line-height:14px;color:#666;letter-spacing:-1px}
|
||||
#smart_editor2 .se2_layer_b_style .se2_b_style2 span{background:url("../img/bg_set.gif") 0 -50px repeat-x}
|
||||
#smart_editor2 .se2_layer_b_style .se2_b_style3 span{background:url("../img/bg_set.gif") 0 -68px repeat-x}
|
||||
#smart_editor2 .se2_layer_b_style .se2_b_style4 span{background:url("../img/bg_set.gif") 0 -86px repeat-x}
|
||||
#smart_editor2 .se2_layer_b_style .se2_b_style5 span{background:url("../img/bg_set.gif") 0 -103px repeat-x}
|
||||
#smart_editor2 .se2_layer_b_style .se2_b_style6 span{background:url("../img/bg_set.gif") 0 -121px repeat-x}
|
||||
#smart_editor2 .se2_layer_b_style .se2_b_style7 span{background:url("../img/bg_set.gif") 0 -139px repeat-x}
|
||||
/* TEXT_TOOLBAR : TABLEEDITOR > COLOR */
|
||||
#smart_editor2 .se2_pre_color{float:left;width:18px;height:18px;border:1px solid #c7c7c7}
|
||||
#smart_editor2 .se2_pre_color button{float:left;width:14px;height:14px;margin:2px 0 0 2px;padding:0}
|
||||
#smart_editor2 .se2_pre_color button span{overflow:hidden;position:absolute;top:-10000px;left:-10000px;z-index:-100;width:0;height:0}
|
||||
/* TEXT_TOOLBAR : TABLEEDITOR > DIMMED */
|
||||
#smart_editor2 .se2_table_set .se2_t_dim1{clear:both;position:absolute;top:71px;left:16px;z-index:60;width:157px;height:118px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_table_set .se2_t_dim2{position:absolute;top:116px;left:16px;z-index:55;width:157px;height:45px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_table_set .se2_t_dim3{clear:both;position:absolute;top:192px;left:16px;z-index:51;width:157px;height:39px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
/* TEXT_TOOLBAR : TABLEEDITOR > STYLE PREVIEW */
|
||||
#smart_editor2 .se2_table_set .se2_t_proper2{float:left;position:relative;z-index:50;width:166px;margin:2px 0 0 0}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper2 dt{float:left;width:84px;height:33px;margin:4px 0 0 0}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper2 dt input{width:15px;height:15px;margin:-1px 3px 1px 0;_margin:-2px 3px 2px 0;vertical-align:middle}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper2 dt label{font-weight:bold;font-size:11px;color:#666;letter-spacing:-1px;vertical-align:middle}
|
||||
#smart_editor2 .se2_table_set .se2_t_proper2 dd{float:left;width:66px;height:33px}
|
||||
#smart_editor2 .se2_select_ty2{position:relative;width:65px;height:31px;border:1px solid #c7c7c7;background:#fff;font-size:11px;line-height:14px;text-align:left}
|
||||
#smart_editor2 .se2_select_ty2 span{float:left;width:45px;height:25px;margin:3px 0 0 3px;background:url("../img/ko_KR/btn_set.png?130306") repeat-x}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style1{background-position:0 -410px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style2{background-position:-46px -410px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style3{background-position:-92px -410px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style4{background-position:-138px -410px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style5{background-position:-184px -410px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style6{background-position:-230px -410px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style7{background-position:-276px -410px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style8{background-position:-322px -410px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style9{background-position:0 -436px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style10{background-position:-46px -436px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style11{background-position:-92px -436px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style12{background-position:-138px -436px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style13{background-position:-184px -436px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style14{background-position:-230px -436px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style15{background-position:-276px -436px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_t_style16{background-position:-322px -436px}
|
||||
#smart_editor2 .se2_select_ty2 .se2_view_more{position:absolute;top:1px;right:1px;_right:0px;width:13px !important;height:29px !important;background:url("../img/ko_KR/btn_set.png?130306") -353px -48px no-repeat !important}
|
||||
#smart_editor2 .se2_select_ty2 .se2_view_more2{position:absolute;top:1px;right:1px;_right:0px;width:13px !important;height:29px !important;background:url("../img/ko_KR/btn_set.png?130306") -340px -48px no-repeat !important}
|
||||
#smart_editor2 .se2_select_ty2 .se2_view_more span{display:none}
|
||||
/* TEXT_TOOLBAR : TABLEEDITOR > STYLE */
|
||||
#smart_editor2 .se2_layer_t_style{position:absolute;top:33px;right:15px;width:208px;border:1px solid #c7c7c7;border-top:1px solid #a8a8a8;background:#fff}
|
||||
#smart_editor2 .se2_layer_t_style ul{width:204px;height:126px;margin:1px 2px;padding:1px 0 0 0;background:#fff}
|
||||
#smart_editor2 .se2_layer_t_style li{_display:inline;float:left;width:45px;height:25px;margin:1px;padding:1px;border:1px solid #fff}
|
||||
#smart_editor2 .se2_layer_t_style .hover,#smart_editor2 .se2_layer_t_style .active{border:1px solid #666;background:#fff}
|
||||
#smart_editor2 .se2_layer_t_style button{width:45px;height:25px;background:url("../img/ko_KR/btn_set.png?130306") repeat-x !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style1{background-position:0 -410px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style2{background-position:-46px -410px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style3{background-position:-92px -410px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style4{background-position:-138px -410px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style5{background-position:-184px -410px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style6{background-position:-230px -410px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style7{background-position:-276px -410px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style8{background-position:-322px -410px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style9{background-position:0 -436px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style10{background-position:-46px -436px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style11{background-position:-92px -436px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style12{background-position:-138px -436px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style13{background-position:-184px -436px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style14{background-position:-230px -436px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style15{background-position:-276px -436px !important}
|
||||
#smart_editor2 .se2_layer_t_style .se2_t_style16{background-position:-322px -436px !important}
|
||||
#smart_editor2 .se2_table_set .se2_btn_area{float:left;width:166px;margin:6px 0 0 0;padding:12px 0 8px 0;background:url("../img/bg_line1.gif") repeat-x;text-align:center}
|
||||
#smart_editor2 .se2_table_set button.se2_apply{width:41px;height:24px;margin-right:3px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat}
|
||||
#smart_editor2 .se2_table_set button.se2_cancel{width:39px;height:24px;background:url("../img/ko_KR/btn_set.png?130306") -41px 0 no-repeat}
|
||||
#smart_editor2 .se2_table_set .se2_rd{width:14px;height:14px;vertical-align:middle}
|
||||
#smart_editor2 .se2_table_set .se2_celltit{font-size:11px;font-size:11px;color:#666;letter-spacing:-1px}
|
||||
#smart_editor2 .se2_table_set dt label.se2_celltit{display:inline}
|
||||
/* TEXT_TOOLBAR : FINDREPLACE */
|
||||
#smart_editor2 .se2_bx_find_revise{position:relative;width:255px;margin:0;padding:0}
|
||||
#smart_editor2 .se2_bx_find_revise .se2_close{position:absolute;top:5px;right:8px;width:20px;height:20px;background:url("../img/ko_KR/btn_set.png?130306") -151px -1px no-repeat}
|
||||
#smart_editor2 .se2_bx_find_revise h3{margin:0;padding:10px 0 13px 10px;background:url("../img/bg_find_h3.gif") 0 -1px repeat-x;font-size:12px;line-height:14px;letter-spacing:-1px}
|
||||
#smart_editor2 .se2_bx_find_revise ul{position:relative;margin:8px 0 0 0;padding:0 0 0 12px}
|
||||
#smart_editor2 .se2_bx_find_revise ul li{_display:inline;float:left;position:static;margin:0 0 0 -1px;padding:0}
|
||||
#smart_editor2 .se2_bx_find_revise .se2_tabfind{width:117px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") 0 -100px no-repeat}
|
||||
#smart_editor2 .se2_bx_find_revise .se2_tabrevise{width:117px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") -116px -100px no-repeat}
|
||||
#smart_editor2 .se2_bx_find_revise .active .se2_tabfind{width:117px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") 0 -126px no-repeat}
|
||||
#smart_editor2 .se2_bx_find_revise .active .se2_tabrevise{width:117px;height:26px;background:url("../img/ko_KR/btn_set.png?130306") -116px -126px no-repeat}
|
||||
#smart_editor2 .se2_bx_find_revise .se2_in_bx_find dl{_display:inline;float:left;width:223px;margin:0 0 0 9px;padding:7px 0 13px 14px;background:url("../img/ko_KR/bx_set_110302.gif") -289px -1518px no-repeat}
|
||||
#smart_editor2 .se2_bx_find_revise .se2_in_bx_revise dl{_display:inline;float:left;width:223px;margin:0 0 0 9px;padding:7px 0 13px 14px;background:url("../img/ko_KR/bx_set_110302.gif") -289px -1619px no-repeat}
|
||||
#smart_editor2 .se2_bx_find_revise dt{_display:inline;float:left;clear:both;width:47px;margin:1px 0 2px 0}
|
||||
#smart_editor2 .se2_bx_find_revise dd{float:left;margin:0 0 2px 0}
|
||||
#smart_editor2 .se2_bx_find_revise label{float:left;padding:5px 0 0 0;font-size:11px;color:#666;letter-spacing:-2px}
|
||||
#smart_editor2 .se2_bx_find_revise input{float:left;width:155px;height:12px;margin:1px 0 0 0;padding:3px 2px 3px 4px;font-size:12px;color:#666}
|
||||
#smart_editor2 .se2_bx_find_revise .se2_find_btns{float:left;clear:both;width:255px;padding:8px 0 10px 0;text-align:center}
|
||||
#smart_editor2 .se2_bx_find_revise .se2_find_next{width:65px;height:24px;margin:0 3px 0 0;background:url("../img/ko_KR/btn_set.png?130306") -180px -48px no-repeat}
|
||||
#smart_editor2 .se2_bx_find_revise .se2_find_next2{width:61px;height:24px;margin:0 3px 0 0;background:url("../img/ko_KR/btn_set.png?130306") -180px -24px no-repeat}
|
||||
#smart_editor2 .se2_bx_find_revise .se2_revise1{width:54px;height:24px;margin:0 3px 0 0;background:url("../img/ko_KR/btn_set.png?130306") -245px -48px no-repeat}
|
||||
#smart_editor2 .se2_bx_find_revise .se2_revise2{width:70px;height:24px;margin:0 3px 0 0;background:url("../img/ko_KR/btn_set.png?130306") -245px -24px no-repeat}
|
||||
#smart_editor2 .se2_bx_find_revise .se2_cancel{width:39px;height:24px;background:url("../img/ko_KR/btn_set.png?130306") -41px 0 no-repeat}
|
||||
/* TEXT_TOOLBAR : QUICKEDITOR_TABLE */
|
||||
#smart_editor2 .se2_qmax{position:absolute;width:18px;height:18px;background:url("../img/ko_KR/btn_set.png?130306") -339px -169px no-repeat}
|
||||
#smart_editor2 .se2_qeditor{position:absolute;top:0;left:0;width:183px;margin:0;padding:0;border:1px solid #c7c7c7;border-right:1px solid #ababab;border-bottom:1px solid #ababab;background:#fafafa}
|
||||
#smart_editor2 .se2_qeditor label,#smart_editor2 .se2_qeditor span,#smart_editor2 .se2_qeditor dt{font-size:11px;color:#666;letter-spacing:-1px}
|
||||
#smart_editor2 .se2_qbar{position:relative;width:183px;height:11px;background:url("../img/ko_KR/bx_set_110302.gif") 0 -731px no-repeat}
|
||||
#smart_editor2 .se2_qbar .se2_qmini{position:absolute;top:-1px;right:0;*right:-1px;_right:-3px;width:18px;height:14px;background:url("../img/ko_KR/btn_set.png?130306") -315px -170px no-repeat}
|
||||
#smart_editor2 .se2_qbar .se2_qmini button{width:20px;height:14px;margin-top:-1px}
|
||||
#smart_editor2 .se2_qeditor .se2_qbody0{float:left;border:1px solid #fefefe}
|
||||
#smart_editor2 .se2_qeditor .se2_qbody{position:relative;z-index:90;width:174px;padding:4px 0 0 7px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe1{overflow:hidden;width:174px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe1 dt{float:left;width:22px;height:18px;padding:4px 0 0 0}
|
||||
#smart_editor2 .se2_qeditor .se2_qe1 dd{float:left;width:65px;height:22px}
|
||||
#smart_editor2 .se2_qeditor .se2_addrow{width:28px;height:19px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat -385px -49px}
|
||||
#smart_editor2 .se2_qeditor .se2_addcol{width:29px;height:19px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat -413px -49px}
|
||||
#smart_editor2 .se2_qeditor .se2_seprow{width:28px;height:19px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat -385px -68px}
|
||||
#smart_editor2 .se2_qeditor .se2_sepcol{width:29px;height:19px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat -413px -68px}
|
||||
#smart_editor2 .se2_qeditor .se2_delrow{width:28px;height:19px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat -385px -106px}
|
||||
#smart_editor2 .se2_qeditor .se2_delcol{width:29px;height:19px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat -413px -106px}
|
||||
#smart_editor2 .se2_qeditor .se2_merrow{width:57px;height:19px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat -385px -125px}
|
||||
#smart_editor2 .se2_qeditor .se2_mercol{width:57px;height:19px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat -413px -125px}
|
||||
#smart_editor2 .se2_qeditor .se2_seprow_off{width:28px;height:19px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat -385px -87px}
|
||||
#smart_editor2 .se2_qeditor .se2_sepcol_off{width:29px;height:19px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat -413px -87px}
|
||||
#smart_editor2 .se2_qeditor .se2_merrow_off{width:57px;height:19px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat -385px -144px}
|
||||
#smart_editor2 .se2_qeditor .se2_mercol_off{width:57px;height:19px;background:url("../img/ko_KR/btn_set.png?130306") no-repeat -413px -144px}
|
||||
/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND */
|
||||
#smart_editor2 .se2_qeditor .se2_qe2{_display:inline;float:left;position:relative;z-index:100;width:165px;margin:2px 0 0 1px;padding:7px 0 0 0;background:url("../img/bg_line1.gif") repeat-x;zoom:1}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_1 dt{float:left;width:62px;padding:3px 0 0 0}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_1 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_1 dd{float:left;position:relative;zoom:1}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_3{padding:7px 0 6px 0}
|
||||
/* My글양식 없을때 */
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2{position:relative;_position:absolute}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 dt{float:left;width:50px;padding:3px 0 0 13px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 dt input{width:15px;height:15px;margin:-1px 2px 1px -1px;vertical-align:middle}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 dd{float:left}
|
||||
/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > STYLE */
|
||||
#smart_editor2 .se2_table_set .se2_qbody .se2_t_proper2{float:left;*float:none;position:static;width:166px;margin:5px 0 0 1px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe3 dt{float:left;width:62px;padding:0}
|
||||
#smart_editor2 .se2_qeditor .se2_qe3 dt label{font-weight:normal}
|
||||
#smart_editor2 .se2_qeditor .se2_qe3 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle}
|
||||
#smart_editor2 .se2_qeditor .se2_qe3 dd .se2_qe3_table{position:relative}
|
||||
/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND PREWVIEW */
|
||||
#smart_editor2 .se2_qeditor .se2_pre_color{float:left;width:18px;height:18px;border:1px solid #c7c7c7}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_color button{float:left;width:14px;height:14px;margin:2px 0 0 2px;padding:0}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_color button span{overflow:hidden;position:absolute;top:-10000px;left:-10000px;z-index:-100;width:0;height:0}
|
||||
/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND LAYER */
|
||||
#smart_editor2 .se2_qeditor .se2_layer{float:left;clear:both;position:absolute;top:20px;left:0;margin:0;padding:0;border:1px solid #c7c7c7;border-top:1px solid #9a9a9a;background:#fafafa}
|
||||
#smart_editor2 .se2_qeditor .se2_layer .se2_in_layer{float:left;margin:0;padding:0;border:1px solid #fff;background:#fafafa}
|
||||
#smart_editor2 .se2_qeditor .se2_layer button{vertical-align:top}
|
||||
#smart_editor2 .se2_qeditor .se2_layer .se2_pick_color li{position:relative}
|
||||
/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND IMAGE */
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg{float:left;width:14px;height:14px;padding:2px;border:1px solid #c7c7c7}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 button{width:16px;height:16px;background:url("../img/ko_KR/btn_set.png?130306") 0 -261px no-repeat}
|
||||
/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > CELL_BACKGROUND IMAGE LAYER */
|
||||
#smart_editor2 .se2_cellimg_set{_display:inline;float:left;width:136px;margin:4px 3px 0 4px;padding-bottom:4px}
|
||||
#smart_editor2 .se2_cellimg_set li{_display:inline;float:left;width:16px;height:16px;margin:0 1px 1px 0}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg0{background-position:-255px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg1{background-position:0 -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg2{background-position:-17px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg3{background-position:-34px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg4{background-position:-51px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg5{background-position:-68px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg6{background-position:-85px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg7{background-position:-102px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg8{background-position:-119px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg9{background-position:-136px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg10{background-position:-153px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg11{background-position:-170px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg12{background-position:-187px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg13{background-position:-204px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg14{background-position:-221px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg15{background-position:-238px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg16{background-position:-255px -261px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg17{background-position:0 -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg18{background-position:-17px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg19{background-position:-34px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg20{background-position:-51px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg21{background-position:-68px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg22{background-position:-85px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg23{background-position:-102px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg24{background-position:-119px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg25{background-position:-136px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg26{background-position:-153px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg27{background-position:-170px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg28{background-position:-187px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg29{background-position:-204px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg30{background-position:-221px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_qe2_2 .se2_cellimg31{background-position:-238px -278px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg button{width:14px;height:14px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg1{background-position:-1px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg2{background-position:-18px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg3{background-position:-35px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg4{background-position:-52px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg5{background-position:-69px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg6{background-position:-86px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg7{background-position:-103px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg8{background-position:-120px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg9{background-position:-137px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg10{background-position:-154px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg11{background-position:-171px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg12{background-position:-188px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg13{background-position:-205px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg14{background-position:-222px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg15{background-position:-239px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg16{background-position:-256px -262px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg17{background-position:-1px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg18{background-position:-18px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg19{background-position:-35px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg20{background-position:-52px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg21{background-position:-69px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg22{background-position:-86px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg23{background-position:-103px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg24{background-position:-120px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg25{background-position:-137px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg26{background-position:-154px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg27{background-position:-171px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg28{background-position:-188px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg29{background-position:-205px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg30{background-position:-222px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg31{background-position:-239px -279px}
|
||||
#smart_editor2 .se2_qeditor .se2_pre_bgimg .se2_cellimg32{background-position:-256px -279px}
|
||||
/* TEXT_TOOLBAR : QUICKEDITOR_TABLE > MY REVIEW */
|
||||
#smart_editor2 .se2_btn_area{_display:inline;float:left;clear:both;width:166px;margin:5px 0 0 1px;padding:7px 0 6px 0;background:url("../img/bg_line1.gif") repeat-x;text-align:center}
|
||||
#smart_editor2 .se2_btn_area .se2_btn_save{width:97px;height:21px;background:url("../img/ko_KR/btn_set.png?130306") -369px -163px no-repeat}
|
||||
/* TEXT_TOOLBAR : QUICKEDITOR_IMAGE */
|
||||
#smart_editor2 .se2_qe10{width:166px;margin:0;*margin:-2px 0 0 0}
|
||||
#smart_editor2 .se2_qe10 label{margin:0 1px 0 0;vertical-align:middle}
|
||||
#smart_editor2 .se2_qe10 .se2_sheight{margin-left:4px}
|
||||
#smart_editor2 .se2_qe10 .input_ty1{width:30px;height:13px;margin:0 0 1px 1px;padding:3px 4px 0 1px;font-size:11px;letter-spacing:0;text-align:right;vertical-align:middle}
|
||||
#smart_editor2 .se2_qe10 .se2_sreset{width:41px;height:19px;margin-left:3px;background:url("../img/ko_KR/btn_set.png?130306") -401px -184px no-repeat;vertical-align:middle}
|
||||
#smart_editor2 .se2_qe10_1{margin-top:4px;padding:10px 0 3px;background:url("../img/bg_line1.gif") repeat-x}
|
||||
#smart_editor2 .se2_qe10_1 input{width:15px;height:15px;margin:-1px 3px 1px -1px;vertical-align:middle}
|
||||
#smart_editor2 .se2_qe11{float:left;width:166px;margin:4px 0 0 0;padding:7px 0 2px 0;background:url("../img/bg_line1.gif") repeat-x}
|
||||
#smart_editor2 .se2_qe11_1{float:left;width:99px}
|
||||
#smart_editor2 .se2_qe11_1 dt{float:left;width:56px;height:15px;padding:5px 0 0 0}
|
||||
#smart_editor2 .se2_qe11_1 dd{float:left;position:relative;width:38px;height:20px}
|
||||
#smart_editor2 .se2_qe11_1 .input_ty1{display:block;width:29px;height:15px;margin:0;*margin:-1px 0 1px 0;padding:3px 1px 0 5px;font-size:11px;letter-spacing:0;text-align:left}
|
||||
#smart_editor2 .se2_qe11_1 .se2_add{position:absolute;top:2px;right:3px;width:13px;height:8px;background:url("../img/ko_KR/btn_set.png?130306") -86px -54px no-repeat}
|
||||
#smart_editor2 .se2_qe11_1 .se2_del{position:absolute;top:10px;right:3px;width:13px;height:8px;background:url("../img/ko_KR/btn_set.png?130306") -86px -62px no-repeat}
|
||||
#smart_editor2 .se2_qe11_2{float:left;width:67px}
|
||||
#smart_editor2 .se2_qe11_2 dt{float:left;width:47px;margin:5px 0 0 0}
|
||||
#smart_editor2 .se2_qe11_2 dd{float:left;position:relative;width:20px}
|
||||
#smart_editor2 .se2_qe12{float:left;width:166px;margin:3px 0 0 0;padding:7px 0 0 0;background:url("../img/bg_line1.gif") repeat-x}
|
||||
#smart_editor2 .se2_qe12 dt{float:left;margin:5px 4px 0 0}
|
||||
#smart_editor2 .se2_qe12 dd{float:left;padding:0 0 6px 0}
|
||||
#smart_editor2 .se2_qe12 .se2_align0{float:left;width:19px;height:21px;background:url("../img/ko_KR/btn_set.png?130306") -276px -121px no-repeat}
|
||||
#smart_editor2 .se2_qe12 .se2_align1{float:left;width:19px;height:21px;background:url("../img/ko_KR/btn_set.png?130306") -295px -121px no-repeat}
|
||||
#smart_editor2 .se2_qe12 .se2_align2{float:left;width:20px;height:21px;background:url("../img/ko_KR/btn_set.png?130306") -314px -121px no-repeat}
|
||||
#smart_editor2 .se2_qe13{position:relative;z-index:10;zoom:1}
|
||||
#smart_editor2 .se2_qe13 dt{float:left;width:62px;padding:3px 0 0}
|
||||
#smart_editor2 .se2_qe13 dt input{width:15px;height:15px;margin:-1px 1px 1px -1px;vertical-align:middle;zoom:1}
|
||||
#smart_editor2 .se2_qe13 dt .se2_qdim2{width:32px}
|
||||
#smart_editor2 .se2_qe13 dd .se2_select_ty1{width:38px}
|
||||
#smart_editor2 .se2_qe13 dd .se2_select_ty1 span{width:15px}
|
||||
#smart_editor2 .se2_qe13 dd .input_ty1{width:20px}
|
||||
#smart_editor2 .se2_qe13 dd .se2_palette2 .input_ty1{width:67px}
|
||||
#smart_editor2 .se2_qe13 .se2_add{*top:3px}
|
||||
#smart_editor2 .se2_qe13 .se2_del{*top:11px}
|
||||
#smart_editor2 .se2_qe13 .se2_layer_b_style{right:-2px;_right:0}
|
||||
#smart_editor2 .se2_qe13 .se2_layer_b_style li span{width:auto;margin:0 4px 0 5px;padding-top:2px}
|
||||
#smart_editor2 .se2_qe13 dd{_display:inline;float:left;position:relative;width:29px;margin-right:5px;_margin-right:3px;zoom:1}
|
||||
#smart_editor2 .se2_qe13 dd .se2_palette h4{margin-top:9px;font-family:dotum;font-size:12px}
|
||||
#smart_editor2 .se2_qe13 dd.dd_type{width:38px}
|
||||
#smart_editor2 .se2_qe13 dd.dd_type2{width:37px;margin-right:3px}
|
||||
#smart_editor2 .se2_qe13 dd.dd_type2 .input_ty1{width:29px}
|
||||
#smart_editor2 .se2_qe13 dd.dd_type2 button{right:2px;_right:1px}
|
||||
#smart_editor2 .se2_qe13 dd.dd_type3{width:20px;margin:0}
|
||||
#smart_editor2 .se2_qe13_v1{_display:inline;float:left;margin:2px 0 1px}
|
||||
#smart_editor2 .se2_qe13_v1 dt{padding:4px 0 0 1px}
|
||||
#smart_editor2 .se2_qe13_v2{_display:inline;float:left;position:relative;z-index:100;width:165px;margin:4px 0 0 1px;zoom:1}
|
||||
#smart_editor2 .se2_qe13_v2 dd{width:18px;margin:0}
|
||||
#smart_editor2 .se2_qeditor .se2_qdim1{clear:both;position:absolute;top:25px;left:115px;width:60px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_qeditor .se2_qdim2{clear:both;position:absolute;top:55px;left:24px;z-index:110;width:70px;height:22px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_qeditor .se2_qdim3{clear:both;position:absolute;top:55px;left:118px;z-index:110;width:56px;height:22px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_qeditor .se2_qdim4{clear:both;position:absolute;top:81px;left:23px;z-index:35;width:116px;height:35px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_qeditor .se2_qdim5{clear:both;position:absolute;top:31px;left:106px;width:68px;height:26px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_qeditor .se2_qdim6c{clear:both;position:absolute;top:25px;left:28px;width:29px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_qeditor .se2_qdim6r{clear:both;position:absolute;top:25px;left:57px;width:29px;height:23px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_highedit{float:right;width:56px;height:21px;margin:-27px 8px 0 0;background:url("../img/ko_KR/btn_set.png?130306") -329px -142px no-repeat}
|
||||
#smart_editor2 .se2_qeditor .se2_qdim7{clear:both;position:absolute;top:55px;left:24px;z-index:110;width:150px;height:48px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_qeditor .se2_qdim8{clear:both;position:absolute;top:105px;left:24px;z-index:110;width:150px;height:37px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_qeditor .se2_qdim9{clear:both;position:absolute;top:55px;left:111px;z-index:110;width:65px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_qeditor .se2_qdim10{clear:both;position:absolute;top:55px;left:100px;z-index:110;width:77px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
#smart_editor2 .se2_qeditor .se2_qdim11{clear:both;position:absolute;top:55px;left:65px;z-index:110;width:115px;height:24px;background:#fafafa;opacity:0.5;filter:alpha(opacity=50)}
|
||||
/* HELP : ACCESSIBILITY */
|
||||
#smart_editor2 .se2_accessibility{z-index:90}
|
||||
#smart_editor2 .se2_accessibility .se2_in_layer{width:568px;padding:0 10px;background:#fafafa;border:1px solid #bcbbbb}
|
||||
#smart_editor2 .se2_accessibility h3{margin:0 -10px;padding:6px 0 12px 0;background:url("../img/bg_find_h3.gif") repeat-x;font-size:12px;line-height:14px;letter-spacing:-1px}
|
||||
#smart_editor2 .se2_accessibility h3 strong{display:inline-block;padding:4px 0 3px 11px;color:#333;letter-spacing:0}
|
||||
#smart_editor2 .se2_accessibility .se2_close{position:absolute;top:10px;right:12px;width:13px;height:12px;background:url("../img/ko_KR/btn_set.png?130306") -155px -5px no-repeat}
|
||||
#smart_editor2 .se2_accessibility .box_help{padding:0 2px;margin-top:8px;background:url("../img/bg_help.gif") 0 100% no-repeat}
|
||||
#smart_editor2 .se2_accessibility .box_help div{overflow:hidden;padding:20px 21px 24px;border-top:1px solid #d0d0d0;color:#333}
|
||||
#smart_editor2 .se2_accessibility .box_help strong{display:block;margin-bottom:2px}
|
||||
#smart_editor2 .se2_accessibility .box_help p{margin-bottom:28px;line-height:1.5}
|
||||
#smart_editor2 .se2_accessibility .box_help ul{width:150%;margin-top:10px}
|
||||
#smart_editor2 .se2_accessibility .box_help li{position:relative;float:left;width:252px;padding:5px 0 5px 9px;margin-right:40px;background:url("../img/ko_KR/btn_set.png?130306") -475px -51px no-repeat;border-right:1px solid #f0f0f0;*zoom:1;line-height:1}
|
||||
#smart_editor2 .se2_accessibility .box_help li span{position:absolute;top:4px;left:138px;line-height:1.2}
|
||||
#smart_editor2 .se2_accessibility .se2_btns{padding:9px 0 10px;text-align:center}
|
||||
#smart_editor2 .se2_accessibility .se2_btns .se2_close2{width:39px;height:24px;background:url("../img/ko_KR/btn_set.png?130306") -235px -120px no-repeat}
|
||||
@@ -0,0 +1,12 @@
|
||||
@charset "UTF-8";
|
||||
/* NHN Web Standardization Team (http://html.nhndesign.com/) HHJ 090226 */
|
||||
/* COMMON */
|
||||
.se2_outputarea,.se2_outputarea th,.se2_outputarea td{margin:0;padding:0;color:#666;font-size:12px;font-family:'돋움',Dotum,'굴림',Gulim,Helvetica,Sans-serif;line-height:1.5}
|
||||
.se2_outputarea p{margin:0;padding:0}
|
||||
.se2_outputarea a:hover{text-decoration:underline}
|
||||
.se2_outputarea a:link{color:#0000ff}
|
||||
.se2_outputarea ul{margin:0 0 0 40px;padding:0}
|
||||
.se2_outputarea ul li{margin:0;list-style-type:disc;padding:0}
|
||||
.se2_outputarea ul ul li{list-style-type:circle}
|
||||
.se2_outputarea ul ul ul li{list-style-type:square}
|
||||
.se2_outputarea img,.se2_outputarea fieldset{border:0}
|
||||
|
After Width: | Height: | Size: 115 B |
|
After Width: | Height: | Size: 526 B |
|
After Width: | Height: | Size: 331 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 159 B |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 103 B |
|
After Width: | Height: | Size: 43 B |
|
After Width: | Height: | Size: 56 B |
|
After Width: | Height: | Size: 941 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 104 B |
|
After Width: | Height: | Size: 139 B |
|
After Width: | Height: | Size: 155 B |
|
After Width: | Height: | Size: 270 B |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
@@ -0,0 +1,134 @@
|
||||
if(typeof window.nhn=='undefined') window.nhn = {};
|
||||
if (!nhn.husky) nhn.husky = {};
|
||||
|
||||
/**
|
||||
* @fileOverview This file contains application creation helper function, which would load up an HTML(Skin) file and then execute a specified create function.
|
||||
* @name HuskyEZCreator.js
|
||||
*/
|
||||
nhn.husky.EZCreator = new (function(){
|
||||
this.nBlockerCount = 0;
|
||||
|
||||
this.createInIFrame = function(htOptions){
|
||||
if(arguments.length == 1){
|
||||
var oAppRef = htOptions.oAppRef;
|
||||
var elPlaceHolder = htOptions.elPlaceHolder;
|
||||
var sSkinURI = htOptions.sSkinURI;
|
||||
var fCreator = htOptions.fCreator;
|
||||
var fOnAppLoad = htOptions.fOnAppLoad;
|
||||
var bUseBlocker = htOptions.bUseBlocker;
|
||||
var htParams = htOptions.htParams || null;
|
||||
}else{
|
||||
// for backward compatibility only
|
||||
var oAppRef = arguments[0];
|
||||
var elPlaceHolder = arguments[1];
|
||||
var sSkinURI = arguments[2];
|
||||
var fCreator = arguments[3];
|
||||
var fOnAppLoad = arguments[4];
|
||||
var bUseBlocker = arguments[5];
|
||||
var htParams = arguments[6];
|
||||
}
|
||||
|
||||
if(bUseBlocker) nhn.husky.EZCreator.showBlocker();
|
||||
|
||||
var attachEvent = function(elNode, sEvent, fHandler){
|
||||
if(elNode.addEventListener){
|
||||
elNode.addEventListener(sEvent, fHandler, false);
|
||||
}else{
|
||||
elNode.attachEvent("on"+sEvent, fHandler);
|
||||
}
|
||||
}
|
||||
|
||||
if(!elPlaceHolder){
|
||||
alert("Placeholder is required!");
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof(elPlaceHolder) != "object")
|
||||
elPlaceHolder = document.getElementById(elPlaceHolder);
|
||||
|
||||
var elIFrame, nEditorWidth, nEditorHeight;
|
||||
|
||||
|
||||
try{
|
||||
elIFrame = document.createElement("<IFRAME frameborder=0 scrolling=no>");
|
||||
}catch(e){
|
||||
elIFrame = document.createElement("IFRAME");
|
||||
elIFrame.setAttribute("frameborder", "0");
|
||||
elIFrame.setAttribute("scrolling", "no");
|
||||
}
|
||||
|
||||
elIFrame.style.width = "1px";
|
||||
elIFrame.style.height = "1px";
|
||||
elPlaceHolder.parentNode.insertBefore(elIFrame, elPlaceHolder.nextSibling);
|
||||
|
||||
attachEvent(elIFrame, "load", function(){
|
||||
fCreator = elIFrame.contentWindow[fCreator] || elIFrame.contentWindow.createSEditor2;
|
||||
|
||||
// top.document.title = ((new Date())-window.STime);
|
||||
// window.STime = new Date();
|
||||
|
||||
try{
|
||||
|
||||
nEditorWidth = elIFrame.contentWindow.document.body.scrollWidth || "500px";
|
||||
nEditorHeight = elIFrame.contentWindow.document.body.scrollHeight + 12;
|
||||
elIFrame.style.width = "100%";
|
||||
elIFrame.style.height = nEditorHeight+ "px";
|
||||
elIFrame.contentWindow.document.body.style.margin = "0";
|
||||
}catch(e){
|
||||
nhn.husky.EZCreator.hideBlocker(true);
|
||||
elIFrame.style.border = "5px solid red";
|
||||
elIFrame.style.width = "500px";
|
||||
elIFrame.style.height = "500px";
|
||||
alert("Failed to access "+sSkinURI);
|
||||
return;
|
||||
}
|
||||
|
||||
var oApp = fCreator(elPlaceHolder, htParams); // oEditor
|
||||
|
||||
|
||||
oApp.elPlaceHolder = elPlaceHolder;
|
||||
|
||||
oAppRef[oAppRef.length] = oApp;
|
||||
if(!oAppRef.getById) oAppRef.getById = {};
|
||||
|
||||
if(elPlaceHolder.id) oAppRef.getById[elPlaceHolder.id] = oApp;
|
||||
|
||||
oApp.run({fnOnAppReady:fOnAppLoad});
|
||||
|
||||
// top.document.title += ", "+((new Date())-window.STime);
|
||||
nhn.husky.EZCreator.hideBlocker();
|
||||
});
|
||||
// window.STime = new Date();
|
||||
elIFrame.src = sSkinURI;
|
||||
this.elIFrame = elIFrame;
|
||||
};
|
||||
|
||||
this.showBlocker = function(){
|
||||
if(this.nBlockerCount<1){
|
||||
var elBlocker = document.createElement("DIV");
|
||||
elBlocker.style.position = "absolute";
|
||||
elBlocker.style.top = 0;
|
||||
elBlocker.style.left = 0;
|
||||
elBlocker.style.backgroundColor = "#FFFFFF";
|
||||
elBlocker.style.width = "100%";
|
||||
|
||||
document.body.appendChild(elBlocker);
|
||||
|
||||
nhn.husky.EZCreator.elBlocker = elBlocker;
|
||||
}
|
||||
|
||||
nhn.husky.EZCreator.elBlocker.style.height = Math.max(document.body.scrollHeight, document.body.clientHeight)+"px";
|
||||
|
||||
this.nBlockerCount++;
|
||||
};
|
||||
|
||||
this.hideBlocker = function(bForce){
|
||||
if(!bForce){
|
||||
if(--this.nBlockerCount > 0) return;
|
||||
}
|
||||
|
||||
this.nBlockerCount = 0;
|
||||
|
||||
if(nhn.husky.EZCreator.elBlocker) nhn.husky.EZCreator.elBlocker.style.display = "none";
|
||||
}
|
||||
})();
|
||||
@@ -0,0 +1,93 @@
|
||||
function createSEditor2(elIRField, htParams, elSeAppContainer){
|
||||
if(!window.$Jindo){
|
||||
parent.document.body.innerHTML="진도 프레임웍이 필요합니다.<br>\n<a href='http://dev.naver.com/projects/jindo/download'>http://dev.naver.com/projects/jindo/download</a>에서 Jindo 1.5.3 버전의 jindo.min.js를 다운로드 받아 /js 폴더에 복사 해 주세요.\n(아직 Jindo 2 는 지원하지 않습니다.)";
|
||||
return;
|
||||
}
|
||||
|
||||
var elAppContainer = (elSeAppContainer || jindo.$("smart_editor2"));
|
||||
var elEditingArea = jindo.$$.getSingle("DIV.husky_seditor_editing_area_container", elAppContainer);
|
||||
var oWYSIWYGIFrame = jindo.$$.getSingle("IFRAME.se2_input_wysiwyg", elEditingArea);
|
||||
var oIRTextarea = elIRField?elIRField:jindo.$$.getSingle("TEXTAREA.blind", elEditingArea);
|
||||
var oHTMLSrc = jindo.$$.getSingle("TEXTAREA.se2_input_htmlsrc", elEditingArea);
|
||||
var oTextArea = jindo.$$.getSingle("TEXTAREA.se2_input_text", elEditingArea);
|
||||
|
||||
if(!htParams){
|
||||
htParams = {};
|
||||
htParams.fOnBeforeUnload = null;
|
||||
}
|
||||
htParams.elAppContainer = elAppContainer; // 에디터 UI 최상위 element 셋팅
|
||||
htParams.oNavigator = jindo.$Agent().navigator(); // navigator 객체 셋팅
|
||||
|
||||
var oEditor = new nhn.husky.HuskyCore(htParams);
|
||||
oEditor.registerPlugin(new nhn.husky.CorePlugin(htParams?htParams.fOnAppLoad:null));
|
||||
oEditor.registerPlugin(new nhn.husky.StringConverterManager());
|
||||
|
||||
var htDimension = {
|
||||
nMinHeight:205,
|
||||
nMinWidth:parseInt(elIRField.style.minWidth, 10)||570,
|
||||
nHeight:elIRField.style.height||elIRField.offsetHeight,
|
||||
nWidth:elIRField.style.width||elIRField.offsetWidth
|
||||
};
|
||||
|
||||
var htConversionMode = {
|
||||
bUseVerticalResizer : htParams.bUseVerticalResizer,
|
||||
bUseModeChanger : htParams.bUseModeChanger
|
||||
};
|
||||
|
||||
var aAdditionalFontList = htParams.aAdditionalFontList;
|
||||
|
||||
oEditor.registerPlugin(new nhn.husky.SE_EditingAreaManager("WYSIWYG", oIRTextarea, htDimension, htParams.fOnBeforeUnload, elAppContainer));
|
||||
oEditor.registerPlugin(new nhn.husky.SE_EditingArea_WYSIWYG(oWYSIWYGIFrame)); // Tab Editor 모드
|
||||
oEditor.registerPlugin(new nhn.husky.SE_EditingArea_HTMLSrc(oHTMLSrc)); // Tab HTML 모드
|
||||
oEditor.registerPlugin(new nhn.husky.SE_EditingArea_TEXT(oTextArea)); // Tab Text 모드
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_EditingModeChanger(elAppContainer, htConversionMode)); // 모드간 변경(Editor, HTML, Text)
|
||||
oEditor.registerPlugin(new nhn.husky.SE_PasteHandler()); // WYSIWYG Paste Handler
|
||||
|
||||
oEditor.registerPlugin(new nhn.husky.HuskyRangeManager(oWYSIWYGIFrame));
|
||||
oEditor.registerPlugin(new nhn.husky.Utils());
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_UtilPlugin());
|
||||
oEditor.registerPlugin(new nhn.husky.SE_WYSIWYGStyler());
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_Toolbar(elAppContainer));
|
||||
|
||||
oEditor.registerPlugin(new nhn.husky.Hotkey()); // 단축키
|
||||
oEditor.registerPlugin(new nhn.husky.SE_EditingAreaVerticalResizer(elAppContainer, htConversionMode)); // 편집영역 리사이즈
|
||||
oEditor.registerPlugin(new nhn.husky.DialogLayerManager());
|
||||
oEditor.registerPlugin(new nhn.husky.ActiveLayerManager());
|
||||
oEditor.registerPlugin(new nhn.husky.SE_WYSIWYGStyleGetter()); // 커서 위치 스타일 정보 가져오기
|
||||
|
||||
oEditor.registerPlugin(new nhn.husky.SE_WYSIWYGEnterKey("P")); // 엔터 시 처리, 현재는 P로 처리
|
||||
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_ColorPalette(elAppContainer)); // 색상 팔레트
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_FontColor(elAppContainer)); // 글자색
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_BGColor(elAppContainer)); // 글자배경색
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_FontNameWithLayerUI(elAppContainer, aAdditionalFontList)); // 글꼴종류
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_FontSizeWithLayerUI(elAppContainer)); // 글꼴크기
|
||||
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_LineStyler());
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_ExecCommand(oWYSIWYGIFrame));
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_LineHeightWithLayerUI(elAppContainer)); // 줄간격
|
||||
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_Quote(elAppContainer)); // 인용구
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_Hyperlink(elAppContainer)); // 링크
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_SCharacter(elAppContainer)); // 특수문자
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_FindReplacePlugin(elAppContainer)); // 찾기/바꾸기
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_TableCreator(elAppContainer)); // 테이블 생성
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_TableEditor(elAppContainer)); // 테이블 편집
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_TableBlockStyler(elAppContainer)); // 테이블 스타일
|
||||
if(nhn.husky.SE2M_AttachQuickPhoto){
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_AttachQuickPhoto(elAppContainer)); // 사진
|
||||
}
|
||||
|
||||
oEditor.registerPlugin(new nhn.husky.MessageManager(oMessageMap));
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_QuickEditor_Common(elAppContainer)); // 퀵에디터 공통(표, 이미지)
|
||||
|
||||
oEditor.registerPlugin(new nhn.husky.SE2B_CSSLoader()); // CSS lazy load
|
||||
if(window.frameElement){
|
||||
oEditor.registerPlugin(new nhn.husky.SE_OuterIFrameControl(elAppContainer, 100));
|
||||
}
|
||||
|
||||
oEditor.registerPlugin(new nhn.husky.SE_ToolbarToggler(elAppContainer, htParams.bUseToolbar));
|
||||
oEditor.registerPlugin(new nhn.husky.SE2M_Accessibility(elAppContainer)); // 에디터내의 웹접근성 관련 기능모음 플러그인
|
||||
|
||||
return oEditor;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Smart Editor 2 Configuration : This setting must be changed by service
|
||||
*/
|
||||
window.nhn = window.nhn || {};
|
||||
nhn.husky = nhn.husky || {};
|
||||
nhn.husky.SE2M_Configuration = nhn.husky.SE2M_Configuration || {};
|
||||
|
||||
/**
|
||||
* CSS LazyLoad를 위한 경로
|
||||
*/
|
||||
nhn.husky.SE2M_Configuration.SE2B_CSSLoader = {
|
||||
sCSSBaseURI : "css"
|
||||
};
|
||||
|
||||
/**
|
||||
* 편집영역 설정
|
||||
*/
|
||||
nhn.husky.SE2M_Configuration.SE_EditingAreaManager = {
|
||||
sCSSBaseURI : "css", // smart_editor2_inputarea.html 파일의 상대경로
|
||||
sBlankPageURL : "smart_editor2_inputarea.html",
|
||||
sBlankPageURL_EmulateIE7 : "smart_editor2_inputarea_ie8.html",
|
||||
aAddtionalEmulateIE7 : [] // IE8 default 사용, IE9 ~ 선택적 사용
|
||||
};
|
||||
|
||||
/**
|
||||
* [웹접근성]
|
||||
* 단축키 ALT+, ALT+. 을 이용하여 스마트에디터 영역의 이전/이후 요소로 이동할 수 있다.
|
||||
* sBeforeElementId : 스마트에디터 영역 이전 요소의 id
|
||||
* sNextElementId : 스마트에디터 영역 이후 요소의 id
|
||||
*
|
||||
* 스마트에디터 영역 이외의 제목 영역 (예:스마트에디터가 적용된 블로그 쓰기 페이지에서의 제목 영역) 에 해당하는 엘리먼트에서 Tab키를 누르면 에디팅 영역으로 포커스를 이동시킬 수 있다.
|
||||
* sTitleElementId : 제목에 해당하는 input 요소의 id.
|
||||
*/
|
||||
nhn.husky.SE2M_Configuration.SE2M_Accessibility = {
|
||||
sBeforeElementId : '',
|
||||
sNextElementId : '',
|
||||
sTitleElementId : ''
|
||||
};
|
||||
|
||||
/**
|
||||
* 링크 기능 옵션
|
||||
*/
|
||||
nhn.husky.SE2M_Configuration.SE2M_Hyperlink = {
|
||||
bAutolink : true // 자동링크기능 사용여부(기본값:true)
|
||||
};
|
||||
|
||||
nhn.husky.SE2M_Configuration.Quote = {
|
||||
sImageBaseURL : 'http://static.se2.naver.com/static/img'
|
||||
};
|
||||
nhn.husky.SE2M_Configuration.SE2M_ColorPalette = {
|
||||
bAddRecentColorFromDefault : false
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
SmartEditor Basic 2.0 릴리즈 패키지
|
||||
|
||||
SmartEdtitor™는 Javascript로 구현된 웹 기반의 WYSIWYG 에디터입니다. SmartEdtitor™는 WYSIWYG 모드 및 HTML 편집 모드와 TEXT 모드를 제공하고, 자유로운 폰트 크기 설정 기능, 줄 간격 설정 기능, 단어 찾기/바꾸기 기능 등 편집에 필요한 다양한 기능을 제공하므로 사용자들은 SmartEdtitor™를 사용하여 쉽고 편리하게 원하는 형태의 글을 작성할 수 있습니다.
|
||||
또한, SmartEdtitor™의 구조는 기능을 쉽게 추가할 수 있는 플러그인 구조로 되어 있어 정해진 규칙에 따라 플러그인을 만들기만 하면 됩니다.
|
||||
|
||||
현재 SmartEdtitor™는 네이버, 한게임 등 NHN의 주요 서비스에 적용되어 있습니다.
|
||||
지원하는 브라우저 환경은 아래와 같으며 지속적으로 지원 대상 브라우저를 확장할 예정입니다.
|
||||
|
||||
* 지원하는 브라우저
|
||||
Internet Explorer 7.0+ / 10.0-
|
||||
FireFox 3.5+
|
||||
Safari 4.0+
|
||||
Chrome 4.0+
|
||||
|
||||
또한 지속적인 기능 추가를 통해 편리하고 강력한 에디터로 거듭날 것입니다.
|
||||
|
||||
라이센스 : LGPL v2
|
||||
홈페이지 : http://dev.naver.com/projects/smarteditor
|
||||
|
||||
===================================================================================
|
||||
|
||||
릴리즈 패키지에 포함된 파일은 아래와 같습니다.
|
||||
/css : 에디터에서 사용하는 css 파일
|
||||
/img : 에디터에서 사용하는 이미지 파일
|
||||
/js : 에디터를 적용할 때 사용하는 JS 파일
|
||||
/photo_uploader : 사진 퀵 업로더 팝업 UI를 구성하는 파일
|
||||
readme.txt : 간략한 설명
|
||||
release_notes.txt : 릴리즈 노트
|
||||
sample.php : SmartEditor2.html을 이용해 편집한 내용을 서버에서 받는 php 예제
|
||||
smart_editor2_inputarea.html : 에디터의 편집 영역을 나타내는 HTML로 에디터를 적용할 때 반드시 필요
|
||||
smart_editor2_inputarea_ie8.html : smart_editor2_inputarea.html와 동일한 기능이나 사용자의 브라우저 Internet Explorer 8.x 이상인 경우에 사용
|
||||
SmartEditor2.html : 에디터 데모 페이지. 에디터 적용 시에도 참고 할 수 있다.
|
||||
SmartEditor2Skin.html : 에디터를 적용한 페이지에서 로드하는 에디터의 스킨 HTML 파일로 에디터에서 사용하는 JS 파일과 css 파일을 링크하며 에디터의 마크업을 가지고 있다. SmartEditor2.html 에서도 확인할 수 있다.
|
||||
src_include.txt : 자바스크립트 플러그인 소스를 직접 수정하고자 할 경우 참고할 수 있는 파일
|
||||
|
||||
===================================================================================
|
||||
|
||||
사용 중 불편한 점이 있거나 버그를 발견하는 경우 SmartEdtitor™ 프로젝트의 이슈에 올려 주세요~~~
|
||||
http://dev.naver.com/projects/smarteditor/issue
|
||||
여기입니다! :)
|
||||
@@ -0,0 +1,255 @@
|
||||
==============================================================================================
|
||||
2.3.10_임시
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 버그 수정
|
||||
- 크롬 > 밑줄 선택 글작성하다 취소선 선택하고 밑줄 선택을 취소한 경우 툴바에 반영되지 않는 문제
|
||||
- 굵게/밑줄/기울림/취소선이 있는 상태에서 엔터치고 폰트크기 수정하면 이전 폰트크기로 줄간격이 유지되는 문제
|
||||
- 외부프로그램 테이블 복사 붙여넣기 관련 오류 수정
|
||||
- IE8이하 > 글자크기 지정 후 엔터를 치면 커서위치가 위로 올라감
|
||||
- IE9이상 > 글꼴 효과를 미리 지정 한 후에 텍스트 입력 시, 색상 변경은 적용되나 굵게 기울임 밑줄 취소선 등의 효과는 적용안됨
|
||||
- [FF]밑줄 선택> 내용입력 후 엔터>밑줄 취소 후 내용 입력>마우스로 커서 클릭 후 내용 계속 입력 시 밑줄이 있는 글로 노출됨
|
||||
- [FF] 메모장에서 작성한 내용을 붙여넣기 후 엔터 > 내용입력 > 엔터 했을 때 줄바꿈이 되지 않는 현상
|
||||
- HTML5 > 글자를 선택하여 폰트크기 지정시 굵게/밑줄/기울림/취소선이 있으면 이전에 적용한 폰트크기 기준으로 줄간격이 유지되는 문제
|
||||
|
||||
2. 기능 개선
|
||||
- IE에서 자동으로 공백이 삽입되는 문제
|
||||
- MacOS > 사파리 > 외부프로그램 테이블 붙여넣기 개선
|
||||
|
||||
3. 보안 패치
|
||||
- 사진첨부 샘플의 null byte injection 취약점 보완
|
||||
|
||||
==============================================================================================
|
||||
2.3.10
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 버그 수정
|
||||
- 크롬 > 브라우저 확대축소시 폰트크기가 잘못 나오는 이슈
|
||||
- IE > 표삽입>임의로 두개 칸 선택하여 셀 병합>행삽입 클릭 시 JS 오류 발생
|
||||
- IE11 > 호환성 보기를 설정하지 않을 경우 글꼴목록이 선택되지 않는 문제 수정
|
||||
|
||||
2. 기능 개선
|
||||
- 외부프로그램 테이블 복사 붙여넣기 개선
|
||||
- 입력창 조절 안내 레이어를 주석처리하면 스크립트 오류 발생
|
||||
|
||||
==============================================================================================
|
||||
2.3.9
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 버그 수정
|
||||
- 파이어폭스에서 에디팅시 스타일깨짐 등 오작동
|
||||
- Chrome > 찾기/바꾸기 > 모두바꾸기 버튼 클릭시 찾을단어가 지워지지 않고 남아있음
|
||||
|
||||
2. 기능 개선
|
||||
- 링크 > 자동링크 설정/해제 옵션 추가
|
||||
- [IE11] WYSIWYG 모드와 HTML 모드를 오갈 때마다 문서의 마지막에 비정상적인 <BR>이 첨가됩니다.
|
||||
- [웹접근성] 빠져나가기 단축키 기능 개선
|
||||
|
||||
==============================================================================================
|
||||
2.3.8
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 버그 수정
|
||||
- 테이블 내부 영역을 Shift + 클릭으로 선택 후 정렬하고 HTML 로 전환하면 더미 P 태그가 생성되는 문제 수정
|
||||
- 테이블 내부 영역 선택 혹은 에디터 내용 전체 선택 후 정렬 시 동작안함
|
||||
- [IE10, IE11] 표의 셀을 드래그했을 때 블럭 지정이 되지 않는 현상
|
||||
- HTML 모드 변환시 태그 자동 정렬에 의한 버그
|
||||
|
||||
2. 기능 개선
|
||||
- [MacOS 대응] 폰트변경이슈
|
||||
|
||||
==============================================================================================
|
||||
2.3.7
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 버그 수정
|
||||
- 에디터에 표 생성 후 일부 셀 선택하여 배경색 설정> 배경색 설정된 셀 선택 후 셀 삽입 시 색상이 삽입되지 않습니다.
|
||||
- [IE9특정] 글 작성 중 번호매기기 또는 글머리 적용 후 정렬방식을 변경하면 엔터키 누를 시 커서가 한줄 떨어져서 노출됩니다.
|
||||
- [IE10] 표 생성 후 표 드래그 시 셀의 너비/높이가 늘어나는 현상
|
||||
|
||||
2. 기능 개선
|
||||
- IE11 대응
|
||||
- 특수기호 삽입시 커서 위치가 뒤쪽으로 나오도록 개선
|
||||
- 커서에 활성화된 글꼴 확인 로직 개선
|
||||
|
||||
==============================================================================================
|
||||
2.3.6
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 버그 수정
|
||||
- 글 작성 후 번호매기기 적용하고 엔터키 수행하는 경우 JS 오류가 발생하는 현상 수정
|
||||
|
||||
==============================================================================================
|
||||
2.3.5
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 기능 개선
|
||||
- 줄간격 설정 시 값을 직접 입력하는 경우 줄간격의 최소값 적용
|
||||
|
||||
==============================================================================================
|
||||
2.3.4
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 버그 수정
|
||||
- [IE9/10] pre 태그의 바로 다음에 \n이 존재하는 경우 개행이 되지 않는 이슈 해결
|
||||
- 입력창 크기 조절바 사용 여부 오류 해결
|
||||
- 사진 퀵 업로더 모듈 오타 수정 ($newPath -> $new_path)
|
||||
|
||||
2. 기능 개선
|
||||
- 글꼴 목록에 글꼴 종류 추가하기 기능 (SmartEditor2.html 참조)
|
||||
- 사진 퀵 업로더 모듈에 이미지 파일 확장자 체크 추가
|
||||
|
||||
==============================================================================================
|
||||
2.3.3
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 버그 수정
|
||||
- IE9 에서 템플릿을 적용한 표 생성 후 일부의 셀을 드래그하는 경우 셀의 높이가 늘어나는 현상 수정
|
||||
|
||||
2. 기능 개선
|
||||
- MAC OS의 CMD 키로 Ctrl 단축키 기능 적용 확장
|
||||
- 기본 글꼴 종류 추가 (Courier New, 나눔고딕 코딩)
|
||||
|
||||
==============================================================================================
|
||||
2.3.1
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 기능 개선
|
||||
- [웹접근성] 글쓰기 영역의 iframe의 title속성에 단축키 설명 제공
|
||||
- [웹접근성] 제목 input영역에서 제목 입력 후 TAB하면 스마트에디터 편집 영역으로 포커스 이동하는 기능 추가
|
||||
- [웹접근성] 툴바 영역의 이전/다음 아이템 이동을 TAB, SHIFT+TAB으로 이동할 수 있도록 추가
|
||||
|
||||
==============================================================================================
|
||||
2.3.0
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 기능 개선
|
||||
- [웹접근성] 키보드로만 메뉴를 이동할 수 있도록 단축키 적용
|
||||
- [웹접근성] 웹접근성 도움말 제공
|
||||
- 편집모드와 사이즈 조절바 사용 옵션 추가
|
||||
- 사진 첨부 팝업 데모 파일 구조 개선
|
||||
|
||||
==============================================================================================
|
||||
2.2.1
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 버그 수정
|
||||
- 사진 퀵 업로더 추가 시, 가이드 대로 수행했을 때 사진 첨부가 2번 실행되는 문제 해결
|
||||
: loader-min.js 파일 내에 사진 퀵 업로더 소스가 포함되어 있던 부분 제거하여 소스 분리
|
||||
|
||||
2. 기능 개선
|
||||
- 툴바의 기능 제거/순서 변경이 쉽도록 마크업 구조 개선
|
||||
※ 툴바의 기능 제거/순서 변경은 가이드 문서를 참고하세요.
|
||||
|
||||
|
||||
3. 폴더/파일 변경
|
||||
- /js_src 폴더 제거
|
||||
- /js/smarteditor2.js 추가
|
||||
: /js_src 폴더를 /js/smarteditor2.js 로 대체했습니다.
|
||||
: /js_src 폴더 구조에서 사용자가 소스를 검색하여 수정하기 어렵던 부분을 보완하기 위하여
|
||||
: /js_src 폴더 내의 플러그인 소스를 통합한 /js/smarteditor2.js 를 추가했습니다.
|
||||
- /js/loader-min.js 제거
|
||||
- /js/smarteditor2.min.js 추가
|
||||
: /js/loader-min.js 파일을 /js/smarteditor2.min.js로 대체했습니다.
|
||||
- /quick_photo_uploader 폴더 추가
|
||||
- /popup 폴더 이동
|
||||
: /popup 폴더 - 사진 퀵 업로더의 팝업과 관련된 소스
|
||||
: /plugin 폴더 - 사진 퀵 업로더의 사진첨부를 처리하는 플러그인 js 소스
|
||||
- /img/ko_KR 폴더 추가
|
||||
: 이후의 다국어 버전 지원을 위하여 이미지 폴더 내 디렉토리가 추가되었습니다.
|
||||
: 언어 별 구분이 필요없는 이미지는 /img 바로 하위에 두었고,
|
||||
: 언어 별로 구분되어야 하는 이미지는 /img/ko_KR 과 같이 언어 별 디렉토리로 구분했습니다.
|
||||
: 버전 업그레이드를 하는 경우 이미지 경로가 변경된 점에 주의하시기 바랍니다.
|
||||
- /js/SE2B_Configuration.js 제거
|
||||
- /js/SE2B_Configuration_Service.js 추가
|
||||
- /js/SE2B_Configuration_General.js 추가
|
||||
: /js/SE2B_Configuration_Service.js 와 /js/SE2B_Configuration_General.js로 파일 분리했습니다.
|
||||
: /js/SE2B_Configuration_Service.js 는 적용을 할 때 사용자가 변경할 가능성이 높은 플러그인 설정을 갖고,
|
||||
: /js/SE2B_Configuration_General.js 는 서비스에 적용할 때 변경할 가능성이 거의 없는 설정입니다.
|
||||
|
||||
==============================================================================================
|
||||
2.1.3
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 버그 수정
|
||||
- [Chrome] 보기 페이지에 글자색이 설정되어 있는 경우 글 작성 시 내용에 적용한 글자색으로 노출되지 않는 문제 해결
|
||||
- 엔터 처리가 <BR>로 설정된 경우에도 텍스트 모드에서 모드변경 혹은 글 저장할 때 개행이 <P>로 표시되는 문제 해결
|
||||
- [IE9] 각주 삽입 시, 하단으로 떨어지는 이슈 해결
|
||||
- [Chrome] 인용구 밖에 글머리기호/번호매기기가 있을 때 인용구 안에서 글머리기호/번호매기기 시 내용이 인용구 밖으로 나가는 문제 해결
|
||||
- [IE] IE에서 특정 블로그 글을 복사하여 붙여넣기 했을 때 개행이 제거되는 문제 해결
|
||||
- 사진을 드래그해서 사이즈를 변경한 후 저장 혹은 HTML모드로 변경하면, 사진 사이즈가 원복되는 현상 해결
|
||||
- [Chrome/FF/Safari] 스크롤바가 생성되도록 문자입력 후 엔터 클릭하지 않은 상태에서 이미지 하나 삽입 시 이미지에 포커싱이 놓이지 않는 문제 해결
|
||||
- [IE9 표준] 사진을 스크롤로 일부 가린 상태에서 재편집하여 적용했을 때 계속 가려진 상태인 문제 해결
|
||||
- FF에서 사진을 여러장 첨부 시 스크롤이 가장 마지막 추가한 사진으로 내려가지 않음 해결
|
||||
- 호환 모드를 제거하고 사진 첨부 시 에디팅 영역의 커서 주위에 <sub><sup> 태그가 붙어서 글자가 매우 작게 되는 현상 해결
|
||||
- [IE9] 에디터에 각주 연속으로 입력 시 커서가 각주사이로 이동되는 현상 해결
|
||||
- 글꼴색/글꼴배경색 더보기에서 글꼴색 선택>다시 다른 색상 선택 후 처음 선택되었던 색상 선택 시 처음 선택색상이 원래 자리에서 삭제되지 않는 현상 해결
|
||||
- 제공하지 않는 기능인 이모티콘 플러그인 소스 제거
|
||||
- 플러그인 태그 코드 추가 시 <li> 태그와 <button> 태그 사이에 개행이 있으면 이벤트가 등록되지 않는 현상 해결
|
||||
|
||||
2. 기능 개선
|
||||
- 표 삽입 시 본문 작성 영역 안에 너비 100%로 생성되도록 개선
|
||||
- 호환모드 설정이 설정 파일 정보에 따라 처리되도록 변경
|
||||
|
||||
|
||||
==============================================================================================
|
||||
2.1.2
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 버그 수정
|
||||
- [IE9]Shift+Enter를 여러번 하고 글의 중간의 마지막 글자 다음에서 엔터를 쳤을 때 엔터 위치가 달라지는 현상 수정
|
||||
- [IE9]메모장에서 붙여 넣기 후 내용 중간의 마지막 글자 다음에서 엔터를 쳤을 때 엔터 위치가 달라지는 현상 수정
|
||||
- 한 줄 입력 후 색상을 적용하고 내용 중간에서 엔터를 쳤을 때 적용되었던 색상이 풀리던 현상 수정
|
||||
- 글꼴 레이어를 열었을 때, 샘플 텍스트가 잘못 나오던 현상 수정
|
||||
- 인용구를 14개까지 중첩하고, 15개부터 경고 창이 나오도록 수정
|
||||
|
||||
2. 기능 개선
|
||||
- 찾기/바꾸기 레이어를 닫았다가 다시 열 때, [바꿀 단어] 입력란이 초기화 되도록 개선
|
||||
- 찾기/바꾸기 레이어 오픈 시 툴바 버튼 inactive 처리
|
||||
- 표 추가 레이어의 테이블 색상, 배경 색상의 기본 값을 SmartEditor2Skin.html에서 변경할 수 있도록 함
|
||||
※주의 : 기존의 html파일에 덮어 씌우게 되면 기본 배경 색상이 다르게 표시됨
|
||||
따라서 반드시 새로 업데이트 된 html 파일을 사용하기를 권장
|
||||
임의로 수정하려면 위 파일의 아래 부분의 value를 아래와 같이 변경해야 함
|
||||
<input id="se2_b_color" name="" type="text" maxlength="7" value="#cccccc" class="input_ty3">
|
||||
<input id="se2_cellbg" name="" type="text" maxlength="7" value="#ffffff" class="input_ty3">
|
||||
|
||||
|
||||
==============================================================================================
|
||||
2.1.1
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 기능 추가
|
||||
- 에디터 로딩 완료 시점에 실행되는 함수 (fOnAppLoad) 정의
|
||||
|
||||
2. 버그 수정
|
||||
- 에디터 초기 Width에 100%가 설정될 수 있도록 수정, minWidth 설정 추가
|
||||
- 마크업에서 나눔 글꼴을 제외하면 JS 에러가 나는 문제 수정
|
||||
- [IE9] 글자 색상 적용 후 내용 중간에서 계속 Enter할 때 Enter가 되지 않는 오류 수정
|
||||
- [Chrome/Safari] 표 간단편집기 위에서 text를 drag하면 JS 에러가 발생하는 문제 수정
|
||||
|
||||
3. 기능 개선
|
||||
- 사진 퀵 업로더 : 쉽게 사용할 수 있도록 소스 수정 및 예제 보강
|
||||
|
||||
|
||||
==============================================================================================
|
||||
2.1.0
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 기능 추가
|
||||
- 사진 퀵 업로더 : 사진 첨부 팝업 UI 제공 (HTML5 지원)
|
||||
- 에디터 본문에 글 작성 후 창을 닫을 때 발생하는 alert 메세지를 사용자가 설정할 수 있도록 옵션을 추가함
|
||||
- Jindo 모듈을 패키지에 포함하도록 빌드를 수정함
|
||||
- document.domain을 제거함
|
||||
- 에디터 초기 Width를 설정할 수 있도록 수정함
|
||||
- 툴바의 접힘/펼침 기능을 제공하는 SE_ToolbarToggler 플러그인 추가함
|
||||
|
||||
2. 버그 수정
|
||||
- 에디터 리사이즈 시 북마크 태그가 본문에 추가되는 이슈 확인 및 수정함
|
||||
|
||||
|
||||
==============================================================================================
|
||||
2.0.0
|
||||
----------------------------------------------------------------------------------------------
|
||||
1. 기능 강화
|
||||
- 글꼴과 글자 크기
|
||||
: 기존의 Selectbox 형태의 글꼴 목록을 깔끔한 디자인의 레이어로 제공한다.
|
||||
- 글자색과 글자 배경색
|
||||
: 기존의 기본 색상표 이외에 다양한 색상을 선택할 수 있는 컬러 팔레트를 확장 지원한다.
|
||||
- 줄간격
|
||||
: 기존의 Selectbox 형태의 줄간격 목록을 깔끔한 디자인의 레이어로 제공한다.
|
||||
또한, 줄간격을 직접 설정할 수 있도록 직접 입력 기능도 확장 지원한다.
|
||||
- 인용구
|
||||
: 기존의 7가지에서 10가지로 인용구 디자인을 확장 지원한다.
|
||||
- 표
|
||||
: 표 생성 시 기존의 테두리 색상과 두께를 설정할 수 있는 기능 이외에 테두리 스타일을 설정할 수 있는 기능을 확장 지원한다.
|
||||
또한, 표 템플릿을 제공하여 보다 쉽게 표 스타일을 생성할 수 있도록 하였다.
|
||||
|
||||
2. 기능 추가
|
||||
- 표 간단편집기
|
||||
: 표 생성 후 스타일을 편집할 수 있도록 표 편집 기능을 추가 제공한다.
|
||||
- TEXT 모드
|
||||
: WYSIWYG와 HTML 모드 이외에 TEXT 모드를 제공하여 텍스트만으로 본문의 내용을 작성할 수 있도록 편집 모드를 추가 제공한다.
|
||||
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="ko" xml:lang="ko">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>Smart Editor™ WYSIWYG Mode</title>
|
||||
<link href="css/smart_editor2_in.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body class="smartOutput se2_inputarea">
|
||||
<p>
|
||||
<b><u>에디터 내용:</u></b>
|
||||
</p>
|
||||
|
||||
<div style="width:736px;">
|
||||
<?php
|
||||
$postMessage = $_POST["ir1"];
|
||||
echo $postMessage;
|
||||
?>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<b><span style="color:#FF0000">주의: </span>sample.php는 샘플 파일로 정상 동작하지 않을 수 있습니다. 이 점 주의바랍니다.</b>
|
||||
</p>
|
||||
|
||||
<?php echo(htmlspecialchars_decode('<img id="test" width="0" height="0">'))?>
|
||||
|
||||
<script>
|
||||
if(!document.getElementById("test")) {
|
||||
alert("PHP가 실행되지 않았습니다. 내용을 로컬 파일로 전송한 것이 아니라 서버로 전송했는지 확인 해 주십시오.");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @use 간단 포토 업로드용으로 제작되었습니다.
|
||||
* @author cielo
|
||||
* @See nhn.husky.SE2M_Configuration
|
||||
* @ 팝업 마크업은 SimplePhotoUpload.html과 SimplePhotoUpload_html5.html이 있습니다.
|
||||
*/
|
||||
|
||||
nhn.husky.SE2M_AttachQuickPhoto = jindo.$Class({
|
||||
name : "SE2M_AttachQuickPhoto",
|
||||
|
||||
$init : function(){},
|
||||
|
||||
$ON_MSG_APP_READY : function(){
|
||||
this.oApp.exec("REGISTER_UI_EVENT", ["photo_attach", "click", "ATTACHPHOTO_OPEN_WINDOW"]);
|
||||
},
|
||||
|
||||
$LOCAL_BEFORE_FIRST : function(sMsg){
|
||||
if(!!this.oPopupMgr){ return; }
|
||||
// Popup Manager에서 사용할 param
|
||||
this.htPopupOption = {
|
||||
oApp : this.oApp,
|
||||
sName : this.name,
|
||||
bScroll : false,
|
||||
sProperties : "",
|
||||
sUrl : ""
|
||||
};
|
||||
this.oPopupMgr = nhn.husky.PopUpManager.getInstance(this.oApp);
|
||||
},
|
||||
|
||||
/**
|
||||
* 포토 웹탑 오픈
|
||||
*/
|
||||
$ON_ATTACHPHOTO_OPEN_WINDOW : function(){
|
||||
this.htPopupOption.sUrl = this.makePopupURL();
|
||||
this.htPopupOption.sProperties = "left=0,top=0,width=403,height=359,scrollbars=yes,location=no,status=0,resizable=no";
|
||||
|
||||
this.oPopupWindow = this.oPopupMgr.openWindow(this.htPopupOption);
|
||||
|
||||
// 처음 로딩하고 IE에서 커서가 전혀 없는 경우
|
||||
// 복수 업로드시에 순서가 바뀜
|
||||
// [SMARTEDITORSUS-1698]
|
||||
this.oApp.exec('FOCUS', [true]);
|
||||
// --[SMARTEDITORSUS-1698]
|
||||
return (!!this.oPopupWindow ? true : false);
|
||||
},
|
||||
|
||||
/**
|
||||
* 서비스별로 팝업에 parameter를 추가하여 URL을 생성하는 함수
|
||||
* nhn.husky.SE2M_AttachQuickPhoto.prototype.makePopupURL로 덮어써서 사용하시면 됨.
|
||||
*/
|
||||
makePopupURL : function(){
|
||||
var sPopupUrl = "./sample/photo_uploader/photo_uploader.html";
|
||||
|
||||
return sPopupUrl;
|
||||
},
|
||||
|
||||
/**
|
||||
* 팝업에서 호출되는 메세지.
|
||||
*/
|
||||
$ON_SET_PHOTO : function(aPhotoData){
|
||||
var sContents,
|
||||
aPhotoInfo,
|
||||
htData;
|
||||
|
||||
if( !aPhotoData ){
|
||||
return;
|
||||
}
|
||||
|
||||
try{
|
||||
sContents = "";
|
||||
for(var i = 0; i <aPhotoData.length; i++){
|
||||
htData = aPhotoData[i];
|
||||
|
||||
if(!htData.sAlign){
|
||||
htData.sAlign = "";
|
||||
}
|
||||
|
||||
aPhotoInfo = {
|
||||
sName : htData.sFileName || "",
|
||||
sOriginalImageURL : htData.sFileURL,
|
||||
bNewLine : htData.bNewLine || false
|
||||
};
|
||||
|
||||
sContents += this._getPhotoTag(aPhotoInfo);
|
||||
}
|
||||
|
||||
this.oApp.exec("PASTE_HTML", [sContents]); // 위즐 첨부 파일 부분 확인
|
||||
}catch(e){
|
||||
// upload시 error발생에 대해서 skip함
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @use 일반 포토 tag 생성
|
||||
*/
|
||||
_getPhotoTag : function(htPhotoInfo){
|
||||
// id와 class는 썸네일과 연관이 많습니다. 수정시 썸네일 영역도 Test
|
||||
var sTag = '<img src="{=sOriginalImageURL}" title="{=sName}" >';
|
||||
if(htPhotoInfo.bNewLine){
|
||||
sTag += '<br style="clear:both;">';
|
||||
}
|
||||
sTag = jindo.$Template(sTag).process(htPhotoInfo);
|
||||
|
||||
return sTag;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,684 @@
|
||||
//변수 선언 및 초기화
|
||||
var nImageInfoCnt = 0;
|
||||
var htImageInfo = []; //image file정보 저장
|
||||
var aResult = [];
|
||||
|
||||
var rFilter = /^(image\/bmp|image\/gif|image\/jpg|image\/jpeg|image\/png)$/i;
|
||||
var rFilter2 = /^(bmp|gif|jpg|jpeg|png)$/i;
|
||||
var nTotalSize = 0;
|
||||
var nMaxImageSize = 10*1024*1024;
|
||||
var nMaxTotalImageSize = 50*1024*1024;
|
||||
var nMaxImageCount = 10;
|
||||
var nImageFileCount = 0;
|
||||
var bSupportDragAndDropAPI = false;
|
||||
var oFileUploader;
|
||||
var bAttachEvent = false;
|
||||
|
||||
//마크업에 따른 할당
|
||||
var elContent= $("pop_content");
|
||||
var elDropArea = jindo.$$.getSingle(".drag_area",elContent);
|
||||
var elDropAreaUL = jindo.$$.getSingle(".lst_type",elContent);
|
||||
var elCountTxtTxt = jindo.$$.getSingle("#imageCountTxt",elContent);
|
||||
var elTotalSizeTxt = jindo.$$.getSingle("#totalSizeTxt",elContent);
|
||||
var elTextGuide = $("guide_text");
|
||||
var welUploadInputBox = $Element("uploadInputBox");
|
||||
var oNavigator = jindo.$Agent().navigator();
|
||||
|
||||
//마크업-공통
|
||||
var welBtnConfirm = $Element("btn_confirm"); //확인 버튼
|
||||
var welBtnCancel= $Element("btn_cancel"); //취소 버튼
|
||||
|
||||
//진도로 랩핑된 element
|
||||
var welTextGuide = $Element(elTextGuide);
|
||||
var welDropArea = $Element(elDropArea);
|
||||
var welDropAreaUL = $Element(elDropAreaUL);
|
||||
var fnUploadImage = null;
|
||||
|
||||
//File API 지원 여부로 결정
|
||||
function checkDragAndDropAPI(){
|
||||
try{
|
||||
if( !oNavigator.ie ){
|
||||
if(!!oNavigator.safari && oNavigator.version <= 5){
|
||||
bSupportDragAndDropAPI = false;
|
||||
}else{
|
||||
bSupportDragAndDropAPI = true;
|
||||
}
|
||||
} else {
|
||||
bSupportDragAndDropAPI = false;
|
||||
}
|
||||
}catch(e){
|
||||
bSupportDragAndDropAPI = false;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------- html5 미지원 브라우저에서 (IE9 이하) ---------------
|
||||
/**
|
||||
* 이미지를 첨부 후 활성화된 버튼 상태
|
||||
*/
|
||||
function goStartMode(){
|
||||
var sSrc = welBtnConfirm.attr("src")|| "";
|
||||
if(sSrc.indexOf("btn_confirm2.png") < 0 ){
|
||||
welBtnConfirm.attr("src","./img/btn_confirm2.png");
|
||||
fnUploadImage.attach(welBtnConfirm.$value(), "click");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 이미지를 첨부 전 비활성화된 버튼 상태
|
||||
* @return
|
||||
*/
|
||||
function goReadyMode(){
|
||||
var sSrc = welBtnConfirm.attr("src")|| "";
|
||||
if(sSrc.indexOf("btn_confirm2.png") >= 0 ){
|
||||
fnUploadImage.detach(welBtnConfirm.$value(), "click");
|
||||
welBtnConfirm.attr("src","./img/btn_confirm.png");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 일반 업로드
|
||||
* @desc oFileUploader의 upload함수를 호출함.
|
||||
*/
|
||||
function generalUpload(){
|
||||
oFileUploader.upload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 이미지 첨부 전 안내 텍스트가 나오는 배경으로 '설정'하는 함수.
|
||||
* @return
|
||||
*/
|
||||
function readyModeBG (){
|
||||
var sClass = welTextGuide.className();
|
||||
if(sClass.indexOf('nobg') >= 0){
|
||||
welTextGuide.removeClass('nobg');
|
||||
welTextGuide.className('bg');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 이미지 첨부 전 안내 텍스트가 나오는 배경을 '제거'하는 함수.
|
||||
* @return
|
||||
*/
|
||||
function startModeBG (){
|
||||
var sClass = welTextGuide.className();
|
||||
if(sClass.indexOf('nobg') < 0){
|
||||
welTextGuide.removeClass('bg');
|
||||
welTextGuide.className('nobg');
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------- html5 지원되는 브라우저에서 사용하는 함수 --------------------------
|
||||
/**
|
||||
* 팝업에 노출될 업로드 예정 사진의 수.
|
||||
* @param {Object} nCount 현재 업로드 예정인 사진 장수
|
||||
* @param {Object} nVariable 삭제되는 수
|
||||
*/
|
||||
function updateViewCount (nCount, nVariable){
|
||||
var nCnt = nCount + nVariable;
|
||||
elCountTxtTxt.innerHTML = nCnt +"장";
|
||||
nImageFileCount = nCnt;
|
||||
return nCnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 팝업에 노출될 업로드될 사진 총 용량
|
||||
*/
|
||||
function updateViewTotalSize(){
|
||||
var nViewTotalSize = Number(parseInt((nTotalSize || 0), 10) / (1024*1024));
|
||||
elTotalSizeTxt.innerHTML = nViewTotalSize.toFixed(2) +"MB";
|
||||
}
|
||||
|
||||
/**
|
||||
* 이미지 전체 용량 재계산.
|
||||
* @param {Object} sParentId
|
||||
*/
|
||||
function refreshTotalImageSize(sParentId){
|
||||
var nDelImgSize = htImageInfo[sParentId].size;
|
||||
if(nTotalSize - nDelImgSize > -1 ){
|
||||
nTotalSize = nTotalSize - nDelImgSize;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* hash table에서 이미지 정보 초기화.
|
||||
* @param {Object} sParentId
|
||||
*/
|
||||
function removeImageInfo (sParentId){
|
||||
//삭제된 이미지의 공간을 초기화 한다.
|
||||
htImageInfo[sParentId] = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* byte로 받은 이미지 용량을 화면에 표시를 위해 포맷팅
|
||||
* @param {Object} nByte
|
||||
*/
|
||||
function setUnitString (nByte) {
|
||||
var nImageSize;
|
||||
var sUnit;
|
||||
|
||||
if(nByte < 0 ){
|
||||
nByte = 0;
|
||||
}
|
||||
|
||||
if( nByte < 1024) {
|
||||
nImageSize = Number(nByte);
|
||||
sUnit = 'B';
|
||||
return nImageSize + sUnit;
|
||||
} else if( nByte > (1024*1024)) {
|
||||
nImageSize = Number(parseInt((nByte || 0), 10) / (1024*1024));
|
||||
sUnit = 'MB';
|
||||
return nImageSize.toFixed(2) + sUnit;
|
||||
} else {
|
||||
nImageSize = Number(parseInt((nByte || 0), 10) / 1024);
|
||||
sUnit = 'KB';
|
||||
return nImageSize.toFixed(0) + sUnit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 화면 목록에 적당하게 이름을 잘라서 표시.
|
||||
* @param {Object} sName 파일명
|
||||
* @param {Object} nMaxLng 최대 길이
|
||||
*/
|
||||
function cuttingNameByLength (sName, nMaxLng) {
|
||||
var sTemp, nIndex;
|
||||
if(sName.length > nMaxLng){
|
||||
nIndex = sName.indexOf(".");
|
||||
sTemp = sName.substring(0,nMaxLng) + "..." + sName.substring(nIndex,sName.length) ;
|
||||
} else {
|
||||
sTemp = sName;
|
||||
}
|
||||
return sTemp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Total Image Size를 체크해서 추가로 이미지를 넣을지 말지를 결정함.
|
||||
* @param {Object} nByte
|
||||
*/
|
||||
function checkTotalImageSize(nByte){
|
||||
if( nTotalSize + nByte < nMaxTotalImageSize){
|
||||
nTotalSize = nTotalSize + nByte;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 이벤트 핸들러 할당
|
||||
function dragEnter(ev) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
function dragExit(ev) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
function dragOver(ev) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* 드랍 영역에 사진을 떨구는 순간 발생하는 이벤트
|
||||
* @param {Object} ev
|
||||
*/
|
||||
function drop(ev) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
|
||||
if (nImageFileCount >= 10){
|
||||
alert("최대 10장까지만 등록할 수 있습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof ev.dataTransfer.files == 'undefined'){
|
||||
alert("HTML5를 지원하지 않는 브라우저입니다.");
|
||||
}else{
|
||||
//변수 선언
|
||||
var wel,
|
||||
files,
|
||||
nCount,
|
||||
sListTag = '';
|
||||
|
||||
//초기화
|
||||
files = ev.dataTransfer.files;
|
||||
nCount = files.length;
|
||||
|
||||
if (!!files && nCount === 0){
|
||||
//파일이 아닌, 웹페이지에서 이미지를 드래서 놓는 경우.
|
||||
alert("정상적인 첨부방식이 아닙니다.");
|
||||
return ;
|
||||
}
|
||||
|
||||
for (var i = 0, j = nImageFileCount ; i < nCount ; i++){
|
||||
if (!rFilter.test(files[i].type)) {
|
||||
alert("이미지파일 (jpg,gif,png,bmp)만 업로드 가능합니다.");
|
||||
} else if(files[i].size > nMaxImageSize){
|
||||
alert("이미지 용량이 10MB를 초과하여 등록할 수 없습니다.");
|
||||
} else {
|
||||
//제한된 수만 업로드 가능.
|
||||
if ( j < nMaxImageCount ){
|
||||
sListTag += addImage(files[i]);
|
||||
|
||||
//다음 사진을위한 셋팅
|
||||
j = j+1;
|
||||
nImageInfoCnt = nImageInfoCnt+1;
|
||||
} else {
|
||||
alert("최대 10장까지만 등록할 수 있습니다.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(j > 0){
|
||||
//배경 이미지 변경
|
||||
startModeBG();
|
||||
if ( sListTag.length > 1){
|
||||
welDropAreaUL.prependHTML(sListTag);
|
||||
}
|
||||
//이미지 총사이즈 view update
|
||||
updateViewTotalSize();
|
||||
//이미치 총 수 view update
|
||||
nImageFileCount = j;
|
||||
updateViewCount(nImageFileCount, 0);
|
||||
// 저장 버튼 활성화
|
||||
goStartMode();
|
||||
}else{
|
||||
readyModeBG();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 이미지를 추가하기 위해서 file을 저장하고, 목록에 보여주기 위해서 string을 만드는 함수.
|
||||
* @param ofile 한개의 이미지 파일
|
||||
* @return
|
||||
*/
|
||||
function addImage(ofile){
|
||||
//파일 사이즈
|
||||
var ofile = ofile,
|
||||
sFileSize = 0,
|
||||
sFileName = "",
|
||||
sLiTag = "",
|
||||
bExceedLimitTotalSize = false,
|
||||
aFileList = [];
|
||||
|
||||
sFileSize = setUnitString(ofile.size);
|
||||
sFileName = cuttingNameByLength(ofile.name, 15);
|
||||
bExceedLimitTotalSize = checkTotalImageSize(ofile.size);
|
||||
|
||||
if( !!bExceedLimitTotalSize ){
|
||||
alert("전체 이미지 용량이 50MB를 초과하여 등록할 수 없습니다. \n\n (파일명 : "+sFileName+", 사이즈 : "+sFileSize+")");
|
||||
} else {
|
||||
//이미지 정보 저장
|
||||
htImageInfo['img'+nImageInfoCnt] = ofile;
|
||||
|
||||
//List 마크업 생성하기
|
||||
aFileList.push(' <li id="img'+nImageInfoCnt+'" class="imgLi"><span>'+ sFileName +'</span>');
|
||||
aFileList.push(' <em>'+ sFileSize +'</em>');
|
||||
aFileList.push(' <a onclick="delImage(\'img'+nImageInfoCnt+'\')"><img class="del_button" src="./img/btn_del.png" width="14" height="13" alt="첨부 사진 삭제"></a>');
|
||||
aFileList.push(' </li> ');
|
||||
|
||||
sLiTag = aFileList.join(" ");
|
||||
aFileList = [];
|
||||
}
|
||||
return sLiTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML5 DragAndDrop으로 사진을 추가하고, 확인버튼을 누른 경우에 동작한다.
|
||||
* @return
|
||||
*/
|
||||
function html5Upload() {
|
||||
var tempFile,
|
||||
sUploadURL;
|
||||
|
||||
//sUploadURL= 'file_uploader_html5.php'; //upload URL
|
||||
sUploadURL= 'file_uploader_html5.jsp'; //upload URL
|
||||
|
||||
//파일을 하나씩 보내고, 결과를 받음.
|
||||
for(var j=0, k=0; j < nImageInfoCnt; j++) {
|
||||
tempFile = htImageInfo['img'+j];
|
||||
try{
|
||||
if(!!tempFile){
|
||||
//Ajax통신하는 부분. 파일과 업로더할 url을 전달한다.
|
||||
callAjaxForHTML5(tempFile,sUploadURL);
|
||||
k += 1;
|
||||
}
|
||||
}catch(e){}
|
||||
tempFile = null;
|
||||
}
|
||||
}
|
||||
|
||||
function callAjaxForHTML5 (tempFile, sUploadURL){
|
||||
var oAjax = jindo.$Ajax(sUploadURL, {
|
||||
type: 'xhr',
|
||||
method : "post",
|
||||
onload : function(res){ // 요청이 완료되면 실행될 콜백 함수
|
||||
var sResString = res._response.responseText;
|
||||
if (res.readyState() == 4) {
|
||||
if(sResString.indexOf("NOTALLOW_") > -1){
|
||||
var sFileName = sResString.replace("NOTALLOW_", "");
|
||||
alert("이미지 파일(jpg,gif,png,bmp)만 업로드 하실 수 있습니다. ("+sFileName+")");
|
||||
}else{
|
||||
//성공 시에 responseText를 가지고 array로 만드는 부분.
|
||||
makeArrayFromString(res._response.responseText);
|
||||
}
|
||||
}
|
||||
},
|
||||
timeout : 3,
|
||||
onerror : jindo.$Fn(onAjaxError, this).bind()
|
||||
});
|
||||
oAjax.header("contentType","multipart/form-data");
|
||||
oAjax.header("file-name",encodeURIComponent(tempFile.name));
|
||||
oAjax.header("file-size",tempFile.size);
|
||||
oAjax.header("file-Type",tempFile.type);
|
||||
oAjax.request(tempFile);
|
||||
}
|
||||
|
||||
function makeArrayFromString(sResString){
|
||||
var aTemp = [],
|
||||
aSubTemp = [],
|
||||
htTemp = {}
|
||||
aResultleng = 0;
|
||||
|
||||
try{
|
||||
if(!sResString || sResString.indexOf("sFileURL") < 0){
|
||||
return ;
|
||||
}
|
||||
aTemp = sResString.split("&");
|
||||
for (var i = 0; i < aTemp.length ; i++){
|
||||
if( !!aTemp[i] && aTemp[i] != "" && aTemp[i].indexOf("=") > 0){
|
||||
aSubTemp = aTemp[i].split("=");
|
||||
htTemp[aSubTemp[0]] = aSubTemp[1];
|
||||
}
|
||||
}
|
||||
}catch(e){}
|
||||
|
||||
aResultleng = aResult.length;
|
||||
aResult[aResultleng] = htTemp;
|
||||
|
||||
if(aResult.length == nImageFileCount){
|
||||
setPhotoToEditor(aResult);
|
||||
aResult = null;
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 사진 삭제 시에 호출되는 함수
|
||||
* @param {Object} sParentId
|
||||
*/
|
||||
function delImage (sParentId){
|
||||
var elLi = jindo.$$.getSingle("#"+sParentId);
|
||||
|
||||
refreshTotalImageSize(sParentId);
|
||||
|
||||
updateViewTotalSize();
|
||||
updateViewCount(nImageFileCount,-1);
|
||||
//사진 file array에서 정보 삭제.
|
||||
removeImageInfo(sParentId);
|
||||
//해당 li삭제
|
||||
$Element(elLi).leave();
|
||||
|
||||
//마지막 이미지인경우.
|
||||
if(nImageFileCount === 0){
|
||||
readyModeBG();
|
||||
//사진 추가 버튼 비활성화
|
||||
goReadyMode();
|
||||
}
|
||||
|
||||
// drop 영역 이벤트 다시 활성화.
|
||||
if(!bAttachEvent){
|
||||
addEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 이벤트 할당
|
||||
*/
|
||||
function addEvent() {
|
||||
bAttachEvent = true;
|
||||
elDropArea.addEventListener("dragenter", dragEnter, false);
|
||||
elDropArea.addEventListener("dragexit", dragExit, false);
|
||||
elDropArea.addEventListener("dragover", dragOver, false);
|
||||
elDropArea.addEventListener("drop", drop, false);
|
||||
}
|
||||
|
||||
function removeEvent(){
|
||||
bAttachEvent = false;
|
||||
elDropArea.removeEventListener("dragenter", dragEnter, false);
|
||||
elDropArea.removeEventListener("dragexit", dragExit, false);
|
||||
elDropArea.removeEventListener("dragover", dragOver, false);
|
||||
elDropArea.removeEventListener("drop", drop, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax 통신 시 error가 발생할 때 처리하는 함수입니다.
|
||||
* @return
|
||||
*/
|
||||
function onAjaxError (){
|
||||
alert("[가이드]사진 업로더할 서버URL셋팅이 필요합니다.-onAjaxError");
|
||||
}
|
||||
|
||||
/**
|
||||
* 이미지 업로드 시작
|
||||
* 확인 버튼 클릭하면 호출되는 msg
|
||||
*/
|
||||
function uploadImage (e){
|
||||
if(!bSupportDragAndDropAPI){
|
||||
generalUpload();
|
||||
}else{
|
||||
html5Upload();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* jindo에 파일 업로드 사용.(iframe에 Form을 Submit하여 리프레시없이 파일을 업로드하는 컴포넌트)
|
||||
*/
|
||||
function callFileUploader (){
|
||||
oFileUploader = new jindo.FileUploader(jindo.$("uploadInputBox"),{
|
||||
// sUrl : location.href.replace(/\/[^\/]*$/, '') + '/file_uploader.php', //샘플 URL입니다.
|
||||
// sCallback : location.href.replace(/\/[^\/]*$/, '') + '/callback.html', //업로드 이후에 iframe이 redirect될 콜백페이지의 주소
|
||||
sUrl : '/imageUpload.do', //파일업로드를 처리하는 페이지
|
||||
sCallback : '/SE2/sample/photo_uploader/callback.html', //업로드 이후에 iframe이 redirect될 콜백페이지의 주소
|
||||
sFiletype : "*.jpg;*.png;*.bmp;*.gif", //허용할 파일의 형식. ex) "*", "*.*", "*.jpg", 구분자(;)
|
||||
sMsgNotAllowedExt : 'JPG, GIF, PNG, BMP 확장자만 가능합니다', //허용할 파일의 형식이 아닌경우에 띄워주는 경고창의 문구
|
||||
bAutoUpload : false, //파일이 선택됨과 동시에 자동으로 업로드를 수행할지 여부 (upload 메소드 수행)
|
||||
bAutoReset : true // 업로드한 직후에 파일폼을 리셋 시킬지 여부 (reset 메소드 수행)
|
||||
}).attach({
|
||||
select : function(oCustomEvent) {
|
||||
//파일 선택이 완료되었을 때 발생
|
||||
// oCustomEvent (이벤트 객체) = {
|
||||
// sValue (String) 선택된 File Input의 값
|
||||
// bAllowed (Boolean) 선택된 파일의 형식이 허용되는 형식인지 여부
|
||||
// sMsgNotAllowedExt (String) 허용되지 않는 파일 형식인 경우 띄워줄 경고메세지
|
||||
// }
|
||||
// 선택된 파일의 형식이 허용되는 경우만 처리
|
||||
if(oCustomEvent.bAllowed === true){
|
||||
goStartMode();
|
||||
}else{
|
||||
goReadyMode();
|
||||
oFileUploader.reset();
|
||||
}
|
||||
// bAllowed 값이 false인 경우 경고문구와 함께 alert 수행
|
||||
// oCustomEvent.stop(); 수행시 bAllowed 가 false이더라도 alert이 수행되지 않음
|
||||
},
|
||||
success : function(oCustomEvent) {
|
||||
// alert("success");
|
||||
// 업로드가 성공적으로 완료되었을 때 발생
|
||||
// oCustomEvent(이벤트 객체) = {
|
||||
// htResult (Object) 서버에서 전달해주는 결과 객체 (서버 설정에 따라 유동적으로 선택가능)
|
||||
// }
|
||||
var aResult = [];
|
||||
aResult[0] = oCustomEvent.htResult;
|
||||
setPhotoToEditor(aResult);
|
||||
//버튼 비활성화
|
||||
goReadyMode();
|
||||
oFileUploader.reset();
|
||||
window.close();
|
||||
},
|
||||
error : function(oCustomEvent) {
|
||||
//업로드가 실패했을 때 발생
|
||||
//oCustomEvent(이벤트 객체) = {
|
||||
// htResult : { (Object) 서버에서 전달해주는 결과 객체. 에러발생시 errstr 프로퍼티를 반드시 포함하도록 서버 응답을 설정하여야한다.
|
||||
// errstr : (String) 에러메시지
|
||||
// }
|
||||
//}
|
||||
//var wel = jindo.$Element("info");
|
||||
//wel.html(oCustomEvent.htResult.errstr);
|
||||
alert(oCustomEvent.htResult.errstr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 페이지 닫기 버튼 클릭
|
||||
*/
|
||||
function closeWindow(){
|
||||
if(bSupportDragAndDropAPI){
|
||||
removeEvent();
|
||||
}
|
||||
window.close();
|
||||
}
|
||||
|
||||
window.onload = function(){
|
||||
checkDragAndDropAPI();
|
||||
|
||||
if(bSupportDragAndDropAPI){
|
||||
$Element("pop_container2").hide();
|
||||
$Element("pop_container").show();
|
||||
|
||||
welTextGuide.removeClass("nobg");
|
||||
welTextGuide.className("bg");
|
||||
|
||||
addEvent();
|
||||
} else {
|
||||
$Element("pop_container").hide();
|
||||
$Element("pop_container2").show();
|
||||
callFileUploader();
|
||||
}
|
||||
fnUploadImage = $Fn(uploadImage,this);
|
||||
$Fn(closeWindow,this).attach(welBtnCancel.$value(), "click");
|
||||
};
|
||||
|
||||
/**
|
||||
* 서버로부터 받은 데이타를 에디터에 전달하고 창을 닫음.
|
||||
* @parameter aFileInfo [{},{},...]
|
||||
* @ex aFileInfo = [
|
||||
* {
|
||||
sFileName : "nmms_215646753.gif",
|
||||
sFileURL :"http://static.naver.net/www/u/2010/0611/nmms_215646753.gif",
|
||||
bNewLine : true
|
||||
},
|
||||
{
|
||||
sFileName : "btn_sch_over.gif",
|
||||
sFileURL :"http://static1.naver.net/w9/btn_sch_over.gif",
|
||||
bNewLine : true
|
||||
}
|
||||
* ]
|
||||
*/
|
||||
function setPhotoToEditor(oFileInfo){
|
||||
if (!!opener && !!opener.nhn && !!opener.nhn.husky && !!opener.nhn.husky.PopUpManager) {
|
||||
//스마트 에디터 플러그인을 통해서 넣는 방법 (oFileInfo는 Array)
|
||||
opener.nhn.husky.PopUpManager.setCallback(window, 'SET_PHOTO', [oFileInfo]);
|
||||
//본문에 바로 tag를 넣는 방법 (oFileInfo는 String으로 <img src=....> )
|
||||
//opener.nhn.husky.PopUpManager.setCallback(window, 'PASTE_HTML', [oFileInfo]);
|
||||
}
|
||||
}
|
||||
|
||||
// 2012.05 현재] jindo.$Ajax.prototype.request에서 file과 form을 지원하지 안함.
|
||||
jindo.$Ajax.prototype.request = function(oData) {
|
||||
this._status++;
|
||||
var t = this;
|
||||
var req = this._request;
|
||||
var opt = this._options;
|
||||
var data, v,a = [], data = "";
|
||||
var _timer = null;
|
||||
var url = this._url;
|
||||
this._is_abort = false;
|
||||
|
||||
if( opt.postBody && opt.type.toUpperCase()=="XHR" && opt.method.toUpperCase()!="GET"){
|
||||
if(typeof oData == 'string'){
|
||||
data = oData;
|
||||
}else{
|
||||
data = jindo.$Json(oData).toString();
|
||||
}
|
||||
}else if (typeof oData == "undefined" || !oData) {
|
||||
data = null;
|
||||
} else {
|
||||
data = oData;
|
||||
}
|
||||
|
||||
req.open(opt.method.toUpperCase(), url, opt.async);
|
||||
if (opt.sendheader) {
|
||||
if(!this._headers["Content-Type"]){
|
||||
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
|
||||
}
|
||||
req.setRequestHeader("charset", "utf-8");
|
||||
for (var x in this._headers) {
|
||||
if(this._headers.hasOwnProperty(x)){
|
||||
if (typeof this._headers[x] == "function")
|
||||
continue;
|
||||
req.setRequestHeader(x, String(this._headers[x]));
|
||||
}
|
||||
}
|
||||
}
|
||||
var navi = navigator.userAgent;
|
||||
if(req.addEventListener&&!(navi.indexOf("Opera") > -1)&&!(navi.indexOf("MSIE") > -1)){
|
||||
/*
|
||||
* opera 10.60에서 XMLHttpRequest에 addEventListener기 추가되었지만 정상적으로 동작하지 않아 opera는 무조건 dom1방식으로 지원함.
|
||||
* IE9에서도 opera와 같은 문제가 있음.
|
||||
*/
|
||||
if(this._loadFunc){ req.removeEventListener("load", this._loadFunc, false); }
|
||||
this._loadFunc = function(rq){
|
||||
clearTimeout(_timer);
|
||||
_timer = undefined;
|
||||
t._onload(rq);
|
||||
}
|
||||
req.addEventListener("load", this._loadFunc, false);
|
||||
}else{
|
||||
if (typeof req.onload != "undefined") {
|
||||
req.onload = function(rq){
|
||||
if(req.readyState == 4 && !t._is_abort){
|
||||
clearTimeout(_timer);
|
||||
_timer = undefined;
|
||||
t._onload(rq);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
/*
|
||||
* IE6에서는 onreadystatechange가 동기적으로 실행되어 timeout이벤트가 발생안됨.
|
||||
* 그래서 interval로 체크하여 timeout이벤트가 정상적으로 발생되도록 수정. 비동기 방식일때만
|
||||
|
||||
*/
|
||||
if(window.navigator.userAgent.match(/(?:MSIE) ([0-9.]+)/)[1]==6&&opt.async){
|
||||
var onreadystatechange = function(rq){
|
||||
if(req.readyState == 4 && !t._is_abort){
|
||||
if(_timer){
|
||||
clearTimeout(_timer);
|
||||
_timer = undefined;
|
||||
}
|
||||
t._onload(rq);
|
||||
clearInterval(t._interval);
|
||||
t._interval = undefined;
|
||||
}
|
||||
};
|
||||
this._interval = setInterval(onreadystatechange,300);
|
||||
|
||||
}else{
|
||||
req.onreadystatechange = function(rq){
|
||||
if(req.readyState == 4){
|
||||
clearTimeout(_timer);
|
||||
_timer = undefined;
|
||||
t._onload(rq);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
req.send(data);
|
||||
return this;
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>FileUploader Callback</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
// alert("callback");
|
||||
// document.domain 설정
|
||||
try { document.domain = "http://localhost"; } catch(e) {}
|
||||
|
||||
// execute callback script
|
||||
var sUrl = document.location.search.substr(1);
|
||||
if (sUrl != "blank") {
|
||||
var oParameter = {}; // query array
|
||||
|
||||
sUrl.replace(/([^=]+)=([^&]*)(&|$)/g, function(){
|
||||
oParameter[arguments[1]] = arguments[2];
|
||||
return "";
|
||||
});
|
||||
|
||||
if ((oParameter.errstr || '').length) { // on error
|
||||
(parent.jindo.FileUploader._oCallback[oParameter.callback_func+'_error'])(oParameter);
|
||||
} else {
|
||||
(parent.jindo.FileUploader._oCallback[oParameter.callback_func+'_success'])(oParameter);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,96 @@
|
||||
<%--------------------------------------------------------------------------------
|
||||
* 화면명 : Smart Editor 2.8 에디터 - 싱글 파일 업로드 처리
|
||||
* 파일명 : /SE2/sample/photo_uploader/file_uploader.jsp
|
||||
--------------------------------------------------------------------------------%>
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="java.util.List"%>
|
||||
<%@ page import="java.util.UUID"%>
|
||||
<%@ page import="java.io.File"%>
|
||||
<%@ page import="java.io.FileOutputStream"%>
|
||||
<%@ page import="java.io.InputStream"%>
|
||||
<%@ page import="java.io.OutputStream"%>
|
||||
<%@ page import="org.apache.commons.fileupload.FileItem"%>
|
||||
<%@ page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%>
|
||||
<%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%>
|
||||
<%
|
||||
// 로컬경로에 파일 저장하기 ============================================
|
||||
String return1 = "";
|
||||
String return2 = "";
|
||||
String return3 = "";
|
||||
String name = "";
|
||||
|
||||
// multipart로 전송되었는가 체크
|
||||
if(ServletFileUpload.isMultipartContent(request)) {
|
||||
ServletFileUpload uploadHandler = new ServletFileUpload(new DiskFileItemFactory());
|
||||
|
||||
// UTF-8 인코딩 설정
|
||||
uploadHandler.setHeaderEncoding("UTF-8");
|
||||
|
||||
List<FileItem> items = uploadHandler.parseRequest(request);
|
||||
|
||||
// 각 필드태그들을 FOR문을 이용하여 비교를 합니다.
|
||||
for(FileItem item : items) {
|
||||
if(item.getFieldName().equals("callback")) {
|
||||
return1 = item.getString("UTF-8");
|
||||
} else if(item.getFieldName().equals("callback_func")) {
|
||||
return2 = "?callback_func="+item.getString("UTF-8");
|
||||
} else if(item.getFieldName().equals("Filedata")) {
|
||||
// FILE 태그가 1개이상일 경우
|
||||
if(item.getSize() > 0) {
|
||||
// 확장자
|
||||
String ext = item.getName().substring(item.getName().lastIndexOf(".")+1);
|
||||
|
||||
// 파일 기본경로
|
||||
String defaultPath = request.getServletContext().getRealPath("/");
|
||||
|
||||
// 파일 기본경로 _ 상세경로
|
||||
String path = defaultPath + "upload" + File.separator;
|
||||
|
||||
File file = new File(path);
|
||||
|
||||
// 디렉토리 존재하지 않을경우 디렉토리 생성
|
||||
if(!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
|
||||
// 서버에 업로드 할 파일명(한글문제로 인해 원본파일은 올리지 않는것이 좋음)
|
||||
String realname = UUID.randomUUID().toString() + "." + ext;
|
||||
|
||||
///////////////// 서버에 파일쓰기 /////////////////
|
||||
InputStream is = item.getInputStream();
|
||||
OutputStream os=new FileOutputStream(path + realname);
|
||||
int numRead;
|
||||
byte b[] = new byte[(int)item.getSize()];
|
||||
|
||||
while((numRead = is.read(b,0,b.length)) != -1) {
|
||||
os.write(b,0,numRead);
|
||||
}
|
||||
|
||||
if(is != null) is.close();
|
||||
|
||||
os.flush();
|
||||
os.close();
|
||||
|
||||
System.out.println("path : "+path);
|
||||
System.out.println("realname : "+realname);
|
||||
|
||||
// 파일 삭제
|
||||
// File f1 = new File(path, realname);
|
||||
// if (!f1.isDirectory()) {
|
||||
// if(!f1.delete()) {
|
||||
// System.out.println("File 삭제 오류!");
|
||||
// }
|
||||
// }
|
||||
|
||||
///////////////// 서버에 파일쓰기 /////////////////
|
||||
return3 += "&bNewLine=true&sFileName="+name+"&sFileURL=/upload/"+realname;
|
||||
} else {
|
||||
return3 += "&errstr=error";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.sendRedirect(return1+return2+return3);
|
||||
// ./로컬경로에 파일 저장하기 ============================================
|
||||
%>
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
// default redirection
|
||||
$url = $_REQUEST["callback"].'?callback_func='.$_REQUEST["callback_func"];
|
||||
$bSuccessUpload = is_uploaded_file($_FILES['Filedata']['tmp_name']);
|
||||
|
||||
// SUCCESSFUL
|
||||
if(bSuccessUpload) {
|
||||
$tmp_name = $_FILES['Filedata']['tmp_name'];
|
||||
$name = $_FILES['Filedata']['name'];
|
||||
|
||||
$filename_ext = strtolower(array_pop(explode('.',$name)));
|
||||
$allow_file = array("jpg", "png", "bmp", "gif");
|
||||
|
||||
if(!in_array($filename_ext, $allow_file)) {
|
||||
$url .= '&errstr='.$name;
|
||||
} else {
|
||||
$uploadDir = '../../upload/';
|
||||
if(!is_dir($uploadDir)){
|
||||
mkdir($uploadDir, 0777);
|
||||
}
|
||||
|
||||
$newPath = $uploadDir.urlencode($_FILES['Filedata']['name']);
|
||||
|
||||
@move_uploaded_file($tmp_name, $newPath);
|
||||
|
||||
$url .= "&bNewLine=true";
|
||||
$url .= "&sFileName=".urlencode(urlencode($name));
|
||||
$url .= "&sFileURL=upload/".urlencode(urlencode($name));
|
||||
}
|
||||
}
|
||||
// FAILED
|
||||
else {
|
||||
$url .= '&errstr=error';
|
||||
}
|
||||
|
||||
header('Location: '. $url);
|
||||
?>
|
||||
@@ -0,0 +1,69 @@
|
||||
<%--------------------------------------------------------------------------------
|
||||
* 화면명 : Smart Editor 2.8 에디터 - 다중 파일 업로드 처리
|
||||
* 파일명 : /SE2/sample/photo_uploader/file_uploader_html5.jsp
|
||||
--------------------------------------------------------------------------------%>
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="java.util.List"%>
|
||||
<%@ page import="java.util.UUID"%>
|
||||
<%@ page import="java.io.File"%>
|
||||
<%@ page import="java.io.FileOutputStream"%>
|
||||
<%@ page import="java.io.InputStream"%>
|
||||
<%@ page import="java.io.OutputStream"%>
|
||||
<%@ page import="org.apache.commons.fileupload.FileItem"%>
|
||||
<%@ page import="org.apache.commons.fileupload.disk.DiskFileItemFactory"%>
|
||||
<%@ page import="org.apache.commons.fileupload.servlet.ServletFileUpload"%>
|
||||
<%
|
||||
// 로컬경로에 파일 저장하기 ============================================
|
||||
String sFileInfo = "";
|
||||
|
||||
// 파일명 - 싱글파일업로드와 다르게 멀티파일업로드는 HEADER로 넘어옴
|
||||
String name = request.getHeader("file-name");
|
||||
|
||||
// 확장자
|
||||
String ext = name.substring(name.lastIndexOf(".")+1);
|
||||
|
||||
// 파일 기본경로
|
||||
String defaultPath = request.getServletContext().getRealPath("/");
|
||||
|
||||
// 파일 기본경로 _ 상세경로
|
||||
String path = defaultPath + "upload" + File.separator;
|
||||
|
||||
File file = new File(path);
|
||||
if(!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
|
||||
String realname = UUID.randomUUID().toString() + "." + ext;
|
||||
InputStream is = request.getInputStream();
|
||||
OutputStream os = new FileOutputStream(path + realname);
|
||||
int numRead;
|
||||
|
||||
// 파일쓰기
|
||||
byte b[] = new byte[Integer.parseInt(request.getHeader("file-size"))];
|
||||
while((numRead = is.read(b,0,b.length)) != -1) {
|
||||
os.write(b,0,numRead);
|
||||
}
|
||||
|
||||
if(is != null) {
|
||||
is.close();
|
||||
}
|
||||
|
||||
os.flush();
|
||||
os.close();
|
||||
|
||||
System.out.println("path : "+path);
|
||||
System.out.println("realname : "+realname);
|
||||
|
||||
// 파일 삭제
|
||||
// File f1 = new File(path, realname);
|
||||
// if (!f1.isDirectory()) {
|
||||
// if(!f1.delete()) {
|
||||
// System.out.println("File 삭제 오류!");
|
||||
// }
|
||||
// }
|
||||
|
||||
sFileInfo += "&bNewLine=true&sFileName="+ name+"&sFileURL="+"/upload/"+realname;
|
||||
out.println(sFileInfo);
|
||||
|
||||
// ./로컬경로에 파일 저장하기 ============================================
|
||||
%>
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
$sFileInfo = '';
|
||||
$headers = array();
|
||||
|
||||
foreach($_SERVER as $k => $v) {
|
||||
if(substr($k, 0, 9) == "HTTP_FILE") {
|
||||
$k = substr(strtolower($k), 5);
|
||||
$headers[$k] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
$file = new stdClass;
|
||||
$file->name = str_replace("\0", "", rawurldecode($headers['file_name']));
|
||||
$file->size = $headers['file_size'];
|
||||
$file->content = file_get_contents("php://input");
|
||||
|
||||
$filename_ext = strtolower(array_pop(explode('.',$file->name)));
|
||||
$allow_file = array("jpg", "png", "bmp", "gif");
|
||||
|
||||
if(!in_array($filename_ext, $allow_file)) {
|
||||
echo "NOTALLOW_".$file->name;
|
||||
} else {
|
||||
$uploadDir = '../../upload/';
|
||||
if(!is_dir($uploadDir)){
|
||||
mkdir($uploadDir, 0777);
|
||||
}
|
||||
|
||||
$newPath = $uploadDir.iconv("utf-8", "cp949", $file->name);
|
||||
|
||||
if(file_put_contents($newPath, $file->content)) {
|
||||
$sFileInfo .= "&bNewLine=true";
|
||||
$sFileInfo .= "&sFileName=".$file->name;
|
||||
$sFileInfo .= "&sFileURL=upload/".$file->name;
|
||||
}
|
||||
|
||||
echo $sFileInfo;
|
||||
}
|
||||
?>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 718 B |
|
After Width: | Height: | Size: 553 B |
|
After Width: | Height: | Size: 553 B |
|
After Width: | Height: | Size: 157 B |
|
After Width: | Height: | Size: 506 B |
@@ -0,0 +1,390 @@
|
||||
/**
|
||||
* Jindo Component
|
||||
* @version 1.0.3
|
||||
* NHN_Library:Jindo_Component-1.0.3;JavaScript Components for Jindo;
|
||||
* @include Component, UIComponent, FileUploader
|
||||
*/
|
||||
jindo.Component = jindo.$Class({
|
||||
_htEventHandler: null,
|
||||
_htOption: null,
|
||||
$init: function () {
|
||||
var aInstance = this.constructor.getInstance();
|
||||
aInstance.push(this);
|
||||
this._htEventHandler = {};
|
||||
this._htOption = {};
|
||||
this._htOption._htSetter = {};
|
||||
},
|
||||
option: function (sName, vValue) {
|
||||
switch (typeof sName) {
|
||||
case "undefined":
|
||||
return this._htOption;
|
||||
case "string":
|
||||
if (typeof vValue != "undefined") {
|
||||
if (sName == "htCustomEventHandler") {
|
||||
if (typeof this._htOption[sName] == "undefined") {
|
||||
this.attach(vValue);
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
this._htOption[sName] = vValue;
|
||||
if (typeof this._htOption._htSetter[sName] == "function") {
|
||||
this._htOption._htSetter[sName](vValue);
|
||||
}
|
||||
} else {
|
||||
return this._htOption[sName];
|
||||
}
|
||||
break;
|
||||
case "object":
|
||||
for (var sKey in sName) {
|
||||
if (sKey == "htCustomEventHandler") {
|
||||
if (typeof this._htOption[sKey] == "undefined") {
|
||||
this.attach(sName[sKey]);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
this._htOption[sKey] = sName[sKey];
|
||||
if (typeof this._htOption._htSetter[sKey] == "function") {
|
||||
this._htOption._htSetter[sKey](sName[sKey]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
optionSetter: function (sName, fSetter) {
|
||||
switch (typeof sName) {
|
||||
case "undefined":
|
||||
return this._htOption._htSetter;
|
||||
case "string":
|
||||
if (typeof fSetter != "undefined") {
|
||||
this._htOption._htSetter[sName] = jindo.$Fn(fSetter, this).bind();
|
||||
} else {
|
||||
return this._htOption._htSetter[sName];
|
||||
}
|
||||
break;
|
||||
case "object":
|
||||
for (var sKey in sName) {
|
||||
this._htOption._htSetter[sKey] = jindo.$Fn(sName[sKey], this).bind();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
fireEvent: function (sEvent, oEvent) {
|
||||
oEvent = oEvent || {};
|
||||
var fInlineHandler = this['on' + sEvent],
|
||||
aHandlerList = this._htEventHandler[sEvent] || [],
|
||||
bHasInlineHandler = typeof fInlineHandler == "function",
|
||||
bHasHandlerList = aHandlerList.length > 0;
|
||||
if (!bHasInlineHandler && !bHasHandlerList) {
|
||||
return true;
|
||||
}
|
||||
aHandlerList = aHandlerList.concat();
|
||||
oEvent.sType = sEvent;
|
||||
if (typeof oEvent._aExtend == 'undefined') {
|
||||
oEvent._aExtend = [];
|
||||
oEvent.stop = function () {
|
||||
if (oEvent._aExtend.length > 0) {
|
||||
oEvent._aExtend[oEvent._aExtend.length - 1].bCanceled = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
oEvent._aExtend.push({
|
||||
sType: sEvent,
|
||||
bCanceled: false
|
||||
});
|
||||
var aArg = [oEvent],
|
||||
i, nLen;
|
||||
for (i = 2, nLen = arguments.length; i < nLen; i++) {
|
||||
aArg.push(arguments[i]);
|
||||
}
|
||||
if (bHasInlineHandler) {
|
||||
fInlineHandler.apply(this, aArg);
|
||||
}
|
||||
if (bHasHandlerList) {
|
||||
var fHandler;
|
||||
for (i = 0, fHandler;
|
||||
(fHandler = aHandlerList[i]); i++) {
|
||||
fHandler.apply(this, aArg);
|
||||
}
|
||||
}
|
||||
return !oEvent._aExtend.pop().bCanceled;
|
||||
},
|
||||
attach: function (sEvent, fHandlerToAttach) {
|
||||
if (arguments.length == 1) {
|
||||
jindo.$H(arguments[0]).forEach(jindo.$Fn(function (fHandler, sEvent) {
|
||||
this.attach(sEvent, fHandler);
|
||||
}, this).bind());
|
||||
return this;
|
||||
}
|
||||
var aHandler = this._htEventHandler[sEvent];
|
||||
if (typeof aHandler == 'undefined') {
|
||||
aHandler = this._htEventHandler[sEvent] = [];
|
||||
}
|
||||
aHandler.push(fHandlerToAttach);
|
||||
return this;
|
||||
},
|
||||
detach: function (sEvent, fHandlerToDetach) {
|
||||
if (arguments.length == 1) {
|
||||
jindo.$H(arguments[0]).forEach(jindo.$Fn(function (fHandler, sEvent) {
|
||||
this.detach(sEvent, fHandler);
|
||||
}, this).bind());
|
||||
return this;
|
||||
}
|
||||
var aHandler = this._htEventHandler[sEvent];
|
||||
if (aHandler) {
|
||||
for (var i = 0, fHandler;
|
||||
(fHandler = aHandler[i]); i++) {
|
||||
if (fHandler === fHandlerToDetach) {
|
||||
aHandler = aHandler.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
detachAll: function (sEvent) {
|
||||
var aHandler = this._htEventHandler;
|
||||
if (arguments.length) {
|
||||
if (typeof aHandler[sEvent] == 'undefined') {
|
||||
return this;
|
||||
}
|
||||
delete aHandler[sEvent];
|
||||
return this;
|
||||
}
|
||||
for (var o in aHandler) {
|
||||
delete aHandler[o];
|
||||
}
|
||||
return this;
|
||||
}
|
||||
});
|
||||
jindo.Component.factory = function (aObject, htOption) {
|
||||
var aReturn = [],
|
||||
oInstance;
|
||||
if (typeof htOption == "undefined") {
|
||||
htOption = {};
|
||||
}
|
||||
for (var i = 0, el;
|
||||
(el = aObject[i]); i++) {
|
||||
oInstance = new this(el, htOption);
|
||||
aReturn[aReturn.length] = oInstance;
|
||||
}
|
||||
return aReturn;
|
||||
};
|
||||
jindo.Component.getInstance = function () {
|
||||
if (typeof this._aInstance == "undefined") {
|
||||
this._aInstance = [];
|
||||
}
|
||||
return this._aInstance;
|
||||
};
|
||||
jindo.UIComponent = jindo.$Class({
|
||||
$init: function () {
|
||||
this._bIsActivating = false;
|
||||
},
|
||||
isActivating: function () {
|
||||
return this._bIsActivating;
|
||||
},
|
||||
activate: function () {
|
||||
if (this.isActivating()) {
|
||||
return this;
|
||||
}
|
||||
this._bIsActivating = true;
|
||||
if (arguments.length > 0) {
|
||||
this._onActivate.apply(this, arguments);
|
||||
} else {
|
||||
this._onActivate();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
deactivate: function () {
|
||||
if (!this.isActivating()) {
|
||||
return this;
|
||||
}
|
||||
this._bIsActivating = false;
|
||||
if (arguments.length > 0) {
|
||||
this._onDeactivate.apply(this, arguments);
|
||||
} else {
|
||||
this._onDeactivate();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}).extend(jindo.Component);
|
||||
jindo.FileUploader = jindo.$Class({
|
||||
_bIsActivating: false,
|
||||
_aHiddenInput: [],
|
||||
$init: function (elFileSelect, htOption) {
|
||||
var htDefaultOption = {
|
||||
sUrl: '',
|
||||
sCallback: '',
|
||||
htData: {},
|
||||
sFiletype: '*',
|
||||
sMsgNotAllowedExt: "업로드가 허용되지 않는 파일형식입니다",
|
||||
bAutoUpload: false,
|
||||
bAutoReset: true,
|
||||
bActivateOnload: true
|
||||
};
|
||||
this.option(htDefaultOption);
|
||||
this.option(htOption || {});
|
||||
this._el = jindo.$(elFileSelect);
|
||||
this._wel = jindo.$Element(this._el);
|
||||
this._elForm = this._el.form;
|
||||
this._aHiddenInput = [];
|
||||
this.constructor._oCallback = {};
|
||||
this._wfChange = jindo.$Fn(this._onFileSelectChange, this);
|
||||
if (this.option("bActivateOnload")) {
|
||||
this.activate();
|
||||
}
|
||||
},
|
||||
_appendIframe: function () {
|
||||
var sIframeName = 'tmpFrame_' + this._makeUniqueId();
|
||||
this._welIframe = jindo.$Element(jindo.$('<iframe name="' + sIframeName + '" src="' + this.option("sCallback") + '?blank">')).css({
|
||||
width: '10px',
|
||||
border: '2px',
|
||||
height: '10px',
|
||||
left: '10px',
|
||||
top: '10px'
|
||||
});
|
||||
document.body.appendChild(this._welIframe.$value());
|
||||
},
|
||||
_removeIframe: function () {
|
||||
this._welIframe.leave();
|
||||
},
|
||||
getBaseElement: function () {
|
||||
return this.getFileSelect();
|
||||
},
|
||||
getFileSelect: function () {
|
||||
return this._el;
|
||||
},
|
||||
getFormElement: function () {
|
||||
return this._elForm;
|
||||
},
|
||||
upload: function () {
|
||||
this._appendIframe();
|
||||
var elForm = this.getFormElement(),
|
||||
welForm = jindo.$Element(elForm),
|
||||
sIframeName = this._welIframe.attr("name"),
|
||||
sFunctionName = sIframeName + '_func',
|
||||
sAction = this.option("sUrl");
|
||||
welForm.attr({
|
||||
target: sIframeName,
|
||||
action: sAction
|
||||
});
|
||||
this._aHiddenInput.push(this._createElement('input', {
|
||||
'type': 'hidden',
|
||||
'name': 'callback',
|
||||
'value': this.option("sCallback")
|
||||
}));
|
||||
this._aHiddenInput.push(this._createElement('input', {
|
||||
'type': 'hidden',
|
||||
'name': 'callback_func',
|
||||
'value': sFunctionName
|
||||
}));
|
||||
for (var k in this.option("htData")) {
|
||||
this._aHiddenInput.push(this._createElement('input', {
|
||||
'type': 'hidden',
|
||||
'name': k,
|
||||
'value': this.option("htData")[k]
|
||||
}));
|
||||
}
|
||||
for (var i = 0; i < this._aHiddenInput.length; i++) {
|
||||
elForm.appendChild(this._aHiddenInput[i]);
|
||||
}
|
||||
this.constructor._oCallback[sFunctionName + '_success'] = jindo.$Fn(function (oParameter) {
|
||||
this.fireEvent("success", {
|
||||
htResult: oParameter
|
||||
});
|
||||
delete this.constructor._oCallback[oParameter.callback_func + '_success'];
|
||||
delete this.constructor._oCallback[oParameter.callback_func + '_error'];
|
||||
for (var i = 0; i < this._aHiddenInput.length; i++) {
|
||||
jindo.$Element(this._aHiddenInput[i]).leave();
|
||||
}
|
||||
this._aHiddenInput.length = 0;
|
||||
this._removeIframe();
|
||||
}, this).bind();
|
||||
this.constructor._oCallback[sFunctionName + '_error'] = jindo.$Fn(function (oParameter) {
|
||||
this.fireEvent("error", {
|
||||
htResult: oParameter
|
||||
});
|
||||
delete this.constructor._oCallback[oParameter.callback_func + '_success'];
|
||||
delete this.constructor._oCallback[oParameter.callback_func + '_error'];
|
||||
for (var i = 0; i < this._aHiddenInput.length; i++) {
|
||||
jindo.$Element(this._aHiddenInput[i]).leave();
|
||||
}
|
||||
this._aHiddenInput.length = 0;
|
||||
this._removeIframe();
|
||||
}, this).bind();
|
||||
|
||||
elForm.submit();
|
||||
if (this.option("bAutoReset")) {
|
||||
this.reset();
|
||||
}
|
||||
},
|
||||
reset: function () {
|
||||
var elWrapForm = jindo.$("<form>");
|
||||
this._wel.wrap(elWrapForm);
|
||||
elWrapForm.reset();
|
||||
jindo.$Element(elWrapForm).replace(this._el);
|
||||
var elForm = this.getFormElement(),
|
||||
welForm = jindo.$Element(elForm);
|
||||
welForm.attr({
|
||||
target: this._sPrevTarget,
|
||||
action: this._sAction
|
||||
});
|
||||
return this;
|
||||
},
|
||||
_onActivate: function () {
|
||||
var elForm = this.getFormElement(),
|
||||
welForm = jindo.$Element(elForm);
|
||||
this._sPrevTarget = welForm.attr("target");
|
||||
this._sAction = welForm.attr("action");
|
||||
this._el.value = "";
|
||||
this._wfChange.attach(this._el, "change");
|
||||
},
|
||||
_onDeactivate: function () {
|
||||
this._wfChange.detach(this._el, "change");
|
||||
},
|
||||
_makeUniqueId: function () {
|
||||
return new Date().getMilliseconds() + Math.floor(Math.random() * 100000);
|
||||
},
|
||||
_createElement: function (name, attributes) {
|
||||
var el = jindo.$("<" + name + ">");
|
||||
var wel = jindo.$Element(el);
|
||||
for (var k in attributes) {
|
||||
wel.attr(k, attributes[k]);
|
||||
}
|
||||
return el;
|
||||
},
|
||||
_checkExtension: function (sFile) {
|
||||
var aType = this.option("sFiletype").split(';');
|
||||
for (var i = 0, sType; i < aType.length; i++) {
|
||||
sType = (aType[i] == "*.*") ? "*" : aType[i];
|
||||
sType = sType.replace(/^\s+|\s+$/, '');
|
||||
sType = sType.replace(/\./g, '\\.');
|
||||
sType = sType.replace(/\*/g, '[^\\\/]+');
|
||||
if ((new RegExp(sType + '$', 'gi')).test(sFile)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
_onFileSelectChange: function (we) {
|
||||
var sValue = we.element.value,
|
||||
bAllowed = this._checkExtension(sValue),
|
||||
htParam = {
|
||||
sValue: sValue,
|
||||
bAllowed: bAllowed,
|
||||
sMsgNotAllowedExt: this.option("sMsgNotAllowedExt")
|
||||
};
|
||||
if (sValue.length && this.fireEvent("select", htParam)) {
|
||||
if (bAllowed) {
|
||||
if (this.option("bAutoUpload")) {
|
||||
this.upload();
|
||||
}
|
||||
} else {
|
||||
alert(htParam.sMsgNotAllowedExt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).extend(jindo.UIComponent);
|
||||
@@ -0,0 +1,101 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Script-Type" content="text/javascript">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<title>사진 첨부하기 :: SmartEditor2</title>
|
||||
<style type="text/css">
|
||||
/* NHN Web Standard 1Team JJS 120106 */
|
||||
/* Common */
|
||||
body,p,h1,h2,h3,h4,h5,h6,ul,ol,li,dl,dt,dd,table,th,td,form,fieldset,legend,input,textarea,button,select{margin:0;padding:0}
|
||||
body,input,textarea,select,button,table{font-family:'돋움',Dotum,Helvetica,sans-serif;font-size:12px}
|
||||
img,fieldset{border:0}
|
||||
ul,ol{list-style:none}
|
||||
em,address{font-style:normal}
|
||||
a{text-decoration:none}
|
||||
a:hover,a:active,a:focus{text-decoration:underline}
|
||||
|
||||
/* Contents */
|
||||
.blind{visibility:hidden;position:absolute;line-height:0}
|
||||
#pop_wrap{width:383px}
|
||||
#pop_header{height:26px;padding:14px 0 0 20px;border-bottom:1px solid #ededeb;background:#f4f4f3}
|
||||
.pop_container{padding:11px 20px 0}
|
||||
#pop_footer{margin:21px 20px 0;padding:10px 0 16px;border-top:1px solid #e5e5e5;text-align:center}
|
||||
h1{color:#333;font-size:14px;letter-spacing:-1px}
|
||||
.btn_area{word-spacing:2px}
|
||||
.pop_container .drag_area{overflow:hidden;overflow-y:auto;position:relative;width:341px;height:129px;margin-top:4px;border:1px solid #eceff2}
|
||||
.pop_container .drag_area .bg{display:block;position:absolute;top:0;left:0;width:341px;height:129px;background:#fdfdfd url(./img/bg_drag_image.png) 0 0 no-repeat}
|
||||
.pop_container .nobg{background:none}
|
||||
.pop_container .bar{color:#e0e0e0}
|
||||
.pop_container .lst_type li{overflow:hidden;position:relative;padding:7px 0 6px 8px;border-bottom:1px solid #f4f4f4;vertical-align:top}
|
||||
.pop_container :root .lst_type li{padding:6px 0 5px 8px}
|
||||
.pop_container .lst_type li span{float:left;color:#222}
|
||||
.pop_container .lst_type li em{float:right;margin-top:1px;padding-right:22px;color:#a1a1a1;font-size:11px}
|
||||
.pop_container .lst_type li a{position:absolute;top:6px;right:5px}
|
||||
.pop_container .dsc{margin-top:6px;color:#666;line-height:18px}
|
||||
.pop_container .dsc_v1{margin-top:12px}
|
||||
.pop_container .dsc em{color:#13b72a}
|
||||
.pop_container2{padding:46px 60px 20px}
|
||||
.pop_container2 .dsc{margin-top:6px;color:#666;line-height:18px}
|
||||
.pop_container2 .dsc strong{color:#13b72a}
|
||||
.upload{margin:0 4px 0 0;_margin:0;padding:6px 0 4px 6px;border:solid 1px #d5d5d5;color:#a1a1a1;font-size:12px;border-right-color:#efefef;border-bottom-color:#efefef;length:300px;}
|
||||
:root .upload{padding:6px 0 2px 6px;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="pop_wrap">
|
||||
<!-- header -->
|
||||
<div id="pop_header">
|
||||
<h1>사진 첨부하기</h1>
|
||||
</div>
|
||||
<!-- //header -->
|
||||
<!-- container -->
|
||||
|
||||
<!-- [D] HTML5인 경우 pop_container 클래스와 하위 HTML 적용
|
||||
그밖의 경우 pop_container2 클래스와 하위 HTML 적용 -->
|
||||
<div id="pop_container2" class="pop_container2">
|
||||
<!-- content -->
|
||||
<!-- <form id="editor_upimage" name="editor_upimage" action="FileUploader.php" method="post" enctype="multipart/form-data" onSubmit="return false;"> -->
|
||||
<form id="editor_upimage" name="editor_upimage" method="post" enctype="multipart/form-data" onSubmit="return false;">
|
||||
<div id="pop_content2">
|
||||
<input type="file" class="upload" id="uploadInputBox" name="Filedata">
|
||||
<p class="dsc" id="info"><strong>10MB</strong>이하의 이미지 파일만 등록할 수 있습니다.<br>(JPG, GIF, PNG, BMP)</p>
|
||||
</div>
|
||||
</form>
|
||||
<!-- //content -->
|
||||
</div>
|
||||
<div id="pop_container" class="pop_container" style="display:none;">
|
||||
<!-- content -->
|
||||
<div id="pop_content">
|
||||
<p class="dsc"><em id="imageCountTxt">0장</em>/10장 <span class="bar">|</span> <em id="totalSizeTxt">0MB</em>/50MB</p>
|
||||
<!-- [D] 첨부 이미지 여부에 따른 Class 변화
|
||||
첨부 이미지가 있는 경우 : em에 "bg" 클래스 적용 //첨부 이미지가 없는 경우 : em에 "nobg" 클래스 적용 -->
|
||||
|
||||
<div class="drag_area" id="drag_area">
|
||||
<ul class="lst_type" >
|
||||
</ul>
|
||||
<em class="blind">마우스로 드래그해서 이미지를 추가해주세요.</em><span id="guide_text" class="bg"></span>
|
||||
</div>
|
||||
<div style="display:none;" id="divImageList"></div>
|
||||
<p class="dsc dsc_v1"><em>한 장당 10MB, 1회에 50MB까지, 10개</em>의 이미지 파일을<br>등록할 수 있습니다. (JPG, GIF, PNG, BMP)</p>
|
||||
</div>
|
||||
<!-- //content -->
|
||||
</div>
|
||||
|
||||
<!-- //container -->
|
||||
<!-- footer -->
|
||||
<div id="pop_footer">
|
||||
<div class="btn_area">
|
||||
<a href="#"><img src="./img/btn_confirm.png" width="49" height="28" alt="확인" id="btn_confirm"></a>
|
||||
<a href="#"><img src="./img/btn_cancel.png" width="48" height="28" alt="취소" id="btn_cancel"></a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- //footer -->
|
||||
</div>
|
||||
<script type="text/javascript" src="jindo.min.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="jindo.fileuploader.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="attach_photo.js" charset="utf-8"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Smart Editor™ WYSIWYG Mode</title>
|
||||
</head>
|
||||
<body class="se2_inputarea" style="height:0;-webkit-nbsp-mode:normal"></body>
|
||||
</html>
|
||||
@@ -0,0 +1,9 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
|
||||
<title>Smart Editor™ WYSIWYG Mode</title>
|
||||
</head>
|
||||
<body class="se2_inputarea" style="height:0"></body>
|
||||
</html>
|
||||
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:task="http://www.springframework.org/schema/task"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
|
||||
http://www.springframework.org/schema/util
|
||||
http://www.springframework.org/schema/util/spring-util-4.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-4.0.xsd
|
||||
http://www.springframework.org/schema/task
|
||||
http://www.springframework.org/schema/task/spring-task-3.0.xsd
|
||||
">
|
||||
|
||||
<context:component-scan base-package="com.pms"></context:component-scan>
|
||||
|
||||
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
|
||||
<property name="basenames">
|
||||
<list>
|
||||
<value>classpath:com/pms/message/message</value>
|
||||
<value>classpath:com/pms/message/common</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="cacheSeconds">
|
||||
<value>60</value>
|
||||
</property>
|
||||
<property name="defaultEncoding" value="UTF-8"/>
|
||||
</bean>
|
||||
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
|
||||
<property name="defaultLocale" value="ko"/>
|
||||
</bean>
|
||||
|
||||
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
|
||||
<property name="paramName" value="lang" />
|
||||
</bean>
|
||||
|
||||
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
|
||||
<property name="prefix" value="/WEB-INF/view"/>
|
||||
<property name="suffix" value=".jsp"/>
|
||||
<property name="order" value="1"/>
|
||||
</bean>
|
||||
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
|
||||
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
|
||||
<property name="messageConverters">
|
||||
<list>
|
||||
<ref bean="jacksonMessageConverter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
<task:scheduler id="gsScheduler" pool-size="10" />
|
||||
<task:annotation-driven scheduler="gsScheduler" />
|
||||
</beans>
|
||||
|
||||