Заказ в вызовах jquery

У меня есть цикл jQuery, который перебирает определенные элементы страницы HTML. Для каждого элемента я делаю выключатель над переменной и добавляю код HTML в определенных местах.

Проблема в том, что одно из этих добавлений является импортом в другой файл Javascript. В этом файле используется переменная из первого, но по какой-то причине эта переменная не всегда имеет правильное значение, в зависимости от порядка элементов HTML на странице.

UPDATE

As requested, I created a Plunker so it's easy to see code: http://plnkr.co/edit/mrEhgbZhhvu0Z4iniXGl?p=preview

Note: For this to work, you need to have correct pageId and appId for Instagram.

Для наглядности поставлю код:

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Demo</title>
    <link rel="stylesheet" href="estilo.css">
  </head>
  <body>
    <section id="rrss">
      <!-- If I put this article block as the last one, it works -->
      <article id="instagram">
        <div data-rrss="instagram"></div>
      </article>
      <br/>
      <article id="facebook">
        <div data-rrss="facebook"></div>
      </article>
      <br/>
      <article id="twitter">
        <div data-rrss="twitter"></div>
      </article>
    </section>

    <!-- SCRIPTS -->
    <script src='scripts/data.js'></script>
    <script src='scripts/jquery.js'></script>
    <script>var customJquery = $.noConflict(true);</script>
    <script src='../magic.js'></script>
  </body>
</html>

data.js

var data = {
  "facebook": {
    "id": "facebook",
    "width": 0,
    "height": 0,
    "custom_style": "border:none;overflow:hidden",
    "hide_cover": false,
    "show_facepile": true,
    "small_header": false,
    "adapt_container_width": true
  },
  "twitter": {
    "id": "twitter",
    "width": 0,
    "height": 0,
    "chrome": "nofooter noscrollbar noheader", // noborders  transparent
    "tweet_limit": 0,
    "lang": "es",
    "theme": "dark",
    "link_color": "#0084b4"
  },
  "instagram": {
    "id": "123456798123467/9876543219876543",
    "hidecaption": false,
    "custom_style": "overflow:auto;",
    "max_width": 0,
    "max_height": 500
  },
  "defaults": {
    "width": 380,
    "height": 500
  }
}

magic.js

var rrss = customJquery('div[data-rrss]');
var conf = undefined;
var defaults = undefined;
var node = document.querySelectorAll('[data-rrss="instagram"]')[0];

customJquery.each(rrss, function(ix, it) {
    var html = '';

    var network = customJquery(it).data('rrss');

    if (network === undefined || network == null || network.length <= 0)
        return;


    conf = data[network];

    if (conf === undefined ||conf === null || conf.length <= 0)
        return;

    defaults = data['defaults'];

    //Comprobamos si existe el key y si el value tiene texto
    if(conf.id === undefined || conf.id === null || conf.id.length === 0)
        return;

    switch(network) {
        case 'facebook':
            html =  '<iframe id="iFB" src="https://www.facebook.com/plugins/page.php?href=https%3A%2F%2Fwww.facebook.com%2F' + conf.id +
                        '&tabs=timeline' +
                        '&width=' + (conf.width <= 0 ? defaults.width : conf.width) +
                        '&height=' + (conf.height <= 0 ? defaults.height : conf.height) +
                        '&small_header=' + conf.small_header +
                        '&adapt_container_width=' + conf.adapt_container_width +
                        '&hide_cover=' + conf.hide_cover +
                        '&show_facepile=' + conf.show_facepile + '"' +
                        'width="' + (conf.width <= 0 ? defaults.width : conf.width) + '" ' +
                        'height="' + (conf.height <= 0 ? defaults.height : conf.height) + '" ' +
                        'style="' + conf.custom_style + '" ' +
                        'scrolling="no" frameborder="0" allowTransparency="true" allow="encrypted-media"></iframe>\n' +
                    '<script type="text/javascript">\n' +
                    '  setInterval(() => {\n' +
                    '    customJquery("#iFB")[0].src = customJquery("#iFB")[0].src\n' +
                    '  }, 5 * 60 * 1000);\n'
                    '</script>';
        break;
        case 'twitter':
            html =  '<a class="twitter-timeline" '+
                        'href="https://twitter.com/' + conf.id + '" ' +
                        'data-width="' + (conf.width <= 0 ? defaults.width : conf.width) + '" ' +
                        'data-height="' + (conf.height <= 0 ? defaults.height : conf.height) + '" ';

            if (conf.chrome !== undefined && conf.chrome !== '') {
                html += 'data-chrome="' + conf.chrome + '" ';
            }

            if (conf.tweet_limit > 0) {
                html += 'data-tweet-limit="' + conf.tweet_limit + '" ';
            }

            html += 'data-lang="' + conf.lang + '" ' +
                    'data-theme="' + conf.theme + '" ' +
                    'data-link-color="' + conf.link_color + '"' +
                    '>Tweets by ' + conf.id + '</a>\n' +
                    '<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>';
        break;
        case 'instagram':
            node = node.parentElement;
            html =  '<script async src="https://connect.facebook.net/es_ES/sdk.js"></script>\n' +
                    '<script src="../insta.js"></script>\n' +
                    '<script async defer src="https://www.instagram.com/embed.js"></script>\n' +
                    '<script>\n'+
                    '  setInterval(() => {\n' +
                    '    if (document.readyState === "complete") {\n' +
                    '      window.instgrm.Embeds.process();\n' +
                    '    }\n' +
                    '  }, 100);\n' +
                    '  setInterval(() => {\n' +
                    '    fbAsyncInit();\n' +
                    '  }, 5 * 60 * 1000);\n'
                    '</script>';
        break;
        default:
            html = '';
    }

    if (html != '') {
        customJquery(it).replaceWith(html);
    }
});

insta.js

window.fbAsyncInit = function () {
  var html = '';
  var style = '';

  // When the Instagram's article bloke in HTML isn't the last one, this shows data from Twitter bloke
  console.log(conf);

  if (node !== undefined) {
    if (document.getElementById('instagram') !== null) {
      document.getElementById('instagram').innerHTML = '';
    }

    if (conf !== undefined && conf !== '') {
      if (conf.max_width !== undefined && conf.max_width > 0) {
        style += 'max-width: ' + conf.max_width + 'px;';
      } else {
        style += 'max-width: ' + defaults.width + 'px;';
      }

      if (conf.max_height !== undefined && conf.max_height > 0) {
        style += 'max-height: ' + conf.max_height + 'px;';
      } else {
        style += 'max-height: ' + defaults.height + 'px;';
      }

      style += conf.custom_style;
    }

    var div = document.createElement('div');
    div.id = 'instagram';

    if (style !== '') {
      div.style = style;
    }

    node.appendChild(div);
  }

  var pageId = conf.id.substring(0, conf.id.indexOf('/'));
  var appId = conf.id.substring(conf.id.indexOf('/') + 1);

  FB.init({
    appId: appId,
    autoLogAppEvents: true,
    xfbml: true,
    version: "v3.1"
  });

  FB.getLoginStatus(function (response) {
    if (response.status === "connected") {
      FB.api(
        "/" + pageId + "/",
        "GET", { "fields": "instagram_business_account" },
        function (response) {
          if (response.error && response.error !== '') {
            console.log("Error recovering 'instagram_business_account': " + response.error.message);
          } else {
            FB.api(
              "/" + response.instagram_business_account.id + "/media",
              "GET", { "fields": "shortcode" },
              function (response) {
                for (var i = 0; i < response.data.length; i++) {
                  var xhttp = new XMLHttpRequest();

                  xhttp.onreadystatechange = function() {
                    if (this.readyState == 4 && this.status == 200) {
                      html = JSON.parse(this.response).html;
                      document.getElementById("instagram").innerHTML += html;
                    }
                  };

                  xhttp.open("GET", "https://api.instagram.com/oembed/?url=http://instagr.am/p/" + response.data[i].shortcode + "&omitscript=true&hidecaption=" + conf.hidecaption, true);
                  xhttp.send();
                }
              }
            );
          }
        }
      );
    } else {
      console.log("Error recovering access token: Not connected.")
      console.log(response)
    }
  });
};

Пожалуйста, сделайте это как фрагмент.

Sumesh TG 26.10.2018 09:05

Извините, я никогда не использовал это, если есть возможность или вы говорите что-то вроде Fiddle?

Andrés Marotta 26.10.2018 09:28

да, как рабочий пример.

Sumesh TG 26.10.2018 09:29

Вместо этого вам следует использовать фрагмент кода в редакторе.

Esko 26.10.2018 09:50

Я создал Plunker, так как мне нужно было больше файлов.

Andrés Marotta 26.10.2018 09:50
0
5
66
2

Ответы 2

Что ж, я решил с какой-то уродливой одинокой строкой:

case 'instagram':
    node = node.parentElement;
    instaconf = conf; // ***** Saved the conf here *****
    html = '<script async src="https://connect.facebook.net/es_ES/sdk.js"></script>\n' +
           '<script src="../tecInsta.js"></script>\n' +
           '<script async defer src="https://www.instagram.com/embed.js"></script>\n' +
           '<script>\n'+
           '  setInterval(() => {\n' +
           '    if (document.readyState === "complete") {\n' +
           '      window.instgrm.Embeds.process();\n' +
           '    }\n' +
           '  }, 100);\n' +
           '  setInterval(() => {\n' +
           '    fbAsyncInit();\n' +
           '  }, 5 * 60 * 1000);\n'
           '</script>';
    break;

Затем изменили ссылки conf на instaconf в файле insta.js.

Поскольку этот файл был загружен после завершения циклов jQuery, конфигурация была последней в этом цикле (последний статья в файле index.html).

Это мы не можем использовать, поскольку объект будет передаваться по ссылке, поэтому он будет указывать на последний объект, что означает информацию, связанную с твиттером.

Kesavan R 26.10.2018 14:05

Нет, не будет. Поскольку instaconf - это глобальная переменная, и она будет установлена ​​только тогда, когда network имеет значение «instagram». Проверил и работает нормально.

Andrés Marotta 26.10.2018 14:26

да, это сработает, но он ищет динамически подбирать значения

Kesavan R 26.10.2018 14:36

Проблема в том, что вы динамически добавляете HTML-элементы. Здесь jquery будет добавлен в DOM, а затем браузер будет анализировать его. Пока этот контроллер не будет ждать операции, поэтому цикл продолжит выполнение. Итак, здесь конфигурация содержит последний элемент конфигурации твиттера.

И мы не можем передать ссылку на строку html, насколько мне известно. Этого можно добиться, передав config как строку в строку html, оттуда мы можем перейти к методу fbAsyncInit ().

                    '<script>\n'+
                '  setInterval(() => {\n' +
                '    if (document.readyState === "complete") {\n' +
                '      window.instgrm.Embeds.process();\n' +
                '    }\n' +
                '  }, 100);\n' +
                '  setInterval(() => {\n' +
                ' let configuration = '+ JSON.stringify(conf) +';'+
                '    fbAsyncInit(configuration);\n' +
                '  }, 5 * 60 * 1000);\n'
                '</script>';

и мы можем получить как

window.fbAsyncInit = function (con) {

или мы можем передать функцию обратного вызова методу html и выполнить операцию, которая выполняется в magic.js

Ссылка: http://api.jquery.com/html/#html-function

тогда мы можем вернуть html соответственно.

Я надеюсь, что это поможет вам.

Другие вопросы по теме