# 🎯 FX DOM Dollar Plugin - Complete Cheat Sheet ## 🎯 **Plugin Overview** **FX DOM Dollar** provides jQuery-like DOM manipulation with FX reactive binding and lazy mounting. It offers familiar syntax while integrating seamlessly with FX's reactive node system. ### **Core Features** - ✅ **jQuery-like API** - Familiar selectors and methods - ✅ **Reactive Binding** - Automatic updates when FX nodes change - ✅ **Lazy Mounting** - Elements only mount when accessed - ✅ **Event Handling** - Clean event binding and delegation - ✅ **Form Integration** - Two-way data binding with form elements - ✅ **Traversal Methods** - Parent, child, sibling navigation --- ## 📦 **Installation & Setup** ### **Auto-Loading (Recommended)** ```javascript // Just use $ - auto-loads fx-dom-dollar plugin $('#element').text('Hello World'); $('.items').addClass('active'); ``` ### **Manual Loading** ```html ``` --- ## 🚀 **Core API Reference** ### **Selection Methods** | Selector | Description | Example | |----------|-------------|---------| | `$('#id')` | Select by ID | `$('#username')` | | `$('.class')` | Select by class | `$('.menu-item')` | | `$('tag')` | Select by tag | `$('button')` | | `$('[attr="value"]')` | Select by attribute | `$('[data-role="admin"]')` | | `$('parent > child')` | CSS combinators | `$('.menu > .item')` | ### **Content Manipulation** | Method | Description | Example | |--------|-------------|---------| | `.text(value?)` | Get/set text content | `$('#title').text('New Title')` | | `.html(value?)` | Get/set HTML content | `$('#content').html('Bold')` | | `.val(value?)` | Get/set form values | `$('#input').val('default')` | ### **Attribute & Style** | Method | Description | Example | |--------|-------------|---------| | `.attr(name, value?)` | Get/set attributes | `$('#link').attr('href', '/page')` | | `.css(prop, value?)` | Get/set CSS properties | `$('#box').css('color', 'red')` | | `.addClass(class)` | Add CSS class | `$('.item').addClass('active')` | | `.removeClass(class)` | Remove CSS class | `$('.item').removeClass('hidden')` | | `.toggleClass(class)` | Toggle CSS class | `$('.item').toggleClass('selected')` | --- ## 🎪 **Reactive Binding** ### **FX Node to DOM (Reactive Updates)** ```javascript // Text content updates automatically $('#user-name').text($$('user.name')); // HTML content with reactive expressions $('#user-info').html(`

${$$('user.name')}

${$$('user.email')}

`); // CSS properties reactive to FX nodes $('#theme-box').css('background-color', $$('theme.primaryColor')); $('#sidebar').css('width', $$('ui.sidebarWidth')); // Attributes reactive to FX state $('#status-icon').attr('src', $$('user.status') === 'online' ? '/online.png' : '/offline.png'); $('#theme-toggle').attr('checked', $$('ui.theme') === 'dark'); // Classes reactive to conditions $('#user-badge').addClass($$('user.isPremium') ? 'premium' : 'standard'); $('#notification').toggleClass('unread', $$('notifications.unreadCount') > 0); ``` ### **DOM to FX (Event-Driven Updates)** ```javascript // Input to FX node $('#username').on('input', function() { $$('form.username').set($(this).val()); }); // Form to FX state $('#settings-form').on('submit', function(e) { e.preventDefault(); const formData = { theme: $('#theme-select').val(), notifications: $('#notifications-checkbox').prop('checked'), language: $('#language-select').val() }; $$('user.settings').set(formData); }); // Button clicks update FX state $('#increment-btn').on('click', function() { const current = $$('counter.value').get() || 0; $$('counter.value').set(current + 1); }); // Complex interactions $('.todo-item').on('click', function() { const todoId = $(this).attr('data-id'); const completed = $(this).hasClass('completed'); // Update FX state $$(`todos.items.${todoId}.completed`).set(!completed); // UI updates automatically via reactive binding }); ``` ### **Two-Way Data Binding** ```javascript // Complete two-way binding setup function setupUserProfileBinding() { const userNameInput = $('#user-name-input'); const userEmailInput = $('#user-email-input'); // FX → DOM (reactive) userNameInput.val($$('user.profile.name')); userEmailInput.val($$('user.profile.email')); // DOM → FX (on changes) userNameInput.on('input', function() { $$('user.profile.name').set($(this).val()); }); userEmailInput.on('input', function() { $$('user.profile.email').set($(this).val()); }); // Watch for external changes and update DOM $$('user.profile.name').watch(name => { if (userNameInput.val() !== name) { userNameInput.val(name); } }); $$('user.profile.email').watch(email => { if (userEmailInput.val() !== email) { userEmailInput.val(email); } }); } ``` --- ## 🔧 **Event Handling** ### **Basic Events** ```javascript // Click events $('#submit-btn').on('click', function(e) { e.preventDefault(); submitForm(); }); // Multiple events $('#hover-element').on('mouseenter mouseleave', function(e) { $(this).toggleClass('hovered', e.type === 'mouseenter'); }); // Event delegation $('#container').on('click', '.dynamic-button', function() { const itemId = $(this).closest('.item').attr('data-id'); handleItemClick(itemId); }); // Custom events $('#component').on('fx:dataChanged', function(e) { console.log('Data changed:', e.detail); refreshComponent(); }); // Trigger custom events $('#trigger-btn').on('click', function() { $('#component').trigger('fx:dataChanged', { newData: 'example' }); }); ``` ### **Form Handling** ```javascript // Form submission $('#user-form').on('submit', function(e) { e.preventDefault(); const formData = { name: $('#name').val(), email: $('#email').val(), age: parseInt($('#age').val()), preferences: { theme: $('#theme').val(), notifications: $('#notifications').prop('checked') } }; // Save to FX $$('user.profile').set(formData); // Submit to API $api.post('/api/users', formData).watch(response => { if (response.success) { showSuccessMessage('Profile updated!'); $('#user-form')[0].reset(); } }); }); // Real-time form validation $('#email').on('input', function() { const email = $(this).val(); const isValid = email.includes('@') && email.includes('.'); $(this).toggleClass('invalid', !isValid); $('#email-error').text(isValid ? '' : 'Please enter a valid email'); $$('form.validation.email').set(isValid); }); // Auto-save form data $('#auto-save-form input, #auto-save-form textarea').on('input', function() { const fieldName = $(this).attr('name'); const fieldValue = $(this).val(); $$(`form.draft.${fieldName}`).set(fieldValue); }); ``` --- ## 🔍 **Traversal & Navigation** ### **Parent/Child Navigation** ```javascript // Find specific elements const menuItem = $('.menu-item').first(); const parentMenu = menuItem.parent('.menu'); const siblingItems = menuItem.parent().children('.menu-item'); // Navigate DOM tree $('.article') .find('.content') // Find descendant .children('p') // Direct children only .first() // First paragraph .addClass('intro'); // Style it // Complex traversal $('.user-card') .filter(function() { return $(this).find('.status').text() === 'online'; }) .addClass('online-user') .find('.actions') .removeClass('hidden'); ``` ### **Conditional Operations** ```javascript // Conditional DOM manipulation const userRole = $$('user.role').get(); if (userRole === 'admin') { $('.admin-controls').removeClass('hidden'); $('.user-controls').addClass('hidden'); } else { $('.admin-controls').addClass('hidden'); $('.user-controls').removeClass('hidden'); } // Reactive conditional classes $$('user.role').watch(role => { $('body') .removeClass('role-admin role-user role-guest') .addClass(`role-${role}`); }); // Show/hide based on FX state $$('ui.sidebar.visible').watch(visible => { $('#sidebar').css('display', visible ? 'block' : 'none'); $('#main-content').toggleClass('sidebar-collapsed', !visible); }); ``` --- ## 🎊 **Advanced Patterns** ### **Dynamic Content Generation** ```javascript // Generate user list from FX data function renderUserList() { const users = $$('app.users.list').get() || []; const userHTML = users.map(user => `
${user.name}

${user.name}

${user.email}

${user.status}
`).join(''); $('#user-list').html(userHTML); // Set up event handlers for new elements $('.edit-btn').on('click', function() { const userId = $(this).attr('data-id'); editUser(userId); }); $('.delete-btn').on('click', function() { const userId = $(this).attr('data-id'); deleteUser(userId); }); } // Reactive rendering $$('app.users.list').watch(renderUserList); ``` ### **Component-like Patterns** ```javascript // Reusable component pattern function createUserCard(user) { const cardHTML = `
${user.name}

${user.name}

${user.email}

${user.role}

`; const $card = $(cardHTML); // Set up reactive bindings for this card $card.find('.user-name').text($$(`users.${user.id}.name`)); $card.find('.user-email').text($$(`users.${user.id}.email`)); $card.find('.status-indicator').attr('class', `status-indicator ${$$(`users.${user.id}.status`)}` ); // Event handlers $card.find('.action-edit').on('click', () => editUser(user.id)); $card.find('.action-message').on('click', () => messageUser(user.id)); $card.find('.action-delete').on('click', () => deleteUser(user.id)); return $card; } // Usage const users = $$('app.users.active').get(); const userCards = users.map(createUserCard); $('#users-container').empty().append(...userCards); ``` --- ## 🚨 **Best Practices** ### ✅ **DO: Efficient DOM Operations** ```javascript // ✅ Use specific selectors $('#specific-id').text('content'); // Fast ID lookup $('.specific-class').addClass('active'); // Efficient class selector // ✅ Chain operations $('#element') .text('New content') .addClass('updated') .css('color', 'green'); // ✅ Use reactive binding for dynamic content $('#user-count').text($$('users.active.count')); // Updates automatically // ✅ Cache selectors for repeated use const $menu = $('#main-menu'); $menu.find('.item').addClass('initialized'); $menu.on('click', '.item', handleMenuClick); ``` ### ❌ **DON'T: Common Mistakes** ```javascript // ❌ Don't query repeatedly in loops users.forEach(user => { $(`#user-${user.id}`).text(user.name); // Inefficient repeated queries }); // ✅ DO: Batch operations const updates = users.map(user => ({ id: user.id, name: user.name })); updates.forEach(update => { $(`#user-${update.id}`).text(update.name); }); // ❌ Don't create elements without cleanup $('#container').append('
New element
'); // Potential memory leak // ✅ DO: Manage element lifecycle const $newElement = $('
New element
'); $('#container').append($newElement); // Clean up when needed: $newElement.remove(); // ❌ Don't ignore event cleanup $('#temp-button').on('click', handler); // Event remains after element removed // ✅ DO: Clean up events $('#temp-button').off('click', handler); ``` --- ## 🎯 **Form Integration Patterns** ### **Complete Form Binding** ```javascript // Comprehensive form setup function setupContactForm() { const form = $('#contact-form'); // Bind form fields to FX nodes $('#contact-name').val($$('form.contact.name')); $('#contact-email').val($$('form.contact.email')); $('#contact-message').val($$('form.contact.message')); // Two-way binding form.find('input, textarea').on('input change', function() { const fieldName = $(this).attr('name'); const fieldValue = $(this).val(); $$(`form.contact.${fieldName}`).set(fieldValue); }); // Reactive validation $$('form.contact.email').watch(email => { const isValid = email && email.includes('@'); $('#contact-email').toggleClass('invalid', !isValid); $('#email-error').text(isValid ? '' : 'Please enter a valid email'); }); // Form submission form.on('submit', function(e) { e.preventDefault(); const formData = { name: $$('form.contact.name').get(), email: $$('form.contact.email').get(), message: $$('form.contact.message').get() }; // Submit via FX API const response = $api.post('/api/contact', formData); response.watch(result => { if (result.success) { showSuccessMessage('Message sent successfully!'); form[0].reset(); $$('form.contact').set({ name: '', email: '', message: '' }); } else { showErrorMessage('Failed to send message: ' + result.error); } }); }); } ``` ### **Dynamic Form Generation** ```javascript // Generate form from FX schema function generateForm(schema, targetSelector) { const formHTML = Object.entries(schema.fields).map(([name, field]) => { const inputType = field.type === 'email' ? 'email' : field.type === 'number' ? 'number' : 'text'; return `
`; }).join(''); $(targetSelector).html(`
${formHTML}
`); // Set up reactive binding for generated form Object.keys(schema.fields).forEach(fieldName => { const $field = $(`#${fieldName}`); // FX → DOM $field.val($$(`form.${schema.name}.${fieldName}`)); // DOM → FX $field.on('input', function() { $$(`form.${schema.name}.${fieldName}`).set($(this).val()); }); }); } // Usage const userSchema = { name: 'userProfile', fields: { name: { type: 'text', label: 'Full Name', required: true }, email: { type: 'email', label: 'Email Address', required: true }, age: { type: 'number', label: 'Age', placeholder: 'Enter your age' } } }; generateForm(userSchema, '#form-container'); ``` --- ## 🎊 **Real-World Integration Examples** ### **Shopping Cart with Reactive UI** ```javascript class ShoppingCartUI { static initialize() { this.setupCartDisplay(); this.setupItemControls(); this.setupCheckout(); } static setupCartDisplay() { // Reactive cart count $('#cart-count').text($$('cart.items.length')); // Reactive cart total $('#cart-total').text($$('cart.total')); // Reactive cart visibility $$('cart.items').watch(items => { $('#cart-container').toggleClass('empty', items.length === 0); this.renderCartItems(items); }); } static renderCartItems(items) { const itemsHTML = items.map(item => `
${item.name}

${item.name}

$${item.price}

${item.quantity}
`).join(''); $('#cart-items').html(itemsHTML); } static setupItemControls() { // Quantity controls $('#cart-items').on('click', '.qty-increase', function() { const itemId = $(this).attr('data-id'); const cartItems = $$('cart.items').get(); const item = cartItems.find(item => item.id === itemId); if (item) { item.quantity += 1; $$('cart.items').set([...cartItems]); } }); $('#cart-items').on('click', '.qty-decrease', function() { const itemId = $(this).attr('data-id'); const cartItems = $$('cart.items').get(); const item = cartItems.find(item => item.id === itemId); if (item && item.quantity > 1) { item.quantity -= 1; $$('cart.items').set([...cartItems]); } }); // Remove items $('#cart-items').on('click', '.remove-item', function() { const itemId = $(this).attr('data-id'); const cartItems = $$('cart.items').get(); $$('cart.items').set(cartItems.filter(item => item.id !== itemId)); }); } static setupCheckout() { $('#checkout-btn').on('click', function() { const cartItems = $$('cart.items').get(); const total = $$('cart.total').get(); if (cartItems.length === 0) { alert('Cart is empty'); return; } // Process checkout $flow('checkout') .node('validate', { runsOn: 'client', effect: validateCart }) .node('payment', { runsOn: 'server', effect: processPayment }) .node('complete', { runsOn: 'both', effect: completeOrder }) .start('validate', { items: cartItems, total }); }); } } // Initialize cart UI ShoppingCartUI.initialize(); ``` This comprehensive cheat sheet covers all aspects of fx-dom-dollar, from basic DOM manipulation to advanced reactive patterns and real-world integration examples.