ヒューゴのためのリアルターテーマの開発:ステップ1


導入


私は私の街の不動産の多くのように私の街の不動産のためのテーマを開発することを決めた私の都市ではまだWordPressを使用していると私はそれらの代替案を作成したい.

計画


こちらがゲームプランです.
  • で働くSSGを見つけます
  • はHTML、SASSとJS
  • で最初にページを構築します
  • テンプレートをビルドする
  • は、テーマとSSG
  • で動くCMSを見つけます
    この記事のために、私はSSGとページをカバーするつもりです

    SSG


    静的サイトジェネレータのために、私はhugoと行くことに決めました.これは、テンプレートエンジンを使用するように簡単です素晴らしいです!ドキュメントを読んだ後に、私はそれが私が必要とするもので働くと思います.

    ページの作成


    それで、私が必要とする主なページは以下の通りです.
  • ホーム
  • リスティング
  • のリスト
  • のスタッフページ
  • は、
  • に連絡します

    のホームページ


    リスト


    出品ページには、フィルタリング可能なギャラリーを設定する必要があります.

    ギャラリー


    私はそれが素敵に見えると思うギャラリーのティーズスタイルに行くことにした.次にフィルターを追加する

    フィルタ


    // File#: _3_advanced-filter
    // Usage: codyhouse.co/license
    (function() {
      // the AdvFilter object is used to handle: 
      // - number of results
      // - form reset
      // - filtering sections label (to show a preview of the option selected by the users)
      var AdvFilter = function(element) {
        this.element = element; 
        this.form = this.element.getElementsByClassName('js-adv-filter__form');
        this.resultsList = this.element.getElementsByClassName('js-adv-filter__gallery')[0];
        this.resultsCount = this.element.getElementsByClassName('js-adv-filter__results-count');
        initAdvFilter(this);
      };
    
      function initAdvFilter(filter) {
        if(filter.form.length > 0) {
          // reset form
          filter.form[0].addEventListener('reset', function(event){
            setTimeout(function(){
              resetFilters(filter);
              resetGallery(filter);
            });
          });
          // update section labels on form change
          filter.form[0].addEventListener('change', function(event){
            var section = event.target.closest('.js-adv-filter__item');
            if(section) resetSelection(filter, section);
            else if( Util.is(event.target, '.js-adv-filter__form') ) {
              // reset the entire form lables
              var sections = filter.form[0].getElementsByClassName('js-adv-filter__item');
              for(var i = 0; i < sections.length; i++) resetSelection(filter, sections[i]);
            }
          });
        }
    
        // reset results count
        if(filter.resultsCount.length > 0) {
          filter.resultsList.addEventListener('filter-selection-updated', function(event){
            updateResultsCount(filter);
          });
        }
      };
    
      function resetFilters(filter) {
        // check if there are custom form elemets - reset appearance
        // custom select
        var customSelect = filter.element.getElementsByClassName('js-select');
        if(customSelect.length > 0) {
          for(var i = 0; i < customSelect.length; i++) customSelect[i].dispatchEvent(new CustomEvent('select-updated'));
        }
        // custom slider
        var customSlider = filter.element.getElementsByClassName('js-slider');
        if(customSlider.length > 0) {
          for(var i = 0; i < customSlider.length; i++) customSlider[i].dispatchEvent(new CustomEvent('slider-updated'));
        }
      };
    
      function resetSelection(filter, section) {
        // change label value based on input types
        var labelSelection = section.getElementsByClassName('js-adv-filter__selection');
        if(labelSelection.length == 0) return;
        // select
        var select = section.getElementsByTagName('select');
        if(select.length > 0) {
          labelSelection[0].textContent = getSelectLabel(section, select[0]);
          return;
        }
        // input number
        var number = section.querySelectorAll('input[type="number"]');
        if(number.length > 0) {
          labelSelection[0].textContent = getNumberLabel(section, number);
          return;
        }
        // input range
        var slider = section.querySelectorAll('input[type="range"]');
        if(slider.length > 0) {
          labelSelection[0].textContent = getSliderLabel(section, slider);
          return;
        }
        // radio/checkboxes
        var radio = section.querySelectorAll('input[type="radio"]'),
          checkbox = section.querySelectorAll('input[type="checkbox"]');
        if(radio.length > 0) {
          labelSelection[0].textContent = getInputListLabel(section, radio);
          return;
        } else if(checkbox.length > 0) {
          labelSelection[0].textContent = getInputListLabel(section, checkbox);
          return;
        }
      };
    
      function getSelectLabel(section, select) {
        if(select.multiple) {
          var label = '',
            counter = 0;
          for (var i = 0; i < select.options.length; i++) {
            if(select.options[i].selected) {
              label = label + '' + select.options[i].text;
              counter = counter + 1;
            } 
            if(counter > 1) label = section.getAttribute('data-multi-select-text').replace('{n}', counter);
          }
          return label;
        } else {
          return select.options[select.selectedIndex].text;
        }
      };
    
      function getNumberLabel(section, number) {
        var counter = 0;
        for(var i = 0; i < number.length; i++) {
          if(number[i].value != number[i].min) counter = counter + 1;
        }
        if(number.length > 1) { // multiple input number in this section
          if(counter > 0) {
            return section.getAttribute('data-multi-select-text').replace('{n}', counter);
          } else {
            return section.getAttribute('data-default-text');
          }
    
        } else {
          if(number[0].value == number[0].min) return section.getAttribute('data-default-text');
          else return section.getAttribute('data-number-format').replace('{n}', number[0].value);
        }
      };
    
      function getSliderLabel(section, slider) {
        var label = '',
          labelFormat = section.getAttribute('data-number-format');
        for(var i = 0; i < slider.length; i++) {
          if(i != 0 ) label = label+' - ';
          label = label + labelFormat.replace('{n}', slider[i].value);
        }
        return label;
      };
    
      function getInputListLabel(section, inputs) {
        var counter = 0;
          label = '';
        for(var i = 0; i < inputs.length; i++) {
          if(inputs[i].checked) {
            var labelElement = inputs[i].parentNode.getElementsByTagName('label');
            if(labelElement.length > 0) label = labelElement[0].textContent;
            counter = counter + 1;
          }
        }
        if(counter > 1) return section.getAttribute('data-multi-select-text').replace('{n}', counter);
        else if(counter == 0 ) return section.getAttribute('data-default-text');
        else return label;
      };
    
      function resetGallery(filter) {
        // emit change event + reset filtering 
        filter.form[0].dispatchEvent(new CustomEvent('change'));
        filter.resultsList.dispatchEvent(new CustomEvent('update-filter-results'));
      };
    
      function updateResultsCount(filter) {
        var resultItems = filter.resultsList.children,
          counter = 0;
        for(var i = 0; i < resultItems.length; i++) {
          if(isVisible(resultItems[i])) counter = counter + 1;
        }
        filter.resultsCount[0].textContent = counter;
      };
    
      function isVisible(element) {
            return (element.offsetWidth || element.offsetHeight || element.getClientRects().length);
        };
    
      //initialize the AdvFilter objects
        var advFilter = document.getElementsByClassName('js-adv-filter');
        if( advFilter.length > 0 ) {
            for( var i = 0; i < advFilter.length; i++) {
                (function(i){new AdvFilter(advFilter[i]);})(i);
            }
      }
    
      // Remove the code below if you want to use a custom filtering function (e.g., you need to fetch your results from a database)
    
      // The code below is used for filtering of page content (animation of DOM elements, no fetching results from database).  
      // It uses the Filter component (https://codyhouse.co/ds/components/app/filter) - you can modify the custom filtering functions based on your needs
      // Check the info page of the component for info on how to use it: https://codyhouse.co/ds/components/info/filter
      var gallery = document.getElementById('adv-filter-gallery');
      if(gallery) {
        new Filter({
          element: gallery, // this is your gallery element
          priceRange: function(items){ // this is the price custom function
            var filteredArray = [],
              minVal = document.getElementById('slider-min-value').value,
              maxVal = document.getElementById('slider-max-value').value;
            for(var i = 0; i < items.length; i++) {
              var price = parseInt(items[i].getAttribute('data-price'));
              filteredArray[i] = (price >= minVal) && (price <= maxVal);
            } 
            return filteredArray;
          },
          indexValue: function(items){ // this is the index custom function
            var filteredArray = [],
              value = document.getElementById('index-value').value;
            for(var i = 0; i < items.length; i++) {
              var index = parseInt(items[i].getAttribute('data-sort-index'));
              filteredArray[i] = index >= value;
            } 
            return filteredArray;
          }
        });
      }
    }());
    

    リスト


    イメージ



    タブ


    私はリストの主な内容のすべてをホストするためにいくつかのタブを設定します.私は、これがすべてを分離するのを助けて、それがユーザーがナビゲートするのをより簡単にすると思います.

    インフォメーション


    リストに入る多くの情報があります.それで、私はFAQセクションのためにテンプレートを使用して、それの中ですべての情報を切り離しました.