I'm currently using Express, Mustache and QRCode.js.
Currently, when editing a product from the database, a mustache template is used and the /id is added to the end of the URL to specify which product ID will be edited. On this edit page, at the bottom, I was able to create a QR code with QRCode.js that links to the current page. It is to be downloaded and printed on to a sticker, which will go on a shelf. That way, users can scan the QR code with their phone and subtract from the product inventory.
However, I'd really like to add the {{product.productId}}, {{product.Manufacturer}} and {{product.product.Sku}} on the right of that downloadable QR code. That way, they can easily be downloaded and go straight to a printer, instead of having to drop them in an editing program to add the information manually. This is my first back-end product. Would someone give me a roadmap on how to accomplish it?
Here is my code:
<pre>
<div class="generate">
<div class="generate_qrcode" id="output"></div>
</div>
<div class="qrcode__span">Right click to download as a .png</div>
<!-- <img class="QRCode" src="qrcode-encoding.png" /> -->
<script>
let qrcode = new QRCode("output", {
text: window.location.href,
width: 256,
height: 256,
colorDark : "#04243c",
colorLight : "#FFFFFF",
correctLevel : QRCode.CorrectLevel.H
});
</script>
<!-- HTML/Product Edit Field (on same page as above code) -->
<body class="product_edit">
<h2 class="ep__h2">Edit Product</h2>
<div class="ep">
<form class="ep__form"
action="/product_edit/{{product.productId}}" method="POST"
autocomplete="off">
<label for="productname" class="ep__label">Product Name:
</label>
<input type="text" name="product_name" class="ep__input"
placeholder="Product Name" value="{{product.productName}}">
<label for="manufacturer" class="ep__label">Manufacturer:
</label>
<input type="text" name="product_manufacturer"
class="ep__input" placeholder="Manufacturer" value=" .
{{product.productManufacturer}}">
<label for="product_size" class="ep__label">Size:</label>
<input type="text" name="product_size" class="ep__input"
placeholder="Size" value="{{product.productSize}}">
<label for="product_qty" class="ep__label">Quantity:
</label>
<button type="button" class="ep__qtyminus" value="-"
name="product_qty" field="product_qty">-</button>
<input type="number" name="product_qty"
class="ep__qtynumber" value="{{product.productQty}}">
<button type="button" class="ep__qtyplus" value="+"
name="product_qty" field="product_qty">+</button>
<label for="product_sku" class="ep__label--half">SKU:
</label>
<label for="product_minimum" class="ep__label--
half">Minimum:</label>
<input type="text" name="product_sku" class="ep__input--
half" placeholder="SKU" value="{{product.productSku}}">
<input type="number" name="product_minimum"
class="ep__input--half" placeholder="Minimum" value="
{{product.productMinimum}}">
<label for="product_color" class="ep__label--half">Color:
</label>
<label for="product_number" class="ep__label--half">Number:
</label>
<input type="text" name="product_color" class="ep__input--
half" placeholder="Color" value="{{product.productColor}}">
<input type="number" name="product_number"
class="ep__input--half" placeholder="Minimum" value=" .
{{product.productNumber}}">
<button class="ep__save" type="submit">Save</button>
</form>
</div>
</pre>
Typing here for more space:
Assuming you have access to the Express server, why can't you create a route that retrieves all products, and for each unique product, generates a little html that includes name, id, price, and QR code? Then express can compile all the HTML and send it to the browser.
app.get('/products/print_stickers', function(req, res, next){
// below is psuedo code
var products_array = database.getAllProductInfo();
res.render('print_page', {
products: products_array // pass data to mustahce template
});
})
Then in your print_page mustache file, you just loop over information we got from the server. If it contains data for all the products, then we can create the html stickers for every product on just one page!
var sticker_html = `
<ul>
{{#.}}
<li>
<div class="left_side">
${new QRCode("output", {
text: 'http://mywebsite/product/id/{{product_id}}', // using {{ mustache }} to insert product id
width: 256,
height: 256,
colorDark : "#04243c",
colorLight : "#FFFFFF",
correctLevel : QRCode.CorrectLevel.H
})}
</div>
<div class="right_side">
<p>{{name}}</p>
<p>{{date}}</p> // using {{ mustache }} to insert product information
<p>{{price}}</p>
</div>
</li>
{{/.}}
</ul>;
`;
Mustache.render(tmp, products_array);
So at this point, you'd go to this page, and the server would get the products, generate html for each unique item, send it to your browser, you print it, then use scissors to cut them up and post them where you need them. If you need to just print a single sticker, you can use an optional query param with the ID of the product, and say if product_id, then only get 1 product from DB, generate sticker html as normal.
Related
I want to pull data using JavaScript and show it in console. I don't know what I did wrong.
main.js
// ADD TO CART
$("#addToCartBtn").on('click',function(){
var _qty=$("#productQty").val();
var _productId=$(".product-id").val();
var _productName=$(".product-name").val();
console.log(_productId,_productName,_qty);
});
I am using django framework to write backend
detail.html
<div class="product-btns">
<div class="qty-input">
<span class="text-uppercase">Ədəd: </span>
<input class="input" type="number" value="1" id="productQty">
</div>
<input type="hidden" class="product-id" value="{{product.id}}">
<input type="hidden" class="product-name" value="{{product.name}}">
<button class="primary-btn add-to-cart"><i class="fa fa-shopping-cart" id="addToCartBtn"></i> Səbətə at</button>
</div>
The problem is probably that the element that has id="addToCartBtn" is not really the button but the <i> element - which has no content and therefore no width. So it is never clickable.
The issue I'm having is that various translations on the page use URL parameters to fill in the content for a form dynamically. The form has radio buttons and I want to have one of them checked by default depending on the URL Parameter.
So for example, if the URL says ?lang=dk, I would want the European radio button to be checked, but if it says ?lang=fr-ca, I'd want it to check North America:
<form id="contact-form" method="post" class="form-contact" enctype="multipart/form-data">
<div id="form-platform" class="form-platform--radio-group">
<label class="radio--button" for="option-na">
<input class="form__input" type="radio" id="option-na" name="platform"
value="NA">
<i></i>
<span class="radio--label">North America</span>
</label>
<label class="radio--button" for="option-eu">
<input class="form__input" type="radio" id="option-eu" name="platform"
value="EU">
<i></i>
<span class="radio--label">Europe</span>
</label>
</div>
</form>
So far, I've tried using this.param but it's been unsuccessful so far.
Is my only option to use Javascript to achieve what I need, or is this possible with OctoberCMS?
For Clarification:
A url like "example.com?lang=us" is making a request on the server. The request is Input::get('lang') = 'us'.
A url like "example.com/:lang?/" is using the Laravel routing system to access parameters of the slug. This would look like "example.com/us/page" and the request looks like this.param('lang') = 'us'.
Both of these could work for your system depending on how you are setting the language.
My recommendation is to design your website with dynamic values in mind and use collections like this.
PHP CODE in CMS page for adhoc:
function onStart() {
$language = Input::get('lang'); //check for a language request
$languages = [ //build language array
'dk' => [
'place' => 'European',
'selected' => false,
'value' => 'eu'
],
'fr-ca' => [
'place' => 'North America',
'selected' => false,
'value' => 'na'
]
];
if (isset($languages[$language])) {
$languages[$language]['selected'] = true; //see if the language request is in the array then set selected to true
}
$this['languages'] = $languages; //return languages to the page
}
In your Markup side of the page you can then do this - With twig you can just make a for loop set the variables and check to see if the language is selected.
<form id="contact-form" method="post" class="form-contact" enctype="multipart/form-data">
<div id="form-platform" class="form-platform--radio-group">
{% for language in languages %}
<label class="radio--button" for="option-{{ language.value}}">
<input class="form__input" type="radio" id="option-{{ language.value }}" name="platform"
value="{{ language.value | upper }}" {% if language.selected %}checked{% endif %} >
<i></i>
<span class="radio--label">{{ language.place }}</span>
</label>
{% endfor %}
</div>
</form>
I have a form with multiple fields but also a file upload. I am able to upload multiple files.
I also know that it is possible to upload files with AJAX.
So I would like to upload my files using ajax while i'm filling in every other field. But how would I link the already uploaded images then? And also prevent the images to be uploaded again?
This is the form:
<form id="form_validation" method="POST" action="{{route('storeexpense')}}" enctype="multipart/form-data">
{{ csrf_field() }}
<div class="form-group form-float">
<div class="form-line">
<input type="text" class="form-control" name="description" required>
<label class="form-label">Omschrijving</label>
</div>
</div>
<div class="form-group form-float">
<div class="form-line">
<input type="number" class="form-control" name="amount" required>
<label class="form-label">Bedrag</label>
</div>
</div>
<div class="form-group form-float">
#foreach ($types as $type)
#if ($type->id === 1)
<input name="transactiontype" type="radio" id="rdio{{$type->id}}" value="{{$type->id}}" checked />
<label for="rdio{{$type->id}}">{{$type->description}}</label>
#else
<input name="transactiontype" type="radio" id="rdio{{$type->id}}" value="{{$type->id}}" />
<label for="rdio{{$type->id}}">{{$type->description}}</label>
#endif
#endforeach
</div>
<div class="form-group form-float">
<div class="form-line">
<input type="text" class="datepicker form-control" name="date" placeholder="Please choose a date..." required>
<!-- <label class="form-label">Datum</label> -->
</div>
</div>
<div class="form-group demo-tagsinput-area">
<div class="form-line">
<input type="text" class="form-control" id="tagsinput" data-role="tagsinput" placeholder="Labels" name="tags" required>
</div>
</div>
<div class="form-group form-float">
<div class="form-line">
#if (count($errors) > 0)
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
#endif
<input type="file" name="attachments[]" multiple class="custom-file-control"/>
</div>
</div>
<button class="btn btn-primary waves-effect" type="submit">SAVE</button>
</form>
This is the PHP code that saves the information from the form:
public function store(UploadRequest $request)
{
// Save new transaction in database
$transaction = new Transaction;
$transaction->description = $request->description;
$transaction->amount = $request->amount;
$input = $request->date;
$format = 'd/m/Y';
$date = Carbon::createFromFormat($format, $input);
$transaction->date = $date;
$transaction->transactiontype_id = $request->transactiontype;
$transaction->user_id = Auth::id();
$transaction->save();
// Put tags in array
$inputtags = explode(",", $request->tags);
// Loop through every tag exists
// EXISTS: get ID
// NOT EXISTS: Create and get ID
foreach ($inputtags as $inputtag)
{
$tag = Tag::firstOrCreate(['description' => $inputtag]);
$transaction->tags()->attach($tag->id); //Put the 2 ID's in intermediate table ('tag_transaction')
}
//Check if there are files
if (!is_null($request->attachments))
{
//Loop through every file and upload it
foreach ($request->attachments as $attachment) {
$filename = $attachment->store('attachments');
// Store the filename in the database with link to the transaction
Attachment::create([
'transaction_id' => $transaction->id,
'path' => $filename
]);
}
}
Thanks,
Bart
It sounds like you want to make a fancy form that starts uploading the file as soon as you choose it and meanwhile the user can continue filling the rest of the form. If so, I'd do it like this:
Implement your main text/data form, eg.
<form method="POST" action="/save-data-endpoint.php">
<input name="email" type="text" />
<button type="submit>Submit</button>
</form>
Next to it, a form for the images. eg.
<form method="POST" class="file-upload-form" action="/save-file.php">
<input name="my-file" type="file" />
<!-- note that we wont show a submit button -->
</form>
For the user, it all looks like the same form but clicking the submit button will send only the data to the save-data-endpoint.php. Now we need some js to control this madness (I'll use jQuery for brevity). But you can use FileReader api in js, ajax progress tracking to make it even fancier. See https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications for more.
$(function(){ // run when document is ready
// listen when the input changes (when a file is selected)
$('.file-upload-form').on('change', function(e){
// file has been selected, submit it via ajax
// show some kind of uploading indication, eg. a spinner
$.ajax({
type:'POST',
url: $(this).attr('action'),
data: new FormData(this),
cache:false,
contentType: false,
processData: false,
success:function(data){
// the save-file.php endpoint returns an id and/or a url to the saved/resized/sanitized image
console.log(data.id, data.url);
// we then inject this id/url, into the main data form
var $hiddenInput = $('<input type="hidden" name="uploads[]" value="'+data.id+'">');
$('.main-form').append($hiddenInput);
// show a thumbnail maybe?
var $thumbnail = $('<img src="'+data.url+'" width="20" height="20" />');
$('.main-form').append($thumbnail);
// hide spinner
// reactivate file upload form to choose another file
$('.file-upload-form').find('input').val('');
},
error: function(){
console.log("error");
}
});
});
});
Your backend will get the images as they are selected, one by one. You then save them and return an id and/or a url to the image to be used in the success handler in js. After adding some images your main form should look something like this:
<form method="POST" action="/save-data-endpoint.php">
<input name="email" type="text" />
<button type="submit>Submit</button>
<input type="hidden" name="uploads[]" value="x">
<img src="...x.jpg" width="20" height="20" />
<input type="hidden" name="uploads[]" value="y">
<img src="...y.jpg" width="20" height="20" />
</form>
Now when the user fills the remaining fields and clicks submit, your server will get all the data along with an array called uploads which contains all the image ids/paths you have already saved. You can now store this data and relate it to the files.
I wont go deeper on the backend side as it can be implemented on any language. In summary the basic flow would be:
send files one at a time to a save file endpoint that returns a file identifier (can be an id, hash, full path to image, etc)
js injects those ids into the main form
the main form is submitted to a save data endpoint that returns a success or error message and stores + relates all the data in your preferred method of storage.
Hope it helps!
Hi i currently have a document where i need to send data off via either email(which i am using php mailer) or sql. which is all pretty well sorted.
my only question is. as i am using append to generate a set of variables. how would i use pull all this user generated data to then send a json file.
below is the current code i have.
<div align="center" class="addsection"></div>
<button align="center" id="addbutton" class="btn btn-default">Add a product</button>
<button id="submitbutton" class="btn btn-default" onclick="sbmitbtn()">Submit</button>
<script>$('#addbutton').on('click', function () {
var count = $('div.addsection div').length, id = count + 1;
var large = '<p class="accordian_container">
<hr/>
<p class="accordian_item" id="accord_item_2">
<label> First Name</label><br/>
<input type="text"/><br/>
<label>Middle Name</label><br/>
<input type="text"/><br/>
<label>Last Name</label><br/>
<input type="text" /><br/>
<label>Home Number</label><br/>
<input type="text"/><br>
<label>Work Number</label><br/>
<input type="text"/><br>
<label>Cell Number</label><br/>
<input type="text"/><br>
</p>
</p>';
$('div.addsection').append('<div class="contentprint" id="product' + id + '">' +
'<h4>Product: ' + id + '</h4> <table class="selection1"></table>content goes here</div>');
$('div.addsection').append(large);
event.preventDefault();
});
$('#submitbutton').on('click', function () {
}
as you can tell i have a button to generate content. with a div to put that content in. now i need to figure out how to use that data that was created from the textboxes to send off via json. is this possible. any help would be awesome. do i need to move large within the append and make each items id have the id of the overall div. and if so is it as simple as running a for loop until all divs with ids have been passed.
can this json type array be done in php if it were on a php page. its a little confusing to get my head around so any help is greatly appreciated.
In the admin portion of my Django app I want to extend how an existing inline formset works. Currently, I have an inline formset for images with 2 fields - name and image. That model looks similar to this:
models.py
class Slideshow(models.Model):
name = models.CharField(max_length=200,blank=True)
image = models.ImageField(max_length=200,upload_to=destination)
...
Now, in Django admin, I can click "Add another" in my inline, and that adds another block of name and image fields to the inline formset. In that form I can select "Choose file" and add an image file (and optionally a name), click Save and all works well using the existing Django admin functionality.
Is there a way for me to add multiple image files at once to this existing inline formset? Say using an HTML multiple file selection?
Example formset row with sample data
<div class="grp-module grp-tbody has_original grp-dynamic-form" id="asset_set0">
<h3 style="display: none;"><b>asset #1</b> sample-banner-444-fff.gif</h3>
<div class="grp-tr">
<div class="grp-td name ">
<input class="vTextField" id="id_asset_set-0-name" maxlength="200" name="asset_set-0-name" type="text" value="test asset">
</div>
<div class="grp-td file ">
<p class="file-upload">Currently: asset_files/2014/02/13/10/52/1392317533/sample-banner-444-fff.gif <br>Change: <input id="id_asset_set-0-file" name="asset_set-0-file" type="file"></p>
</div>
<div class="grp-td grp-tools-container">
<ul class="grp-tools"><li class="grp-delete-handler-container"><input id="id_asset_set-0-DELETE" name="asset_set-0-DELETE" type="checkbox"></li></ul>
</div>
<input id="id_asset_set-0-campaign" name="asset_set-0-campaign" type="hidden" value="25">
<input id="id_asset_set-0-id" name="asset_set-0-id" type="hidden" value="71">
</div>
</div>
Example formset row without data
<div class="grp-module grp-tbody grp-dynamic-form" id="asset_set1">
<h3 style="display: none;"><b>asset #2</b> </h3>
<div class="grp-tr">
<div class="grp-td name ">
<input class="vTextField" id="id_asset_set-1-name" maxlength="200" name="asset_set-1-name" type="text">
</div>
<div class="grp-td file ">
<input id="id_asset_set-1-file" name="asset_set-1-file" type="file">
</div>
<div class="grp-td grp-tools-container">
<ul class="grp-tools"><li></li></ul>
</div>
<input id="id_asset_set-1-campaign" name="asset_set-1-campaign" type="hidden" value="25">
<input id="id_asset_set-1-id" name="asset_set-1-id" type="hidden">
</div>
</div>
By the way, I have reviewed a few other apps, filer and photologue for example, that offer similar functionality at the cost of including several other features that may or may not affect the rest of my application.