{"id":355,"date":"2015-08-12T12:07:32","date_gmt":"2015-08-12T12:07:32","guid":{"rendered":"http:\/\/savoy.nordicmade.com\/?page_id=355"},"modified":"2026-08-28T16:57:09","modified_gmt":"2026-08-28T16:57:09","slug":"order-tracking","status":"publish","type":"page","link":"https:\/\/fdvape.com\/order-tracking\/","title":{"rendered":"Order Tracking"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"355\" class=\"elementor elementor-355\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-772f86d1 e-flex e-con-boxed e-con e-parent\" data-id=\"772f86d1\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t<div class=\"elementor-element elementor-element-a397a64 e-flex e-con-boxed e-con e-child\" data-id=\"a397a64\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-56d8cf1 elementor-widget elementor-widget-heading\" data-id=\"56d8cf1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h1 class=\"elementor-heading-title elementor-size-default\">Order Tracking<\/h1>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-24ab20c elementor-widget elementor-widget-heading\" data-id=\"24ab20c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<p class=\"elementor-heading-title elementor-size-default\">Enter your order number in the designated box<\/p>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-40470a2 elementor-widget elementor-widget-heading\" data-id=\"40470a2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<p class=\"elementor-heading-title elementor-size-default\">Click the 'Track' button on the page<\/p>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-fc6736c elementor-widget__width-auto elementor-widget elementor-widget-html\" data-id=\"fc6736c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div id=\"main\">\r\n  <div class=\"track-main\">\r\n    <div class=\"track-form\">\r\n      <input id=\"inputNo\" class=\"track-input\" type=\"text\" placeholder=\"Please fill in Logistics tracking number\" \/>\r\n      <span id=\"checkButton\" class=\"track-button\">Track<\/span>\r\n    <\/div>\r\n  <\/div> \r\n  \r\n  <div id=\"trackingResults\" class=\"track-result\"><\/div>\r\n    \r\n  <div class=\"lang-switch\">\r\n      <span>Language: <\/span>\r\n      <a class=\"ignore\" href=\"javascript:translate.changeLanguage('english');\">English<\/a> |\r\n      <a class=\"ignore\" href=\"javascript:translate.changeLanguage('deutsch');\">Deutsch<\/a> |\r\n      <a class=\"ignore\" href=\"javascript:translate.changeLanguage('french');\">Fran\u00e7ais<\/a> |\r\n      <a class=\"ignore\" href=\"javascript:translate.changeLanguage('spanish');\">Espa\u00f1ol<\/a> |\r\n      <a class=\"ignore\" href=\"javascript:translate.changeLanguage('italian');\">Italiano<\/a> |\r\n      <a class=\"ignore\" href=\"javascript:translate.changeLanguage('swedish');\">Svenska<\/a> |\r\n      <a class=\"ignore\" href=\"javascript:translate.changeLanguage('dutch');\">Nederlands<\/a> |\r\n      <a class=\"ignore\" href=\"javascript:translate.changeLanguage('chinese_simplified');\">\u7b80\u4f53\u4e2d\u6587<\/a>\r\n  <\/div>\r\n<\/div>\r\n\r\n<script>\r\n\/**\r\n * Logistics Tracking Pro - Pure JS (Dual Translation Engines + Zero jQuery Dependency)\r\n *\/\r\n\r\nwindow.rawTrackingData = []; \r\n\r\n\/\/ \u8bed\u8a00\u4ee3\u7801\u89c4\u8303\u5316\u8f6c\u6362\r\nfunction normalizeLangCode(lang) {\r\n    if (!lang) return 'en';\r\n    if (lang === 'zh-Hans') return 'zh-CN';\r\n    if (lang === 'zh-Hant') return 'zh-TW';\r\n    return lang;\r\n}\r\n\r\n\/\/ \u52a8\u6001\u751f\u6210\u968f\u673a\u90ae\u7bb1\r\nfunction getRandomEmail() {\r\n    const rand = Math.random().toString(36).substring(2, 10);\r\n    return `user_${rand}@gmail.com`;\r\n}\r\n\r\n\/\/ \u83b7\u53d6\u521d\u59cb\u8bed\u8a00\r\nconst getInitialLang = () => {\r\n    const savedLang = localStorage.getItem('SelectedLanguage') || localStorage.getItem('Language');\r\n    if (savedLang) return savedLang;\r\n\r\n    const htmlLang = document.documentElement.lang.toLowerCase();\r\n    if (htmlLang.startsWith('zh')) return 'zh-Hans';\r\n    if (htmlLang.startsWith('en')) return 'en';\r\n    return htmlLang.split('-')[0] || 'en'; \r\n};\r\n\r\nwindow.currentLanguage = getInitialLang();\r\n\r\n\/\/ \u8bed\u8a00\u5207\u6362\u63a7\u5236\u5668\r\nwindow.translate = {\r\n    changeLanguage: function(langKey) {\r\n        const languageMap = { \r\n            'chinese_simplified': 'zh-Hans',\r\n            'english': 'en', \r\n            'deutsch': 'de', \r\n            'french': 'fr', \r\n            'spanish': 'es', \r\n            'japanese': 'ja', \r\n            'polish': 'pl', \r\n            'italian': 'it',\r\n            'swedish': 'sv',\r\n            'dutch': 'nl'\r\n        };\r\n        \r\n        window.currentLanguage = languageMap[langKey] || 'en';\r\n        localStorage.setItem('SelectedLanguage', window.currentLanguage);\r\n        localStorage.setItem('Language', window.currentLanguage);\r\n        \r\n        if (window.rawTrackingData.length > 0) {\r\n            renderAndTranslate(window.rawTrackingData);\r\n        }\r\n    }\r\n};\r\n\r\n\/\/ \u5f15\u64ce 1\uff1aGoogle GTX \u6d4f\u89c8\u5668\u76f4\u8fde\r\nasync function translateWithGoogleBrowser(text, targetLang) {\r\n    const gLang = normalizeLangCode(targetLang);\r\n    const url = `https:\/\/translate.googleapis.com\/translate_a\/single?client=gtx&dt=t&sl=auto&tl=${gLang}&q=${encodeURIComponent(text)}`;\r\n    const response = await fetch(url);\r\n    if (!response.ok) throw new Error(`Google GTX status: ${response.status}`);\r\n    const data = await response.json();\r\n    if (Array.isArray(data) && Array.isArray(data[0])) {\r\n        return data[0].map(item => item[0] || '').join('');\r\n    }\r\n    throw new Error('Invalid Google GTX response');\r\n}\r\n\r\n\/\/ ==============================\r\n\/\/ \u5f15\u64ce 2\uff1aMyMemory \u5907\u7528 (\u5df2\u6574\u5408\u4f18\u5316\u7248)\r\n\/\/ ==============================\r\nasync function translateWithMyMemoryBrowser(text, targetLang, sourceLang = 'zh-CN') {\r\n    const target = normalizeLangCode(targetLang);\r\n    const source = normalizeLangCode(sourceLang);\r\n    const email = getRandomEmail();\r\n\r\n    const url = `https:\/\/api.mymemory.translated.net\/get?q=${encodeURIComponent(text)}&langpair=${source}|${target}&de=${encodeURIComponent(email)}`;\r\n\r\n    const response = await fetch(url);\r\n    if (!response.ok) throw new Error(`MyMemory HTTP error: ${response.status}`);\r\n    \r\n    const data = await response.json();\r\n\r\n    if (data.responseData && data.responseStatus === 200) {\r\n        return data.responseData.translatedText;\r\n    }\r\n\r\n    throw new Error(data.responseDetails || \"MyMemory failed\");\r\n}\r\n\r\n\/\/ \u7edf\u4e00\u7ffb\u8bd1\u5165\u53e3\uff1a\u4f18\u5148 Google\uff0c\u5931\u8d25\u81ea\u52a8\u964d\u7ea7\u5230 MyMemory\r\nasync function translateSingle(text, targetLang) {\r\n    if (!text || targetLang === 'zh-Hans') return text;\r\n    try {\r\n        return await translateWithGoogleBrowser(text, targetLang);\r\n    } catch (googleErr) {\r\n        console.warn(\"Google translation failed, switching to MyMemory:\", googleErr);\r\n        try {\r\n            return await translateWithMyMemoryBrowser(text, targetLang, 'zh-CN');\r\n        } catch (myMemoryErr) {\r\n            console.warn(\"MyMemory translation failed:\", myMemoryErr);\r\n            return text; \/\/ \u53cc\u5f15\u64ce\u5747\u5931\u8d25\u65f6\u4fdd\u7559\u539f\u6587\r\n        }\r\n    }\r\n}\r\n\r\n\/\/ XSS \u9632\u62a4\u4e0e\u8d85\u94fe\u63a5\u8f6c\u6362\r\nfunction escapeAndFormatHtml(text) {\r\n    if (!text) return \"\";\r\n    const div = document.createElement('div');\r\n    div.textContent = text;\r\n    const safeText = div.innerHTML;\r\n    const regex = \/(https?:\\\/\\\/[^\\s]+)\/g;\r\n    return safeText.replace(regex, (match) => `<a style=\"color: #00c7ff;\" href=\"${match}\" target=\"_blank\" rel=\"noopener noreferrer\">${match}<\/a>`);\r\n}\r\n\r\n\/\/ \u6e32\u67d3\u4e0e\u7ffb\u8bd1\r\nasync function renderAndTranslate(list) {\r\n    const resultBox = document.querySelector('#trackingResults');\r\n    const isZh = window.currentLanguage === 'zh-Hans';\r\n    \r\n    let html = `<ul class=\"track-list\">`;\r\n    list.forEach((item, index) => {\r\n        html += `\r\n            <li id=\"track-item-${index}\">\r\n                <span class=\"time\">${item.time || ''}<\/span>\r\n                <span class=\"location\" id=\"location-${index}\">${isZh ? (item.location || '') : '...'}<\/span>\r\n                <span class=\"detail\" id=\"detail-${index}\">${isZh ? escapeAndFormatHtml(item.detail || '') : 'Translating...'}<\/span>\r\n            <\/li>`;\r\n    });\r\n    html += `<\/ul>`;\r\n    resultBox.innerHTML = html;\r\n\r\n    if (isZh) return;\r\n\r\n    \/\/ \u5355\u6761\u72ec\u7acb\u5e76\u884c\u7ffb\u8bd1\uff0c\u9632\u6b62\u6362\u884c\u5408\u5e76\u5bfc\u81f4\u6587\u672c\u9519\u4f4d\r\n    await Promise.all(list.map(async (item, index) => {\r\n        const [transLoc, transDet] = await Promise.all([\r\n            translateSingle(item.location || '', window.currentLanguage),\r\n            translateSingle(item.detail || '', window.currentLanguage)\r\n        ]);\r\n        \r\n        const locElem = document.querySelector(`#location-${index}`);\r\n        const detElem = document.querySelector(`#detail-${index}`);\r\n        \r\n        if (locElem) locElem.textContent = transLoc;\r\n        if (detElem) detElem.innerHTML = escapeAndFormatHtml(transDet);\r\n    }));\r\n}\r\n\r\nfunction setUrlParam(key, value) {\r\n    let obj = new URL(window.location.href);\r\n    obj.searchParams.set(key, value);\r\n    return obj.href;\r\n}\r\n\r\n\/\/ \u53d1\u8d77\u7269\u6d41\u67e5\u8be2\r\nasync function performTrackingQuery(trackingNumber) {\r\n    if (!trackingNumber) return;\r\n    const resultBox = document.querySelector('#trackingResults');\r\n    const checkBtn = document.querySelector('#checkButton');\r\n\r\n    resultBox.innerHTML = `<p>Checking. Please wait...<\/p>`;\r\n    if (checkBtn) checkBtn.style.pointerEvents = 'none';\r\n\r\n    try {\r\n        const response = await fetch('\/wp-json\/api\/v1\/tracking\/' + encodeURIComponent(trackingNumber));\r\n        if (!response.ok) throw new Error('API Request Failed');\r\n        \r\n        const json = await response.json();\r\n        const list = typeof json === 'string' ? JSON.parse(json) : json;\r\n        \r\n        window.rawTrackingData = Array.isArray(list) ? list : [];\r\n\r\n        if (!window.rawTrackingData.length) {\r\n            resultBox.innerHTML = `<p>No records found.<\/p>`;\r\n        } else {\r\n            renderAndTranslate(window.rawTrackingData);\r\n        }\r\n    } catch (error) {\r\n        console.error('Tracking Query Error:', error);\r\n        resultBox.innerHTML = `<p>\u67e5\u8be2\u51fa\u9519\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5\u3002<\/p>`;\r\n    } finally {\r\n        if (checkBtn) checkBtn.style.pointerEvents = 'auto';\r\n    }\r\n}\r\n\r\n\/\/ \u521d\u59cb\u5316\u7ed1\u5b9a\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n    const inputNo = document.querySelector('#inputNo');\r\n    const checkBtn = document.querySelector('#checkButton');\r\n\r\n    if (checkBtn) {\r\n        checkBtn.addEventListener('click', function() {\r\n            const number = inputNo.value.trim();\r\n            if (number) {\r\n                history.pushState({}, '', setUrlParam('no', number));\r\n                performTrackingQuery(number);\r\n            } else {\r\n                alert('Please enter the tracking number!');\r\n            }\r\n        });\r\n    }\r\n\r\n    if (inputNo) {\r\n        inputNo.addEventListener('keypress', function(e) {\r\n            if (e.key === 'Enter') checkBtn.click();\r\n        });\r\n    }\r\n\r\n    const trackingNumber = new URLSearchParams(window.location.search).get('no');\r\n    if (trackingNumber) {\r\n        if (inputNo) inputNo.value = trackingNumber;\r\n        performTrackingQuery(trackingNumber);\r\n    }\r\n});\r\n<\/script>\r\n\r\n<style>\r\n#main .lang-switch a {\r\n  color: #2196F3 !important;\r\n}\r\n\r\n#main .lang-switch {\r\n  margin: 10px 0;\r\n}\r\n\r\n#main .track-form {\r\n  display: flex;\r\n}\r\n\r\n#main .track-input {\r\n  width: 100%;\r\n  height: auto;\r\n  margin: 0;\r\n  border: 1px solid #f4f4f4;\r\n  padding: 0 10px;\r\n}\r\n\r\n#main .track-button {\r\n  background: #17ef97;\r\n  padding: 4px 50px;\r\n  color: #000;\r\n  font-weight: 500;\r\n  line-height: 3;\r\n  cursor: pointer;\r\n}\r\n\r\n#main .track-list {\r\n  padding: 0;\r\n  margin: 0;\r\n  list-style-type: none;\r\n}\r\n\r\n#main .track-list li {\r\n  padding: 10px 15px 10px 45px;\r\n  border-bottom: 1px solid #EBEAEB !important;\r\n  font-size: 16px;\r\n  position: relative;\r\n}\r\n\r\n#main .track-list li::before {\r\n  content: '';\r\n  display: inline-block;\r\n  width: 10px;\r\n  height: 10px;\r\n  border-radius: 50%;\r\n  background-color: #a4a4a4;\r\n  margin-right: 10px;\r\n  position: absolute;\r\n  left: 5px;\r\n  top: 50%;\r\n  transform: translateY(-50%);\r\n}\r\n\r\n.track-list li:first-child::before {\r\n  background-color: #17ef97;\r\n  animation: glowGreen 1.5s ease-in-out infinite;\r\n}\r\n\r\n#main .track-list .time {\r\n  display: block;\r\n  font-weight: bold;\r\n}\r\n\r\n#main .track-list .location {\r\n  display: block;\r\n}\r\n\r\n#main .track-list .detail {\r\n  display: block;\r\n  word-wrap: break-word;\r\n}\r\n\r\n#main .track-list .detail a {\r\n  color: #00c7ff !important;\r\n  text-decoration: none;\r\n}\r\n\r\n@media (max-width: 768px) {\r\n  #main .track-list li {\r\n    flex-direction: column;\r\n    padding: 10px 0 10px 30px;\r\n  }\r\n\r\n  #main .track-list .time,\r\n  #main .track-list .location {\r\n    width: 100%;\r\n    display: block;\r\n    font-size: 14px;\r\n  }\r\n\r\n  #main .track-list .detail {\r\n    width: 100%;\r\n    margin-top: 10px;\r\n    font-size: 14px;\r\n  }\r\n}\r\n\r\n@keyframes glowGreen {\r\n  0% { box-shadow: 0 0 5px #17ef97, 0 0 15px #17ef97, 0 0 20px #17ef97; }\r\n  50% { box-shadow: 0 0 10px #17ef97, 0 0 25px #17ef97, 0 0 30px #0f0; }\r\n  100% { box-shadow: 0 0 5px #17ef97, 0 0 15px #17ef97, 0 0 20px #17ef97; }\r\n}\r\n<\/style>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Order Tracking Enter your order number in the designated box Click the &#8216;Track&#8217; button on the page Track Language: English | Deutsch | Fran\u00e7ais | Espa\u00f1ol | Italiano | Svenska | Nederlands | \u7b80\u4f53\u4e2d\u6587<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_seopress_titles_title":"","_seopress_titles_desc":"","_seopress_robots_index":"","_seopress_robots_follow":"","_seopress_robots_imageindex":"","_seopress_robots_snippet":"","_seopress_robots_primary_cat":"","_seopress_robots_breadcrumbs":"","_seopress_robots_freeze_modified_date":"","_seopress_robots_custom_modified_date":"","_seopress_robots_canonical":"","_seopress_social_fb_title":"","_seopress_social_fb_desc":"","_seopress_social_fb_img":"","_seopress_social_fb_img_attachment_id":0,"_seopress_social_fb_img_width":0,"_seopress_social_fb_img_height":0,"_seopress_social_twitter_title":"","_seopress_social_twitter_desc":"","_seopress_social_twitter_img":"","_seopress_social_twitter_img_attachment_id":0,"_seopress_social_twitter_img_width":0,"_seopress_social_twitter_img_height":0,"_seopress_redirections_value":"","_seopress_redirections_enabled":"","_seopress_redirections_enabled_regex":"","_seopress_redirections_logged_status":"both","_seopress_redirections_param":"","_seopress_redirections_type":301,"_seopress_analysis_target_kw":"Order Tracking,vape,vapeshop,Disposable Vape,fdvape","_seopress_news_disabled":"","_seopress_video_disabled":"","_seopress_video":[],"_seopress_pro_schemas_manual":[],"_seopress_pro_rich_snippets_disable_all":"","_seopress_pro_rich_snippets_disable":[],"_seopress_pro_schemas":[],"rs_blank_template":"","rs_page_bg_color":"","slide_template_v7":"","footnotes":""},"class_list":["post-355","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/fdvape.com\/wp-json\/wp\/v2\/pages\/355","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fdvape.com\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/fdvape.com\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/fdvape.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fdvape.com\/wp-json\/wp\/v2\/comments?post=355"}],"version-history":[{"count":0,"href":"https:\/\/fdvape.com\/wp-json\/wp\/v2\/pages\/355\/revisions"}],"wp:attachment":[{"href":"https:\/\/fdvape.com\/wp-json\/wp\/v2\/media?parent=355"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}