PageSourceSearch

https://trxresidences.my/

html trxresidences.my collected 2026-10-06 18:04:10 UTC 20,332 bytes, 473 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3
4<head>
5  <meta charset="UTF-8">
6  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7  <title></title>
8  <link rel="icon" type="image/png" href="./assets/svg/favicon.png">
9
10  <!-- Google Tag Manager -->
11  
11<script>
vendor: 335 bytes, lines 11-15
11(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
12  new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
13  j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
14  'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
15  })(window,document,'script','dataLayer','
15GTM-MQV3P4H
vendor: 3 bytes, line 15
15');
15</script>
15
16  <!-- End Google Tag Manager -->
17
18  <!-- Fonts (loaded via @font-face in variables.css) -->
19
20  <!-- GSAP -->
21  
21<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
21
22  
22<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/SplitText.min.js"></script>
22
23
24  <!-- intl-tel-input -->
25  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/build/css/intlTelInput.css">
26
27  <!-- Styles -->
28  <link rel="stylesheet" href="./css/reset.css">
29  <link rel="stylesheet" href="./css/variables.css">
30  <link rel="stylesheet" href="./css/layout.css">
31  <link rel="stylesheet" href="./css/modal.css">
32  <link rel="stylesheet" href="./css/intl-tel-input.css">
33  <link rel="stylesheet" href="./css/animations.css">
34</head>
35
36<body>
37
38  <!-- Google Tag Manager (noscript) -->
vendor: 70 bytes, lines 38-39
38
39  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
39GTM-MQV3P4H
vendor: 89 bytes, lines 39-41
39"
40    height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
41  
41<!-- End Google Tag Manager (noscript) -->
42
43  <!-- ── Page ─────────────────────────────────────────────────────────── -->
44  <main class="page">
45
46    <!-- Hero -->
47    <section class="hero" data-animate="hero">
48      <div class="hero__overlay"></div>
49    </section>
50
51    <!-- UI Layer -->
52    <div class="ui">
53
54      <!-- Logo -->
55      <div class="logo" data-animate="logo">
56        <img class="logo__img" alt="">
57        <a class="logo__phase-btn" href="#" target="_blank" rel="noopener noreferrer"></a>
58      </div>
59
60      <!-- Content (centered) -->
61      <div class="content">
62
63        <!-- Headline -->
64        <div class="headline">
65          <span class="headline__line headline__line--left" id="headline-1" data-animate="headline-1"></span>
66          <span class="headline__line headline__line--right" id="headline-2" data-animate="headline-2"></span>
67        </div>
68
69        <div class="bottom-group">
70          <!-- Bottom Bar -->
71          <div class="bottom-bar">
72            <span class="bottom-bar__line"></span>
73            <div class="bottom-bar__feature">
74              <span class="bottom-bar__label" id="bar-label"></span>
75              <div class="bottom-bar__text">
76                <div class="bottom-bar__text-title" id="bar-feature-title"></div>
77                <p class="bottom-bar__text-body" id="bar-feature-body"></p>
78              </div>
79            </div>
80            <button class="bottom-bar__cta" id="cta-btn" data-modal-open>
81              <span id="cta-text"></span>
82            </button>
83          </div>
84
85        </div>
86
87      </div><!-- /content -->
88
89      <!-- Footer -->
90      <footer class="footer">
91        <div class="footer__main">
92
93          <!-- Brand + JV logos -->
94          <div class="footer__brand">
95            <img class="footer__brand-logo" src="./assets/svg/footer-logo.svg"
96              alt="A joint venture between TRX Tun Razak Exchange and Lendlease">
97          </div>
98
99          <!-- Links + Social -->
100          <div class="footer__right">
101            <div class="footer__links" id="footer-links">
102              <!-- Injected by content.js -->
103            </div>
104            <div class="footer__social" id="footer-social">
105              <!-- Injected by content.js -->
106            </div>
107          </div>
108
109        </div>
110      </footer>
111
112    </div><!-- /ui -->
113
114  </main>
115
116  <!-- ── Splash ──────────────────────────────────────────────────────── -->
117  <div class="splash" id="splash">
118    <img class="splash__logo" alt="">
119  </div>
120
121  <!-- ── Backdrop ──────────────────────────────────────────────────────── -->
122  <div class="backdrop" id="backdrop"></div>
123
124  <!-- ── Modal ─────────────────────────────────────────────────────────── -->
125  <aside class="modal" id="modal" role="dialog" aria-modal="true" aria-label="">
126    <div class="modal__container">
127
128      <div class="modal__buttons">
129        <!-- Back (shown on policy view) -->
130        <button class="modal__back" id="policy-back" aria-label="Back" type="button" style="display:none;">
131          <svg viewBox="0 0 24 24">
132            <polyline points="15 18 9 12 15 6" />
133          </svg>
134        </button>
135
136        <!-- Close -->
137        <button class="modal__close" id="modal-close" aria-label="Close">
138          <svg viewBox="0 0 24 24" fill="none">
139            <line x1="18" y1="6" x2="6" y2="18" />
140            <line x1="6" y1="6" x2="18" y2="18" />
141          </svg>
142        </button>
143      </div>
144
145
146      <div class="modal__inner">
147
148        <!-- Form content -->
149        <div id="form-content" data-animate="form-content">
150          <form class="form" id="registration-form" action="https://submit-form.com/pVGPCTieH" method="POST" novalidate>
151            
152
153            <!-- Salutation + Full Name row -->
154            <div class="field-row">
155
156              <!-- Salutation -->
157              <div class="field field--salutation" data-field="salutation">
158                <select class="field__input field__input--select" name="salutation" id="salutation" required>
159                  <option value="" disabled selected><!-- Placeholder injected by content.js --></option>
160                  <!-- Options injected by content.js -->
161                </select>
162                <span class="field__error" role="alert"></span>
163              </div>
164
165              <!-- Full Name -->
166              <div class="field field--name" data-field="fullName">
167                <input class="field__input" type="text" name="fullName" id="fullName" placeholder=" " autocomplete="name"
168                  required>
169                <label class="field__label" for="fullName"></label>
170                <span class="field__error" role="alert"></span>
171              </div>
172
173            </div>
174
175            <!-- Email -->
176            <div class="field" data-field="email">
177              <input class="field__input" type="email" name="email" id="email" placeholder=" " autocomplete="email"
178                required>
179              <label class="field__label" for="email"></label>
180              <span class="field__error" role="alert"></span>
181            </div>
182
183            <!-- Phone -->
184            <div class="field" data-field="phone">
185              <input class="field__input" type="tel" name="phone" id="phone" placeholder=" " autocomplete="tel"
186                required>
187              <label class="field__label" for="phone"></label>
188              <span class="field__error" role="alert"></span>
189            </div>
190
191            <!-- Nationality -->
192            <div class="field" data-field="nationality">
193              <input type="hidden" name="nationality" id="nationality" value="">
194              <div class="dropdown" id="dropdown-nationality">
195                <button class="dropdown__trigger" type="button" aria-haspopup="listbox" aria-expanded="false">
196                  <span class="dropdown__value" id="nationality-value"></span>
197                  <span class="dropdown__chevron">
198                    <img src="./assets/svg/chevron.svg" alt="">
199                  </span>
200                </button>
201                <div class="dropdown__menu" id="nationality-menu">
202                  <input type="text" class="dropdown__search" id="nationality-search" placeholder="Search..." autocomplete="off">
203                  <ul class="dropdown__list" id="nationality-list" role="listbox">
204                    <!-- Options injected by content.js -->
205                  </ul>
206                </div>
207              </div>
208              <span class="field__error" role="alert"></span>
209            </div>
210
211            <!-- Unit Type -->
212            <div class="field" data-field="unitType">
213              <input type="hidden" name="unitType" id="unitType" value="">
214              <div class="dropdown" id="dropdown-unitType">
215                <button class="dropdown__trigger" type="button" aria-haspopup="listbox" aria-expanded="false">
216                  <span class="dropdown__value" id="dropdown-value"></span>
217                  <span class="dropdown__chevron">
218                    <img src="./assets/svg/chevron.svg" alt="">
219                  </span>
220                </button>
221                <ul class="dropdown__menu" id="dropdown-menu" role="listbox">
222                  <!-- Options injected by content.js -->
223                </ul>
224              </div>
225              <span class="field__error" role="alert"></span>
226            </div>
227
228            <!-- Checkboxes -->
229            <div class="form__checkboxes">
230              <label class="checkbox" data-field="agreePrivacy">
231                <input class="checkbox__input" type="checkbox" name="agreePrivacy" id="agreePrivacy" required>
232                <span class="checkbox__box"></span>
233                <span class="checkbox__label" id="checkbox-privacy-label"></span>
234              </label>
235
236              <label class="checkbox" data-field="agreeDisclaimer">
237                <input class="checkbox__input" type="checkbox" name="agreeDisclaimer" id="agreeDisclaimer" required>
238                <span class="checkbox__box"></span>
239                <span class="checkbox__label" id="checkbox-disclaimer-label"></span>
240              </label>
241            </div>
242
243            <!-- Submit + Disclaimer -->
244            <div class="form__footer">
245
246              <!-- API error -->
247              <div class="form__api-error" id="form-api-error" role="alert"></div>
248              <button class="form__submit" id="form-submit" type="submit">
249                <span class="btn-text" id="submit-text"></span>
250              </button>
251            </div>
252
253          </form>
254        </div><!-- /form-content -->
255
256        <!-- Success message -->
257        <div class="success-message" id="success-message" data-animate="success-content">
258          <h2 class="success-message__header" id="success-header"></h2>
259          <p class="success-message__text" id="success-text"></p>
260        </div>
261
262        <!-- Error message -->
263        <div class="success-message" id="error-message" data-animate="error-content">
264          <h2 class="success-message__header" id="error-header"></h2>
265          <p class="success-message__text" id="error-text"></p>
266        </div>
267
268        <!-- Policy view (replaces form content) -->
269        <div class="modal__policy" id="policy-view">
270          <div class="modal__policy-header">
271            <h2 class="modal__policy-title" id="policy-title"></h2>
272          </div>
273          <hr class="modal__policy-divider">
274          <div class="modal__policy-body" id="policy-body"></div>
275        </div>
276
277      </div><!-- /modal__inner -->
278
279    </div>
280  </aside>
281
282  <!-- ── Scripts ───────────────────────────────────────────────────────── -->
283  
283<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/js/intlTelInput.min.js"></script>
283
284  
284<script src="https://unpkg.com/@botpoison/browser" async></script>
284
285  
285<script src="./js/content.js"></script>
285
286  
286<script src="./js/animations.js"></script>
286
287  
287<script src="./js/modal.js"></script>
287
288  
288<script src="./js/form.js"></script>
288
289
290  
290<script>
291    // ── Inject content ────────────────────────────────────
292
293    // Page title
294    document.title = CONTENT.pageTitle;
295
296    // Logo + splash
297    document.querySelector('.logo__img').src = CONTENT.logoSrc;
298    document.querySelector('.logo__img').alt = CONTENT.logoAlt;
299    document.querySelector('.splash__logo').src = CONTENT.logoSrc;
300    document.querySelector('.splash__logo').alt = CONTENT.logoAlt;
301    document.querySelector('.logo__phase-btn').textContent = CONTENT.phaseTag;
302
303    // Headline
304    document.getElementById('headline-1').textContent = CONTENT.headlineLine1;
305    document.getElementById('headline-2').textContent = CONTENT.headlineLine2;
306
307    // Bottom bar
308    document.getElementById('bar-label').textContent = CONTENT.whatToExpectLabel;
309    const feature = CONTENT.features[0];
310    document.getElementById('bar-feature-title').textContent = feature.number + '\u2003' + feature.title;
311    document.getElementById('bar-feature-body').textContent = feature.body;
312    document.getElementById('cta-text').textContent = CONTENT.ctaButton;
313
314    // Salutation options
315    const salutationSelect = document.getElementById('salutation');
316    salutationSelect.options[0].textContent = CONTENT.formFields.salutation;
317    CONTENT.salutations.forEach(s => {
318      const opt = document.createElement('option');
319      opt.value = s;
320      opt.textContent = s;
321      salutationSelect.appendChild(opt);
322    });
323
324    // Form field labels
325    document.querySelector('label[for="fullName"]').textContent = CONTENT.formFields.fullName;
326    document.querySelector('label[for="email"]').textContent = CONTENT.formFields.email;
327    document.querySelector('label[for="phone"]').textContent = CONTENT.formFields.phone;
328    // Nationality placeholder set by dropdown injection below
329
330    // Modal aria-label
331    document.getElementById('modal').setAttribute('aria-label', CONTENT.ctaButton);
332
333    // Submit + success
334    document.getElementById('submit-text').textContent = CONTENT.submitButton;
335    document.getElementById('success-header').textContent = CONTENT.successHeader;
336    document.getElementById('success-text').textContent = CONTENT.successMessage;
337    document.getElementById('error-header').textContent = CONTENT.errorHeader;
338    document.getElementById('error-text').textContent = CONTENT.errorMessage;
339
340    // Checkbox consent
341    document.getElementById('checkbox-privacy-label').innerHTML =
342      CONTENT.checkboxPrivacy.en + '<br><em>' + CONTENT.checkboxPrivacy.ms + '</em>';
343    document.getElementById('checkbox-disclaimer-label').innerHTML =
344      CONTENT.checkboxDisclaimer.en + '<br><em>' + CONTENT.checkboxDisclaimer.ms + '</em>';
345
346    // Dropdown options
347    const dropdownMenu = document.getElementById('dropdown-menu');
348    const dropdownValue = document.getElementById('dropdown-value');
349    dropdownValue.textContent = CONTENT.formFields.unitType;
350    dropdownValue.classList.add('is-placeholder');
351    CONTENT.unitTypes.forEach(type => {
352      const li = document.createElement('li');
353      li.className = 'dropdown__item';
354      li.dataset.value = type;
355      li.textContent = type;
356      li.setAttribute('role', 'option');
357      dropdownMenu.appendChild(li);
358    });
359
360    // Nationality dropdown options
361    const nationalityList = document.getElementById('nationality-list');
362    const nationalityValue = document.getElementById('nationality-value');
363    nationalityValue.textContent = CONTENT.formFields.nationality;
364    nationalityValue.classList.add('is-placeholder');
365    document.getElementById('nationality-search').placeholder = 'Search ' + CONTENT.formFields.nationality.toLowerCase() + '...';
366    CONTENT.nationalities.forEach(name => {
367      const li = document.createElement('li');
368      li.className = 'dropdown__item';
369      li.dataset.value = name;
370      li.textContent = name;
371      li.setAttribute('role', 'option');
372      nationalityList.appendChild(li);
373    });
374
375    // ── Policy View (inside modal) ──────────────────────────────────────────
376    (() => {
377      const formContent = document.getElementById('form-content');
378      const policyView = document.getElementById('policy-view');
379      const policyTitle = document.getElementById('policy-title');
380      const policyBody = document.getElementById('policy-body');
381      const backBtn = document.getElementById('policy-back');
382
383      function showPolicy(title, paragraphs) {
384        return (e) => {
385          e.preventDefault();
386          e.stopPropagation();
387          policyTitle.textContent = title;
388          policyBody.innerHTML = '';
389          paragraphs.forEach(item => {
390            if (typeof item === 'string') {
391              const p = document.createElement('p');
392              p.textContent = item;
393              policyBody.appendChild(p);
394            } else if (item && item.heading) {
395              const h = document.createElement('h4');
396              h.className = 'policy__heading';
397              h.textContent = item.heading;
398              policyBody.appendChild(h);
399            } else if (item && item.list) {
400              const ul = document.createElement('ul');
401              ul.className = 'policy__list';
402              item.list.forEach(li => {
403                const liEl = document.createElement('li');
404                liEl.textContent = li;
405                ul.appendChild(liEl);
406              });
407              policyBody.appendChild(ul);
408            }
409          });
410          Animations.formToPolicy(formContent, policyView);
411          policyBody.scrollTop = 0;
412        };
413      }
414
415      function hidePolicy() {
416        Animations.policyToForm(policyView, formContent);
417      }
418
419      document.querySelectorAll('[data-open-privacy]').forEach(link => {
420        link.addEventListener('click', showPolicy(CONTENT.privacyPolicyTitle, CONTENT.privacyPolicy));
421      });
422
423      document.querySelectorAll('[data-open-disclaimer]').forEach(link => {
424        link.addEventListener('click', showPolicy(CONTENT.websiteDisclaimerTitle, CONTENT.websiteDisclaimer || []));
425      });
426
427      backBtn.addEventListener('click', hidePolicy);
428    })();
429
430    // ── Footer ──────────────────────────────────────────────────────────────
431    (() => {
432      const f = CONTENT.footer;
433
434      // Links
435      const linksEl = document.getElementById('footer-links');
436      const socialIcons = {
437        Facebook: '<svg viewBox="0 0 40 40" fill="none"><path d="M22.5 20h-2v7h-3v-7h-1.5v-2.5h1.5V16c0-2 1-3.2 3.2-3.2h2.3v2.5h-1.4c-.7 0-.9.3-.9.9v1.3h2.3L22.5 20z" fill="currentColor"/></svg>',
438        Instagram: '<svg viewBox="0 0 40 40" fill="none"><rect x="13" y="13" width="14" height="14" rx="3.5" stroke="currentColor" stroke-width="1.5"/><circle cx="20" cy="20" r="3.5" stroke="currentColor" stroke-width="1.5"/><circle cx="25.5" cy="14.5" r="1" fill="currentColor"/></svg>',
439      };
440
441      f.links.forEach(link => {
442        const a = document.createElement('a');
443        a.className = 'footer__link';
444        a.href = link.url;
445        a.target = '_blank';
446        a.rel = 'noopener noreferrer';
447        a.innerHTML = '<span class="footer__link-bar footer__link-bar--' + link.color + '"></span>' + link.label;
448        linksEl.appendChild(a);
449      });
450
451      // Social icons
452      const socialEl = document.getElementById('footer-social');
453      f.social.forEach(s => {
454        const a = document.createElement('a');
455        a.className = 'footer__social-link';
456        a.href = s.url;
457        a.target = '_blank';
458        a.rel = 'noopener noreferrer';
459        a.setAttribute('aria-label', s.label);
460        a.innerHTML = socialIcons[s.label] || '';
461        socialEl.appendChild(a);
462      });
463    })();
464
465    // ── Init modules ───────────────────────────────────────────────────────
466    Modal.init();
467    Form.init();
468    Animations.init();
469  </script>
469
470
471</body>
472
473</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.