forked from izu/student-web-if-development-kit
feat(LimaEm): tambah halaman Kehidupan Mahasiswa & Himpunan (HMIF)
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
node_modules/
|
||||
dist/
|
||||
.DS_Store
|
||||
|
||||
groups/LimaEm/assets/images/
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,564 @@
|
||||
// =============================================================================
|
||||
// main.js — Logika Interaksi Halaman HMIF
|
||||
//
|
||||
// Struktur:
|
||||
// 1. Mobile Menu — Toggle menu navigasi mobile
|
||||
// 2. Language Toggle — Terjemahan halaman ID/EN
|
||||
// 3. Galeri Keseruan — Slider bento grid foto keseruan
|
||||
// 4. Kegiatan Unggulan — Slider kartu kegiatan tahunan
|
||||
// =============================================================================
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// 1. MOBILE MENU
|
||||
// Toggle visibilitas menu navigasi pada tampilan mobile.
|
||||
// =============================================================================
|
||||
|
||||
(function () {
|
||||
var mobileMenuButton = document.getElementById('mobile-menu-button');
|
||||
var mobileMenu = document.getElementById('mobile-menu');
|
||||
|
||||
if (!mobileMenuButton || !mobileMenu) return;
|
||||
|
||||
mobileMenuButton.addEventListener('click', function () {
|
||||
var isHidden = mobileMenu.classList.contains('hidden');
|
||||
mobileMenu.classList.toggle('hidden', !isHidden);
|
||||
mobileMenuButton.setAttribute('aria-expanded', String(isHidden));
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// 2. LANGUAGE TOGGLE
|
||||
// Terjemahan konten halaman antara Bahasa Indonesia dan Bahasa Inggris.
|
||||
// Preferensi bahasa disimpan di localStorage agar persisten antar sesi.
|
||||
// =============================================================================
|
||||
|
||||
(function () {
|
||||
var languageToggles = document.querySelectorAll('[data-language-toggle]');
|
||||
|
||||
if (!languageToggles.length) return;
|
||||
|
||||
var translationMap = {
|
||||
'Kehidupan Mahasiswa & Himpunan (HMIF)': {
|
||||
id: 'Kehidupan Mahasiswa & <span class="text-hmif-secondary" style="color:var(--color-hmif-secondary)">Himpunan (HMIF)</span>',
|
||||
en: 'Student Life & <span class="text-hmif-secondary" style="color:var(--color-hmif-secondary)">Association (HMIF)</span>'
|
||||
},
|
||||
'ABOUT US': { id: 'TENTANG KAMI', en: 'ABOUT US' },
|
||||
'PROGRAMS': { id: 'PROGRAM', en: 'PROGRAMS' },
|
||||
'HUMAN RESOURCES': { id: 'SUMBER DAYA MANUSIA', en: 'HUMAN RESOURCES' },
|
||||
'FACILITIES': { id: 'FASILITAS', en: 'FACILITIES' },
|
||||
'WORKS & EVENTS': { id: 'KARYA & KEGIATAN', en: 'WORKS & EVENTS' },
|
||||
'CONTACT': { id: 'KONTAK', en: 'CONTACT' },
|
||||
'COMMUNITY & LEADERSHIP': { id: 'KOMUNITAS & KEPEMIMPINAN', en: 'COMMUNITY & LEADERSHIP' },
|
||||
'Membangun ekosistem kolaboratif di mana teknologi bertemu dengan kreativitas, membentuk calon pemimpin industri masa depan.': {
|
||||
id: 'Membangun ekosistem kolaboratif di mana teknologi bertemu dengan kreativitas, membentuk calon pemimpin industri masa depan.',
|
||||
en: 'Building a collaborative ecosystem where technology meets creativity, shaping future industry leaders.'
|
||||
},
|
||||
'Lihat Struktur Kepengurusan': { id: 'Lihat Struktur Kepengurusan', en: 'View Organization Structure' },
|
||||
'Ruang Tumbuh Bagi Mahasiswa Informatika': {
|
||||
id: 'Ruang Tumbuh Bagi<br class="hidden sm:block"> Mahasiswa Informatika',
|
||||
en: 'A Growth Space For<br class="hidden sm:block"> Informatics Students'
|
||||
},
|
||||
'Himpunan Mahasiswa Informatika (HMIF) Universitas Tanjungpura bukan sekadar organisasi, melainkan rumah bagi para pemimpin teknologi. Kami percaya bahwa pendidikan formal adalah fondasi, namun komunitas adalah akselerator.': {
|
||||
id: 'Himpunan Mahasiswa Informatika (HMIF) Universitas Tanjungpura bukan sekadar organisasi, melainkan rumah bagi para pemimpin teknologi. Kami percaya bahwa pendidikan formal adalah fondasi, namun komunitas adalah akselerator.',
|
||||
en: 'The Informatics Student Association (HMIF) of Universitas Tanjungpura is more than an organization; it is a home for future technology leaders. We believe formal education is the foundation, while community is the accelerator.'
|
||||
},
|
||||
'Melalui berbagai inisiatif, kami menjembatani kesenjangan antara kurikulum akademik dan kebutuhan industri, sambil tetap menjaga semangat kekeluargaan dan integritas ilmiah.': {
|
||||
id: 'Melalui berbagai inisiatif, kami menjembatani kesenjangan antara kurikulum akademik dan kebutuhan industri, sambil tetap menjaga semangat kekeluargaan dan integritas ilmiah.',
|
||||
en: 'Through various initiatives, we bridge the gap between academic curricula and industry needs while preserving a spirit of kinship and academic integrity.'
|
||||
},
|
||||
'Mahasiswa Aktif': { id: 'Mahasiswa Aktif', en: 'Active Students' },
|
||||
'MITRA': { id: 'MITRA', en: 'PARTNERS' },
|
||||
'Partner Industri': { id: 'Partner Industri', en: 'Industry Partners' },
|
||||
'Inklusivitas & Kolaborasi': { id: 'Inklusivitas &<br>Kolaborasi', en: 'Inclusivity &<br>Collaboration' },
|
||||
'Partner & Kolaborator': { id: 'Partner & Kolaborator', en: 'Partners & Collaborators' },
|
||||
'Partner dan Kolaborator': { id: 'Partner dan Kolaborator', en: 'Partners and Collaborators' },
|
||||
'Divisi Kepengurusan HMIF': { id: 'Divisi Kepengurusan HMIF', en: 'HMIF Management Divisions' },
|
||||
'Struktur organisasi yang dirancang untuk efisiensi dan pengembangan kapasitas anggota di berbagai bidang strategis.': {
|
||||
id: 'Struktur organisasi yang dirancang untuk efisiensi dan pengembangan kapasitas anggota di berbagai bidang strategis.',
|
||||
en: 'An organizational structure designed for efficiency and member capacity development across strategic areas.'
|
||||
},
|
||||
'Bidang 1': { id: 'Bidang 1', en: 'Division 1' },
|
||||
'Bidang 2': { id: 'Bidang 2', en: 'Division 2' },
|
||||
'Bidang 3': { id: 'Bidang 3', en: 'Division 3' },
|
||||
'Bidang 4': { id: 'Bidang 4', en: 'Division 4' },
|
||||
'Bidang 5': { id: 'Bidang 5', en: 'Division 5' },
|
||||
'Bidang 6': { id: 'Bidang 6', en: 'Division 6' },
|
||||
'Pengembangan Sumber Daya Mahasiswa dan Kaderisasi': {
|
||||
id: 'Pengembangan Sumber Daya Mahasiswa dan Kaderisasi',
|
||||
en: 'Student Resource Development and Cadre Formation'
|
||||
},
|
||||
'Divisi ini menyelenggarakan kaderisasi terstruktur, mentoring berkala, dan pelatihan kepemimpinan serta soft-skill. Program kerja mencakup onboarding anggota baru, workshop kepemimpinan, proyek kolaboratif, dan kegiatan pengabdian yang melatih tanggung jawab sosial. Fokusnya adalah menyiapkan kader yang kompeten dan menjaga regenerasi organisasi.': {
|
||||
id: 'Divisi ini menyelenggarakan kaderisasi terstruktur, mentoring berkala, dan pelatihan kepemimpinan serta soft-skill. Program kerja mencakup onboarding anggota baru, workshop kepemimpinan, proyek kolaboratif, dan kegiatan pengabdian yang melatih tanggung jawab sosial. Fokusnya adalah menyiapkan kader yang kompeten dan menjaga regenerasi organisasi.',
|
||||
en: 'This division runs structured cadre development, regular mentoring, and leadership and soft-skill training. Its programs include new member onboarding, leadership workshops, collaborative projects, and community service activities that build social responsibility. The focus is preparing competent members and sustaining organizational regeneration.'
|
||||
},
|
||||
'Mendukung mahasiswa untuk terus berkembang, dengan pembinaan dan kaderisasi yang berkelanjutan.': {
|
||||
id: 'Mendukung mahasiswa untuk terus berkembang, dengan pembinaan dan kaderisasi yang berkelanjutan.',
|
||||
en: 'Supporting students to keep growing through continuous mentoring and cadre development.'
|
||||
},
|
||||
'Pengembangan Organisasi': { id: 'Pengembangan Organisasi', en: 'Organizational Development' },
|
||||
'Divisi ini memperkuat tata kelola dan kapabilitas internal melalui pelatihan pengurus, penyusunan SOP sederhana, dan evaluasi proses kerja. Program kerjanya mencakup pengembangan budaya organisasi, peningkatan efektivitas koordinasi, dan kegiatan peningkatan profesionalisme sehingga operasi HMIF menjadi lebih terstruktur dan efisien.': {
|
||||
id: 'Divisi ini memperkuat tata kelola dan kapabilitas internal melalui pelatihan pengurus, penyusunan SOP sederhana, dan evaluasi proses kerja. Program kerjanya mencakup pengembangan budaya organisasi, peningkatan efektivitas koordinasi, dan kegiatan peningkatan profesionalisme sehingga operasi HMIF menjadi lebih terstruktur dan efisien.',
|
||||
en: 'This division strengthens governance and internal capability through board training, simple SOP development, and workflow evaluation. Its programs include organizational culture development, coordination effectiveness improvement, and professionalism initiatives so HMIF operations become more structured and efficient.'
|
||||
},
|
||||
'Mendukung organisasi agar berjalan lebih rapi, terstruktur, dan semakin berkembang.': {
|
||||
id: 'Mendukung organisasi agar berjalan lebih rapi, terstruktur, dan semakin berkembang.',
|
||||
en: 'Helping the organization run in a more orderly, structured, and progressive way.'
|
||||
},
|
||||
'Media Komunikasi dan Konten Digital': {
|
||||
id: 'Media Komunikasi dan Konten Digital',
|
||||
en: 'Communication Media and Digital Content'
|
||||
},
|
||||
'Divisi ini mengelola strategi komunikasi dan produksi konten HMIF, termasuk perencanaan editorial, manajemen media sosial, serta dokumentasi acara. Program kerjanya meliputi pembuatan materi promosi, publikasi kegiatan, dan penguatan identitas digital agar informasi organisasi tersampaikan konsisten dan menarik.': {
|
||||
id: 'Divisi ini mengelola strategi komunikasi dan produksi konten HMIF, termasuk perencanaan editorial, manajemen media sosial, serta dokumentasi acara. Program kerjanya meliputi pembuatan materi promosi, publikasi kegiatan, dan penguatan identitas digital agar informasi organisasi tersampaikan konsisten dan menarik.',
|
||||
en: 'This division manages HMIF communication strategy and content production, including editorial planning, social media management, and event documentation. Its programs cover promotional materials, activity publications, and digital identity strengthening so organizational information is delivered consistently and attractively.'
|
||||
},
|
||||
'Mengelola media dan komunikasi digital untuk menyampaikan informasi dengan lebih menarik dan mudah diakses.': {
|
||||
id: 'Mengelola media dan komunikasi digital untuk menyampaikan informasi dengan lebih menarik dan mudah diakses.',
|
||||
en: 'Managing digital media and communication to deliver information in a more engaging and accessible way.'
|
||||
},
|
||||
'Sosial Masyarakat': { id: 'Sosial Masyarakat', en: 'Community Service' },
|
||||
'Divisi ini merancang dan melaksanakan program pengabdian serta aksi sosial yang berdampak, termasuk pendampingan komunitas dan bantuan kemanusiaan. Kegiatan meliputi identifikasi kebutuhan lapangan, pelaksanaan terstruktur, dan evaluasi dampak untuk memastikan keberlanjutan dan manfaat nyata bagi masyarakat.': {
|
||||
id: 'Divisi ini merancang dan melaksanakan program pengabdian serta aksi sosial yang berdampak, termasuk pendampingan komunitas dan bantuan kemanusiaan. Kegiatan meliputi identifikasi kebutuhan lapangan, pelaksanaan terstruktur, dan evaluasi dampak untuk memastikan keberlanjutan dan manfaat nyata bagi masyarakat.',
|
||||
en: 'This division designs and carries out impactful community service programs and social actions, including community assistance and humanitarian support. Activities include field needs assessment, structured implementation, and impact evaluation to ensure sustainability and real benefits for the community.'
|
||||
},
|
||||
'Berbagi dan berkontribusi melalui berbagai kegiatan sosial, sekaligus membawa dampak positif bagi masyarakat.': {
|
||||
id: 'Berbagi dan berkontribusi melalui berbagai kegiatan sosial, sekaligus membawa dampak positif bagi masyarakat.',
|
||||
en: 'Sharing and contributing through social activities while bringing positive impact to the community.'
|
||||
},
|
||||
'Inovasi dan Kompetisi Teknologi': {
|
||||
id: 'Inovasi dan Kompetisi Teknologi',
|
||||
en: 'Technology Innovation and Competition'
|
||||
},
|
||||
'Divisi ini memfasilitasi persiapan lomba dan pengembangan proyek teknis melalui coaching clinic, bootcamp berbasis proyek, serta study club untuk Competitive Programming, Software Development, dan Data/ML. Kegiatan termasuk seleksi internal, bimbingan kompetitif, dan inisiatif digitalisasi seperti pengembangan website dan dashboard untuk mendukung ekosistem inovasi HMIF.': {
|
||||
id: 'Divisi ini memfasilitasi persiapan lomba dan pengembangan proyek teknis melalui coaching clinic, bootcamp berbasis proyek, serta study club untuk Competitive Programming, Software Development, dan Data/ML. Kegiatan termasuk seleksi internal, bimbingan kompetitif, dan inisiatif digitalisasi seperti pengembangan website dan dashboard untuk mendukung ekosistem inovasi HMIF.',
|
||||
en: 'This division facilitates competition preparation and technical project development through coaching clinics, project-based bootcamps, and study clubs for Competitive Programming, Software Development, and Data/ML. Activities include internal selection, competitive mentoring, and digitalization initiatives such as website and dashboard development to support HMIF innovation.'
|
||||
},
|
||||
'Mengembangkan inovasi dan skill teknologi, sambil mendorong mahasiswa untuk berani mencoba dan ikut berbagai tantangan.': {
|
||||
id: 'Mengembangkan inovasi dan skill teknologi, sambil mendorong mahasiswa untuk berani mencoba dan ikut berbagai tantangan.',
|
||||
en: 'Developing innovation and technology skills while encouraging students to try new challenges.'
|
||||
},
|
||||
'Kewirausahaan dan Kemitraan': { id: 'Kewirausahaan dan Kemitraan', en: 'Entrepreneurship and Partnership' },
|
||||
'Divisi ini mengembangkan unit usaha organisasi, merancang skema pendanaan kreatif, dan menjalin kemitraan strategis untuk mendukung keberlanjutan program HMIF. Unit kerjanya meliputi riset peluang usaha, penyusunan proposal kemitraan, dan pengelolaan sponsor untuk meningkatkan kemandirian finansial dan akses jaringan profesional.': {
|
||||
id: 'Divisi ini mengembangkan unit usaha organisasi, merancang skema pendanaan kreatif, dan menjalin kemitraan strategis untuk mendukung keberlanjutan program HMIF. Unit kerjanya meliputi riset peluang usaha, penyusunan proposal kemitraan, dan pengelolaan sponsor untuk meningkatkan kemandirian finansial dan akses jaringan profesional.',
|
||||
en: 'This division develops organizational business units, designs creative funding schemes, and builds strategic partnerships to support HMIF program sustainability. Its work includes business opportunity research, partnership proposal development, and sponsor management to improve financial independence and professional network access.'
|
||||
},
|
||||
'Mengembangkan jiwa kewirausahaan, sekaligus membangun kolaborasi dan membuka peluang bersama berbagai mitra.': {
|
||||
id: 'Mengembangkan jiwa kewirausahaan, sekaligus membangun kolaborasi dan membuka peluang bersama berbagai mitra.',
|
||||
en: 'Developing an entrepreneurial mindset while building collaboration and opportunities with partners.'
|
||||
},
|
||||
'Kegiatan Unggulan': { id: 'Kegiatan Unggulan', en: 'Featured Activities' },
|
||||
'Kegiatan tahunan yang menjadi ikon Informatika UNTAN.': {
|
||||
id: 'Kegiatan tahunan yang menjadi ikon Informatika UNTAN.',
|
||||
en: 'Annual activities that have become icons of Informatics UNTAN.'
|
||||
},
|
||||
'Kompetisi Coding untuk mengasah skill coding mahasiswa Informatika.': {
|
||||
id: 'Kompetisi Coding untuk mengasah skill coding mahasiswa Informatika.',
|
||||
en: 'A coding competition to sharpen Informatics students coding skills.'
|
||||
},
|
||||
'Silaturahmi Keluarga Besar Informatika': {
|
||||
id: 'Silaturahmi Keluarga Besar Informatika',
|
||||
en: 'Informatics Family Gathering'
|
||||
},
|
||||
'Feb': { id: 'Feb', en: 'Feb' },
|
||||
'Jul': { id: 'Jul', en: 'Jul' },
|
||||
'Sep': { id: 'Sep', en: 'Sep' },
|
||||
'Kegiatan buka bersama seluruh keluarga Informatika Untan yang selalu diadakan setiap tahunnya.': {
|
||||
id: 'Kegiatan buka bersama seluruh keluarga Informatika Untan yang selalu diadakan setiap tahunnya.',
|
||||
en: 'An annual iftar gathering for the entire Informatics UNTAN family.'
|
||||
},
|
||||
'Program intensif GEMASTIK adalah kompetisi IT tahunan tingkat nasional yang mempertemukan mahasiswa se-Indonesia. Lomba ini fokus pada pemecahan masalah lewat teknologi, dengan cabang yang beragam seperti programming, cyber security, data mining, sampai pengembangan UI/UX.': {
|
||||
id: 'Program intensif GEMASTIK adalah kompetisi IT tahunan tingkat nasional yang mempertemukan mahasiswa se-Indonesia. Lomba ini fokus pada pemecahan masalah lewat teknologi, dengan cabang yang beragam seperti <em>programming</em>, <em>cyber security</em>, <em>data mining</em>, sampai pengembangan UI/UX.',
|
||||
en: 'GEMASTIK is an intensive annual national IT competition that brings together students from across Indonesia. It focuses on solving problems through technology, with categories ranging from <em>programming</em>, <em>cyber security</em>, and <em>data mining</em> to UI/UX development.'
|
||||
},
|
||||
'Okt': { id: 'Okt', en: 'Oct' },
|
||||
'Ultah Informatika': { id: 'Ultah Informatika', en: 'Informatics Anniversary' },
|
||||
'Perayaan ulang tahun Informatika UNTAN, momen kebersamaan dan kebanggaan seluruh keluarga besar Informatika.': {
|
||||
id: 'Perayaan ulang tahun Informatika UNTAN, momen kebersamaan dan kebanggaan seluruh keluarga besar Informatika.',
|
||||
en: 'The Informatics UNTAN anniversary celebration, a moment of togetherness and pride for the whole Informatics family.'
|
||||
},
|
||||
'Agu': { id: 'Agu', en: 'Aug' },
|
||||
'Program intensif pengembangan skill teknis mahasiswa Informatika bersama mentor profesional dari industri.': {
|
||||
id: 'Program intensif pengembangan skill teknis mahasiswa Informatika bersama mentor profesional dari industri.',
|
||||
en: 'An intensive program for developing Informatics students technical skills with professional mentors from industry.'
|
||||
},
|
||||
'STUDY CLUB': { id: 'STUDY CLUB', en: 'STUDY CLUB' },
|
||||
'Belajar logika dan algoritma bersama, di mana kalian bisa berkembang dan membuka peluang mengikuti kompetisi pemrograman di berbagai level.': {
|
||||
id: 'Belajar logika dan algoritma bersama, di mana kalian bisa berkembang dan membuka peluang mengikuti kompetisi pemrograman di berbagai level.',
|
||||
en: 'Learn logic and algorithms together, grow your abilities, and open opportunities to join programming competitions at various levels.'
|
||||
},
|
||||
'Gali potensi tersembunyi dari tumpukan data! Di sini kita akan bereksplorasi dengan algoritma Machine Learning, membedah teknik klasifikasi, hingga melatih model prediktif untuk menghasilkan insight yang bermakna.': {
|
||||
id: 'Gali potensi tersembunyi dari tumpukan data! Di sini kita akan bereksplorasi dengan algoritma <em>Machine Learning</em>, membedah teknik klasifikasi, hingga melatih model prediktif untuk menghasilkan <em>insight</em> yang bermakna.',
|
||||
en: 'Explore hidden potential in piles of data! Here we experiment with <em>Machine Learning</em> algorithms, examine classification techniques, and train predictive models to produce meaningful <em>insights</em>.'
|
||||
},
|
||||
'Wujudkan idemu jadi produk digital yang nyata! Kita akan ngoding bareng dari merancang frontend yang interaktif, membangun backend yang tangguh, serta mengintegrasikan berbagai API untuk menciptakan aplikasi web masa kini.': {
|
||||
id: 'Wujudkan idemu jadi produk digital yang nyata! Kita akan ngoding bareng dari merancang <em>frontend</em> yang interaktif, membangun <em>backend</em> yang tangguh, serta mengintegrasikan berbagai API untuk menciptakan aplikasi web masa kini.',
|
||||
en: 'Turn your ideas into real digital products! We will code together, from designing interactive <em>frontends</em> and building robust <em>backends</em> to integrating APIs for modern web applications.'
|
||||
},
|
||||
'Di sini, kalian bisa belajar membuat website dan aplikasi web, sekaligus mengembangkan ide menjadi sesuatu yang nyata.': {
|
||||
id: 'Di sini, kalian bisa belajar membuat website dan aplikasi web, sekaligus mengembangkan ide menjadi sesuatu yang nyata.',
|
||||
en: 'Here, you can learn to build websites and web applications while turning ideas into something real.'
|
||||
},
|
||||
'Belajar memahami sistem dan cara menjaganya, supaya lebih siap menghadapi berbagai ancaman digital.': {
|
||||
id: 'Belajar memahami sistem dan cara menjaganya, supaya lebih siap menghadapi berbagai ancaman digital.',
|
||||
en: 'Learn to understand systems and how to protect them, so you are better prepared for digital threats.'
|
||||
},
|
||||
'Galeri Keseruan': { id: 'Galeri Keseruan', en: 'Activity Gallery' },
|
||||
'Ada yang Ingin Ditanyakan Seputar HMIF?': {
|
||||
id: 'Ada yang Ingin Ditanyakan Seputar HMIF?',
|
||||
en: 'Have Questions About HMIF?'
|
||||
},
|
||||
'Bergabunglah dengan HMIF untuk memperluas jaringan, mengasah skill, dan menciptakan dampak nyata.': {
|
||||
id: 'Bergabunglah dengan HMIF untuk memperluas jaringan, mengasah skill, dan menciptakan dampak nyata.',
|
||||
en: 'Join HMIF to expand your network, sharpen your skills, and create real impact.'
|
||||
},
|
||||
'Hubungi Kami': { id: 'Hubungi Kami', en: 'Contact Us' },
|
||||
'Sekretariat': { id: 'Sekretariat', en: 'Secretariat' },
|
||||
'Gedung Fakultas Teknik Lt. 2 Jl. Prof. Dr. H. Hadari Nawawi': {
|
||||
id: 'Gedung Fakultas Teknik Lt. 2<br>Jl. Prof. Dr. H. Hadari Nawawi',
|
||||
en: 'Faculty of Engineering Building, 2nd Floor<br>Jl. Prof. Dr. H. Hadari Nawawi'
|
||||
},
|
||||
'Jam Operasional': { id: 'Jam Operasional', en: 'Operating Hours' },
|
||||
'Senin - Jumat 08:00 - 17:00 WIB': {
|
||||
id: 'Senin - Jumat<br>08:00 - 17:00 WIB',
|
||||
en: 'Monday - Friday<br>08:00 - 17:00 WIB'
|
||||
},
|
||||
'Media Sosial': { id: 'Media Sosial', en: 'Social Media' },
|
||||
'Jl. Prof. Dr. H. Hadari Nawawi, Bansir Laut, Kec. Pontianak Tenggara,': {
|
||||
id: 'Jl. Prof. Dr. H. Hadari Nawawi, Bansir Laut, Kec. Pontianak Tenggara,',
|
||||
en: 'Prof. Dr. H. Hadari Nawawi St., Bansir Laut, Southeast Pontianak District,'
|
||||
},
|
||||
'Kota Pontianak, Kalimantan Barat 78124': {
|
||||
id: 'Kota Pontianak, Kalimantan Barat 78124',
|
||||
en: 'Pontianak City, West Kalimantan 78124'
|
||||
},
|
||||
'FOLLOW US': { id: 'IKUTI KAMI', en: 'FOLLOW US' }
|
||||
};
|
||||
|
||||
// Normalisasi whitespace untuk pencocokan teks yang konsisten
|
||||
function normalizeText(value) {
|
||||
return value.replace(/\s+/g, ' ').trim();
|
||||
}
|
||||
|
||||
function stripHtmlTags(value) {
|
||||
var template = document.createElement('template');
|
||||
template.innerHTML = value;
|
||||
return template.content.textContent || '';
|
||||
}
|
||||
|
||||
// Ambil teks murni dari elemen, termasuk teks dalam child nodes
|
||||
function getElementText(element) {
|
||||
function collectText(node) {
|
||||
if (node.nodeType === Node.TEXT_NODE) return node.nodeValue;
|
||||
if (node.nodeName === 'BR') return ' ';
|
||||
return Array.prototype.map.call(node.childNodes, collectText).join('');
|
||||
}
|
||||
return normalizeText(collectText(element));
|
||||
}
|
||||
|
||||
// Buat lookup map dari teks yang sudah dinormalisasi ke key translationMap
|
||||
var translationLookup = Object.keys(translationMap).reduce(function (lookup, key) {
|
||||
lookup[normalizeText(key)] = key;
|
||||
lookup[normalizeText(translationMap[key].id)] = key;
|
||||
lookup[normalizeText(stripHtmlTags(translationMap[key].id))] = key;
|
||||
return lookup;
|
||||
}, {});
|
||||
|
||||
// Tandai semua elemen yang bisa diterjemahkan dengan data attribute
|
||||
function markTranslatableElements() {
|
||||
document.querySelectorAll('a, button, h1, h2, h3, p, span').forEach(function (element) {
|
||||
var key = translationLookup[getElementText(element)];
|
||||
if (key) element.dataset.i18nKey = key;
|
||||
});
|
||||
}
|
||||
|
||||
// Render teks terjemahan — gunakan innerHTML jika ada tag HTML, textContent jika tidak
|
||||
function renderTranslatedText(element, value) {
|
||||
if (value.indexOf('<') !== -1) {
|
||||
element.innerHTML = value;
|
||||
} else {
|
||||
element.textContent = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Update tampilan tombol toggle sesuai bahasa aktif
|
||||
function updateLanguageToggle(language) {
|
||||
languageToggles.forEach(function (toggle) {
|
||||
toggle.innerHTML = language === 'id'
|
||||
? '<span class="text-hmif-secondary">ID</span> | <span>EN</span>'
|
||||
: '<span>ID</span> | <span class="text-hmif-secondary">EN</span>';
|
||||
toggle.setAttribute('aria-pressed', String(language === 'en'));
|
||||
toggle.setAttribute('aria-label', language === 'id'
|
||||
? 'Ganti bahasa ke Inggris'
|
||||
: 'Switch language to Indonesian');
|
||||
});
|
||||
}
|
||||
|
||||
// Terapkan bahasa ke seluruh elemen yang sudah ditandai
|
||||
function applyLanguage(language) {
|
||||
var safeLanguage = language === 'en' ? 'en' : 'id';
|
||||
|
||||
document.documentElement.lang = safeLanguage;
|
||||
document.title = translationMap['Kehidupan Mahasiswa & Himpunan (HMIF)'][safeLanguage];
|
||||
|
||||
document.querySelectorAll('[data-i18n-key]').forEach(function (element) {
|
||||
var key = element.dataset.i18nKey;
|
||||
renderTranslatedText(element, translationMap[key][safeLanguage]);
|
||||
});
|
||||
|
||||
updateLanguageToggle(safeLanguage);
|
||||
|
||||
try {
|
||||
localStorage.setItem('hmif-language', safeLanguage);
|
||||
} catch (error) {
|
||||
// Browser mungkin memblokir localStorage di mode private/incognito.
|
||||
}
|
||||
}
|
||||
|
||||
// Inisialisasi: tandai elemen, muat preferensi bahasa, pasang event listener
|
||||
markTranslatableElements();
|
||||
|
||||
var savedLanguage = 'id';
|
||||
try {
|
||||
savedLanguage = localStorage.getItem('hmif-language') || 'id';
|
||||
} catch (error) {
|
||||
savedLanguage = 'id';
|
||||
}
|
||||
|
||||
applyLanguage(savedLanguage);
|
||||
|
||||
languageToggles.forEach(function (toggle) {
|
||||
toggle.addEventListener('click', function () {
|
||||
applyLanguage(document.documentElement.lang === 'en' ? 'id' : 'en');
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// 3. GALERI KESERUAN — SLIDER
|
||||
// Slider bento grid foto keseruan dengan auto-slide, navigasi manual,
|
||||
// dot indicator, pause on hover, dan recalculate on resize.
|
||||
// =============================================================================
|
||||
|
||||
(function () {
|
||||
var AUTO_DELAY_MS = 4000; // 4 detik per slide
|
||||
var GAP_PX = 16 * 2; // grid gap-4 = 1rem? but original used gap-4; keep reasonable spacing if needed
|
||||
|
||||
var track = document.getElementById('galeri-track');
|
||||
var viewport = document.getElementById('galeri-viewport');
|
||||
var prevBtn = document.getElementById('galeri-prev');
|
||||
var nextBtn = document.getElementById('galeri-next');
|
||||
var dotsContainer = document.getElementById('galeri-dots');
|
||||
|
||||
if (!track || !viewport || !prevBtn || !nextBtn) return;
|
||||
|
||||
var currentSlide = 0;
|
||||
var autoSlideTimer;
|
||||
var originalHTML = track.innerHTML;
|
||||
|
||||
// collect all anchor elements (images) in the original order
|
||||
var originalAnchors = Array.from((function () {
|
||||
var tmp = document.createElement('div'); tmp.innerHTML = originalHTML; return tmp;
|
||||
})().querySelectorAll('a'));
|
||||
|
||||
// builds slides where each slide contains a single image (for small screens)
|
||||
function buildSingleImageSlides() {
|
||||
var slides = originalAnchors.map(function (a) {
|
||||
// clone anchor and remove mobile-hidden class so it becomes visible in single-image slides
|
||||
try {
|
||||
var clone = a.cloneNode(true);
|
||||
if (clone.classList) clone.classList.remove('hidden');
|
||||
// also remove inline style display:none if present
|
||||
if (clone.style) clone.style.display = '';
|
||||
return '<div class="flex-shrink-0 w-full">' +
|
||||
'<div class="aspect-video w-full overflow-hidden rounded-xl">' +
|
||||
clone.outerHTML +
|
||||
'</div></div>';
|
||||
} catch (e) {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
return slides.join('');
|
||||
}
|
||||
|
||||
function getTotalSlides() {
|
||||
return track.children.length;
|
||||
}
|
||||
|
||||
// render dot buttons dynamically according to total slides
|
||||
function renderDots(n) {
|
||||
if (!dotsContainer) return;
|
||||
dotsContainer.innerHTML = '';
|
||||
for (var i = 0; i < n; i++) {
|
||||
var btn = document.createElement('button');
|
||||
btn.className = 'galeri-dot h-2.5 rounded-full transition-all duration-300 ' + (i === 0 ? 'bg-hmif-primary w-6' : 'bg-gray-200 w-2.5');
|
||||
btn.setAttribute('data-index', String(i));
|
||||
btn.setAttribute('aria-label', 'Slide ' + (i+1));
|
||||
(function (idx) { btn.addEventListener('click', function () { goToSlide(idx); startAutoSlide(); }); })(i);
|
||||
dotsContainer.appendChild(btn);
|
||||
}
|
||||
}
|
||||
|
||||
function updateDots(activeIndex) {
|
||||
if (!dotsContainer) return;
|
||||
var dots = dotsContainer.querySelectorAll('button');
|
||||
dots.forEach(function (dot, i) {
|
||||
if (i === activeIndex) {
|
||||
dot.classList.remove('bg-gray-200', 'w-2.5');
|
||||
dot.classList.add('bg-hmif-primary', 'w-6');
|
||||
} else {
|
||||
dot.classList.remove('bg-hmif-primary', 'w-6');
|
||||
dot.classList.add('bg-gray-200', 'w-2.5');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function rebuildTrackForViewport() {
|
||||
var isMobile = window.innerWidth < 768; // md breakpoint
|
||||
if (isMobile) {
|
||||
track.innerHTML = buildSingleImageSlides();
|
||||
} else {
|
||||
track.innerHTML = originalHTML;
|
||||
}
|
||||
renderDots(getTotalSlides());
|
||||
}
|
||||
|
||||
// Pindah ke slide dengan index tertentu, loop otomatis di kedua arah
|
||||
function goToSlide(index) {
|
||||
var total = getTotalSlides();
|
||||
if (total === 0) return;
|
||||
currentSlide = ((index % total) + total) % total;
|
||||
track.style.transform = 'translateX(-' + (currentSlide * viewport.offsetWidth) + 'px)';
|
||||
updateDots(currentSlide);
|
||||
}
|
||||
|
||||
// Mulai atau restart timer auto-slide
|
||||
function startAutoSlide() {
|
||||
clearInterval(autoSlideTimer);
|
||||
autoSlideTimer = setInterval(function () { goToSlide(currentSlide + 1); }, AUTO_DELAY_MS);
|
||||
}
|
||||
|
||||
prevBtn.addEventListener('click', function () { goToSlide(currentSlide - 1); startAutoSlide(); });
|
||||
nextBtn.addEventListener('click', function () { goToSlide(currentSlide + 1); startAutoSlide(); });
|
||||
|
||||
// Pause saat kursor di atas galeri
|
||||
viewport.addEventListener('mouseenter', function () { clearInterval(autoSlideTimer); });
|
||||
viewport.addEventListener('mouseleave', startAutoSlide);
|
||||
|
||||
// Recalculate posisi slide saat browser di-resize
|
||||
window.addEventListener('resize', function () { rebuildTrackForViewport(); goToSlide(currentSlide); });
|
||||
|
||||
// initial build
|
||||
rebuildTrackForViewport();
|
||||
goToSlide(0);
|
||||
startAutoSlide();
|
||||
})();
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// 4. KEGIATAN UNGGULAN — SLIDER
|
||||
// Slider kartu kegiatan tahunan yang menampilkan 2 kartu sekaligus pada desktop,
|
||||
// dan 1 kartu pada layar sempit. Logika pergantian disesuaikan agar pergeseran
|
||||
// selalu berpindah tepat satu item, memperhitungkan gap antar-kartu.
|
||||
// =============================================================================
|
||||
|
||||
(function () {
|
||||
var TOTAL_CARDS = 6;
|
||||
var AUTO_DELAY_MS = 2000;
|
||||
var GAP_PX = 32; // gap-8 = 2rem = 32px (tailwind)
|
||||
|
||||
var track = document.getElementById('slider-track');
|
||||
var viewport = document.getElementById('slider-viewport');
|
||||
var prevBtn = document.getElementById('slider-prev');
|
||||
var nextBtn = document.getElementById('slider-next');
|
||||
var dotsContainer = document.getElementById('slider-dots');
|
||||
|
||||
if (!track || !viewport || !prevBtn || !nextBtn) return;
|
||||
|
||||
var current = 0;
|
||||
var autoTimer;
|
||||
|
||||
function getCardsVisible() {
|
||||
return window.innerWidth >= 768 ? 2 : 1; // md breakpoint
|
||||
}
|
||||
|
||||
// lebar kartu yang terlihat (tidak termasuk gap)
|
||||
function getCardWidth() {
|
||||
var visible = getCardsVisible();
|
||||
if (visible === 1) return viewport.offsetWidth;
|
||||
return (viewport.offsetWidth - GAP_PX) / visible;
|
||||
}
|
||||
|
||||
function getMaxIndex() {
|
||||
return Math.max(0, TOTAL_CARDS - getCardsVisible());
|
||||
}
|
||||
|
||||
// Pindah ke posisi slide tertentu; perhitungan berbeda untuk 1 atau 2 kartu
|
||||
function goTo(index) {
|
||||
var maxIndex = getMaxIndex();
|
||||
current = ((index % (maxIndex + 1)) + (maxIndex + 1)) % (maxIndex + 1);
|
||||
|
||||
if (getCardsVisible() === 1) {
|
||||
// langkah pergeseran = viewport width + gap
|
||||
var step = viewport.offsetWidth + GAP_PX;
|
||||
track.style.transform = 'translateX(-' + (current * step) + 'px)';
|
||||
} else {
|
||||
var cardW = getCardWidth();
|
||||
track.style.transform = 'translateX(-' + (current * (cardW + GAP_PX)) + 'px)';
|
||||
}
|
||||
|
||||
updateDots(current);
|
||||
}
|
||||
|
||||
// Render dot indicators dynamically based on total slides
|
||||
function renderSliderDots(n) {
|
||||
if (!dotsContainer) return;
|
||||
dotsContainer.innerHTML = '';
|
||||
for (var i = 0; i < n; i++) {
|
||||
var btn = document.createElement('button');
|
||||
btn.className = 'slider-dot h-2.5 rounded-full transition-all duration-300 ' + (i === 0 ? 'bg-hmif-primary w-6' : 'bg-gray-200 w-2.5');
|
||||
btn.setAttribute('data-index', String(i));
|
||||
btn.setAttribute('aria-label', 'Slide ' + (i+1));
|
||||
(function (idx) { btn.addEventListener('click', function () { goTo(idx); startAuto(); }); })(i);
|
||||
dotsContainer.appendChild(btn);
|
||||
}
|
||||
}
|
||||
|
||||
function updateDots(activeIndex) {
|
||||
if (!dotsContainer) return;
|
||||
var dots = dotsContainer.querySelectorAll('button');
|
||||
dots.forEach(function (dot, i) {
|
||||
if (i === activeIndex) {
|
||||
dot.classList.remove('bg-gray-200', 'w-2.5');
|
||||
dot.classList.add('bg-hmif-primary', 'w-6');
|
||||
} else {
|
||||
dot.classList.remove('bg-hmif-primary', 'w-6');
|
||||
dot.classList.add('bg-gray-200', 'w-2.5');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Mulai atau restart timer auto-slide
|
||||
function startAuto() {
|
||||
clearInterval(autoTimer);
|
||||
autoTimer = setInterval(function () { goTo(current + 1); }, AUTO_DELAY_MS);
|
||||
}
|
||||
|
||||
prevBtn.addEventListener('click', function () { goTo(current - 1); startAuto(); });
|
||||
nextBtn.addEventListener('click', function () { goTo(current + 1); startAuto(); });
|
||||
|
||||
// initial render of dots according to current viewport
|
||||
renderSliderDots(getMaxIndex() + 1);
|
||||
|
||||
// Pause saat kursor di atas slider
|
||||
viewport.addEventListener('mouseenter', function () { clearInterval(autoTimer); });
|
||||
viewport.addEventListener('mouseleave', startAuto);
|
||||
|
||||
// Recalculate posisi slide and dots saat browser di-resize
|
||||
window.addEventListener('resize', function () { renderSliderDots(getMaxIndex() + 1); goTo(current); });
|
||||
|
||||
goTo(0);
|
||||
startAuto();
|
||||
})();
|
||||
+1001
-1289
File diff suppressed because it is too large
Load Diff
+6
-48
@@ -1,48 +1,6 @@
|
||||
:root {
|
||||
--brand-navy: #003150;
|
||||
--brand-yellow: #feb401;
|
||||
--text-main: #1e293b;
|
||||
--text-soft: #64748b;
|
||||
--bg-soft: #f8fafc;
|
||||
--line: #e2e8f0;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
html, body { margin: 0; padding: 0; }
|
||||
body { font-family: "Roboto", Arial, sans-serif; color: var(--text-main); background: #fff; line-height: 1.6; }
|
||||
.container { width: min(1100px, 92%); margin-inline: auto; }
|
||||
|
||||
.nav { background: var(--brand-navy); color: #fff; border-bottom: 4px solid var(--brand-yellow); padding: 14px 0; }
|
||||
.brand { font-size: 1.1rem; font-weight: 700; letter-spacing: .02em; }
|
||||
|
||||
.hero { position: relative; color: #fff; min-height: 220px; display: flex; align-items: flex-end; overflow: hidden; }
|
||||
.hero-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: brightness(0.45); }
|
||||
.hero-inner { position: relative; z-index: 1; padding: 36px 0; }
|
||||
.badge { display: inline-block; background: var(--brand-yellow); color: #111827; font-size: .68rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; padding: .2rem .45rem; margin-bottom: 12px; }
|
||||
.hero h1 { margin: 0; font-size: clamp(1.6rem, 3.2vw, 2.8rem); line-height: 1.2; }
|
||||
|
||||
.layout { display: grid; grid-template-columns: 1fr; gap: 2rem; padding: 2rem 0 4rem; }
|
||||
@media (min-width: 1024px) { .layout { grid-template-columns: minmax(0, 3fr) minmax(260px, 1fr); } }
|
||||
|
||||
.meta { font-size: .78rem; text-transform: uppercase; color: #475569; display: flex; flex-wrap: wrap; gap: .75rem 1rem; margin-bottom: 1rem; }
|
||||
.cover { background: var(--bg-soft); border: 1px solid var(--line); margin-bottom: 1.5rem; }
|
||||
.cover img { width: 100%; height: auto; display: block; }
|
||||
|
||||
.article-body > * + * { margin-top: 1.1em; }
|
||||
.article-body h2 { font-size: 1.35rem; margin: 1.6em 0 .5em; }
|
||||
.article-body h3 { font-size: 1.1rem; margin: 1.4em 0 .4em; }
|
||||
.article-body p { margin: 0 0 1em; }
|
||||
.article-body ul, .article-body ol { padding-left: 1.4rem; }
|
||||
.article-body blockquote { border-left: 4px solid #005eb8; background: #eef6ff; padding: .8rem 1rem; color: #334155; }
|
||||
.article-body a { color: #005eb8; }
|
||||
.article-body img { max-width: 100%; border-radius: 8px; }
|
||||
.article-body code { background: #f1f5f9; padding: .1em .35em; border-radius: 4px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
|
||||
|
||||
.note { border: 1px solid var(--line); background: var(--bg-soft); padding: 1rem; }
|
||||
.note h3 { margin: 0 0 .5rem; font-size: .76rem; text-transform: uppercase; letter-spacing: .12em; color: #475569; }
|
||||
|
||||
.footer { margin-top: 2rem; background: var(--brand-navy); color: #fff; border-top: 4px solid var(--brand-yellow); }
|
||||
.footer-inner { display: flex; align-items: center; justify-content: center; gap: .75rem; padding: 1rem 0; }
|
||||
.footer-logo { height: 28px; width: auto; }
|
||||
.footer-ornament { width: 100%; display: block; opacity: .9; }
|
||||
|
||||
/*
|
||||
* LimaEm — Group 07 | Kehidupan Mahasiswa & Himpunan (HMIF)
|
||||
*
|
||||
* CSS utama ada di: assets/css/output.css (Tailwind custom build)
|
||||
* File ini tersedia untuk CSS tambahan jika diperlukan.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user