import web2app from '../lib/web2app'
import { addEvent, buildQueryString, extend, getElement, map, removeEvent } from '../util'
import { applyAttributes, emptyCleanups, getAppKey, getInstallUrl, KakaoError, KAKAO_AGENT, logDebug, processRules, URL, VERSION, windowOpen } from '../common'
import rules from './rules'
/**
* 지정한 Element를 클릭할 때 카카오스토리 공유 창이 열리도록 합니다.
* @function createShareButton
* @param {Object} settings 카카오스토리 공유 버튼과 관련된 설정을 key/value로 전달합니다.
* @param {String|HTMLElement} settings.container DOM Element 또는 Element의 ID Selector를 넘기면, 해당 Element를 클릭할 때 카카오스토리 공유 창이 열립니다.
* @param {String} [settings.url=${current page's URL}] 카카오스토리로 공유할 웹 페이지의 URL.
* @param {String} [settings.text=""] 공유 창에 표시할 텍스트
* @see {@link https://developers.kakao.com/tool/demo/story/share?method=web-button|데모 보러가기}
* @memberof Kakao.Story
*/
export function createShareButton(settings) {
const container$ = getElement(settings.container)
if (!container$) {
throw new KakaoError('container is required for Story.createShareButton: pass in element or id')
} else {
applyAttributes(settings, container$, {
url: 'data-url',
})
}
settings = processRules(settings, rules.createShareButton, 'Story.createShareButton')
const anchor$ = createAnchorImage(URL.storyIcon, '카카오스토리 웹 공유 버튼')
container$.appendChild(anchor$)
const clickHandler = e => {
e.preventDefault()
openSharePopup(settings)
}
addEvent(anchor$, 'click', clickHandler)
cleanups.push(() => {
removeEvent(anchor$, 'click', clickHandler)
container$.removeChild(anchor$)
})
}
function createAnchorImage(imgSrc, imgTitle) {
const a$ = document.createElement('a')
a$.setAttribute('href', '#')
const img$ = document.createElement('img')
img$.setAttribute('src', imgSrc)
img$.setAttribute('title', imgTitle)
img$.setAttribute('alt', imgTitle)
a$.appendChild(img$)
return a$
}
/**
* 카카오스토리 웹 공유 창을 엽니다.
* @function share
* @param {Object} settings 카카오스토리 공유 버튼과 관련된 설정을 key/value로 전달합니다.
* @param {String} [settings.url=${current page's URL}] 카카오스토리로 공유할 웹페이지의 URL
* @param {String} [settings.text=""] 공유 창에 표시할 텍스트
* @see {@link https://developers.kakao.com/tool/demo/story/share|데모 보러가기}
* @memberof Kakao.Story
*/
export function share(settings) {
settings = processRules(settings, rules.share, 'Story.share')
openSharePopup(settings)
}
function openSharePopup(settings) {
const params = extend({
url: settings.url,
}, makeStoryParams())
if (settings.text) {
params.text = settings.text
}
windowOpen(
`${URL.storyShare}?${buildQueryString(params)}`,
'kakaostory_social_plugin',
'width=670, height=800, scrollbars=yes',
)
}
/**
* 모바일 환경에서 카카오스토리 앱 공유 화면을 엽니다.
* @function open
* @param {Object} settings 카카오스토리 공유 버튼과 관련된 설정을 key/value로 전달합니다.
* @param {Boolean} [settings.install=false] 카카오스토리 앱이 설치되어 있지 않은 경우 마켓의 카카오스토리 설치 페이지로 이동합니다.
* @param {String} [settings.url=${current page's URL}] 카카오스토리로 공유할 웹 페이지의 URL
* @param {String} [settings.text=""] 공유 창에 표시할 텍스트
* @param {Obejct} [settings.urlInfo] 위에 입력한 url에 대한 추가적인 정보 (입력하지 않을 경우 스크랩 서버가 자동으로 생성)
* @param {String} settings.urlInfo.title 스크랩 영역에 표시할 제목
* @param {String} [settings.urlInfo.desc] 스크랩 영역에 표시할 설명
* @param {String} [settings.urlInfo.name] 스크랩 영역에 표시할 사이트 이름
* @param {String[]} [settings.urlInfo.images] 스크랩 영역에 표시할 대표 이미지 URL
* @example
* // 1. 필수 옵션만 사용. 메타 정보는 스크랩 서버가 자동으로 생성
* Kakao.Story.open({
* url: 'http://my.share.url.com',
* text: 'Text to share'
* })
* @example
* // 2. 스크랩된 url의 메타 정보를 바꾸고 싶을때
* Kakao.Story.open({
* url: 'http://my.share.url.com',
* text: 'Text to share',
* urlInfo: {
* title: 'The title of a shared site',
* desc: 'A description of a website',
* name: 'The name at the bottom',
* images: ['http://my.image.url']
* }
* })
* @see {@link https://developers.kakao.com/tool/demo/story/share?method=app|데모 보러가기}
* @memberof Kakao.Story
*/
export function open(settings) {
settings = processRules(settings, rules.open, 'Story.open')
const storyPostScheme = makeStoryPostScheme(settings)
const androidIntent = [
`intent:${storyPostScheme}#Intent`,
`${(settings.install ? 'package=com.kakao.story;' : '')}end;`
].join(';')
const web2appOptions = {
urlScheme: storyPostScheme,
intentURI: androidIntent,
appName: 'KakaoStory',
storeURL: getInstallUrl('com.kakao.story', '486244601'),
onUnsupportedEnvironment() {
settings.fail && settings.fail()
},
}
try {
web2app(web2appOptions)
} catch (error) {
logDebug(error)
}
}
function makeStoryPostScheme(settings) {
const domain = location.hostname || ''
const params = extend({
apiver: '1.0',
appver: VERSION,
appid: domain,
appname: domain,
post: settings.text ? `${settings.text}\n${settings.url}` : settings.url,
}, makeStoryParams())
if (settings.urlInfo) {
params.urlinfo = JSON.stringify(settings.urlInfo)
params.appname = settings.urlInfo.name || params.appname
}
return `${URL.storyPostScheme}?${buildQueryString(params)}`
}
/**
* 지정한 Element를 클릭할 때 카카오스토리 채널로부터 소식을 받도록 합니다.
* @function createFollowButton
* @param {Object} settings 카카오스토리 소식받기 버튼과 관련된 설정을 key/value로 전달합니다.
* @param {String|HTMLElement} settings.container DOM Element 또는 Element의 ID Selector를 넘기면, 해당 Element를 클릭할 때 지정한 채널을 구독합니다.
* @param {String} settings.id 소식을 받을 카카오스토리 채널 ID. ex) kakao
* @param {Boolean} [settings.showFollowerCount=true] 구독자 수를 노출합니다.
* @param {String} [settings.type="horizontal"] 구독자 수를 노출할 형태를 정합니다.
* @see {@link https://developers.kakao.com/tool/demo/story/follow|데모 보러가기}
* @memberof Kakao.Story
*/
export function createFollowButton(settings) {
const container$ = getElement(settings.container)
if (!container$) {
throw new KakaoError('container is required for Story.createFollowButton: pass in element or id')
} else {
applyAttributes(settings, container$, {
id: 'data-id',
showFollowerCount: 'data-show-follower-count',
type: 'data-type',
})
}
settings = processRules(settings, rules.createFollowButton, 'Story.createFollowButton')
const { iframe$, messageHandler } = createStoryFollowIframe(settings)
container$.appendChild(iframe$)
addEvent(window, 'message', messageHandler)
cleanups.push(() => {
removeEvent(window, 'message', messageHandler)
container$.removeChild(iframe$)
})
}
let _storyFollowIframeId = 0
function createStoryFollowIframe(settings) {
const iframeId = _storyFollowIframeId++
let iframeWidth = settings.showFollowerCount && settings.type === 'horizontal' ? 85 : 59
let iframeHeight = settings.showFollowerCount && settings.type === 'vertical' ? 46 : 20
const iframe$ = document.createElement('iframe')
iframe$.src = makeStoryFollowUrl(settings, iframeId)
iframe$.setAttribute('frameborder', '0')
iframe$.setAttribute('marginwidth', '0')
iframe$.setAttribute('marginheight', '0')
iframe$.setAttribute('scrolling', 'no')
iframe$.setAttribute('style', `width:${iframeWidth}px; height:${iframeHeight}px;`)
const messageHandler = e => {
if (e.data && /\.kakao\.com$/.test(e.origin) && typeof e.data === 'string') {
const [ originIframeId, afterWidth, afterHeight ] = map(e.data.split(','), e => parseInt(e, 10))
if (originIframeId === iframeId) {
if (iframeWidth !== afterWidth) {
iframeWidth = afterWidth
iframe$.style.width = `${iframeWidth}px`
}
if (iframeHeight !== afterHeight) {
iframeHeight = afterHeight
iframe$.style.height = `${iframeHeight}px`
}
}
}
}
return { iframe$, messageHandler }
}
function makeStoryFollowUrl(settings, iframeId) {
const params = extend({
id: settings.id,
type: settings.type,
hideFollower: !settings.showFollowerCount,
frameId: iframeId,
}, makeStoryParams())
return `${URL.storyChannelFollow}?${buildQueryString(params)}`
}
function makeStoryParams() {
const params = {
kakao_agent: KAKAO_AGENT,
}
if (getAppKey() !== null) {
params.app_key = getAppKey()
}
return params
}
const cleanups = []
export function cleanup() {
emptyCleanups(cleanups)
}