ស្លាកជំនួស (Alt tags) គឺជាទិដ្ឋភាពដែលគេស្គាល់ច្បាស់បំផុតនៃការកសាងគេហទំព័រដែលអាចចូលប្រើបាន ប៉ុន្តែជាអកុសលពួកវាជារឿយៗត្រូវបានគេមិនយកចិត្តទុកដាក់ ឬអនុវត្តមិនបានល្អ។ ស្លាកជំនួស (Alt tags) គឺជាការពិពណ៌នាអត្ថបទខ្លីៗដែលត្រូវបានបន្ថែមទៅរូបភាព។ អ្នកអានអេក្រង់អានខ្លឹមសារនៃគេហទំព័រទៅកាន់អ្នកប្រើប្រាស់ ហើយការពណ៌នារូបភាពគឺជាអ្វីដែលពួកគេអានដើម្បីទំនាក់ទំនងអ្វីដែលមាននៅក្នុងរូបភាពនៅលើទំព័រទៅកាន់អ្នកប្រើប្រាស់ដែលមានពិការភ្នែក ដោយសារពួកគេមើលមិនឃើញ។
ជាអកុសល វាជារឿងធម្មតាទេដែលរូបភាពបាត់ស្លាក alt ទាំងអស់។ ខ្ញុំក៏ធ្លាប់ឃើញស្លាក alt ប្រើខុសក្នុងវិធីដែលធ្វើឱ្យអ្វីៗកាន់តែពិបាកសម្រាប់អ្នកប្រើប្រាស់ដែលពិការភ្នែក ដូចជាស្លាកដែលគ្រាន់តែនិយាយថា "រូបភាព" ឬ "រូបភាព" ដែលជាស្លាកដែលមានចំណងជើងគួរឱ្យស្រលាញ់ ដែលអ្នកនិពន្ធបានបន្ថែមដោយគ្មានឯកសារយោងទៅលើអ្វីដែលមាននៅក្នុងរូបភាព ( ពោលគឺរូបភាពកាហ្វេ និងកុំព្យូទ័រយួរដៃមួយនៅលើទំព័រប្លុក ដោយមានចំណងជើងថា “កំណត់ហេតុប្រចាំថ្ងៃជាទីគោរព ខ្ញុំចង់ត្រូវបានជ្រើសរើសជាអ្នកនិពន្ធភ្ញៀវ”)។ ខ្ញុំក៏បានឃើញស្លាក alt ដែលរួមបញ្ចូល 3 បន្ទាត់នៃពាក្យគន្លឹះ SEO ។ តើអ្នកអាចស្រមៃថាព្យាយាមស្តាប់អ្វីដែលមាននៅលើគេហទំព័រដើម្បីតែឮ “រូបភាពនៃរូបភាព” ឬបញ្ជីពាក្យគន្លឹះ SEO ដ៏វែង?
នេះគឺជាផ្នែកបន្ថែមរបស់ Chrome ដែលត្រូវបានរចនាឡើងដើម្បីផ្តល់សិទ្ធិអំណាចដល់អ្នកប្រើប្រាស់ដែលមើលឃើញដោយអនុញ្ញាតឱ្យពួកគេសរសេរជាន់លើស្លាក alt មិនល្អ និងប្រើប្រាស់ Open AI ដើម្បីបញ្ចូលការពិពណ៌នាដែលបានបង្កើត AI ។ នេះអនុញ្ញាតឱ្យអ្នកប្រើពិការភ្នែកអាចចូលប្រើប្រាស់ខ្លឹមសារទាំងអស់នៅលើគេហទំព័រដែលអ្នកប្រើប្រាស់ដែលមើលមិនឃើញអាចចូលប្រើបាន (ឬយ៉ាងហោចណាស់មិនត្រូវបានបន្ថយល្បឿនដោយបញ្ជីវែងនៃពាក្យគន្លឹះ SEO)។
ប្រសិនបើអ្នកគ្រាន់តែចង់បានផ្នែកបន្ថែម នោះអ្នកត្រូវបានស្វាគមន៍ក្នុងការទាញយក repo នេះ ហើយធ្វើតាមការណែនាំនៅក្នុង README ។
ទោះជាយ៉ាងណាក៏ដោយ ប្រសិនបើអ្នកចាប់អារម្មណ៍លើការណែនាំជាជំហាន ៗ អំពីរបៀបបង្កើតផ្នែកបន្ថែម Chrome ជាមួយ OpenAI ខាងក្រោមនេះគឺជាដំណើរឆ្លងកាត់។
ជាដំបូង ចូរយើងទទួលបានបន្ទះ Chrome មូលដ្ឋាន និងដំណើរការ។ ក្លូនឃ្លាំងនេះ ហើយធ្វើតាមការណែនាំនៅក្នុង README៖
នៅពេលដែលអ្នកដំឡើងវាហើយ អ្នកគួរតែមានរូបតំណាងរូបភាពនៅក្នុងរបារផ្នែកបន្ថែមរបស់អ្នក (ខ្ញុំសូមណែនាំឱ្យខ្ទាស់វាដើម្បីធ្វើឱ្យការធ្វើតេស្តលឿនជាងមុន) ហើយនៅពេលអ្នកចុចលើវា អ្នកគួរតែឃើញការលេចឡើងជាមួយ "hello world"។
តោះបើកកូដ boilerplate ហើយដើរកាត់ឯកសារដែលមានស្រាប់។ នេះក៏នឹងគ្របដណ្តប់មូលដ្ឋានផ្នែកបន្ថែម Chrome មួយចំនួនផងដែរ៖
Static/manifest.json - រាល់ផ្នែកបន្ថែមរបស់ Chrome មានឯកសារ manifest.json ។ វារួមបញ្ចូលព័ត៌មានមូលដ្ឋាន និងការរៀបចំអំពីផ្នែកបន្ថែម។ នៅក្នុងឯកសារ Manifest របស់យើង យើងមានឈ្មោះ ការពណ៌នា ឯកសារផ្ទៃខាងក្រោយដែលបានកំណត់ទៅ src/background.js រូបតំណាងកំណត់ទៅ image-icon.png (នេះគឺជារូបតំណាងដែលនឹងបង្ហាញតំណាងឱ្យផ្នែកបន្ថែមនៅលើម៉ឺនុយផ្នែកបន្ថែម) ហើយវាកំណត់ popup.html ជាប្រភពឯកសារសម្រាប់ការលេចឡើងរបស់យើង។
src/background.js - ឯកសារ background.js ដែលបង្កើតឡើងនៅក្នុង manifest របស់យើង។ កូដនៅក្នុងឯកសារនេះនឹងដំណើរការក្នុងផ្ទៃខាងក្រោយ និងតាមដានព្រឹត្តិការណ៍ដែលបង្កឱ្យមានមុខងារនៅក្នុងផ្នែកបន្ថែម។
src/content.js - ស្គ្រីបណាមួយដែលដំណើរការក្នុងបរិបទនៃគេហទំព័រ ឬការកែប្រែគេហទំព័រត្រូវដាក់ក្នុងស្គ្រីបមាតិកា។
src/popup.js, static/popup.css, និង static/popup.html - ឯកសារទាំងនេះគ្រប់គ្រងការលេចឡើងដែលអ្នកឃើញនៅពេលអ្នកចុចរូបតំណាងផ្នែកបន្ថែម
តោះរៀបចំមូលដ្ឋានមួយចំនួន - បើក static/manifest.json ហើយប្តូរឈ្មោះ និងការពិពណ៌នាទៅជា "Screen Reader Image Description Generator" (ឬអ្វីក៏ដោយដែលអ្នកចង់បាន)។
បើកដំណើរការអន្តរកម្មជាមួយគេហទំព័រដោយប្រើស្គ្រីបមាតិកា
ផ្នែកបន្ថែមរបស់យើងនឹងសរសេរជាន់លើស្លាក alt នៅលើគេហទំព័រដែលអ្នកប្រើប្រាស់បើក ដែលមានន័យថាយើងត្រូវការចូលទៅកាន់ទំព័រ html ។ វិធីដើម្បីធ្វើវានៅក្នុងផ្នែកបន្ថែមរបស់ Chrome គឺតាមរយៈស្គ្រីបមាតិកា។ ស្គ្រីបមាតិការបស់យើងនឹងស្ថិតនៅក្នុងឯកសារ src/content.js របស់យើង។
វិធីសាមញ្ញបំផុតក្នុងការចាក់បញ្ចូលស្គ្រីបមាតិកាគឺដោយបន្ថែមវាល "ស្គ្រីប" ទៅ manifest ដោយយោងទៅឯកសារ js ។ នៅពេលអ្នករៀបចំស្គ្រីបមាតិកាតាមវិធីនេះ ស្គ្រីបដែលបានភ្ជាប់នឹងដំណើរការនៅពេលណាដែលផ្នែកបន្ថែមត្រូវបានផ្ទុក។ ទោះយ៉ាងណាក៏ដោយ ក្នុងករណីរបស់យើង យើងមិនចង់ឱ្យផ្នែកបន្ថែមរបស់យើងដំណើរការដោយស្វ័យប្រវត្តិទេ នៅពេលអ្នកប្រើប្រាស់បើកកម្មវិធីបន្ថែម។ គេហទំព័រខ្លះមានស្លាក alt ល្អឥតខ្ចោះដែលបានកំណត់នៅលើរូបភាព ដូច្នេះយើងចង់ដំណើរការកូដនៅពេលអ្នកប្រើប្រាស់សម្រេចចិត្តថាវាចាំបាច់។
យើងនឹងបន្ថែមប៊ូតុងមួយនៅក្នុងការលេចឡើងរបស់យើង និងកុងសូលកំណត់ហេតុនៅក្នុងស្គ្រីបមាតិការបស់យើង ដូច្នេះនៅពេលដែលអ្នកប្រើប្រាស់ចុចលើប៊ូតុងនោះ ស្គ្រីបមាតិកាត្រូវបានផ្ទុក ហើយយើងអាចបញ្ជាក់បានថាដោយឃើញសេចក្តីថ្លែងការណ៍របស់យើងបានបោះពុម្ពនៅក្នុងកុងសូល Chrome ។
Popup.html
<button id="generate-alt-tags-button">Generate image descriptions</button>
src/content.js
console.log('hello console')
វិធីដើម្បីភ្ជាប់ប៊ូតុងនោះ ចុចលើផ្ទាំងលេចឡើងទៅស្គ្រីបមាតិកាមានទាំង popup.js និង background.js ។
នៅក្នុង popup.js យើងនឹងចាប់យកប៊ូតុងពី DOM ហើយបន្ថែមកម្មវិធីស្តាប់ព្រឹត្តិការណ៍។ នៅពេលដែលអ្នកប្រើប្រាស់ចុចលើប៊ូតុងនោះ យើងនឹងផ្ញើសារដែលបញ្ជាក់ថា ស្គ្រីបមាតិកាគួរតែត្រូវបានចាក់។ យើងនឹងដាក់ឈ្មោះសារថា "injectContentScript"
const generateAltTagButton = document.body.querySelector('#generate-alt-tags-button'); generateAltTagButton.addEventListener('click', async () => { chrome.runtime.sendMessage({action: 'injectContentScript'}) });
នៅក្នុង background.js យើងមានកូដដែលតាមដានព្រឹត្តិការណ៍ និងប្រតិកម្មចំពោះពួកគេ។ នៅទីនេះ យើងកំពុងរៀបចំកម្មវិធីស្តាប់ព្រឹត្តិការណ៍ ហើយប្រសិនបើសារដែលបានទទួលគឺ 'injectContentScript' វានឹងដំណើរការស្គ្រីបមាតិកានៅក្នុងផ្ទាំងសកម្ម (ទំព័របណ្ដាញបច្ចុប្បន្នរបស់អ្នកប្រើ)។
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.action === 'injectContentScript') { chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { chrome.scripting.executeScript({ target: { tabId: tabs[0].id }, files: ['content.js'] }); }); } });
ជំហានចុងក្រោយដើម្បីរៀបចំនេះគឺដើម្បីបន្ថែមការអនុញ្ញាត "activeTab" និង "scripting" ទៅ manifest របស់យើង។ ការអនុញ្ញាត "ការសរសេរស្គ្រីប" គឺត្រូវបានទាមទារ ដើម្បីដំណើរការស្គ្រីបមាតិកាណាមួយ។ យើងក៏ត្រូវបន្ថែមការអនុញ្ញាតសម្រាប់ទំព័រដែលយើងបញ្ចូលស្គ្រីបទៅក្នុង។ ក្នុងករណីនេះ យើងនឹងបញ្ចូលស្គ្រីបទៅក្នុងគេហទំព័របច្ចុប្បន្នរបស់អ្នកប្រើ ហៅថាផ្ទាំងសកម្មរបស់ពួកគេ ហើយនោះជាអ្វីដែលអនុញ្ញាត activeTab អនុញ្ញាត។
នៅក្នុង manifest.json៖
"permissions": [ "activeTab", "scripting" ],
នៅចំណុចនេះ អ្នកប្រហែលជាត្រូវដកផ្នែកបន្ថែមចេញពី Chrome ហើយផ្ទុកវាឡើងវិញដើម្បីឱ្យវាដំណើរការបានត្រឹមត្រូវ។ នៅពេលដែលវាដំណើរការ យើងគួរតែឃើញកុងសូលរបស់យើងនៅក្នុងកុងសូល Chrome របស់យើង។
នេះគឺជាតំណ github សម្រាប់កូដធ្វើការសម្រាប់ repo នៅដំណាក់កាលនេះ ។
ការប្រមូលរូបភាពទំព័រ និងបញ្ចូលស្លាកសញ្ញាសាកល្បង
ជំហានបន្ទាប់របស់យើងគឺប្រើប្រាស់ឯកសារស្គ្រីបខ្លឹមសាររបស់យើងដើម្បីចាប់យករូបភាពទាំងអស់នៅលើទំព័រ ដូច្នេះយើងមានព័ត៌មាននោះរួចរាល់ដើម្បីផ្ញើនៅក្នុងការហៅ API របស់យើងដើម្បីទទួលបានការពិពណ៌នារូបភាព។ យើងក៏ចង់ធ្វើឱ្យប្រាកដថា យើងគ្រាន់តែធ្វើការហៅទូរសព្ទសម្រាប់រូបភាព ដែលវាមានប្រយោជន៍ក្នុងការមានពណ៌នា។ រូបភាពខ្លះមានការតុបតែងសុទ្ធសាធ ហើយមិនមានតម្រូវការក្នុងការបន្ថយល្បឿនអ្នកអានអេក្រង់ជាមួយនឹងការពិពណ៌នារបស់ពួកគេ។ ឧទាហរណ៍ ប្រសិនបើអ្នកមានរបារស្វែងរកដែលមានទាំងស្លាក "ស្វែងរក" និងរូបតំណាងកែវពង្រីក។ ប្រសិនបើរូបភាពមានស្លាក alt របស់វាកំណត់ទៅខ្សែអក្សរទទេ ឬបានកំណត់ aria-hidden ទៅពិត នោះមានន័យថារូបភាពមិនចាំបាច់បញ្ចូលក្នុងកម្មវិធីអានអេក្រង់ទេ ហើយយើងអាចរំលងការបង្កើតការពិពណ៌នាសម្រាប់វាបាន។
ដូច្នេះដំបូងនៅក្នុង content.js យើងនឹងប្រមូលរូបភាពទាំងអស់នៅលើទំព័រ។ ខ្ញុំកំពុងបន្ថែម console.log ដូច្នេះខ្ញុំអាចបញ្ជាក់បានយ៉ាងរហ័សថាវាដំណើរការត្រឹមត្រូវ៖
const images = document.querySelectorAll("img"); console.log(images)
បន្ទាប់មក យើងនឹងមើលរូបភាពដែលយើងត្រូវការបង្កើតស្លាក alt សម្រាប់។ វារួមបញ្ចូលទាំងរូបភាពទាំងអស់ដែលមិនមានស្លាក alt និងរូបភាពដែលមានស្លាក alt ដែលមិនមែនជាខ្សែអក្សរទទេ និងរូបភាពដែលមិនត្រូវបានលាក់យ៉ាងច្បាស់ពីអ្នកអានអេក្រង់ជាមួយនឹងគុណលក្ខណៈ aria-hidden ។
for (let image of images) { const imageHasAltTag = image.hasAttribute('alt'); const imageAltTagIsEmptyString = image.hasAttribute('alt') && image.alt === ""; const isAriaHidden = image.ariaHidden ?? false; if (!imageHasAltTag || !imageAltTagIsEmptyString || !isAriaHidden) { // this is an image we want to generate an alt tag for! } }
បន្ទាប់មកយើងអាចបន្ថែមខ្សែអក្សរសាកល្បងដើម្បីកំណត់ស្លាក alt ដូច្នេះយើងអាចបញ្ជាក់ថាយើងមានវិធីមុខងារដើម្បីកំណត់ពួកវាមុនពេលយើងបន្តទៅការហៅ OpenAI របស់យើង។ content.js របស់យើងឥឡូវនេះមើលទៅដូចជា៖
function scanPhotos() { const images = document.querySelectorAll("img"); console.log(images) for (let image of images) { const imageHasAltTag = image.hasAttribute('alt'); const imageAltTagIsEmptyString = image.hasAttribute('alt') && image.alt === ""; const isAriaHidden = image.ariaHidden ?? false; if (!imageHasAltTag || !imageAltTagIsEmptyString || !isAriaHidden) { image.alt = 'Test Alt Text' } } } scanPhotos()
នៅចំណុចនេះ ប្រសិនបើយើងបើក Chrome dev tools Elements ចុចលើរូបភាពមួយ យើងគួរតែឃើញ "Test Alt Text" ដែលកំណត់ជា alt tag។
Repo ធ្វើការសម្រាប់កន្លែងដែលលេខកូដស្ថិតនៅដំណាក់កាលនេះនៅទីនេះ។
ដំឡើង OpenAI និងបង្កើតការពិពណ៌នារូបភាព
ដើម្បីប្រើ OpenAI អ្នកនឹងត្រូវបង្កើតសោ OpenAI ហើយបន្ថែមឥណទានទៅក្នុងគណនីរបស់អ្នក។ ដើម្បីបង្កើតសោ OpenAI៖
រក្សាទុកសោនេះ។ ដូចគ្នានេះផងដែររក្សាវាឯកជន - ត្រូវប្រាកដថាកុំរុញវាចូលទៅក្នុងកន្លែងផ្ទុក git សាធារណៈណាមួយ។
ឥឡូវនេះ ត្រលប់មកវិញនៅក្នុង repo របស់យើងដំបូងយើងចង់ដំឡើង OpenAi ។ នៅក្នុងស្ថានីយខាងក្នុងថតគម្រោង សូមដំណើរការ៖
npm install openai
ឥឡូវនេះនៅក្នុង content.js យើងនឹងនាំចូល OpenAI ដោយបន្ថែមកូដនេះនៅផ្នែកខាងលើនៃឯកសារ ដោយប្រើសោ OpenAI របស់អ្នកបានបិទភ្ជាប់ក្នុងជួរទី 1៖
const openAiSecretKey = 'YOUR_KEY_GOES_HERE' import OpenAI from "openai"; const openai = new OpenAI({ apiKey: openAiSecretKey, dangerouslyAllowBrowser: true });
“DangerouslyAllowBrowser” អនុញ្ញាតឱ្យការហៅទូរស័ព្ទត្រូវបានធ្វើឡើងដោយប្រើសោរបស់អ្នកពីកម្មវិធីរុករក។ ជាទូទៅ នេះគឺជាការអនុវត្តដែលមិនមានសុវត្ថិភាព។ ដោយសារយើងកំពុងដំណើរការគម្រោងនេះតែក្នុងមូលដ្ឋានប៉ុណ្ណោះ យើងនឹងទុកវាដូចនេះ ជាជាងរៀបចំការទាញយកមកវិញ។ ប្រសិនបើអ្នកប្រើ OpenAI នៅក្នុងគម្រោងផ្សេងទៀត ត្រូវប្រាកដថាអ្នកធ្វើតាមការអនុវត្តល្អបំផុតទាក់ទងនឹងការរក្សាការសម្ងាត់គន្លឹះ។
ឥឡូវនេះយើងបន្ថែមការហៅរបស់យើងដើម្បីឱ្យ OpenAI បង្កើតការពិពណ៌នារូបភាព។ យើងកំពុងហៅចំណុចបញ្ចប់នៃការបញ្ចប់ការជជែក ( ឯកសារ OpenAI សម្រាប់ចំណុចបញ្ចប់បញ្ចប់ការជជែក )។
យើងត្រូវសរសេរប្រអប់បញ្ចូលផ្ទាល់ខ្លួនរបស់យើង ហើយក៏បញ្ជូនទៅក្នុង src URL របស់រូបភាពផងដែរ ( ព័ត៌មានបន្ថែមអំពី AI prompt engineering )។ អ្នកអាចសម្របប្រអប់បញ្ចូលតាមការចង់បាន។ ខ្ញុំបានជ្រើសរើសកំណត់ការពិពណ៌នាត្រឹម 20 ការងារ ដោយសារ OpenAI កំពុងត្រលប់មកវិញនូវការពិពណ៌នាដ៏វែង។ លើសពីនេះទៀត ខ្ញុំបានកត់សម្គាល់ឃើញថា វាត្រូវបានពណ៌នាយ៉ាងពេញលេញនូវនិមិត្តសញ្ញាដូចជា Yelp ឬនិមិត្តសញ្ញា Facebook (ឧទាហរណ៍ 'ប្រអប់ពណ៌ខៀវដ៏ធំដែលមានអក្សរតូចពណ៌សនៅខាងក្នុង') ដែលមិនមានប្រយោជន៍។ ក្នុងករណីដែលវាជា Infographic ខ្ញុំសុំថាកម្រិតពាក្យមិនត្រូវបានអើពើ ហើយអត្ថបទរូបភាពពេញត្រូវបានចែករំលែក។
នេះគឺជាការហៅទូរសព្ទពេញលេញ ដែលត្រឡប់ខ្លឹមសារនៃការឆ្លើយតប AI ដំបូង ហើយក៏បញ្ជូនកំហុសទៅក្នុងមុខងារ "ដោះស្រាយកំហុស" ផងដែរ។ ខ្ញុំបានបញ្ចូល console.log នៃការឆ្លើយតបនីមួយៗ ដូច្នេះយើងអាចទទួលបានមតិកែលម្អលឿនជាងមុន ប្រសិនបើការហៅទូរសព្ទនោះជោគជ័យ ឬអត់៖
async function generateDescription(imageSrcUrl) { const response = await openai.chat.completions.create({ model: "gpt-4o-mini", messages: [ { role: "user", content: [ { type: "text", text: "Describe this image in 20 words or less. If the image looks like the logo of a large company, just say the company name and then the word logo. If the image has text, share the text. If the image has text and it is more than 20 words, ignore the earlier instruction to limit the words and share the full text."}, { type: "image_url", image_url: { "url": imageSrcUrl, }, }, ], }, ], }).catch(handleError); console.log(response) if (response) { return response.choices[0].message.content;} } function handleError(err) { console.log(err); }
យើងបន្ថែមការហៅទៅកាន់មុខងារនេះទៅក្នុង if statement ដែលយើងបានសរសេរពីមុន (យើងក៏ត្រូវបន្ថែមពាក្យគន្លឹះ async នៅដើមមុខងារ scanImages ដើម្បីរួមបញ្ចូលការហៅ asynchronous នេះផងដែរ)៖
const imageDescription = await generateDescription(image.src) if (!imageDescription) { return; } image.alt = imageDescription
នេះគឺជាតំណភ្ជាប់ទៅកាន់ content.js ពេញលេញ និង repo នៅចំណុចនេះ។
បង្កើត UI
បន្ទាប់មក យើងចង់បង្កើត UI របស់យើងដើម្បីឱ្យអ្នកប្រើប្រាស់ដឹងពីអ្វីដែលកំពុងកើតឡើងបន្ទាប់ពីពួកគេចុចប៊ូតុងដើម្បីបង្កើតស្លាក។ វាត្រូវការពេលពីរបីវិនាទីសម្រាប់ស្លាកដើម្បីផ្ទុក ដូច្នេះយើងចង់បានសារ 'កំពុងផ្ទុក' ដូច្នេះអ្នកប្រើប្រាស់ដឹងថាវាដំណើរការ។ លើសពីនេះ យើងចង់ឱ្យពួកគេដឹងថាវាជោគជ័យ ឬប្រសិនបើមានកំហុស។ ដើម្បីរក្សាអ្វីដែលសាមញ្ញ យើងនឹងមានសារអ្នកប្រើប្រាស់ទូទៅ div នៅក្នុង html ហើយបន្ទាប់មកប្រើ popup.js ដើម្បីបញ្ចូលសារដែលសមស្របទៅអ្នកប្រើប្រាស់ដោយថាមវន្តដោយផ្អែកលើអ្វីដែលកំពុងកើតឡើងនៅក្នុងផ្នែកបន្ថែម។
របៀបដែលផ្នែកបន្ថែមរបស់ Chrome ត្រូវបានតំឡើង ស្គ្រីបមាតិការបស់យើង (content.js) ត្រូវបានបំបែកចេញពី popup.js របស់យើង ហើយពួកគេមិនអាចចែករំលែកអថេរដូចឯកសារ JavaScript ធម្មតាបានទេ។ វិធីដែលស្គ្រីបមាតិកាអាចឱ្យអ្នកលេចឡើងដឹងថាស្លាកកំពុងផ្ទុក ឬត្រូវបានផ្ទុកដោយជោគជ័យ គឺតាមរយៈការបញ្ជូនសារ។ យើងបានប្រើការបញ្ជូនសាររួចហើយនៅពេលដែលយើងអនុញ្ញាតឱ្យអ្នកធ្វើការផ្ទៃខាងក្រោយដឹងថានឹងចាក់ស្គ្រីបមាតិកានៅពេលដែលអ្នកប្រើចុចលើប៊ូតុងដើម។
ជាដំបូង នៅក្នុង html របស់យើង យើងនឹងបន្ថែម div ជាមួយនឹង id 'user-message' នៅក្រោមប៊ូតុងរបស់យើង។ ខ្ញុំបានបន្ថែមការពិពណ៌នាបន្តិចបន្ថែមទៀតសម្រាប់សារដំបូងផងដែរ។
<div id="user-message"> <img src="image-icon.png" width="40" class="icon" alt=""/> This extension uses OpenAI to generate alternative image descriptions for screen readers. </div>
បន្ទាប់មក នៅក្នុង popup.js របស់យើង យើងនឹងបន្ថែមអ្នកស្តាប់ដែលស្តាប់សារណាមួយដែលបានផ្ញើ ដែលអាចមានការអាប់ដេតទៅកាន់ស្ថានភាពផ្នែកបន្ថែម។ យើងក៏នឹងសរសេរ html មួយចំនួនដើម្បីចាក់ដោយផ្អែកលើលទ្ធផលនៃរដ្ឋណាមួយដែលយើងទទួលបានមកវិញពីស្គ្រីបមាតិកា។
const userMessage = document.body.querySelector('#user-message'); chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { renderUI(message.action) } ); function renderUI(extensionState) { generateAltTagButton.disabled=true; if (extensionState === 'loading') { userMessage.innerHTML = '<img src="loading-icon.png" width="50" class="icon" alt=""/> New image descriptions are loading... <br> <br>Please wait. We will update you when the descriptions have loaded.' } else if (extensionState === 'success') { userMessage.innerHTML = '<img src="success-icon.png" width="50" class="icon" alt=""/> New image descriptions have been loaded! <br> <br> If you would like to return to the original image descriptions set by the web page author, please refresh the page.' } else if (extensionState === 'errorGeneric') { userMessage.innerHTML = '<img src="error-icon.png" width="50" class="icon"alt=""/> There was an error generating new image descriptions. <br> <br> Please refresh the page and try again.' } else if (extensionState === 'errorAuthentication') { userMessage.innerHTML = '<img src="error-icon.png" width="50" class="icon"alt=""/> There was an error generating new image descriptions. <br> <br> Your OpenAI key is not valid. Please double check your key and try again.' } else if (extensionState === 'errorMaxQuota') { userMessage.innerHTML = '<img src="error-icon.png" width="50" class="icon"alt=""/> There was an error generating new image descriptions. <br> <br> You\'ve either used up your current OpenAI plan and need to add more credit, or you\'ve made too many requests too quickly. Please check your plan, add funds if needed, or slow down the requests.' } }
នៅក្នុងស្គ្រីបមាតិការបស់យើង យើងនឹងកំណត់អថេរថ្មីមួយហៅថា 'extensionState' ដែលអាចជា 'initial' (ផ្នែកបន្ថែមត្រូវបានផ្ទុក ប៉ុន្តែមិនទាន់មានអ្វីកើតឡើង) 'loading' 'success' ឬ 'error' (យើង នឹងបន្ថែមស្ថានភាពកំហុសមួយចំនួនផ្សេងទៀតផងដែរ ដោយផ្អែកលើសារកំហុស OpenAI)។ យើងក៏នឹងធ្វើបច្ចុប្បន្នភាពអថេរស្ថានភាពផ្នែកបន្ថែម ហើយផ្ញើសារទៅ popup.js រាល់ពេលដែលស្ថានភាពផ្លាស់ប្តូរការផ្លាស់ប្តូរ។
let extensionState = 'initial';
កម្មវិធីដោះស្រាយកំហុសរបស់យើងសម្រាប់ក្លាយជា៖
function handleError(err) { if (JSON.stringify(err).includes('401')) { extensionState = 'errorAuthentication' chrome.runtime.sendMessage({action: extensionState}) } else if (JSON.stringify(err).includes('429')) { extensionState = 'errorMaxQuota' chrome.runtime.sendMessage({action: extensionState}) } else { extensionState = 'errorGeneric' chrome.runtime.sendMessage({action: extensionState}) } console.log(err); }
ហើយនៅក្នុងមុខងារ scanPhotos របស់យើង យើងបានកំណត់ស្ថានភាពទៅ 'loading' នៅដើមមុខងារ ហើយដើម្បី 'success' ប្រសិនបើវាដំណើរការពេញលេញដោយគ្មានកំហុស។
async function scanPhotos() { extensionState = 'loading' chrome.runtime.sendMessage({action: extensionState}) const images = document.querySelectorAll("img"); for (let image of images) { const imageHasAltTag = image.hasAttribute('alt'); const imageAltTagIsEmptyString = image.hasAttribute('alt') && image.alt === ""; const isAriaHidden = image.ariaHidden ?? false; if (!imageHasAltTag || !imageAltTagIsEmptyString || !isAriaHidden) { const imageDescription = await generateDescription(image.src) if (!imageDescription) { return; } image.alt = imageDescription } } extensionState = 'success' chrome.runtime.sendMessage({action: extensionState}) }
ជួសជុលឥរិយាបទលេចឡើងដែលច្រឡំ - ស្ថានភាពផ្នែកបន្ថែមបន្តនៅពេលបង្អួចលេចឡើងបិទ និងបើកឡើងវិញ
អ្នកអាចកត់សម្គាល់នៅចំណុចនេះថា ប្រសិនបើអ្នកបង្កើតស្លាក alt ទទួលបានសារជោគជ័យ ហើយបិទ និងបើកការលេចឡើងម្តងទៀត វានឹងបង្ហាញសារដំបូងដែលជំរុញឱ្យអ្នកប្រើប្រាស់បង្កើតស្លាក alt ថ្មី។ ទោះបីជាស្លាក alt ដែលបានបង្កើតនៅក្នុងកូដឥឡូវនេះក៏ដោយ!
នៅក្នុង Chrome រាល់ពេលដែលអ្នកបើកការលេចឡើងផ្នែកបន្ថែម វាគឺជាការលេចឡើងថ្មី។ វានឹងមិនចងចាំអ្វីទាំងអស់ដែលបានធ្វើពីមុនដោយផ្នែកបន្ថែម ឬអ្វីដែលកំពុងដំណើរការនៅក្នុងស្គ្រីបមាតិកា។ ទោះជាយ៉ាងណាក៏ដោយ យើងអាចប្រាកដថាការលេចឡើងដែលទើបនឹងបើកថ្មីកំពុងបង្ហាញស្ថានភាពត្រឹមត្រូវនៃផ្នែកបន្ថែមដោយហៅវាមក និងពិនិត្យមើលស្ថានភាពផ្នែកបន្ថែមនៅពេលវាត្រូវបានបើក។ ដើម្បីធ្វើដូច្នេះ យើងនឹងមានការបញ្ចូលសារមួយទៀត ដែលលើកនេះស្នើសុំស្ថានភាពផ្នែកបន្ថែម ហើយយើងនឹងបន្ថែមកម្មវិធីស្តាប់សារនៅក្នុង content.js របស់យើងដែលស្តាប់សារនោះ ហើយផ្ញើមកវិញនូវស្ថានភាពបច្ចុប្បន្ន។
popup.js
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { chrome.tabs.sendMessage(tabs[0].id, {action: "getExtensionState"}, function(response) { // if the content script hasn't been injected, then the code in that script hasn't been run, and we'll get an error or no response if (chrome.runtime.lastError || !response) { return; } else if (response) { // if the code in content script HAS been injected, we'll get a response which tells us what state the code is at (loading, success, error, etc) renderUI(response.extensionState) } }); });
content.js
chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) { if (request.action === "getExtensionState") sendResponse({extensionState}); });
ប្រសិនបើស្គ្រីបមាតិកាមិនដែលត្រូវបានដំណើរការទេ (អ្នកប្រើប្រាស់មិនដែលចុចប៊ូតុងដើម្បីបង្កើតស្លាក alt) នោះវានឹងមិនមានអថេរស្ថានភាពផ្នែកបន្ថែម ឬកម្មវិធីស្តាប់ព្រឹត្តិការណ៍ទេ។ ក្នុងករណីនេះ chrome នឹងត្រឡប់កំហុសពេលរត់ក្នុងការឆ្លើយតប។ ដូច្នេះយើងរួមបញ្ចូលការពិនិត្យមើលកំហុសមួយ ហើយប្រសិនបើយើងទទួលបាន សូមទុក UI លំនាំដើមដូចជា។
ភាពងាយស្រួលនៃផ្នែកបន្ថែម - aria-live, កម្រិតពណ៌ និងប៊ូតុងបិទ
ផ្នែកបន្ថែមនេះត្រូវបានរចនាឡើងសម្រាប់អ្នកដែលប្រើកម្មវិធីអានអេក្រង់ ដូច្នេះឥឡូវនេះយើងត្រូវធ្វើឱ្យប្រាកដថាវាពិតជាអាចប្រើបានជាមួយកម្មវិធីអានអេក្រង់! ឥឡូវនេះជាពេលវេលាដ៏ល្អដើម្បីបើកកម្មវិធីអានអេក្រង់របស់អ្នក ហើយមើលថាតើវាដំណើរការល្អដែរឬទេ។
មានរឿងមួយចំនួនដែលយើងចង់សម្អាត ដើម្បីភាពងាយស្រួល។ ជាដំបូង យើងចង់ធ្វើឱ្យប្រាកដថា អត្ថបទទាំងអស់មានកម្រិតពណ៌ខ្ពស់គ្រប់គ្រាន់។ សម្រាប់ប៊ូតុង ខ្ញុំបានសម្រេចចិត្តកំណត់ផ្ទៃខាងក្រោយទៅ #0250C5 ហើយពុម្ពអក្សរទៅជាដិតពណ៌ស។ វាមានសមាមាត្រកម្រិតពណ៌នៃ 7.1 ហើយត្រូវបានអនុលោមតាម WCAG នៅកម្រិត AA និង AAA ។ អ្នកអាចពិនិត្យមើលសមាមាត្រកម្រិតពណ៌សម្រាប់ពណ៌ណាមួយដែលអ្នកចង់ប្រើ នៅទីនេះនៅ WebAim Contrast Checker ។
ទីពីរ នៅពេលប្រើកម្មវិធីអានអេក្រង់របស់ខ្ញុំ ខ្ញុំកត់សំគាល់ថាកម្មវិធីអានអេក្រង់មិនអានព័ត៌មានថ្មីៗដោយស្វ័យប្រវត្តិទេ នៅពេលដែលសាររបស់អ្នកប្រើផ្លាស់ប្តូរទៅជាការផ្ទុក ការជោគជ័យ ឬសារកំហុស។ ដើម្បីជួសជុលបញ្ហានេះ យើងនឹងប្រើគុណលក្ខណៈ html ដែលហៅថា aria-live។ Aria-live អនុញ្ញាតឱ្យអ្នកអភិវឌ្ឍន៍អនុញ្ញាតឱ្យអ្នកអានអេក្រង់ដឹងដើម្បីធ្វើបច្ចុប្បន្នភាពអ្នកប្រើប្រាស់នៃការផ្លាស់ប្តូរ។ អ្នកអាចកំណត់ aria-live ទៅជាការអះអាង ឬគួរសម - ប្រសិនបើវាត្រូវបានកំណត់ជាការអះអាង ការអាប់ដេតនឹងត្រូវបានអានភ្លាមៗ ដោយមិនគិតពីថាតើមានធាតុផ្សេងទៀតដែលកំពុងរង់ចាំអាននៅក្នុងជួរកម្មវិធីអានអេក្រង់នោះទេ។ ប្រសិនបើវាត្រូវបានកំណត់ឱ្យគួរសម ការធ្វើបច្ចុប្បន្នភាពនឹងត្រូវបានអាននៅចុងបញ្ចប់នៃអ្វីគ្រប់យ៉ាងដែលអ្នកអានអេក្រង់កំពុងដំណើរការ។ ក្នុងករណីរបស់យើង យើងចង់ធ្វើបច្ចុប្បន្នភាពអ្នកប្រើប្រាស់ឱ្យបានឆាប់តាមដែលអាចធ្វើទៅបាន។ ដូច្នេះនៅក្នុង popup-container ដែលជាធាតុមេនៃធាតុសារអ្នកប្រើប្រាស់របស់យើង យើងនឹងបន្ថែមគុណលក្ខណៈនោះ។
<div class="popup-container" aria-live="assertive">
ជាចុងក្រោយ ដោយប្រើកម្មវិធីអានអេក្រង់ ខ្ញុំសង្កេតឃើញថា វាមិនមែនជាវិធីងាយស្រួលក្នុងការបិទការលេចឡើងនោះទេ។ ពេលប្រើកណ្ដុរ អ្នកគ្រាន់តែចុចកន្លែងណាមួយនៅខាងក្រៅបង្អួចលេចឡើង ហើយវានឹងបិទ ប៉ុន្តែខ្ញុំមិនអាចយល់ច្បាស់ពីរបៀបបិទវាដោយប្រើក្ដារចុចទេ។ ដូច្នេះយើងនឹងបន្ថែមប៊ូតុង 'បិទ' នៅផ្នែកខាងក្រោមនៃការលេចឡើង ដូច្នេះអ្នកប្រើប្រាស់អាចបិទវាបានយ៉ាងងាយស្រួល ហើយត្រឡប់ទៅទំព័របណ្ដាញវិញ។
នៅក្នុង popup.html យើងបន្ថែម៖
<div> <button id="close-button">Close</button> </div>
នៅក្នុង popup.js យើងបន្ថែមមុខងារបិទទៅ onclick៖
const closeButton = document.body.querySelector('#close-button'); closeButton.addEventListener('click', async () => { window.close() });
ហើយនោះហើយជាវា! ប្រសិនបើអ្នកមានសំណួរ ឬសំណូមពរណាមួយ សូមទាក់ទងមក។