search
f.name)); if (this.uploadedFiles.length + files.length > 5) { alert('You can only upload up to 5 branding files.'); return; } files.forEach(file => { const ext = file.name.split('.').pop().toLowerCase(); if (!['pdf', 'ai', 'eps', 'jpg', 'jpeg', 'png'].includes(ext)) { alert('Only PDF, AI, EPS, JPG, and PNG files are accepted.'); return; } if (file.size > 10 * 1024 * 1024) { alert('File size exceeds the 10MB limit.'); return; } this.uploadFile(file); }); }, updateFileState(filename, data) { const fileObj = this.uploadedFiles.find(f => f.name === filename); if (fileObj) { Object.assign(fileObj, data); this.uploadedFiles = [...this.uploadedFiles]; // Force Alpine reactivity } }, uploadFile(file) { this.uploadedFiles.push({ name: file.name, progress: 0, hashed_name: null, error: null, status: 'uploading' }); this.isUploading = true; this.uploadedFiles = [...this.uploadedFiles]; // Force immediate display of progress bar console.log('uploadFile: Preparing payload for:', file.name); const formData = new FormData(); formData.append('file', file); const csrfToken = document.querySelector('meta[name=csrf-token]')?.getAttribute('content') || ''; console.log('uploadFile: CSRF token lookup result:', csrfToken ? 'Token Found' : 'Token Missing!'); const xhr = new XMLHttpRequest(); xhr.open('POST', '/upload-quote-file'); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); if (csrfToken) { xhr.setRequestHeader('X-CSRF-TOKEN', csrfToken); } xhr.upload.addEventListener('progress', e => { if (e.lengthComputable) { const percentage = Math.round((e.loaded / e.total) * 100); console.log('uploadFile progress (' + file.name + '): ' + percentage + '%'); this.updateFileState(file.name, { progress: percentage }); } }); xhr.addEventListener('load', () => { console.log('uploadFile load complete (' + file.name + '). Status code:', xhr.status); if (xhr.status >= 200 && xhr.status < 300) { try { const response = JSON.parse(xhr.responseText); console.log('uploadFile response (' + file.name + '):', response); if (response.success) { this.updateFileState(file.name, { hashed_name: response.hashed_name, status: 'success', progress: 100 }); } else { this.updateFileState(file.name, { error: response.message || 'Upload failed.', status: 'error' }); } } catch(err) { console.error('JSON parse exception during load handler:', err); this.updateFileState(file.name, { error: 'Invalid server response.', status: 'error' }); } } else { let msg = 'Upload failed.'; try { const err = JSON.parse(xhr.responseText); msg = err.message || msg; } catch(e) {} this.updateFileState(file.name, { error: msg, status: 'error' }); } this.checkUploadStatus(); }); xhr.addEventListener('error', () => { console.error('uploadFile net error (' + file.name + ')'); this.updateFileState(file.name, { error: 'Network error occurred.', status: 'error' }); this.checkUploadStatus(); }); xhr.send(formData); console.log('uploadFile: Sent payload for:', file.name); }, checkUploadStatus() { this.isUploading = this.uploadedFiles.some(f => f.status === 'uploading'); }, removeUploadedFile(index) { this.uploadedFiles.splice(index, 1); this.checkUploadStatus(); }, getBrandingFilesPayload() { return this.uploadedFiles .filter(f => f.status === 'success') .map(f => ({ original_name: f.name, hashed_name: f.hashed_name })); }, getAddIsDisabled(id) { const cartElement = document.querySelector('[x-data=\'shoppingCart\']'); const cart = Alpine.$data(cartElement); return cart.isInCart(id, this.getColourTitle()); }, init() { // Clean up any leading '?&' from the search query string and parse parameters let search = window.location.search; search = search.replace(/^\?&/, '?'); const params = new URLSearchParams(search); // Automatically set the Quantity const quantityParam = params.get('quantity') || params.get('qty'); if (quantityParam) { const qty = parseInt(quantityParam, 10); if (!isNaN(qty) && qty > 0) { this._quantity = qty; } } // Automatically select the Color const colourParam = params.get('colour') || params.get('color'); if (colourParam) { this.$nextTick(() => { const decodedColour = decodeURIComponent(colourParam).trim().toLowerCase(); const buttons = Array.from(document.querySelectorAll('.product-details button[title]')); const match = buttons.find(b => b.getAttribute('title').trim().toLowerCase() === decodedColour); if (match) match.click(); // Triggers the Alpine click handler to select color and update corresponding image }); } } }">

Banners Ink NZ

Vertical Pop Up Banners

Colour:

Quantity

Branding Logo or Images

Accepted file types: PDF, AI, EPS, JPG, PNG | Max file size: 10MB | Max files: 1

Product Description expand_more

Explore our vertical pop-up banners, the ideal solution for high-impact visual promotion. Combining quality and affordability, these banners are designed to capture attention at trade shows, events, and any environment where your message needs to stand out. Offering professional-grade design and easy portability, they provide excellent visibility for businesses of all sizes. Versatile and adaptable, these pop-up banners work seamlessly in a variety of settings—from busy trade shows to intimate product launches. They’re perfect for drawing attention at job fairs, enhancing convention booths, creating photo backdrops for corporate events, or elevating retail displays. With a user-friendly design, they allow for fast and simple setup, delivering a polished, professional presentation every time.

Product Features

The frame is crafted from strong spring steel, offering excellent stability and resistance to everyday wear. With included pegs for secure anchoring, these banners are suitable for both indoor and outdoor advertising, ensuring your display remains steady and reliable in any setting.

Product Materials

110gsm knitted polyester

Product Item Size

920mm x 1100mm

Product Packaging Inner

Carry Bag

You might also like...

More in Exhibitions & Events