Remove jQuery dependency, convert to vanilla JavaScript
This commit is contained in:
parent
4bc0c67e3a
commit
42241d79b7
6 changed files with 59 additions and 70 deletions
|
|
@ -8,17 +8,12 @@ This project minimizes JavaScript usage, preferring pure CSS solutions where pos
|
|||
- Use `<details>` elements for toggles instead of JS
|
||||
- External SDKs loaded only when payment method is enabled
|
||||
- No build step - vanilla JS only
|
||||
- jQuery used minimally (legacy, being phased out)
|
||||
- No jQuery - all vanilla JavaScript
|
||||
|
||||
## Static JavaScript Files
|
||||
|
||||
Located in `make_post_sell/static/js/`:
|
||||
|
||||
### jquery-3.6.0.min.js
|
||||
- jQuery library (legacy dependency)
|
||||
- Used by: Stripe card form, markdown preview
|
||||
- Loaded via `snippets/optional-javascript.j2` and `snippets/stripe.j2`
|
||||
|
||||
### qrcode.min.js
|
||||
- QRious library for QR code generation
|
||||
- Used by: Crypto checkout page
|
||||
|
|
@ -27,7 +22,7 @@ Located in `make_post_sell/static/js/`:
|
|||
### custom.js
|
||||
- Markdown preview functionality
|
||||
- Functions: `previewAjax()`, `sendPreview()`
|
||||
- Uses jQuery for AJAX calls to `/markup-editor-preview`
|
||||
- Uses fetch API for AJAX calls to `/markup-editor-preview`
|
||||
|
||||
## Inline JavaScript by Template
|
||||
|
||||
|
|
@ -43,7 +38,7 @@ Located in `make_post_sell/static/js/`:
|
|||
|
||||
- Crypto wallets toggle (checkbox + localStorage)
|
||||
- Theme preview for shop default theme radio buttons
|
||||
- Note: Payment provider toggles now use pure CSS `<details>` elements
|
||||
- Note: Payment provider toggles use pure CSS `<details>` elements
|
||||
|
||||
### user_settings.j2
|
||||
**Purpose:** User theme preference sync
|
||||
|
|
@ -80,7 +75,7 @@ Located in `make_post_sell/static/js/`:
|
|||
- Loads Stripe.js SDK
|
||||
- Creates Payment Element for card input
|
||||
- Handles `stripe.confirmSetup()` flow
|
||||
- Requires jQuery
|
||||
- Uses vanilla JS with `DOMContentLoaded`
|
||||
|
||||
### snippets/analytics.j2
|
||||
**Purpose:** Analytics tracking (optional)
|
||||
|
|
@ -92,7 +87,7 @@ Located in `make_post_sell/static/js/`:
|
|||
### snippets/optional-javascript.j2
|
||||
**Purpose:** Optional JS loading
|
||||
|
||||
- Loads jQuery and custom.js async
|
||||
- Loads custom.js async
|
||||
- Used for markdown preview functionality
|
||||
|
||||
## External SDKs
|
||||
|
|
@ -119,6 +114,5 @@ Pages work without JavaScript where possible:
|
|||
|
||||
## Future Improvements
|
||||
|
||||
- Remove jQuery dependency (replace with vanilla JS)
|
||||
- Convert remaining checkbox toggles to `<details>` elements
|
||||
- Consider removing Google Analytics option (privacy)
|
||||
|
|
|
|||
|
|
@ -1,30 +1,52 @@
|
|||
// post_preview
|
||||
// previewTimer must live outside the functions.
|
||||
// Markdown preview functionality (vanilla JS, no jQuery)
|
||||
var previewTimer = null;
|
||||
|
||||
function previewAjax(textarea, div, show_raw = false){
|
||||
// set div to raw textarea while waiting for remote Markdown rendering.
|
||||
function previewAjax(textareaId, divId, show_raw = false) {
|
||||
var textarea = document.getElementById(textareaId);
|
||||
var div = document.getElementById(divId);
|
||||
|
||||
if (!textarea || !div) return;
|
||||
|
||||
// Show raw textarea content while waiting for server-rendered Markdown
|
||||
if (show_raw) {
|
||||
// bust HTML tags like <script> to prevent running evil code.
|
||||
var busted_textarea = $('#'+textarea).val().replace(/&/g, '&').replace(/</g,'<');
|
||||
$('#' + div).html('<span class="preview-raw-markup">'+busted_textarea+'</span>');
|
||||
// Escape HTML tags to prevent XSS
|
||||
var escaped = textarea.value
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
div.innerHTML = '<span class="preview-raw-markup">' + escaped + '</span>';
|
||||
}
|
||||
|
||||
// Debounce: clear previous timer and set new one
|
||||
if (previewTimer) {
|
||||
clearTimeout(previewTimer);
|
||||
}
|
||||
previewTimer = setTimeout(
|
||||
function() { sendPreview( textarea, div); },
|
||||
800
|
||||
);
|
||||
previewTimer = setTimeout(function() {
|
||||
sendPreview(textareaId, divId);
|
||||
}, 800);
|
||||
}
|
||||
|
||||
function sendPreview(textarea, div){
|
||||
$.ajaxSetup ({
|
||||
cache: false
|
||||
function sendPreview(textareaId, divId) {
|
||||
var textarea = document.getElementById(textareaId);
|
||||
var div = document.getElementById(divId);
|
||||
|
||||
if (!textarea || !div) return;
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append('data', textarea.value);
|
||||
|
||||
fetch('/markup-editor-preview', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
cache: 'no-store'
|
||||
})
|
||||
.then(function(response) {
|
||||
return response.text();
|
||||
})
|
||||
.then(function(html) {
|
||||
div.innerHTML = html;
|
||||
})
|
||||
.catch(function(error) {
|
||||
console.error('Preview error:', error);
|
||||
});
|
||||
|
||||
var url = '/markup-editor-preview';
|
||||
var params = { 'data' : $('#'+textarea).val() };
|
||||
|
||||
$( '#' + div ).load( url, params );
|
||||
}
|
||||
|
|
|
|||
3
make_post_sell/static/js/jquery-3.6.0.min.js
vendored
3
make_post_sell/static/js/jquery-3.6.0.min.js
vendored
File diff suppressed because one or more lines are too long
1
make_post_sell/static/js/jquery.min.js
vendored
1
make_post_sell/static/js/jquery.min.js
vendored
|
|
@ -1 +0,0 @@
|
|||
jquery-3.6.0.min.js
|
||||
|
|
@ -1,2 +1 @@
|
|||
<script async src="/static/js/jquery.min.js"></script>
|
||||
<script async src="/static/js/custom.js"></script>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@
|
|||
|
||||
|
||||
{% macro new_card() %}
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<script src="https://js.stripe.com/v3/"></script>
|
||||
<form action="/billing/add-card?shop_id={{ request.shop.id }}" method="post" data-secret="{{ client_secret }}" id="payment-form">
|
||||
{% include 'snippets/csrf.j2' %}
|
||||
|
|
@ -51,13 +50,10 @@
|
|||
<div id="payment-element">
|
||||
<!-- Elements will create form elements here -->
|
||||
</div>
|
||||
|
||||
<!--
|
||||
-->
|
||||
|
||||
<a href="https://stripe.com/docs/security/stripe" target="_blank"><img class="stripe-initial-width" src="https://stripe.com/img/about/logos/badge/outline-dark.svg"></a>
|
||||
|
||||
<button class="green-button button-max-width stripe-save-button">🔒 Save Card</button>
|
||||
|
||||
|
||||
<!-- Used to display Element errors. -->
|
||||
<div id="error-message" role="alert" class="bold-text"></div>
|
||||
|
|
@ -66,49 +62,31 @@
|
|||
</form>
|
||||
|
||||
<script>
|
||||
|
||||
//$(document).ready(function() {
|
||||
$(function () {
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var stripe = Stripe("{{ request.shop.stripe_public_api_key }}");
|
||||
|
||||
const options = {clientSecret: '{{ client_secret }}'};
|
||||
|
||||
var elements = stripe.elements(options);
|
||||
var elements = stripe.elements({clientSecret: '{{ client_secret }}'});
|
||||
|
||||
// Create and mount the Payment Element
|
||||
const paymentElement = elements.create('payment');
|
||||
var paymentElement = elements.create('payment');
|
||||
paymentElement.mount('#payment-element');
|
||||
|
||||
// confirm stripe payment method setup intent.
|
||||
// Handle form submission
|
||||
var form = document.getElementById('payment-form');
|
||||
|
||||
form.addEventListener('submit', async (event) => {
|
||||
form.addEventListener('submit', async function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const {error} = await stripe.confirmSetup({
|
||||
//`Elements` instance that was used to create the Payment Element
|
||||
elements,
|
||||
|
||||
var result = await stripe.confirmSetup({
|
||||
elements: elements,
|
||||
confirmParams: {
|
||||
return_url: '{{ request.route_url("add-card", shop_id=request.shop.id) }}',
|
||||
}
|
||||
});
|
||||
|
||||
if (error) {
|
||||
// This point will only be reached if there is an immediate error when
|
||||
// confirming the payment. Show error to your customer (for example, payment
|
||||
// details incomplete)
|
||||
const messageContainer = document.querySelector('#error-message');
|
||||
messageContainer.textContent = error.message;
|
||||
} else {
|
||||
// Your customer will be redirected to your `return_url`. For some payment
|
||||
// methods like iDEAL, your customer will be redirected to an intermediate
|
||||
// site first to authorize the payment, then redirected to the `return_url`.
|
||||
|
||||
if (result.error) {
|
||||
document.getElementById('error-message').textContent = result.error.message;
|
||||
}
|
||||
|
||||
// On success, customer is redirected to return_url
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endmacro %}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue