I have two test files:
test1.js
fetchData().then((data)=>{
console.log('fetched', data);
});
test2.js
fetchData().then((data)=>{
console.log('fetched', data);
}).then(()=>{
console.log('finished');
});
I run clang-format on them as follows:
clang-format-5.0 -style="{ColumnLimit: 0}" testX.js
Formatted test1.js
fetchData().then((data) => {
console.log('fetched', data);
});
Formatted test2.js
fetchData().then((data) => {
console.log('fetched', data);
})
.then(() => {
console.log('finished');
});
(clang-format-3.8 produces the same output)
What style options (in addition to column limit 0) would format test2.js as follows?
fetchData().then((data) => {
console.log('fetched', data);
}).then(() => {
console.log('finished');
});
In other words, I want the presence or absence of the 2nd lambda not to affect the formatting of the 1st lambda.
Related
Everything seems to be right and the files are being cached but it just doesn't work offline. Am I missing something obvious?
the cache.addAll did not want to work with my const FILES_TO_CACHE but do work when I put them in directly. Thus the repeated code.
Here is my service worker file:
const FILES_TO_CACHE = [
"/",
"/index.html",
"/style.css",
"/db.js",
"/index.js",
"/manifest.webmanifest"
];
const CACHE_NAME = "static-cache-v2";
const DATA_CACHE_NAME = "data-cache-v1";
// install
self.addEventListener("install", function(evt) {
evt.waitUntil(
caches.open(CACHE_NAME).then(cache => {
console.log("Your files were pre-cached successfully!");
return cache.addAll([
"/",
"/index.html",
"/style.css",
"/db.js",
"/index.js",
"/manifest.webmanifest"
]);
})
);
self.skipWaiting();
});
// activate
self.addEventListener("activate", function(evt) {
console.log("activated");
evt.waitUntil(
caches.keys().then(keyList => {
return Promise.all(
keyList.map(key => {
if (key !== CACHE_NAME && key !== DATA_CACHE_NAME) {
console.log("Removing old cache data", key);
return caches.delete(key);
}
})
).catch(err => console.log(err));
})
);
self.clients.claim();
});
// fetch
self.addEventListener("fetch", function(evt) {
console.log("fetched", evt.request.url);
if (evt.request.url.includes("/api/")) {
evt.respondWith(
caches
.open(FILES_TO_CACHE)
.then(cache => {
return fetch(evt.request)
.then(response => {
// If the response was good, clone it and store it in the cache.
if (response.status === 200) {
cache.put(evt.request.url, response.clone());
}
return response;
})
.catch(err => {
// Network request failed, try to get it from the cache.
return cache.match(evt.request);
});
})
.catch(err => console.log(err))
);
return;
}
});
link in html:
<script>
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("/service-worker.js").then(function() {
console.log("Service Worker Registered");
});
}
</script>
I also have my manifest linked in the HTML file.
Thank you in advance for any help you can provide!
If you look at the last line of code here:
// fetch
self.addEventListener("fetch", function(evt) {
console.log("fetched", evt.request.url);
if (evt.request.url.includes("/api/")) {
you see that there's a very simple mistake – your Service Worker is ONLY responding to requests that start with "/api/". If they don't, the SW doesn't touch them. Thus only "/api/" calls work offline (which doesn't make any sense :-), apis being mostly dynamic, right?).
(It is possible that there's another bug in the code of course, but this is a good point to start making changes.)
I'm importing these library:
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.8.0/xlsx.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.8.0/jszip.js"></script>
and trying to fetch & parse local file saved in my project folder:
fetch('Eshop_product_list.xlsx').then(res => {
return res.blob();
}).then(res => {
console.log('file:', res);
var workbook = XLSX.read(res, {
type: 'binary'
});
});
But I can't get it working. I've tried different combinations of XLSX type arguments with res.blob(), res.text(), res.bufferArray() but everytime it is throwing an error.
What is the correct way?
Try to use res.arrayBuffer() instead of res.bufferArray()
Replaced in your example:
fetch('Eshop_product_list.xlsx').then(res => {
return res.arrayBuffer();
}).then(res => {
console.log('file:', res);
var workbook = XLSX.read(new Uint8Array(res), {
type: 'array'
});
});
i am currently using braintree hosted fields, to embed the credit cards into my app. i am looking at how i pass the payment nonce from the view to the controller. the javascript i have seems to be triggering the braintree api and returning a nonce to my alert but i just need to now push this through to the controller to execute the final piece of the code
within the controller create method i have
def create
result = Braintree::PaymentMethod.create(
:customer_id => current_user.customer_cim_id,
:payment_method_nonce => nonce_from_the_client,
:cardholder_name => "#{current_user.first_name} #{current_user.last_name}",
:options => {
:make_default => true,
:fail_on_duplicate_payment_method => true
}
)
new view
- title t('.title')
= form_for(#payment_method, :url => myaccount_payment_methods_path(#payment_method), :html => {:id => 'cardForm'}) do |f|
= render :partial => 'form', :locals => {:f => f}
/ Load Hosted Fields component.
%script{:src => '//js.braintreegateway.com/web/3.0.0-beta.10/js/hosted-fields.min.js'}
form view
.mdl-grid
.panel
%header.panel__header
%h1 Card Payment
.panel__content
.textfield--float-label
%label.hosted-field--label{:for => "card-number"}
%i.material-icons credit_card
Card Number
#card-number.hosted-field
.textfield--float-label
%label.hosted-field--label{:for => "expiration-date"}
%i.material-icons date_range
Expiration Date
#expiration-date.hosted-field
.textfield--float-label
%label.hosted-field--label{:for => "cvv"}
%i.material-icons lock
CVV
#cvv.hosted-field
%footer.panel__footer
= f.submit class: 'pay-button', id: 'button-pay', disabled: true
application.js
var form = document.querySelector('#cardForm');
var submit = document.querySelector('input[type="submit"]');
braintree.client.create({
authorization: 'sandbox_92dswc7q_mbmb637xwpzgxbrd'
}, function (err, clientInstance) {
if (err) {
console.error(err);
return;
}
// Create input fields and add text styles
braintree.hostedFields.create({
client: clientInstance,
styles: {
'input': {
'color': '#282c37',
'font-size': '16px',
'transition': 'color 0.1s',
'line-height': '3'
},
// Style the text of an invalid input
'input.invalid': {
'color': '#E53A40'
},
// placeholder styles need to be individually adjusted
'::-webkit-input-placeholder': {
'color': 'rgba(0,0,0,0.6)'
},
':-moz-placeholder': {
'color': 'rgba(0,0,0,0.6)'
},
'::-moz-placeholder': {
'color': 'rgba(0,0,0,0.6)'
},
':-ms-input-placeholder ': {
'color': 'rgba(0,0,0,0.6)'
}
},
// Add information for individual fields
fields: {
number: {
selector: '#card-number',
placeholder: '1111 1111 1111 1111'
},
cvv: {
selector: '#cvv',
placeholder: '123'
},
expirationDate: {
selector: '#expiration-date',
placeholder: '10 / 2019'
}
}
}, function (err, hostedFieldsInstance) {
if (err) {
console.error(err);
return;
}
hostedFieldsInstance.on('validityChange', function (event) {
// Check if all fields are valid, then show submit button
var formValid = Object.keys(event.fields).every(function (key) {
return event.fields[key].isValid;
});
if (formValid) {
$('.pay-button').prop("disabled", false);
} else {
$('.pay-button').prop("disabled", true);
}
});
hostedFieldsInstance.on('empty', function (event) {
$('header').removeClass('header-slide');
$('#card-image').removeClass();
$(form).removeClass();
});
hostedFieldsInstance.on('cardTypeChange', function (event) {
// Change card bg depending on card type
if (event.cards.length === 1) {
$(form).removeClass().addClass(event.cards[0].type);
$('#card-image').removeClass().addClass(event.cards[0].type);
$('header').addClass('header-slide');
// Change the CVV length for AmericanExpress cards
if (event.cards[0].code.size === 4) {
hostedFieldsInstance.setPlaceholder('cvv', '1234');
}
} else {
hostedFieldsInstance.setPlaceholder('cvv', '123');
}
});
submit.addEventListener('click', function (event) {
event.preventDefault();
hostedFieldsInstance.tokenize(function (err, payload) {
if (err) {
console.error(err);
return;
}
// This is where you would submit payload.nonce to your server
alert('Got a nonce: ' + payload.nonce);
// If this was a real integration, this is where you would
// send the nonce to your server.
console.log('Got a nonce: ' + payload.nonce);
});
}, false);
});
});
Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.
Right after your alert line in application.js, you will want to send a request to your server that contains the payment method nonce. For example you can do this with Ajax:
$.ajax({
type: "POST",
url: your_payment_url,
data: {"payment_method_nonce":payload.nonce}
});
Then within your Ruby on Rails controller, you can call Transaction.sale using the payment method nonce in the request to complete the transaction.
For more information on hosted fields, please check out this link.
Edit on Vault question:
If you're using Vault, you can charge users without needing a payment nonce each time. After creating the customer (either through the control panel or through Customer.create, you can retrieve a payment_method_token directly through the payment_methods attribute of the Customer object. To charge the user later, retrieve their payment_method_token on your server and call Transaction.sale, passing in the payment_method_token.
result = Braintree::Transaction.sale(
:amount => "your_amount",
:payment_method_token => "payment_method_token"
)
For example, I bind the resource as follows.
.Resources(resource =>
{
resource.Add(m => m.UserName)
.Title("Staff")
.Name("Staff")
.DataTextField("Text")
.DataValueField("Value")
.DataSource(source => source
.Read(read => read.Action("GetStaffList", "Scheduler"))
);
})
When the editor popups, the staff input has type of dropdown list which contains all the Staff in database.
Question: How to change it to an autocomplete widget with server filtering by staff's name for example.
Thank you.
I would jump into JavaScript by hooking up a event on edit to the grid, then you can do it there doing something like this
function onEdit(e) {
//Autocompleter
$("#Staff").kendoAutoComplete({
dataSource: {
serverFiltering: true,
transport: {
read: { url: "/Staff/GetListForAutocompleter" },
parameterMap: function (data, action) {
var newParams = { filter: $("#Staff").val(), filter2: 'something' };
return newParams;
}
}
}
});
}
My autocomplete is not working and I can't spot the error.
Jquery:
<script>
$(function() {
$('#autoComplete').autocomplete({
//source: "/groceries/items/autoComplete", ///This works but response isn't formatted correctly'
//dataType: "json"
minLength: 2,
source: function( request, response ) {
$.ajax({
url: "/groceries/items/autoComplete",
dataType: "jsonp",
data: {
featureClass: "P",
style: "full",
maxRows: 12,
term: request.term
},
success: function( data ) {
response( $.map( data, function( el ) {
return { label: el.id, value: el.name }
}));
}
});
}
});
});
Controller:
public function autoComplete() {
Configure::write('debug', 0);
$this->layout = 'ajax';
$query = $_GET['term'];
$items = $this->Item->find('all', array(
'conditions' => array('Item.name LIKE' => $query . '%'),
'fields' => array('name', 'id', 'category_id'),
'group' => array('name')));
$this->set('items', $items);
}
Form:
<p>
<?php echo $this->Form->create('Item', array('model'=>'item','action' => 'addItem', 'name'=>'AddItem'));?>
<?php echo $this->Form->text('Item.name', array('size'=>'30', 'id'=>'autoComplete', 'autocomplete'=>'off')); ?>
<?php echo $this->Form->text('Item.category_id', array('type'=>'hidden', 'value'=>'0')); ?>
<?php echo $this->Form->text('Groclist.id', array('type'=>'hidden', 'value'=>$groclist['Groclist']['id'])); ?>
<?php echo $this->Form->end('Add'); ?>
</p>
Response:
0: {Item:{name:Cake, id:6, category_id:null}}
1: {Item:{name:Carrot Cake, id:9, category_id:null}}
2: {Item:{name:Carrots, id:8, category_id:null}}
3: {Item:{name:Casserole, id:11, category_id:null}}
4: {Item:{name:Cauliflower, id:10, category_id:null}}
Edited for clarification.
I realize JqueryUI expects label and value and that map should rearrange them, but for some reason it's not. Any ideas?
I found an even better solution. This is done completely in the controller. No view required.
public function autoComplete() {
Configure::write('debug', 0);
*$this->autoRender=false;*
$this->layout = 'ajax';
$query = $_GET['term'];
$items = $this->Item->find('all', array(
'conditions' => array('Item.name LIKE' => $query . '%'),
'fields' => array('name', 'id', 'category_id'),
'group' => array('name')));
*$i=0;
foreach($items as $item){
$response[$i]['value']="'".$item['Item']['id']."'";
$response[$i]['label']="'".$item['Item']['name']."'";
$i++;
}
echo json_encode($response);*
}
What if you reduce the array that is being returned by the Items model. So instead of $this->set('items', $items); you return the json encoded results like so:
foreach($items as $item) {
$data[] = $item['Item'];
}
$data = json_encode($data);
echo $data;
exit;
This is inside the auto_complete method in the controller.
UPDATE:
When querying for Cake for example, it would return a result like so:
[
{"name":"Cake Batter","id":"1","category_id":"3"},
{"name":"Cake Mix","id":"2","category_id":"3"}
]
if you are not wanting to return the json, you could just return $data without the json encoding.
Format Update:
I am not certain if this is to "sloppy", but you could change the foreach loop to:
foreach($items as $item) {
$data[]= array(
'label' => $item['Item']['name'],
'value' => $item['Item']['id']
);
}
Looks like you forgot the Item:
response($.map( data, function( el ) {
return { label: el.Item.id, value: el.Item.name }
});
You can also do it in the server side using Set:
$this->set('items', Set::extract('/Item', $items));