php 클릭 함수에서 직접 url 이동을 해주려면 어떻게 작성해야 하나요?
CMS/프레임워크 | XE 1.x |
---|---|
개발 언어 | PHP 7.1 |
우선 질문을 드리는 이유는
브라우저들이 사용자가 직접 클릭으로 요청한 이동이 아닌경우 팝업허용을 하지 않은 경우 차단을 합니다.
그래서 클릭시 작동되는 함수에서 직접 url 이동을 하려고 하는데요.
기존에 만들어진 것은 클릭함수에서 html을 읽어 거기서 스크립트로 이동 처리 되어있습니다. 검색을 해보고 해도 이건 방법이 없는 것 같아 고쳐야 할 것 같아서요.
function dispPortalpointIndex() {
클릭시 필요한 확인 과정 코드
if($message) Context::set('message',$message);
$this->setTemplateFile('_result');
}
resul.html 의 내용에는
메시지가 있다면 메시지가 출력할 수 있는 코드와
$selected['url'] 로 이동되는 스크립트 가 있습니다.
$selected['url'] 로 이동을 php 함수에서 직접 시도해 보려고 합니다.
단, 저희 사이트 도메인과 일치하지 않는 경우만 새창으로 열어야 합니다.
댓글 35
구체적으로 어떤 용도인지 모르겠습니다만
PHP에서 할 수 있는 것은 Location: 헤더를 전송하여 리다이렉트시키는 것뿐입니다.
현재 창에 여는지 새 창에 여는지는 자바스크립트에서 결정합니다.
물론 PHP를 사용해서 적당한 태그와 자바스크립트가 포함된 HTML을 뿌려줄 수는 있겠지만
HTML 페이지 로딩 직후에 새 창을 열려고 한다면 당연히 팝업차단에 걸리겠지요?
(아마 이게 최신 크롬에서 안 되는 기존 방식일 겁니다.)
웹페이지에서 클릭 → 클릭 확인 PHP 실행 → 타겟 URL을 새 창에 열기
이건 더이상 가망이 없는 방식입니다.
↗ 클릭 확인 PHP 실행 (AJAX)
웹페이지에서 클릭
↘ 타겟 URL을 새 창에 열기
이렇게 최초 화면의 자바스크립트에서 두 가지 작업을 동시에 실행한다면 아마 가능할 겁니다.
아니면
↗ 클릭 확인 PHP 실행 (AJAX) ↘
웹페이지에서 클릭 . . . . . . . . . . . . . . . . . . . . . . . . . 타겟 URL을 새 창에 열기
이렇게 AJAX 결과를 바탕으로 URL을 구성하는 방법도 있을 듯 한데, 잘 될지는 모르겠네요.
(확인을 거치기 전에는 URL이 아예 노출되지 말아야 하는 경우)
어쨌든 새 창을 여는 스크립트는 처음 클릭했던 웹페이지상에 있어야 합니다.
포인트포탈의 문제인데요.
포인트 포탈에 등록된 단위로 링크를 모듈에서 제공하는데요. (이동 url은 노출되지 않아 있고 모듈에서 제공한 링크를 클릭해야 하는 경우입니다.)
그 링크를 사이트 어딘가에 노출시킨 후 방문자가 클릭하면 본문에 적힌 함수가 작동합니다.
본문의 함수에서 확인을 다 거친 후 맨 아랫줄에 html을 불러와서 거기에서 자바스크립트로 이동을 하면서 팝업이 차단이 되는 문제입니다.
php 함수안에 다른 사이트가 새창으로 열리는 코드를 추가해도 마찬가지란 말씀이신거죠?
PHP 함수 안에 넣는다는 것은 그 함수가 작동한 후 뭔가 새로운 HTML이 로딩된다는 뜻이고, 거기에 포함된 코드는 로딩 직후에 실행될 테니 팝업차단에 걸립니다.
함수가 작동한 이후에 새 창이 열려야 한다는 생각을 버리세요. 함수는 함수대로 작동하는 거고, 새 창을 여는 코드는 클릭하기 전에 방문자가 머물던 페이지에 들어 있어야 합니다. 새 창을 여는 소스(window.open)가 함수 작동의 결과물이어서는 안 됩니다. 만약 함수 작동의 결과물을 바탕으로 새 창을 연다고 해도, 새 창을 여는 주체(최종적으로 window.open을 호출하는 소스)는 원래 있던 페이지상에 존재해야 합니다. 즉 위의 도표 중 세 번째 구조가 됩니다.
클릭을 하면 당연히 어떤 url로 이동을 시키려는 목적으로 개발된 모듈이 포탈포인트 모듈입니다. 다만 포인트를 지급해야하니 포인트지급과 확인 기록 등을 할 수 있는 링크단위로 모듈에서 새로운 링크를 제공합니다.
따라서 방문자가 클릭하는 곳 페이지에는 새로 열릴곳의 정보는 아직 없는 상태이며 방문자는 포인트를 받기 위해 클릭을 하게 되는 행동을 하게 됩니다.
여기서 말씀 하신대로 php에서 클릭으로 실행된 함수에서 어디로 이동될 링크인지 확인 후 html을 새로 열어 거기서 자바스크립트로 확인된 주소로 이동시킵니다.
요즘 브라우저들이 사용자가 직접 클릭하지 않은 팝업은 엄격히 차단하면서 이런 방식이 효용성이 없어서 질문을 하게 된 것이구요.
현재 제가 할 수 있는 최대치는 일단 html 자바스크립트에서 팝업차단을 감지하면 팝업허용 해달라는 문구가 나오는 것 까지이네요.
말씀하신 내용을 토대로 링크를 제공하는 페이지에서 자바스크립트 이벤트로 거기서 우선 새창이 먼저 열리도록 연구해서 구현해보도록 하겠습니다.
- url 자체를 제가 미리 알 수 있으니 수동으로 먼저 새창 이동을 만들어 줄 수는 있을 것 같네요.
> php에서 클릭으로 실행된 함수에서 어디로 이동될 링크인지 확인 후 html을 새로 열어 거기서 자바스크립트로 확인된 주소로 이동시킵니다.
네, 이 구조가 잘못되었다는 겁니다. 어디로 이동될 링크인지 확인하는 것까지는 괜찮은데, HTML을 새로 열어서 거기에 자바스크립트를 넣으면 안 됩니다. HTML을 새로 열면 아까 클릭한 이벤트를 잊어버리기 때문에, "새 창을 열기 직전에 클릭 이벤트가 없었다면 차단한다"라는 규칙에 걸립니다.
AJAX를 쓰든 아이프레임을 쓰든 처음부터 소스상의 어딘가에 숨겨놓든, 아무튼 원래 보고 있던 페이지로 URL 정보를 받아와야 합니다. 그리고 원래 보고 있던 페이지상의 자바스크립트에서 새 창을 열어야 할 거예요. 이렇게 하더라도 자칫하면 클릭 이벤트에서 너무 멀리 떨어져 나왔다는 이유로 차단되는 수가 있고요.
모듈에서 제공하는 링크에 실제 팝업으로 열려야할 url을 넣고 이것을 클릭 이벤트시 이 url로 새창이 열리게 할 수 있을까요???
data 같은 걸 쓰는 걸 소스에서 많이 본것 같습니다. ㅡㅡ;
뭔가 될 것 같은데 제가 검색하려면 시간이 엄청 걸릴 듯 합니다. ㅡㅡ;
아.. 그런데 이건 안되겠군요.. 일단 모듈에서 제공하는 링크로 이동이 되어야 저 함수가 동작할텐데.. 동시에 2개창이 열리는게 가능하지 않은일 같은데 안열리겠죠....
기본적인 구조는 이렇게 될 겁니다.
<a href="팝업URL" target="_blank" onclick="exec_json('모듈.액션', 전송할 데이터);">클릭하세요!!!</a>
팝업URL을 새 창에 여는 것이 우선이고, 포인트 지급 액션을 호출하는 부분은 onclick 이벤트에 쑤셔넣는 거지요. 현재 구조는 포인트 지급 액션을 호출하는 것이 우선이라서 문제거든요.
exec_json 부분이 너무 복잡해진다면 별도의 자바스크립트 함수로 빼는 것이 좋습니다.
원래 브라우저에서 클릭시 실행되어야 할 url은 /index.php?module=portalpoint&title=rule 이런 형태입니다.
rule 이라는 것이 등록된 단위이름 이구요.ㅡㅡ;
아마 dispPortalpointIndex 이게 액션일 것 같긴 합니다.
exec_json("portalpoint.dispPortalpointIndex")
여기까지는 알겠는ㄷ.. title 값이 rule 이라는 것을 넣어야 할 것 같아서요.. ㅡㅡ;
라이믹스는 중괄호 안쪽에 한 칸씩 공백을 남기면 템플릿 문법으로 인식하지 않고 그냥 패스하는데, XE에도 그런 기능이 있었던가;;; 아무튼 잘 안 된다면 별도 함수로 빼야 합니다.
중괄호 때문에 500에러가 나는 것 같네요 ㅜㅡ
이제 함수로 빼서 동작시키는 것에 노력을 해보겠습니다.
(&와 # 사이의 띄어쓰기를 제거하세요)
스크립트를 하단에 추가해 봤는데 모듈에 의한 동작은 되지 않네요. 콘솔 에러같은 것은 없구요 ㅡㅡ;
<a class="pointplus_dog114" href="새창url" target="_blank" rel="noopener noopener noopener"><img src="/files/attach/filebox/044/810/001/1810044.png" width="150" height="60" style=""></a>
<script>
jQuery(function ($) {
$(".pointplus_dog114").click(function () {
exec_json('portalpoint.dispPortalpointIndex',{title:'pointplus_dog114'});
});
});
</script>
브라우저의 개발자도구에서 보이는거 가져와봤습니다.
저것도 템플릿의 일부일 텐데 중괄호 문제 없던가요?
모듈에서 exec_json이나 exec_xml로 호출하는 것을 아예 지원하지 않는지도 모르겠네요.
$(".pointplus_dog114").on('click', function() {
$.get(request_uri.setQuery('module', 'portalpoint').setQuery('act', 'dispPortalpointIndex').setQuery('title', 'pointplus_dog114'));
});
이렇게 한번 해보세요. 브라우저에서 직접 오픈하는 것에 그나마 가장 근접한 방식입니다.
고쳐주신것으로 해도 반응이 없는 것 같아서 로그를 확인해보니 포인트 적립이 되었습니다.
창 2개 열리는 것까지는 무리고, 포인트 적립됐으면 된 거죠...
저렇게 ajax로 요청하면 무슨 html이 돌아오더라도 그냥 다 무시됩니다.
회원들 입장에서는 포인트 적립 확인을 주로 메시지로 하다보니.....
alert 해주면 되죠 ㅎㅎ
if($message) Context::set('message',$message);
$this->setTemplateFile('_result');
위에 담긴 메시지를 html에서 페이지 이동과 함께 메시지로 띄우고 있습니다 ㅡㅡ;
https://github.com/poesis/xe-advanced-mailer/blob/master/advanced_mailer.admin.controller.php#L280
https://github.com/poesis/xe-advanced-mailer/blob/master/tpl/js/config.js#L118-L121
계속 보면서 이해해보려고 했는데 잘 이해한 건지 모르겠습니다.
php함수 맨 아래에는 아래와 같이 넣었습니다.
$this->add('result_message', Context::set('message',$message));
<script>
jQuery(document).ready(function($) {
$('.pointplus_dog114').click(function () {
exec_json('portalpoint.dispPortalpointIndex',{title:'pointplus_dog114'},function(response) {alert('response.result_message');});
});
});
</script>
실제 적용해보니 땡! 틀렸네요 ㅋ
굵은색 부분을 추가한건데 저기가 문제네요...
Context::set은 다른 줄로 분리하고 $this->add에 $message를 직접 넣으시고요... (지금은 Context::set의 반환값을 넣고 계시는데, 그 함수는 반환값이 없습니다.)
그리고 alert하실 때 괄호와 따옴표의 순서가 바뀐 것 같습니다.
괄호와 따옴표는 혹시나해서 뒤봐꿔 본건데 말씀하신대로 다시 돌렸습니다.
if($message) Context::set('message',$message);
$this->add('result_message', $message);
$this->setTemplateFile('_result');
그런데 지금 가운데 줄이 추가된 것이거든요. 아래와 같이 작성했는데 반응이 없습니다. 아마 포인트 적립 자체가 안되는 것 같았거든요. 처음에 제가 시도했을때요.
<script>
jQuery(document).ready(function($) {
$('.pointplus_dog114').click(function () {
exec_json('portalpoint.dispPortalpointIndex',{title:'pointplus_dog114'},function(response) {alert'(response.result_message)';});
});
});
</script>
exec_json('portalpoint.dispPortalpointIndex',{title:'pointplus_dog114'},function(response) {alert'(response.result_message)';}); 요 라인에 콘솔 에러가 뜨네요 ㅡㅡ;
반응도 없고 포인트 적립도 안 된다면 자바스크립트 쪽에 에러가 있어서 아예 요청이 이루어지지 않고 있는 거죠... 괄호/따옴표 순서 여전히 거꾸로입니다. 아니, 저기는 작은따옴표가 아예 없어야 해요.
<script>
jQuery(document).ready(function($) {
$('.pointplus_dog114').click(function () {
exec_json('portalpoint.dispPortalpointIndex',{title:'pointplus_dog114'},function(response) {alert(response.result_message);});
});
});
</script>
그런데 이미 충전되었다는 메시지는 여전이 없네요.
잘 뜹니다!
오늘 정말 많은 도움 주셔서 정말 감사히 마쳤습니다. 큰절 올립니다. 꾸벅!
요런 페이지에요. 저기서 클릭하면 지금 구현한 것 때문에 클릭과 동시에 새창이 뜨면서 그쪽으로 탭이 이동되면서 동시에 뜬 알럿창을 못본거구요. 다시 돌아올때 옆에 새로 뜬 탭을 컨트롤 할때 사라지는 경우가 있어 못보는 경우가 있어 그런 듯 합니다.
기존에 html 페이지에서 자바스크립트로 이동할때는 해당 html 페이지에서 알럿창이 뜨고 페이지 이동이 되니 잘 봤던 것이구요.
물론 말씀 하신 대로 저 배너에 메시지가 유지 되어 있으면 좋겠지만 저는 넘사벽 기능이라 ㅋㅋㅋ
제가 알럿을 못본 경우가 테스트를 빨리 하려다 보니 페이지 클릭 하자마자 링크를 클릭해서 그런거네요. 스크립트가 동작이 완료되기 전에 클릭을 해서 그런 듯 하빈다. 실사용에서는 그렇게 빨리 클릭할 일이 많지는 않을 것 같긴 합니다.
배너들을 1초 지연 출력해서 극복! 했습니다 ㅋ
일거리 안받으려고 했는데 안드로이드 크롬이 요상하게 응답값의 알림창을 못띄우는 현상이 발견되어 숙제를 했습니다. 디자인은 내일 좀더 다듬으려구요.