質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.51%

  • JavaScript

    19258questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    7742questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • HTML5

    4791questions

    HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

  • iframe

    136questions

    HTMLのタグ<iframe>です。<iframe>は、ドキュメント内に""inline frame""を作るHTML要素で、同じページでセパレートしているドキュメントが表示されるようにします。

iframeの中へjqueryで動的追加した要素のクリックをトリガーにイベント発火させたい

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 113

alberorana

score 32

スマートフォンUIのまま編集できるWYSIWYGエディタを開発しています。
要件的な問題で iframeの中へ動的にボタンを追加し、 追加したボタンをクリックすると発火するような仕組みを開発しています。
その際にどうしても発火しないのですが、解決策をご存知ではないでしょうか?

コードとしては、まずiframeがあり、iframe中のsectionsに対して、 <label>ラベル</label> を付与しています。

  //非表示ラベルの付与
    $('#edit-iframe').contents().find('section').each(function(i)
    {
      if($(this).attr('class')!='js-no-hidden')
      {
        $(this).append(`<label class="js-section-hidden js-remove-element hidden-btn" data="section-${i}">このエリアを非表示にする</label>`);
      }
    });

そして、 js-section-hiddenクラスに対して、クリックファンクションを設定しておりますが、発火せず、

$('#edit-iframe').contents().find('.js-section-hidden').on('click', function(e) {
  alert('test');
});


おそらく動的に追加した要素なので、 .on('click', クラス名, function(e) { とする必要があり、  $('#edit-iframe').contents().find('.js-section-hidden').on('click',$('#edit-iframe').contents().find('.js-section-hidden'), function(e) {  このようにしてみたのですが、うまく行かなかったため行き詰まっています。

この問題の解決策をご存知の方がいらっしゃいましたら、ご回答いただけますと幸いです。

同じシステム(ドメイン)の /example/ID/ID をiframeのsrcにしています。

<!--{layout_header}-->
<link href="/sass/css/edit.css" rel="stylesheet">
<link href="/css/huebee.css" rel="stylesheet">
<script>
  window.vars = [];
  window.user = <?= $json_user ?> ;
  window.templateId = <?= $user['template_id'] ?> ;
</script>
<!--{/layout_header}-->

<!--{layout_footer}-->
<script src="/plugins/jQueryUI/jquery-ui.min.js"></script>
<script src="/js/HP/edit.js"></script>


<a href="/view/<?= $this->current_user->id ?>" class="mb10" style="display: block;" target="_blank">実際のページを確認</a>

<button class="js-edit-submit save-button">保存 <br><i class="fas fa-save mt5"></i></button>
<button class="js-edit-section section-button">パーツ<br> 追加 <br><i class="fas fa-save mt5"></i></button>

<? if($source): ?>
  <iframe src="/view/<?= $user['id'] ?>" width="99%" height="80%" class="js-iframe" id='iframe' device="pc"></iframe>
  <iframe src="/view/<?= $user['id'] ?>" width="99%" height="80%" id='edit-iframe' device="pc" contenteditable="true"></iframe>
<? else: ?>
  <iframe src="/example/<?= $user['template_id'] ?>/<?= $user['id'] ?>" width="99%" height="80%" class="js-iframe" id='iframe'device="pc"></iframe>
  <iframe src="/example/<?= $user['template_id'] ?>/<?= $user['id'] ?>" width="99%" height="80%" id='edit-iframe' device="pc" contenteditable="true"></iframe>
<? endif; ?>
var protocol = location.protocol;
var url = location.host;
window.editingDom = null;

//要素の中身変更
$(window).on("load", function(){
  $('#edit-iframe').contents().find('head').append('<link rel="stylesheet" href="/sass/css/edit-iframe.css" type="text/css" />');
//保存ボタン
$(document).on("click", ".js-edit-submit", function () {
  //画像変更だけした場合の対策
  //初回に文言だけ変更して保存した場合の分岐
  console.log(window.editingDom);
  if(window.editingDom)
  {
    if(window.editingDom.prop('tagName') != 'img')
    {
      var childVar= {'html_id': window.editingDom.attr('id'), 'content': window.editingDom.html(), 'image_flag': '0'};
      console.log('childVar');
      console.log(childVar);
      window.vars.push(childVar);
    }
  }
  //編集のための要素を削除してから、本番ソースにする
  $('#edit-iframe').contents().find(".js-remove-element").remove();
  $('#edit-iframe').contents().find(".is-hidden").remove();
  $('#edit-iframe').contents().find(".js-section-hidden").each(function(i){
    $(this).remove();
  });
  $('#edit-iframe').contents().find(".js-section-appear").each(function(i){
    $(this).remove();
  });
  //bodyのcontenteditableを削除
  var iframe = $('#edit-iframe')[0];
  iframe.contentDocument.body.contentEditable = false;
  iframe.designMode = 'off';

  console.log($('#edit-iframe').contents().find('html').html());
  commit($('#edit-iframe').contents().find('html').html(), window.vars);

  //以下編集を解除する処理
  unEdit();
  //updatePreview();
  //window.updatePreviewImage();
  window.vars = [];
  alert('保存が完了しました。');
  location.reload();
});

function commit(source,vars=null)
{
  //source = source.replace( /このエリアを非表示にする/g , "" ) ;
  //ソースコード自体を保存する処理
  console.log(source);
  //return false;
  $.ajax({
    url:protocol + '//' + url + '/api/v1/source/commit' ,
    type: 'POST',
    dataType: 'json',
    data: {'source' : source},
    success: function(response){

    },
    error : function(XMLHttpRequest, textStatus, errorThrown) {

    }
  });//AJAX
  //文言と画像をまとめてインサート
  var i;
  for(i=0;i<vars.length;i++)
  {
    console.log(vars[i]);
    if(vars[i].content && vars[i].html_id)
    {
      $.ajax({
        url:protocol + '//' + url + '/api/v1/' + vars[i].html_id + '/commit' ,
        type: 'POST',
        dataType: 'json',
        data: {'content' : vars[i].content, 'image_flag': vars[i].image_flag},
        success: function(response){

        },
        error : function(XMLHttpRequest, textStatus, errorThrown) {

        }
      });//AJAX
    }//if
  }
}





//非表示要素の取得と適用
$(window).on("load", function(e){
  //非表示要素をまとめて取得
  $.get({
    url: protocol + '//' + url + '/api/v1/hiddens/get',
    headers:{
      'Content-Type': 'application/json'
    },
    type: 'GET',
    dataType: 'json',
    data:JSON.stringify(),
    success: function(response){
      //セクションの数だけループ
      $('#edit-iframe').contents().find("js-edit-window section").each(function(i){
        //hidden要素の数だけループし、その中で一致するものがあれば非表示要素にチェンジ!
        console.log('hidden');
        for(h=0; h < response.length; h++)
        {
          if(($(this).attr('id')== response[h].hidden_html_id))
          {
            $(this).css('opacity', '0.2');
            $(this).addClass('js-remove-element');
            $(this).find('.js-section-hidden').remove();
            $(this).before(`<label class="js-section-appear hidden-btn hidden-btn--appear">このエリアを表示する</label>`);
            $(this).find('js-hidden-btn').remove();
            $('iframe').contents().find($(this)).hide();
          }
        }
      });
    },

    });
  $('.js-edit-window').hide();
  //sectionの数だけ非表示ボタンを付与

});
//非表示要素の取得と適用ここまで



//非表示決定ボタンとDBへのインサート
// iframeRef($('#edit-iframe')).on("input", function() {
//  alert('test');
// }) ;
$('#edit-iframe').contents().find('.js-section-hidden').on('click',$('#edit-iframe').contents().find('.js-section-hidden'), function(e) {
  alert('test');
});
$('#edit-iframe').contents().find('.js-section-hidden').on("input", function() {
  alert('aaa');
//$(document).on('click', '.js-section-hidden', function hiddenSection(){
  $(this).parent().css('opacity', '0.2');
  //ソースをDBにインサート前に削除対象とするためにクラス付与
  $(this).parent().addClass('js-remove-element');
  hiddenAjax($(this).parent().attr('id'));
  $(this).parent().before(`<label class="js-section-appear js-remove-element hidden-btn hidden-btn--appear">このエリアを表示する</label>`);
  $(this).remove();
});

$(document).on('click', '.js-section-appear', function appearSection(){
  $(this).next('section').css('opacity', '1');
  //ソースをDBにインサート前に削除対象外とするためにクラス削除
  $(this).next('section').removeClass('js-remove-element');
  hiddenAjax($(this).next('section').attr('id'));
  $(this).next('section').append('<label class="js-section-hidden js-remove-element hidden-btn">このエリアを非表示にする</label>');
  $(this).remove();
});
//非表示決定ボタンとDBへのインサートここまで
//
//プレビュー or 編集モード切り替え
$(".js-hp-edit").on("click", function(){
  state = $(this).attr('state');
  if(state=="preview")
  {
    $('#edit-iframe').show();
    $('#iframe').hide();
    $('#edit-iframe').contents().find('head').append('<link rel="stylesheet" href="/sass/css/edit-iframe.css" type="text/css" />');
    $('#edit-iframe').contents().find('head').append('<link rel="stylesheet" href="/sass/css/sections.css" type="text/css" />');
    //$('#edit-iframe').contents().find('head').append('<script src="/js/HP/edit-iframe.js" type="text/javascript" />');
    var iframe = $('#edit-iframe')[0];
    iframe.contentDocument.body.contentEditable = true;
    iframe.designMode = 'on';
    $(this).html('編集中  <i class="fas fa-desktop"></i>(クリックで戻る)');
    $(this).addClass('hp-edit__edit--now');
    $(this).attr('state', 'edit');
    $('#edit-iframe').contents().find('article').attr('id', 'sortable');
    $('section').addClass('js-droppable');
    $('.js-edit-submit').show();
    $('.js-edit-section').show();
    //非表示ラベルの付与
    $('#edit-iframe').contents().find('section').each(function(i)
    {
      if($(this).attr('class')!='js-no-hidden')
      {
        $(this).append(`<label class="js-section-hidden js-remove-element hidden-btn" data="section-${i}">このエリアを非表示にする</label>`);
      }
    });

    $(".js-add-section").each(function(i){
      //hidden要素の数だけループし、その中で一致するものがあれば非表示要素にチェンジ!
        $(this).addClass('js-remove-element');
        $(this).before(`<label class="js-section-remove js-remove-element hidden-btn hidden-btn--appear">この要素を削除</label>`);
        $(this).find('js-hidden-btn').remove();
        $('iframe').contents().find($(this)).hide();
    });
    sortable();
  }else{
    $('.js-edit-window').hide();
    $('.js-iframe').show();
    $(this).html('このページを編集する    <i class="far fa-desktop"></i>');
    $(this).removeClass('hp-edit__edit--now');
    $(this).attr('state', 'preview');
    $('article').attr('id', '');
    $('.js-edit-submit').hide();
    $('.js-edit-section').hide();
    //↓ プレビューに戻した際に変更点をアップデート
    $(".js-remove-element").remove();
    //window.updatePreview();
    //window.updatePreviewImage();
    //window.changeColor();
  }
});
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2019/03/14 11:41 編集

    コードの流れがわかりません。なるべく全体を、せめて書かれている状況が再現できるだけのHTML/JavaScriptを提示してください。(質問文は編集できますので、質問文に追記してください)

    キャンセル

  • alberorana

    2019/03/14 11:49

    ご回答していただく立場で指摘いただきありがとうございます。相当長いですが、今から追記いたします。

    キャンセル

回答 4

checkベストアンサー

+2

iframe側の$(document).redyに当たる部分が無い為に、iframeの子要素のイベント判定ができていないのではないかと想像します。

下記のような方法でどうでしょうか。

$('iframe').on('load', function () {
    $(this).contents().on('mousemove', onMouseMove);
});

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/14 19:14

    おっしゃるとおりの原因だったようで、
    $('#edit-iframe').on('load', function () {
    $(this).contents().on('click', '.js-section-hidden', function(){
    alert('test");
    )}
    )}
    こちらのコードで無事発火することができました! ご回答ありがとうございました。

    キャンセル

+1

ハズレかもしれませんが・・・ (その場合はすみません)

iframe の中の document オブジェクトが取得できていますか?

以下のようなコードで iframe の document オブジェクトを取得を取得して、それに対して操作するということになると思うのですが。(引数の frameRef は getElementById で取得した iframe オブジェクトです) 

// iframe 内の document オブジェクトを取得。
// contentWindow は IE 用。
// contentDocument は Firefox 用。
function iframeRef(frameRef) {
    return frameRef.contentWindow ?
        frameRef.contentWindow.document : 
            frameRef.contentDocument;
}


具体例は以下の記事を見てください。

ModalPopup を別ページから非表示
http://surferonwww.info/BlogEngine/post/2013/01/27/hide-modalpopup-by-clicking-a-button-placed-in-another-page.aspx

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/14 12:50

    具体例をありがとうございます。
    Documentまでは取得できたのですが、その先のイベント取得ができずなので、もう少しがんばってみます。

    キャンセル

+1

これでどうでしょう。

$('#edit-iframe').contents().find('body').on('click', '.js-section-hidden', function(e) {
  alert('test');
}); // 未検証

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/14 12:51

    ご回答ありがとうございます。
    せっかくご回答いただいたのですが、どうもイベントが取れていないようで、発火しませんでした。

    キャンセル

+1

label要素生成されてから、イベントバインドする処理になっていないように見受けられます。
今のコードデバッグして、クリックファンクション設定しているコードでfind(.’js-section-hidden’)の戻り値でlabelアイテムが取得出来てるか確認してみてはいかがでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • JavaScript

    19258questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • jQuery

    7742questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • HTML5

    4791questions

    HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

  • iframe

    136questions

    HTMLのタグ<iframe>です。<iframe>は、ドキュメント内に""inline frame""を作るHTML要素で、同じページでセパレートしているドキュメントが表示されるようにします。