Một bài viết rãnh ruồi về việc viết một Chrome Extension dành cho Spiderum tên là Spumderi
Logo chôm chỉa và xào nấu từ logo Spiderum
Logo chôm chỉa và xào nấu từ logo Spiderum
Chắc cũng lâu lắm rồi mình chưa viết bài nào kiểu màu mè kỷ thuật tí thì phải. Mà tính ra đó giờ cũng toàn kể chuyện xưa, chuyện cũ, chuyện đi làm thôi chứ cũng chẳng có kể gì về kỹ thuật. Do vậy nên hôm nay mình quyết định... tiếp nối cái truyền thống đó bằng cách viết một bài không mấy liên quan tới kỹ thuật tiếp. Chỉ kể tí về quá trình hai ngày ngồi làm một cái Chrome extension xàm xí để chạy trên Spiderum.

Ý tưởng khởi nguồn

Nếu nói về cái Spumderi thì chắc phải nói đến một extension khác mình từng làm tên là Medium Plugin. Một extension mình viết cho Medium với một số chức năng như hiển ra mục lục của bài viết (Table of Content) một cách tự động thông qua một sidebar phụ và người dùng có thể nhờ đó mà xem tổng quát bài viết cũng nhưng di chuyển nhanh đến các phần mà không cần phải cuộn chuột nhiều. Tạo một nút copy tự động ở phần "Code block" để giúp người dùng có thể sao chép mã nguồn nhanh hơn và cuối cùng là chức năng mình đã bê qua Spumderi. Chức năng cho phép người dùng sao chép địa chỉ của bài viết theo từng block. Nói một cách đơn giản thì nếu bạn thích một đoạn văn nào đó trong bài viết và muốn chia sẽ đoạn văn đó cho người khác bằng một đường dẫn. Khi họ truy cập vào đường dẫn thì họ sẽ được trỏ thẳng vào đoạn văn đó mà không cần cuộn chuột hoặc các thao tác khác. Bạn chỉ cần tốn một cú nhấp chuột thôi.
Có thể bài viết tới đây là xong rồi. Vì chỉ yếu viết để PR, seed bẩn cho cái extension ở trên. Nhưng mà làm thế sợ ăn gạch nên mình sẽ nói tiếp về Spumderi.

Khi rãnh rỗi sinh nông nổi

Thú thật là mình đã không dùng Spiderum hai năm rồi vì nhiều lý do. Nhưng sau khi dự buổi offline cùng mọi người ở Sài Gòn thì mình chợt truy cập vào Spiderum trở lại dù không nhiều như xưa. Tuy nói là sau khi dự buổi offline nhưng trước đó chừng một tuần mình có quay lại viết một bài xàm xí để gọi là có viết, có ghi ở đây (seed bẩn bài có 3 upvote nè).
Trong thời gian dùng mình chợt nghĩ rằng sao không bê thử cái gì đó hay hay (thật ra là xàm xàm mới đúng) từ Medium Plugin qua Spiderum. Thế là mình bắt đầu suy nghĩ xem lụm gì đem về xào được. Đầu tiên là chức năng sao chép mã nguồn nhanh hơn. Mình thấy chức năng này không khả thi lắm vì thật sự ở Spiderum không có nhiều bài về mã nguồn cũng như lập trình như Medium. Thứ hai là chức năng tự động tạo mục lục. Cũng khá hay và mình đã dự định sẽ thực hiện nó. Nhưng gặp một số vấn đề về việc định dạng của các tay viết bên Spiderum khá là đa dạng nên không qua dễ để thực hiện chức năng đó mà có đầu ra phù hợp. Điển hình là bài về bóng đá của Tornad (trong bài này sẽ nhắc đến bài đó kha khá lần vì mình dùng bài viết đó để chạy thử extension trong quá trình phát triển). Trong bài của Tornad thì thay vì chỉ mục được định dạng bằng chữ thì hắn là dùng hình. Thú thật là khá đẹp nhưng với bọn lập trình như mình thì chào thua vụ đó. Do vậy chỉ còn một chức năng đó là chức năng tạo đường dẫn đến một đoạn văn chỉ định trong bài viết. Nên mình quyết định thực hiện chức năng này.

Chung ý tưởng nhưng đôi điều khác biệt khi thực hiện

Như đã nói ở trên mình chôm chức năng này bên Medium Plugin qua nên cách thực hiện sẽ tương đối giống về mặt ý tưởng. Cả bên Medium và Spiderum mình sẽ điều thực hiện các bước đầu tiên như sau:
- Tạo một nút lấy đường dẫn và thêm nút đó vào trang web. - Đặt một sự kiện mỗi khi người dùng rê chuột lên một đoạn văn bản nào đó thì nút lấy đường dẫn sẽ hiện lên ở trước dòng đầu tiên của đoạn văn bản. Đồng thời lưu thông tin của đoạn văn bản đang được rê chuột vào một nơi nào đó. - Khi người dùng nhấp vào nút lấy đường dẫn. Sẽ có một công thức để sinh ra đường dẫn dựa trên thông tin của đoạn văn bản đang được rê chuột. - Sao chép đường dẫn đó vào bên trong bảng tạm của người dùng để họ thích làm gì thì làm.
Đương nhiên đó chỉ là các bước cơ bản thôi vì thực tế sẽ khác đôi chút giữa hai nền tảng. Thú thật là ở Medium thì thực hiện dễ hơn vì định dạng mã nguồn HTML của họ có phần hỗ trợ mình nhiều hơn khi làm. Trước khi nói về sự khác nhau đó mình xin nói một tí về kỹ thuật. Trong lập trình thì các trang web sẽ có mã nguồn sinh ra ở dạng cây, kiểu như cây gia phả. Mỗi thành phần như thế mình sẽ gọi là nốt. Mỗi một nốt như thế có thể có hoặc không các nốt con. Nếu đối chiếu qua thực tế thì có thể hình dung đơn giản rằng mỗi một đoạn văn bản sẽ là một nốt trong cái cây gia phả đó. Ví dụ như sau:
Như trong ảnh trên thì mỗi một câu hội thoại tương đương với một nốt đồng thường tương đương luôn mới một đoạn văn bản. Bên cạnh mỗi nốt mình có vẽ một số id. Đây là thông số nên tồn tại độc nhất trong cả cây nhằm định danh một nốt. Đương nhiên có nhiều cách định danh khác nhưng id vẫn là cách thông dụng nhất. Các trình duyệt có một chức năng là trỏ người dùng đến nhanh vị trí của một nốt thông qua id trên đường dẫn. Mình nghĩ mọi người có thể bắt gặp kiểu đường dẫn này khá nhiều, khi mà id hay còn được gọi là hash được định nghĩa phía sau dấu thăng. Dưới đây là một ví dụ:
https://ahihi.com/ahoho#ahuhu
Khi bạn truy cập vào đường dẫn trên thì sẽ có một cơ chế tự động để tìm xem có nốt nào mang id là "ahuhu" không. Nếu có thì trình duyệt sẽ tự động di chuyển tới vị trí của nốt mang "ahuhu" đó. Điều đó hoạt động khá ổn ở Medium.
Nhưng vấn đề bắt đầu đến khi mình thực hiện bên Spiderum vì bên Spiderum thì các đoạn văn bản không được gán id định danh như bên Medium. Như đã nói ở trên thì việc có hoặc không có id không có vấn đề gì cả. Nhưng với mình thì đúng là "ahuhu" thiệt vì không có id thì lấy gì mà bám vô được? Mình nghĩ ra một số cái xàm xí như lưu vị trí của đoạn văn bản và khi người dùng truy cập vào extension của mình sẽ đọc cái vị trí đó mà cuộc tới. Nhưng ý tưởng này bị dẹp ngay vì đơn giản là nó bắt người nhận đường dẫn cũng phải cài. Thế thì hỏng cả. Chả khác nào khoe rằng mình mới mua máy xay sinh tố, xay xong bỏ vào ly đem đến tặng bạn nhưng kêu bạn phải mua một cái máy gì đó để có thể ăn được. Thôi thì dẹp, khỏi làm chi cho mệt.
Nhưng ngồi chơi Diablo 2 một hồi thì mình chợt nghĩ ra một trò đó là thử dùng Google highlight. Nói đơn giản thì đây là một chức năng của mấy anh Google làm ra cho phép người dùng tạo một đường dẫn đến trang web hiện tại. Khi người dùng truy cập đường dẫn sẽ được dẫn tới đoạn mà người tạo đường dẫn đã tô đậm và đồng thời tô đậm đoạn văn bản đó. Các bạn có thể thử bằng cách tô đen một đoạn văn bản và bấm chuột phải.
Mượn bài của Tornad làm ví dụ
Mượn bài của Tornad làm ví dụ
Thế là mình nghĩ chắc phải có cách nào để làm cái trò này. Nên mình thử tạo một đường dẫn từ Google highlight và phân tích thử. Thì ra họ cũng dùng hash nhưng giá trị không phải là id. Họ dùng một chuỗi với định dạng riêng dùng để định danh phần văn bản sẽ được tô đậm khi truy cập đường dẫn. Nói một cách đơn giản thì chỉ cần khai báo một số chử đầu của đoạn văn bản và một số chử kết thúc của đoạn văn bản và định dạng đúng mẫu của Google là chúng ta sẽ có một đường dẫn như ý. Sau vài lần thử sai, làm lại thì cuối cùng có vẻ cũng hoạt động. Ơn trời nó hoạt động được thật.
Tấm hình PR về chức năng này.
Tấm hình PR về chức năng này.
Thế là coi như xong một chức năng. Nhưng tình cờ mình lại có hứng làm thêm một thứ khác.

Mình ngứa mắt thì mình chặn thôi

Xin cáo lỗi với bạn Nguyễn Bảo Trung khi dùng tài khoản của bạn làm ví dụ. Mình đã bỏ chặn ngay sau đó.
Xin cáo lỗi với bạn Nguyễn Bảo Trung khi dùng tài khoản của bạn làm ví dụ. Mình đã bỏ chặn ngay sau đó.
Ghi tiêu đề cứng cứng thế chứ mình chả ngứa mắt ai cả, mà ngứa thì gãi thôi. Chỉ là khi lướt bài của Tornad để làm cái của nợ Spumderi thì mình lướt bình luận và thấy một bình luận được trả lời khá nhiều. Trong số trả lời đó có một câu đại loại là khuyên anh em đừng nên quan tâm những bình luận của thanh niên kia làm gì. Đại loại là kệ hắn đi, xem hắn không tồn tại. Nghĩ cũng khó, người mình không muốn thấy mà cứ lù lù trước mặt thì sao mà chịu được. Nên mình có ý tưởng làm chức năng chặn người dùng bình luận. Nói chặn thì không đúng lắm, nói đúng hơn là tránh hiển thị người dùng nào đó ở phần bình luận (tiếng Anh là "avoid" thì phải). Để biết chặn ai thì cần một cái định danh cho người dùng nó. Rất cảm ơn anh em Spiderum khi mà mỗi bình luận đều có phần đường dẫn tới trang cá nhân của người viết. Trên đường dẫn chính là mã người dùng định danh. Cứ thế mình viết một đoạn mã đơn giản để ẩn đi những bình luận của những người dùng mà mình muốn chặn. Đây là các bước mà mình làm để thực hiện chức năng này.
Đầu tiên là xin quyền của mấy anh Chrome. Vì cần phải lưu danh sách người chặn nên mình xin luôn quyền "Storage" để lưu lại danh sách. Sẵn đây giải thích luôn là dữ liệu đó được lưu dưới mấy cho mọi người chứ mình không hề chôm chỉa gì được. Với lại chôm danh sách người dùng bị chặn của người khác cũng không có cơm cháo gì lắm nhỉ? Kiếm cái nào thơm thơm hơn tí chôm nó sướng hơn (đồng thời biết đâu ở tù cũng lâu hơn).
Bước tiếp theo là tương tác với chổ lưu dữ liệu. Bước này thì đơn giản chỉ gần lấy ra, thêm hoặc xóa bớt.
Bước kế tiếp là ẩn những người dùng nằm trong danh sách bị chặn. Bước này khá đơn giản như đã nói ở trên, chỉ cần duyệt qua hết những bình luận đang tồn tại, cái nào mà có tác giả nằm trong danh sách "hạn chế" thì mình ẩn đi tự động là xong.
Sau đó thì tương tự bước sao chép đường dẫn ở trên. Mình tạo một cái nút chặn người dùng, mỗi khi rê chuột vào bình luận nào thì nút đó sẽ hiện lên. Nhấp vào thì người dùng đó sẽ bị đưa vào danh sách hạn chế và bình luận ngay lập tức bị ẩn đi.
Đương nhiên có chặn thì sẽ có bỏ chặn. Để thực hiện quản lý danh sách chặn thì mình tạo một cái danh sách nho nhỏ bên góc của màn hình. Có thể mở ra bằng nút có hình bánh răng. Trong đó sẽ chứa danh sách những người bị chặn. Chỉ cần bấm nút "x" kế tên người dùng để bỏ chặn. Khá là đơn giản.
Mình không có chặn ai hết nha
Mình không có chặn ai hết nha
Mọi việc đến đây có vẻ như đã xong. Nhưng rồi mình chợt được gợi ý một chức năng nho nhỏ nửa. Đó là dù chặn nhưng đôi lúc chúng ta vẫn ngứa tay và muốn nhìn ngó xem thiên hạ đang bình luận gì "không che". Mà đi tháo chặn từng người thì cũng khó. Khách hàng là thượng đế, mình cho thêm luôn cái nút bật tắt ở phía dưới cho mọi người lật như lật bánh tráng luôn.

Tô vẽ vài đường trước khi nộp bài.

Đương nhiên là cần mông má một tí trước khi đem nộp cho lãnh chúa Google duyệt. Đầu tiên là tên Extension. Nghĩ hoài không ra thế là đọc lái lại từ Spiderum thành Spumderi có thể đọc là Bum De Guys. Dù nó khá vô nghĩa như nghe cũng lạ lạ. Thế là có tên cho ứng dụng.
Còn logo thì xin phép chôm nhẹ logo của Spiderum và dùng Paint để cắt dán lại thành chử Spumderi.
Viết vài dòng giải thích linh tinh về lý do tại sao xin quyền Storage với Google.
Ấn nút, tên lửa phóng lên vĩ đạo và sau hai hôm mình nhận được thông báo về việc Extension đã được thông qua và có thể cài đặt thông qua Chrome Store.

Kết

Chẳng biết kết bài thế nào cả. Chỉ đơn giản là chém gió tí về việc làm một ứng dụng thôi (đồng thời seed bẩn cái Medium Plugin và bài viết có 3 upvote của mình). Rất vui nếu có người nghía bài viết này.
Link cài đặt Spumderi
Một số thứ khác:
Cám ơn bài viết của Tornad, mình dường như kiểm thử và phát triển dựa trên hình mẫu là bài viết về bóng đá.
Xin lỗi bạn Nguyễn Bảo Trung vì lấy bình luận của bạn ra làm mẫu. Nếu bạn không thích mình có thể đổi hình khác.
Về vấn đề thó và xào nấu Logo nếu Spiderum cần mình sẽ đổi logo khác.