如何创建类似Pinterest的脚本-步骤6

How to create Pinterest-like script - step 6
How to create Pinterest-like script - step 6

How to create Pinterest-like script – step 6 Several our readers asked us to implement an infinite scroll for our Pinterest script, thus I decided to implement it today. I made some research, and came to http://www.infinite-scroll.com/. I think that the library is ideal for the realization of our objectives. It let us make some kind of endless pages. It means that initially we can render a certain amount of images, when we want to see more images, we can easily scroll down, and new set of images will be loaded ajaxy. If you are ready – let’s start.

如何创建类似Pinterest的脚本–步骤6一些读者要求我们为Pinterest脚本实现无限滚动,因此我决定今天实现它。 我进行了一些研究,并访问了http://www.infinite-scroll.com/。 我认为图书馆是实现我们目标的理想选择。 它使我们能够制作出无尽的页面。 这意味着一开始我们可以渲染一定数量的图像,当我们想查看更多图像时,我们可以轻松地向下滚动,并且新的图像集将被ajaxy加载。 如果您准备好了,那就开始吧。

You are welcome to try our updated demo and download the fresh source package:

欢迎您尝试我们更新的演示并下载新的源程序包:

现场演示

[sociallocker]

[社交储物柜]

打包下载

[/sociallocker]

[/ sociallocker]

步骤1. HTML (Step 1. HTML)

The first thing you have to do is – to download the plugin jquery.infinitescroll.min.js and put it into your ‘js’ directory. Now, we can link this new library in the header of our ‘templates/index.html’, now, full list of attached libraries looks like:

您要做的第一件事是–下载插件jquery.infinitescroll.min.js并将其放入“ js”目录。 现在,我们可以在“ templates / index.html”的标题中链接此新库,现在,附加库的完整列表如下所示:

templates / index.html (templates/index.html)

    <!-- add scripts -->
    <script src="js/jquery.min.js"></script>
    <script src="js/jquery.colorbox-min.js"></script>
    <script src="js/jquery.masonry.min.js"></script>
    <script src="js/jquery.infinitescroll.min.js"></script>
    <script src="js/script.js"></script>

    <!-- add scripts -->
    <script src="js/jquery.min.js"></script>
    <script src="js/jquery.colorbox-min.js"></script>
    <script src="js/jquery.masonry.min.js"></script>
    <script src="js/jquery.infinitescroll.min.js"></script>
    <script src="js/script.js"></script>

Another small change in this file – a new template key (in the end of main container) – {infinite}

此文件中的另一个小更改–一个新的模板密钥(在主容器的末尾)– {infinite}


    <!-- main container -->
    <div class="main_container">
        {images_set}
    </div>
    {infinite}

    <!-- main container -->
    <div class="main_container">
        {images_set}
    </div>
    {infinite}

Exactly the same changes we have to repeat in ‘templates/profile.html’ file (in our plans is to add infinite scroll for both: index and profile pages)

我们必须在“ templates / profile.html”文件中重复相同的更改(我们的计划是为索引和配置文件页面添加无限滚动)

步骤2. PHP (Step 2. PHP)

Well, in the previous step we prepared our template files, now – we have to exchange our {infinite} key for a certain value. The first file is index page. Please replace our previous set of template keys

好了,现在在上一步中,我们准备了模板文件–我们必须将{infinite}键交换为某个值。 第一个文件是索引页。 请替换我们之前的模板密钥集

index.php (index.php)

// draw common page
$aKeys = array(
    '{menu_elements}' => $sLoginMenu,
    '{extra_data}' => $sExtra,
    '{images_set}' => $sPhotos
);

// draw common page
$aKeys = array(
    '{menu_elements}' => $sLoginMenu,
    '{extra_data}' => $sExtra,
    '{images_set}' => $sPhotos
);

with next code:

下一个代码:


// infinite scroll
$sPerpage = 20;
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { // ajax
    if($sPhotos) {
        $sPage = (int)$_GET['page'] + 1;
        echo <<<EOF
<div class="main_container">
{$sPhotos}
</div>
<nav id="page-nav">
  <a href="index.php?page={$sPage}&per_page={$sPerpage}"></a>
</nav>
EOF;
    }
    exit;
}
$sInfinite = ($sPhotos == '') ? '' : <<<EOF
<nav id="page-nav">
  <a href="index.php?page=2&per_page={$sPerpage}"></a>
</nav>
EOF;
// draw common page
$aKeys = array(
    '{menu_elements}' => $sLoginMenu,
    '{extra_data}' => $sExtra,
    '{images_set}' => $sPhotos,
    '{infinite}' => $sInfinite
);

// infinite scroll
$sPerpage = 20;
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { // ajax
    if($sPhotos) {
        $sPage = (int)$_GET['page'] + 1;
        echo <<<EOF
<div class="main_container">
{$sPhotos}
</div>
<nav id="page-nav">
  <a href="index.php?page={$sPage}&per_page={$sPerpage}"></a>
</nav>
EOF;
    }
    exit;
}
$sInfinite = ($sPhotos == '') ? '' : <<<EOF
<nav id="page-nav">
  <a href="index.php?page=2&per_page={$sPerpage}"></a>
</nav>
EOF;
// draw common page
$aKeys = array(
    '{menu_elements}' => $sLoginMenu,
    '{extra_data}' => $sExtra,
    '{images_set}' => $sPhotos,
    '{infinite}' => $sInfinite
);

The main idea – to get fresh data each time we request this page (of course, it depends on next GET params: ‘page’ and ‘per_page’). The similar changes I prepared for our profile page, look at the fresh version:

主要思想–每次我们请求此页面时获取最新数据(当然,这取决于下一个GET参数:“ page”和“ per_page”)。 我为个人资料页面准备的类似更改,请查看新版本:

profile.php (profile.php)

require_once('classes/CMySQL.php');
require_once('classes/CMembers.php');
require_once('classes/CPhotos.php');
// get login data
list ($sLoginMenu, $sExtra) = $GLOBALS['CMembers']->getLoginData();
// profile id
$i = (int)$_GET['id'];
if ($i) {
    $aMemberInfo = $GLOBALS['CMembers']->getProfileInfo($i);
    if ($aMemberInfo) {
        // get all photos by profile
        $sPhotos = $GLOBALS['CPhotos']->getAllPhotos($i);
        // infinite scroll
        $sPerpage = 20;
        if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { // ajax
            if($sPhotos) {
                $sPage = (int)$_GET['page'] + 1;
                echo <<<EOF
<div class="main_container">
{$sPhotos}
</div>
<nav id="page-nav">
  <a href="profile.php?id={$i}&page={$sPage}&per_page={$sPerpage}"></a>
</nav>
EOF;
            }
            exit;
        }
        $sInfinite = ($sPhotos == '') ? '' : <<<EOF
<nav id="page-nav">
  <a href="profile.php?id={$i}&page=2&per_page={$sPerpage}"></a>
</nav>
EOF;
        // draw profile page
        $aKeys = array(
            '{menu_elements}' => $sLoginMenu,
            '{extra_data}' => $sExtra,
            '{images_set}' => $sPhotos,
            '{profile_name}' => $aMemberInfo['first_name'],
            '{infinite}' => $sInfinite
        );
        echo strtr(file_get_contents('templates/profile.html'), $aKeys);
        exit;
    }
}
header('Location: error.php');

require_once('classes/CMySQL.php');
require_once('classes/CMembers.php');
require_once('classes/CPhotos.php');
// get login data
list ($sLoginMenu, $sExtra) = $GLOBALS['CMembers']->getLoginData();
// profile id
$i = (int)$_GET['id'];
if ($i) {
    $aMemberInfo = $GLOBALS['CMembers']->getProfileInfo($i);
    if ($aMemberInfo) {
        // get all photos by profile
        $sPhotos = $GLOBALS['CPhotos']->getAllPhotos($i);
        // infinite scroll
        $sPerpage = 20;
        if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { // ajax
            if($sPhotos) {
                $sPage = (int)$_GET['page'] + 1;
                echo <<<EOF
<div class="main_container">
{$sPhotos}
</div>
<nav id="page-nav">
  <a href="profile.php?id={$i}&page={$sPage}&per_page={$sPerpage}"></a>
</nav>
EOF;
            }
            exit;
        }
        $sInfinite = ($sPhotos == '') ? '' : <<<EOF
<nav id="page-nav">
  <a href="profile.php?id={$i}&page=2&per_page={$sPerpage}"></a>
</nav>
EOF;
        // draw profile page
        $aKeys = array(
            '{menu_elements}' => $sLoginMenu,
            '{extra_data}' => $sExtra,
            '{images_set}' => $sPhotos,
            '{profile_name}' => $aMemberInfo['first_name'],
            '{infinite}' => $sInfinite
        );
        echo strtr(file_get_contents('templates/profile.html'), $aKeys);
        exit;
    }
}
header('Location: error.php');

Pay attention, that by default we display 20 images per page. My final touches were in the main Photos class (CPhotos.php). As you remember, we had to operate with two new GET params for pagination: ‘page’ and ‘per_page’. I added the processing of both parameters in the function ‘getAllPhotos’:

请注意,默认情况下,我们每页显示20张图像。 我最后的接触是在主要的Photo类(CPhotos.php)中。 您还记得,我们必须使用两个新的GET参数进行分页:'page'和'per_page'。 我在功能'getAllPhotos'中添加了两个参数的处理:

classes / CPhotos.php (classes/CPhotos.php)

    function getAllPhotos($iPid = 0, $sKeyPar = '') {
        // prepare WHERE filter
        $aWhere = array();
        if ($iPid) {
            $aWhere[] = "`owner` = '{$iPid}'";
        }
        if ($sKeyPar != '') {
            $sKeyword = $GLOBALS['MySQL']->escape($sKeyPar);
            $aWhere[] = "`title` LIKE '%{$sKeyword}%'";
        }
        $sFilter = (count($aWhere)) ? 'WHERE ' . implode(' AND ', $aWhere) : '';
        // pagination
        $iPage = (isset($_GET['page'])) ? (int)$_GET['page'] : 1;
        $iPerPage = (isset($_GET['per_page'])) ? (int)$_GET['per_page'] : 20;
        $iPage = ($iPage < 1) ? 1 : $iPage;
        $iFrom = ($iPage - 1) * $iPerPage;
        $iFrom = ($iFrom < 1) ? 0 : $iFrom;
        $sLimit = "LIMIT {$iFrom}, {$iPerPage}";
        $sSQL = "
            SELECT *
            FROM `pd_photos`
            {$sFilter}
            ORDER BY `when` DESC
            {$sLimit}
        ";
        $aPhotos = $GLOBALS['MySQL']->getAll($sSQL);
        $sImages = '';
        $sFolder = 'photos/';
        foreach ($aPhotos as $i => $aPhoto) {
            $iPhotoId = (int)$aPhoto['id'];
            $sFile = $aPhoto['filename'];
            $sTitle = $aPhoto['title'];
            $iCmts = (int)$aPhoto['comments_count'];
            $iLoggId = (int)$_SESSION['member_id'];
            $iOwner = (int)$aPhoto['owner'];
            $iRepins = (int)$aPhoto['repin_count'];
            $iLikes = (int)$aPhoto['like_count'];
            $sActions = ($iLoggId && $iOwner != $iLoggId) ? '<a href="#" class="button repinbutton">Repin</a><a href="#" class="button likebutton">Like</a>' : '';
            // display a blank image for not existing photos
            $sFile = (file_exists($sFolder . $sFile)) ? $sFile : 'blank_photo.jpg';
            $aPathInfo = pathinfo($sFolder . $sFile);
            $sExt = strtolower($aPathInfo['extension']);
            $sImages .= <<<EOL
<!-- pin element {$iPhotoId} -->
<div class="pin" pin_id="{$iPhotoId}">
    <div class="holder">
        <div class="actions">
            {$sActions}
            <a href="#" class="button comment_tr">Comment</a>
        </div>
        <a class="image ajax" href="service.php?id={$iPhotoId}" title="{$sTitle}">
            <img alt="{$sTitle}" src="{$sFolder}{$sFile}">
        </a>
    </div>
    <p class="desc">{$sTitle}</p>
    <p class="info">
        <span class="LikesCount"><strong>{$iLikes}</strong> likes</span>
        <span>{$iRepins} repins</span>
        <span>{$iCmts} comments</span>
    </p>
    <form class="comment" method="post" action="" style="display: none" onsubmit="return submitComment(this, {$iPhotoId})">
        <textarea placeholder="Add a comment..." maxlength="255" name="comment"></textarea>
        <input type="submit" class="button" value="Comment" />
    </form>
</div>
EOL;
        }
        return $sImages;
    }

    function getAllPhotos($iPid = 0, $sKeyPar = '') {
        // prepare WHERE filter
        $aWhere = array();
        if ($iPid) {
            $aWhere[] = "`owner` = '{$iPid}'";
        }
        if ($sKeyPar != '') {
            $sKeyword = $GLOBALS['MySQL']->escape($sKeyPar);
            $aWhere[] = "`title` LIKE '%{$sKeyword}%'";
        }
        $sFilter = (count($aWhere)) ? 'WHERE ' . implode(' AND ', $aWhere) : '';
        // pagination
        $iPage = (isset($_GET['page'])) ? (int)$_GET['page'] : 1;
        $iPerPage = (isset($_GET['per_page'])) ? (int)$_GET['per_page'] : 20;
        $iPage = ($iPage < 1) ? 1 : $iPage;
        $iFrom = ($iPage - 1) * $iPerPage;
        $iFrom = ($iFrom < 1) ? 0 : $iFrom;
        $sLimit = "LIMIT {$iFrom}, {$iPerPage}";
        $sSQL = "
            SELECT *
            FROM `pd_photos`
            {$sFilter}
            ORDER BY `when` DESC
            {$sLimit}
        ";
        $aPhotos = $GLOBALS['MySQL']->getAll($sSQL);
        $sImages = '';
        $sFolder = 'photos/';
        foreach ($aPhotos as $i => $aPhoto) {
            $iPhotoId = (int)$aPhoto['id'];
            $sFile = $aPhoto['filename'];
            $sTitle = $aPhoto['title'];
            $iCmts = (int)$aPhoto['comments_count'];
            $iLoggId = (int)$_SESSION['member_id'];
            $iOwner = (int)$aPhoto['owner'];
            $iRepins = (int)$aPhoto['repin_count'];
            $iLikes = (int)$aPhoto['like_count'];
            $sActions = ($iLoggId && $iOwner != $iLoggId) ? '<a href="#" class="button repinbutton">Repin</a><a href="#" class="button likebutton">Like</a>' : '';
            // display a blank image for not existing photos
            $sFile = (file_exists($sFolder . $sFile)) ? $sFile : 'blank_photo.jpg';
            $aPathInfo = pathinfo($sFolder . $sFile);
            $sExt = strtolower($aPathInfo['extension']);
            $sImages .= <<<EOL
<!-- pin element {$iPhotoId} -->
<div class="pin" pin_id="{$iPhotoId}">
    <div class="holder">
        <div class="actions">
            {$sActions}
            <a href="#" class="button comment_tr">Comment</a>
        </div>
        <a class="image ajax" href="service.php?id={$iPhotoId}" title="{$sTitle}">
            <img alt="{$sTitle}" src="{$sFolder}{$sFile}">
        </a>
    </div>
    <p class="desc">{$sTitle}</p>
    <p class="info">
        <span class="LikesCount"><strong>{$iLikes}</strong> likes</span>
        <span>{$iRepins} repins</span>
        <span>{$iCmts} comments</span>
    </p>
    <form class="comment" method="post" action="" style="display: none" onsubmit="return submitComment(this, {$iPhotoId})">
        <textarea placeholder="Add a comment..." maxlength="255" name="comment"></textarea>
        <input type="submit" class="button" value="Comment" />
    </form>
</div>
EOL;
        }
        return $sImages;
    }

As you can see, both params affect SQL limits only.

如您所见,这两个参数仅影响SQL限制。

步骤3. Javascript (Step 3. Javascript)

Final changes I made in the main javascript file. There are only two new event handlers:

我在主要javascript文件中所做的最终更改。 只有两个新的事件处理程序:

js / script.js (js/script.js)

function fileSelectHandler() {
    // get selected file
    var oFile = $('#image_file')[0].files[0];
    // html5 file upload
    var formData = new FormData($('#upload_form')[0]);
    $.ajax({
        url: 'upload.php', //server script to process data
        type: 'POST',
        // ajax events
        beforeSend: function() {
        },
        success: function(e) {
            $('#upload_result').html('Thank you for your photo').show();
            setTimeout(function() {
                $("#upload_result").hide().empty();
                window.location.href = 'index.php';
            }, 4000);
        },
        error: function(e) {
            $('#upload_result').html('Error while processing uploaded image');
        },
        // form data
        data: formData,
        // options to tell JQuery not to process data or worry about content-type
        cache: false,
        contentType: false,
        processData: false
    });
}
function submitComment(form, id) {
    $.ajax({
      type: 'POST',
      url: 'service.php',
      data: 'add=comment&id=' + id + '&comment=' + $(form).find('textarea').val(),
      cache: false,
      success: function(html){
        if (html) {
          location.reload();
        }
      }
    });
    return false;
}
function initiateColorboxHandler() {
    $('.ajax').colorbox({
        onOpen:function(){
        },
        onLoad:function(){
        },
        onComplete:function(){
            $(this).colorbox.resize();
            var iPinId = $(this).parent().parent().attr('pin_id');
            $.ajax({
              url: 'service.php',
              data: 'get=comments&id=' + iPinId,
              cache: false,
              success: function(html){
                $('.comments').append(html);
                $(this).colorbox.resize();
              }
            });
        },
        onCleanup:function(){
        },
        onClosed:function(){
        }
    });
}
$(document).ready(function(){
    // file field change handler
    $('#image_file').change(function(){
        var file = this.files[0];
        name = file.name;
        size = file.size;
        type = file.type;
        // extra validation
        if (name && size)  {
            if (! file.type.match('image.*')) {
                alert("Select image please");
            } else {
                fileSelectHandler();
            }
        }
    });
    // masonry initialization
    var $container = $('.main_container');
    $container.imagesLoaded(function(){
      // options
      $container.masonry({
        itemSelector: '.pin',
        isAnimated: true,
        isFitWidth: true,
        isAnimatedFromBottom: true
      });
    });
    $container.infinitescroll({
      navSelector  : '#page-nav',    // selector for the paged navigation
      nextSelector : '#page-nav a',  // selector for the NEXT link (to page 2)
      itemSelector : '.pin',     // selector for all items you'll retrieve
      loading: {
          finishedMsg: 'No more pages to load.'
        }
      },
      // trigger Masonry as a callback
      function( newElements ) {
        // hide new items while they are loading
        var $newElems = $( newElements ).css({ opacity: 0 });
        // ensure that images load before adding to masonry layout
        $newElems.imagesLoaded(function(){
          // show elems now they're ready
          $newElems.animate({ opacity: 1 });
          $container.masonry( 'appended', $newElems, true );
          // initiate colorbox
          initiateColorboxHandler();
        });
      }
    );
    // onclick event handler (for comments)
    $('.comment_tr').click(function () {
        $(this).toggleClass('disabled');
        $(this).parent().parent().parent().find('form.comment').slideToggle(400, function () {
            $('.main_container').masonry();
        });
    });
    // initiate colorbox
    initiateColorboxHandler();
    // onclick event handler (for like button)
    $('.pin .actions .likebutton').click(function () {
        $(this).attr('disabled', 'disabled');
        var iPinId = $(this).parent().parent().parent().attr('pin_id');
        $.ajax({
          url: 'service.php',
          type: 'POST',
          data: 'add=like&id=' + iPinId,
          cache: false,
          success: function(res){
            $('.pin[pin_id='+iPinId+'] .info .LikesCount strong').text(res);
          }
        });
        return false;
    });
    // onclick event handler (for repin button)
    $('.pin .actions .repinbutton').click(function () {
        var iPinId = $(this).parent().parent().parent().attr('pin_id');
        $.ajax({
          url: 'service.php',
          type: 'POST',
          data: 'add=repin&id=' + iPinId,
          cache: false,
          success: function(res){
            window.location.href = 'profile.php?id=' + res;
          }
        });
        return false;
    });
});

function fileSelectHandler() {
    // get selected file
    var oFile = $('#image_file')[0].files[0];
    // html5 file upload
    var formData = new FormData($('#upload_form')[0]);
    $.ajax({
        url: 'upload.php', //server script to process data
        type: 'POST',
        // ajax events
        beforeSend: function() {
        },
        success: function(e) {
            $('#upload_result').html('Thank you for your photo').show();
            setTimeout(function() {
                $("#upload_result").hide().empty();
                window.location.href = 'index.php';
            }, 4000);
        },
        error: function(e) {
            $('#upload_result').html('Error while processing uploaded image');
        },
        // form data
        data: formData,
        // options to tell JQuery not to process data or worry about content-type
        cache: false,
        contentType: false,
        processData: false
    });
}
function submitComment(form, id) {
    $.ajax({
      type: 'POST',
      url: 'service.php',
      data: 'add=comment&id=' + id + '&comment=' + $(form).find('textarea').val(),
      cache: false,
      success: function(html){
        if (html) {
          location.reload();
        }
      }
    });
    return false;
}
function initiateColorboxHandler() {
    $('.ajax').colorbox({
        onOpen:function(){
        },
        onLoad:function(){
        },
        onComplete:function(){
            $(this).colorbox.resize();
            var iPinId = $(this).parent().parent().attr('pin_id');
            $.ajax({
              url: 'service.php',
              data: 'get=comments&id=' + iPinId,
              cache: false,
              success: function(html){
                $('.comments').append(html);
                $(this).colorbox.resize();
              }
            });
        },
        onCleanup:function(){
        },
        onClosed:function(){
        }
    });
}
$(document).ready(function(){
    // file field change handler
    $('#image_file').change(function(){
        var file = this.files[0];
        name = file.name;
        size = file.size;
        type = file.type;
        // extra validation
        if (name && size)  {
            if (! file.type.match('image.*')) {
                alert("Select image please");
            } else {
                fileSelectHandler();
            }
        }
    });
    // masonry initialization
    var $container = $('.main_container');
    $container.imagesLoaded(function(){
      // options
      $container.masonry({
        itemSelector: '.pin',
        isAnimated: true,
        isFitWidth: true,
        isAnimatedFromBottom: true
      });
    });
    $container.infinitescroll({
      navSelector  : '#page-nav',    // selector for the paged navigation
      nextSelector : '#page-nav a',  // selector for the NEXT link (to page 2)
      itemSelector : '.pin',     // selector for all items you'll retrieve
      loading: {
          finishedMsg: 'No more pages to load.'
        }
      },
      // trigger Masonry as a callback
      function( newElements ) {
        // hide new items while they are loading
        var $newElems = $( newElements ).css({ opacity: 0 });
        // ensure that images load before adding to masonry layout
        $newElems.imagesLoaded(function(){
          // show elems now they're ready
          $newElems.animate({ opacity: 1 });
          $container.masonry( 'appended', $newElems, true );
          // initiate colorbox
          initiateColorboxHandler();
        });
      }
    );
    // onclick event handler (for comments)
    $('.comment_tr').click(function () {
        $(this).toggleClass('disabled');
        $(this).parent().parent().parent().find('form.comment').slideToggle(400, function () {
            $('.main_container').masonry();
        });
    });
    // initiate colorbox
    initiateColorboxHandler();
    // onclick event handler (for like button)
    $('.pin .actions .likebutton').click(function () {
        $(this).attr('disabled', 'disabled');
        var iPinId = $(this).parent().parent().parent().attr('pin_id');
        $.ajax({
          url: 'service.php',
          type: 'POST',
          data: 'add=like&id=' + iPinId,
          cache: false,
          success: function(res){
            $('.pin[pin_id='+iPinId+'] .info .LikesCount strong').text(res);
          }
        });
        return false;
    });
    // onclick event handler (for repin button)
    $('.pin .actions .repinbutton').click(function () {
        var iPinId = $(this).parent().parent().parent().attr('pin_id');
        $.ajax({
          url: 'service.php',
          type: 'POST',
          data: 'add=repin&id=' + iPinId,
          cache: false,
          success: function(res){
            window.location.href = 'profile.php?id=' + res;
          }
        });
        return false;
    });
});

As you remember, in the first step we added a new jQuery library: infinitescroll. I added initialization of infinitescroll library here (for our infinite scroll) and modified initialization of masonry. Because we have to sort the new images, plus we have to handle onclick event for all new images (colorbox).

您还记得,第一步,我们添加了一个新的jQuery库:infinitescroll。 我在这里添加了infinitescroll库的初始化(对于我们的无限滚动),并修改了砌体的初始化。 因为我们必须对新图像进行排序,所以我们还必须处理所有新图像(颜色框)的onclick事件。

现场演示

结论 (Conclusion)

We have just finished our sixth lesson where we are writing our own Pinterest-like script. I hope you enjoy this series. It would be kind of you to share our materials with your friends. Good luck and welcome back!

我们刚刚结束了第六课,我们正在编写自己的类似Pinterest的脚本。 希望您喜欢这个系列。 您希望与朋友分享我们的资料。 祝你好运,欢迎回来!

翻译自: https://www.script-tutorials.com/pinterest-like-script-step-6/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值