Αυτός ο οδηγός σας επιτρέπει να εντάξετε ένα ολοκαίνουριο σύστημα στο οποίο, κατά την διάρκεια της δημιουργίας ενός νέου θέματος, θα εμφανίζονται αυτόματα, τα παρόμοια θέματα με βάση τις λέξεις κλειδιά του τίτλου σας.
Προεπισκόπηση Ο κώδικας αυτός δουλεύει μόνο σε phpbb3 προς το παρόν και οποιαδήποτε αλλαγή του κώδικα προκειμένου να προσαρμοστεί σε άλλη έκδοση δεν θα παρέχεται υποστήριξη, παρά μόνο εάν ενταχθεί στο παρών θέμα.
Εγκατάσταση
JavascriptΦτιάχνετε ένα νέο Javascript ως εξής: Πίνακας Διαχείρισης ► Λειτουργικές Μονάδες ► HTML & JAVASCRIPT ► Διαχείριση κωδικών Javascript φτιάξτε ένα νέο Javascript συμπληρώνοντάς το ως εξής: Όνομα: Ότι θέλετε Τοποθεσία: Σε όλες τις σελίδες Κώδικας: Αντιγραφή/Επικόλληση τον παρακάτω κώδικα:
- Κώδικας:
/* The following code is DOM-dependent. It may not work if you modify the posting structure in the forum templates */ var FLRX = FLRX || {}; FLRX.similarTopics = (function () { 'use strict'; let settings = { // default settings forums : [], searchIn : false, maxTopics : 5, wordMinLength: 4, autocomplete: false, // disable browser autocomplete from subject input /* Advanced settings */ excludedCharacters : new RegExp(/[.,\/#!$%\^&\*¿?!¡;:{}\\=\-_`~"«“‘’”»()\[\]]/, 'g'), // The ignored characters from the topic title. dom : { // default settings (should work if left like this with unmodified templates) /* Search page */ topicscontainer : '.forabg', topic : 'dd.dterm', infocontainer : '.span-tab', titlelink : '.topictitle', userlink : 'a[href^="/u"]', forumlink : 'a[href^="/f"]', topicicon : 'dl.icon', /* structure */ visible : 'visible', /* posting page */ titleinput : '#postingbox input[name="subject"]', inputcontainer : 'dl', /* created elements */ maincontainer : $('<div />', { id : 'similarTopics' }), similartopiccont : $('<div />', { class : 'topic-container' }), loadingelm : $('<div />', { class : 'spinner' }) .append($('<div/>', { class:'double-bounce1' })) .append($('<div/>', { class:'double-bounce2' })), topicelmcont : $('<div />', { class: 'topic' }), topicelmtitle : $('<div />', { class: 'topic-title' }), topicdatacont : $('<div />', { class: 'topic-data' }), topicflags : $('<div />', { class: 'topic-flags' }), topiciconcont : $('<div />', { class: 'topic-icon' }), topicstatus : $('<div />', { class: 'topic-status' }), topicelminfo : $('<div />', { class: 'topic-info' }), topicauthor : $('<span />', { class: 'topic-author', text: 'από ' }), topicforum : $('<span />', { class: 'topic-forum', text: ' σε ' }), similarstitle : $('<h4 />', { class: 'similarTopics-title', text: 'πριν ανοιξετε νεο θεμα ριξτε μια ματια σε αυτα τα θεματα' }), }, }, structure = {}, request, debounce = function(cb, delay) { let timeout; return function(...a) { clearTimeout(timeout); timeout = setTimeout( _ => { timeout = null; cb.call(this, ...a); }, delay); }; }, /* transforms a UTF8-encoded URI into Windows-1252 */ sanitizeURI = function(uri) { /* For some reason Forumotion uses Windows-1252 encoding in search URIs. This workaround will only fix issues with Spanish characters */ return uri.replace(/%C3%91/g, '%D1') // Ñ .replace(/%C3%B1/g, '%F1') // ñ .replace(/%C3%81/g, '%C1') // Á .replace(/%C3%89/g, '%C9') // É .replace(/%C3%8D/g, '%CD') // Í .replace(/%C3%93/g, '%D3') // Ó .replace(/%C3%9A/g, '%DA') // Ú .replace(/%C3%9C/g, '%DC') // Ü .replace(/%C3%A1/g, '%E1') // á .replace(/%C3%A9/g, '%E9') // é .replace(/%C3%AD/g, '%ED') // í .replace(/%C3%B3/g, '%F3') // ó .replace(/%C3%BA/g, '%FA') // ú .replace(/%C3%BC/g, '%FC'); // ü }, /* returns an object array (representation of topics) from a search URL synchronously */ searchTopics = function(url, cb) { $.ajax({ url : url, }).done(function(data) { let relatedTopics = [], $forabg = $(settings.dom.topicscontainer, data); if($forabg.length) { $forabg.find(settings.dom.topic).slice(0, settings.maxTopics).each(function() { let $this = $(this), $topictitle = $this.find(settings.dom.titlelink), $spantab = $this.find(settings.dom.infocontainer), $forumlink = $spantab.find(settings.dom.forumlink), $userlink = $spantab.find(settings.dom.userlink), $topicicon = $this.closest(settings.dom.topicicon); relatedTopics.push({ title : $topictitle.text().trim(), url : $topictitle.attr('href'), icon : $this.css('background-image').slice(4, -1), status : $topicicon.css('background-image').length ? $topicicon.css('background-image').slice(4, -1) : false, forum : { name : $forumlink.text(), url : $forumlink.attr('href'), }, user : { name : $userlink.text(), url : $userlink.attr('href'), }, }); }); } cb.call(this, relatedTopics); }).fail(_ => {let up; throw up || false}); }, /* returns an array with the words of a string that fulfil conditions of settings.excludedCharacters */ getWords = function(str) { return str.trim().replace(settings.excludedCharacters, '').split(' ').filter(elm => elm.length >= settings.wordMinLength); }, /* updates the similar topics DOM structure with the ones in the input array */ updateDOM = function(arr) { structure.topiccontainer.empty(); if(arr.length) { let docfrag = document.createDocumentFragment(); $.each(arr, function(index, topic) { let $topicTitle = settings.dom.topicelmtitle.clone(), $topicContainer = settings.dom.topicelmcont.clone(), $topicInfo = settings.dom.topicelminfo.clone(), $topicauthor = settings.dom.topicauthor.clone(), $topicstatus = settings.dom.topicstatus.clone(), $topicforum = settings.dom.topicforum.clone(), $topicflags = settings.dom.topicflags.clone(), $topicdata = settings.dom.topicdatacont.clone(), $topicicon = settings.dom.topiciconcont.clone(), /* link creation */ $topicLink = $('<a />', { href: topic.url, text: topic.title }), $forumlink = $('<a />', { href: topic.forum.url, text: topic.forum.name }), $authorlink = $('<a />', { href: topic.user.url, text: topic.user.name }); $topicicon.css('background-image', `url('${ topic.icon }')`); topic.status && $topicstatus.css('background-image', `url('${ topic.status }')`); $topicauthor.append($authorlink); $topicforum.append($forumlink); $topicTitle.append($topicLink); $topicInfo.append($topicauthor, $topicforum); $topicdata.append($topicTitle, $topicInfo); $topicflags.append($topicstatus, $topicicon); $topicContainer.append($topicflags, $topicdata); docfrag.append($topicContainer[0]); }); structure.topiccontainer[0].appendChild(docfrag); } else structure.maincontainer.removeClass(settings.dom.visible); }, setLoadingStatus = function() { structure.loadingcontainer.addClass(settings.dom.visible); structure.recentstitle.removeClass(settings.dom.visible); structure.topiccontainer.removeClass(settings.dom.visible); }, topicsRetrieved = function (){ structure.loadingcontainer.removeClass(settings.dom.visible); structure.recentstitle.addClass(settings.dom.visible); structure.topiccontainer.addClass(settings.dom.visible); }, searchAlgorithm = function(words, cb) { let params = { search_where : settings.searchIn || `f${/\?f=(\d+)/.exec(location.search)[1]}`, show_results : 'topics', sort_by : 0, sort_dir : 'DESC', search_terms : 'all', search_keywords : words.join(' '), }; searchTopics(`/search?${sanitizeURI($.param(params))}`, function(arr) { let relatedTopics = arr; if(relatedTopics.length < settings.maxTopics) { params.search_terms = 'any'; searchTopics(`/search?${sanitizeURI($.param(params))}`, function(arr) { let searchAnyWord = arr, neededElms = settings.maxTopics - relatedTopics.length; searchAnyWord = searchAnyWord.filter(elm => relatedTopics.find(e => e.url == elm.url) === undefined); // Ignore duplicates relatedTopics = [...relatedTopics, ...searchAnyWord.slice(0, neededElms)]; cb.call(this, relatedTopics); }); } cb.call(this, relatedTopics); }); }, /* main function */ searchSimilarTopics = function($title) { let words = getWords($title.val()); if(words.length == 0) return; // for the first time, if it was hidden structure.maincontainer.addClass(settings.dom.visible); setLoadingStatus(); searchAlgorithm(words, function(arr) { updateDOM(arr); topicsRetrieved(); }); }, generateStructure = function($title) { let $similarTopics = settings.dom.maincontainer.clone(), $spinner = settings.dom.loadingelm.clone(), $topicsContainer = settings.dom.similartopiccont.clone(), $recentsTitle = settings.dom.similarstitle.clone(); structure = { maincontainer : $similarTopics, loadingcontainer : $spinner, topiccontainer : $topicsContainer, recentstitle : $recentsTitle, }; $similarTopics.append($spinner, $recentsTitle, $topicsContainer); $title.closest(settings.dom.inputcontainer).after($similarTopics); }, init = function(options) { $.extend(true, settings, options); let timeout, $title = $(settings.dom.titleinput); if(!settings.autocomplete) $title.attr('autocomplete', 'off'); // append the basic dom structure (should be hidden by default with CSS) generateStructure($title); $title.on('keypress', debounce(function(e) { if(e.which !== 0) searchSimilarTopics($title); }, 500)); }; /* API :-) */ return { init : init, }; })(); !function() { const settings = { forums : [1,2,3,4,5,6,7], // Forum IDs (separated by comma) where the "Similar Topics" feature will be enabled. Set to true to enable the feature everywhere (not recommended). searchIn : '-1', // Where the searches will take place. Use -1 to search everywhere. If not set, it will search the forum where the topic is being created maxTopics : 5, // Maximum amount of topics shown }; location.pathname == '/post' && location.search.indexOf('&mode=newtopic') > -1 && (settings.forums === true || settings.forums.some(id => location.search.indexOf(`?f=${id}`) > -1)) && $(function() { FLRX.similarTopics.init(settings); }); }();
CSSΑκολούθως χρειάζεται να προσθέσουμε το εξής CSS: Πίνακας Διαχείρισης ► Εμφάνιση ► Εικόνες και χρώματα ► Χρώματα ► CSS Stylesheet
- Κώδικας:
#similarTopics { width: 500px; background: #E1EBF2; padding: 5px 10px; border-radius: 5px; margin: 5px 0 0 10em; } #similarTopics, #similarTopics .spinner, #similarTopics .topic-container, #similarTopics .similarTopics-title { display: none } #similarTopics.visible, #similarTopics .spinner.visible, #similarTopics .similarTopics-title.visible, #similarTopics .topic-container.visible { display: block } #similarTopics .topic { display: flex; border-bottom: 1px solid white; padding: 5px 0; margin: 5px 0; } #similarTopics .topic:last-child { border-bottom: none } #similarTopics .topic-data { flex: 1 } #similarTopics .topic-flags { align-items: center; margin-right: 10px; position: relative; } #similarTopics .topic-icon { position: absolute; top: 0; left: 0; bottom: 0; right: 0; background: transparent 50% 50% no-repeat; } #similarTopics .similarTopics-title { border-bottom: 1px solid #0076b1; color: #0076b1; font-size: .9em; margin: .5em 0; text-transform: uppercase; } #similarTopics .topic-status { width: 27px; height: 27px; background: transparent 0 0 no-repeat; }
Επεξήγηση και βοηθήματαΠαρακάτω θα βρείτε όλες τις πληροφορίες που χρειάζεστε προκειμένου να κάνετε τις αλλαγές που επιθυμείτε με τον κώδικα. Προσέξτε ότι όλες οι επιλογές έχουν την ίδια μορφή:
- Κώδικας:
name: value, Αυτό σημαίνει ότι αν θέλετε να προσθέσετε πολλαπλές επιλογές πρέπει να έχουν την μορφή:
- Κώδικας:
const settings = { nameOption1: value, nameOption2: value, nameOption3: value, }; ΠΡΟΣΟΧΗ: Το να προσθέσετε κάποια επιλογή, βάζοντας ως αρχική τιμή την προκαθορισμένη, είναι το ίδιο πράγμα με το να μην την προσθέσετε καν.
ΚατηγορίεςΕπιλέγετε τις ταυτότητες των κατηγοριών που επιθυμείτε να εμφανίζεται αυτό το σύστημα. Κάθε κατηγορία θα αναπαριστάται από την μοναδική ταυτότητά της, ή τον σύνδεσμο που έχει (τον αριθμό της κατηγορίας). Κάθε αριθμός του φόρουμ, χωρίζεται με κόμμα. Για παράδειγμα:
- Κώδικας:
forums: [1, 2, 3, 4, 5], Μια ειδική περίπτωση θα ήταν να απενεργοποιηθεί η μερική επιλογή και το σύστημα αυτό να εμφανίζεται σε όλες τις κατηγορίες. Για να γίνει αυτό θα πρέπει να έχετε σκέτο [] κάπως έτσι:
- Κώδικας:
forums: [], που είναι και η προεπιλεγμένη μορφή.
SearchIn (Αναζήτηση)Το φόρουμ στο οποίο θα γίνει η αναζήτηση. Για να εξακριβώσετε σε ποιό φόρουμ ή ποια κατηγορία θα γίνει η αναζήτηση, θα χρησιμοποιηθεί και πάλι ο αριθμός της κατηγορίας ή του φόρουμ, χρησιμοποιώντας c και τον αριθμό του φόρουμ ή f και τον αριθμό της κατηγορίας αναλόγως που επιθυμείτε (εντώς εισαγωγικών). Για παράδειγμα αν διαλέγαμε το φόρουμ με αριθμό 3 θα είχαμε:
- Κώδικας:
searchIn: 'c3', Ειδικότερα:
- false: Αναζητά στην ίδια κατηγορία που γίνεται το θέμα.
- -1: Αναζητά σε όλο το φόρουμ.
Προεπιλεγμένη μορφή:
- Κώδικας:
searchIn: false,
MaxTopics (Μέγιστος αριθμός θεμάτων)Ο επιθυμητός αριθμός θεμάτων που θα εμφανιστούν. Ελάχιστη τιμή: 3. Παράδειγμα:
- Κώδικας:
maxTopics : 10, Προεπιλεγμένη μορφή:
- Κώδικας:
maxTopics : 5,
AutoComplete (Αυτόματη συμπλήρωση)Προεπιλεγμένη μορφή:
Ενεργοποιήστε ή απενεργοποιήστε την αυτόματη συμπλήρωση του τίτλου του θέματος.
Χρησιμοποιείτε την τιμή true για να ενεργοποιηθεί ή false για να απενεργοποιηθεί.
Παράδειγμα:
- Κώδικας:
autocomplete : true, Προεπιλεγμένη μορφή:
- Κώδικας:
autocomplete : false,
wordMinLength (ελάχιστος αριθμός χαρακτήρων)Ο ελάχιστος αριθμός χαρακτήρων προκειμένου να ξεκινήσει η αναζήτηση θεμάτων. Παρακαλούμε έχετε στο μυαλό σας ότι, λόγω των περιορισμών της Forumgreek η τιμή του τίτλου δεν μπορεί να είναι μικρότερη από 3.
Ο αριθμός μπορείτε να είναι ένας θετικό ακέραιος αριθμός μεταξύ του 4 και του ορίου που τίθεται στα φόρουμ της Forumgreek.
Παράδειγμα:
- Κώδικας:
wordMinLength : 5, Προεπιλεγμένη μορφή:
- Κώδικας:
wordMinLength : 4,
Προχωρημένες ΠληροφορίεςΥπάρχουν περισσότερες πληροφορίες για όσους γνωρίζουν κάποια πράγματα παραπάνω. Σημειώνεται ότι απαιτείται μια καλή γνώση των γλωσσών HTML και Javascript για τα παρακάτω:
- Προχωρημένες Πληροφορίες:
ExludedCharacters (Αφαίρεση χαρακτήρων)Καθημερινές χρήσεις σημείων στίξης ή άλλων ειδικών συμβόλων που επιθυμείτε να αφαιρεθουν. Προεπιλεγμένη μορφή:- Κώδικας:
excludedCharacters : new RegExp(/[.,\/#!$%\^&\*¿?!¡;:{}\\=\-_`~"«“‘’”»()\[\]]/, 'g'),
DOMΤο προσαρμοσμένο αντικείμενο που επιτρέπει την τροποποίηση του τρόπου ερμηνείας του DOM ενός φόρουμ. Είναι χρήσιμο στην περίπτωση που θέλετε να τροποποιήσετε τη δομή της HTML του plugin ή αν έχετε τροποποιήσει τμήματα των προτύπων στα οποία εξαρτάται το plugin. Μπορείτε να δείτε όλες τις επιλογές στην προεπιλεγμένη μορφή, η οποία θα αντιστοιχούσε στο πώς ερμηνεύεται μια δομή ενός φόρουμ phpBB3. Η προσαρμογή σε οποιαδήποτε άλλη έκδοση πρέπει να είναι απλή. Για να είναι πιο εύκολη η προσαρμογή σε οποιοδήποτε είδος τροποποιημένων προτύπων, οι σχέσεις μεταξύ των στοιχείων είναι απολύτως γονική (δηλαδή, δεν υπάρχει καμία πιθανότητα κάποιο από τα αναγνωριστικά DOM αυτού του αντικειμένου είναι τα ίδια) αλλά και πώς σχετίζονται παρεντερικά, ο τύπος είναι βαθιά (δηλαδή, δεν είναι απαραίτητο να είναι "παιδιά" ή "γονείς" μεταξύ τους, καθώς για την άμεση εφαρμογή του plugin, χρησιμοποιείται η μεθόδος find και closest για να επιλεγούν τα στοιχεία). Δεν είναι απαραίτητο να θέσετε όλες τις ιδιότητες του αντικειμένου που εμφανίζονται στην προεπιλεγμένη μορφή, μόνο εκείνες που είναι διαφορετικές από εκείνες του αντικειμένου της προεπιλεγμένης μορφής. Προεπιλεγμένη μορφή:- Κώδικας:
dom : { /* Search page */ topicscontainer : '.forabg', topic : 'dd.dterm', infocontainer : '.span-tab', titlelink : '.topictitle', userlink : 'a[href^="/u"]', forumlink : 'a[href^="/f"]', topicicon : 'dl.icon', /* structure */ visible : 'visible', /* posting page */ titleinput : '#postingbox input[name="subject"]', inputcontainer : 'dl', /* created elements */ maincontainer : $('<div />', { id : 'similarTopics' }), similartopiccont : $('<div />', { class : 'topic-container' }), loadingelm : $('<div />', { class : 'spinner' }) .append($('<div/>', { class:'double-bounce1' })) .append($('<div/>', { class:'double-bounce2' })), topicelmcont : $('<div />', { class: 'topic' }), topicelmtitle : $('<div />', { class: 'topic-title' }), topicdatacont : $('<div />', { class: 'topic-data' }), topicflags : $('<div />', { class: 'topic-flags' }), topiciconcont : $('<div />', { class: 'topic-icon' }), topicstatus : $('<div />', { class: 'topic-status' }), topicelminfo : $('<div />', { class: 'topic-info' }), topicauthor : $('<span />', { class: 'topic-author', text: 'por ' }), topicforum : $('<span />', { class: 'topic-forum', text: ' en ' }), similarstitle : $('<h4 />', { class: 'similarTopics-title', text: 'Quizás te interese...' }), },
|