site.js file
"use strict";
var connection = new signalR.HubConnectionBuilder().withUrl("/radioHub").build();
function processData( ) {
fetch("https://shazam.p.rapidapi.com/songs/detect", {
"method": "POST",
"headers": {
"content-type": "text/plain",
"x-rapidapi-host": "shazam.p.rapidapi.com",
"x-rapidapi-key": "1ab???"
},
"body": "Generate one on your own for testing and send the body with the content-type as text/plain"
})
.then(response => {
console.log(response);
})
.catch(err => {
console.error(err);
});
}
document.getElementById("radioPlayer").disabled = true;
connection.on("ReceiveRadio", function (radio, shazam) {
var li = document.createElement("li");
document.getElementById("songNameList").appendChild(li);
li.textContent = `${radio} return ${shazam}`;
});
connection.start().then(function () {
document.getElementById("radioPlayer").disabled = true;
var radio = document.getElementById("radioPlayer").value;
var shazam = processData();
console.log(shazam)
connection.invoke("SendRadio", radio, shazam).catch(function (err) {
return console.error(err.toString());
});
}).catch(function (err) {
return console.error(err.toString());
});
Hub.cs file
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SignalRCoreServer.Hubs
{
public class ViewHub : Hub
{
public async Task SendRadio(string radio ,string shazam)
{
await Clients.Others.SendAsync("ReceiveRadio",radio, shazam);
}
}
}
index.cshtml
#page
<div class="radio-container">
<div class="radio-header">
</div>
<div class="radio-body">
<div class="shine"></div>
<div class="current-song">
current song
</div>
<div class="row">
<div class="col-2"> </div>
<audio id="radioPlayer" src="https://us4.internet-radio.com/proxy/douglassinclair?mp=/stream;" autoplay="autoplay"></audio>
</div>
</div>
</div>
<script src="~/js/signalr/dist/browser/signalr.js"></script>
<script src="~/js/site.js"></script>
In order to learn the names of the songs playing on the radio, I try to send data to shazam api using the signalR library.
There are hub.cs site.js and index.cshtml files.
(null return null)
result on screen.
it can play song but i couldn't send it to shazam correctly.
What should I do to get the right results?
Related
I'm working on a vanilla javascript project bundled with vitejs everything works fine in development mode however when i run build and preview it with live server, fetching on local json data is not working.
here's the code I'm working on
loadData.js
const initData = {
method: "GET",
headers: {
"Content-Type": "application/json",
},
mode: "cors",
cache: "default",
};
const requestData = new Request("./api/portfolioData.json", initData);
export const loadData = async function fetchData() {
const response = await fetch(requestData);
const data = await response.json();
if (!response.ok) {
return new Error("Not found", response.status);
}
return data;
};
UI project.js
import { loadData } from "../../services/data/loadData";
function Project() {
loadData()
.then((data) => {
let placeholder = document.querySelector(".project-list");
let out ="";
for (let item of data) {
out += `<div class="flip-card" tabindex=${item.id}>
<div class="flip-card-inner">
<div class="flip-card-front">
<img src=${item.image} alt="" />
<h3>${item.title}</h3>
</div>
<div class="flip-card-back">
<h3>
Tech use <i class="fa-sharp fa-solid fa-layer-group"></i>
<br />
<span>${item.techStack}</span>
</h3>
<p>
<span>Description:</span>
${item.description}
</p>
<span class="demo"
><a href=${item.demo} target="_blank"
>demo<i class="fa-solid fa-globe"></i
></a>
<a
href=${item.repo}
target="_blank"
>repo<i class="fa-brands fa-github"></i
></a>
</span>
</div>
</div>
</div>`;
}
placeholder.innerHTML = out;
})
.catch((err) => {
console.log(err);
});
}
export default Project;
I tried to google for solution but there's no luck that works on my case.
i tried to add full path but i'm getting a cors error.
const requestData = new Request("https://localhost:5173/api/portfolioData.json", initData);
Shopping cart with many items how to remove any item asynchronously with JavaScript this is my work so far. Can anyone improve on this?
your help would be greatly appreciated. Have a great day
Ok so this works if you remove items from the top of the list but fails if you remove items from some other place.
The problem seems to be that the form names are all the same "remove" without any indexing.
Problem is I'm not sure how to proceed with this.
document.forms['remove'].onsubmit = () => {
let formData = new FormData(document.forms['remove']);
fetch('/sales/cart?handler=RemoveItem', {
method: 'post',
body: new URLSearchParams(formData)
})
.then(() => {
var url = "/sales/cart?handler=CartPartial";
console.log(url)
$.ajax({
url: url,
success: function (data) {
$("#exampleModal .modal-dialog").html(data);
$("#exampleModal").modal("show");
//alert('Posted using Fetch');
}
});
});
return false;
}
<pre>
#foreach (var item in Model.Items)
{
<form name="remove" method="post">
<h4 class="text-left text-body">#item.Price.ToString("c")
<button class="btn btn-sm" title="Trash"><i style="font-size:large"
class="text-warning icon-Trash"></i></button>
</h4>
<input type="hidden" asp-for="#Model.Id" name="cartId" />
<input type="hidden" asp-for="#item.Id" name="cartItemId" />
</form>
}
</pre>
Update
----------
New markup
I added an index to the id and included an onclick event.
<form method="post" id="#i" onclick="removeItem(this.id)">
<button class="btn btn-sm" title="Trash">Item One</button>
<input type="hidden" asp-for="#Model.Id" name="cartId" />
<input type="hidden" asp-for="#item.Id" name="cartItemId" />
</form>
and create a new function that captured the form id including it in a constant.
<script>
function removeItem(formId) {
const form = document.getElementById(formId);
form.onsubmit = () => {
let formData = new FormData(form);
fetch('/sales/cart?handler=RemoveItem', {
method: 'post',
body: new URLSearchParams(formData)
})
.then(() => {
var url = "/sales/cart?handler=CartPartial";
console.log(url)
$.ajax({
url: url,
success: function (data) {
$("#exampleModal .modal-dialog").html(data);
$("#exampleModal").modal("show");
//alert('Posted using Fetch');
}
});
});
return false;
}
}
</script>
If anybody can improve on this please post it here.
Thanks.
Updates code behind Cart.cshtml.cs
using System;
using System.Threading.Tasks;
using Malawby.Models;
using Malawby.Services.Interfaces;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Malawby.Pages.Sales
{
public class CartModel : PageModel
{
private readonly ICartRepository _cartRepository;
public CartModel(ICartRepository cartRepository)
{
_cartRepository = cartRepository ?? throw new
ArgumentNullException(nameof(cartRepository));
}
[BindProperty]
public Cart Cart { get; set; } = new Cart();
public const string SessionKeyName = "_Name";
public string SessionInfo_Name { get; private set; }
public void OnGetAsync()
{
}
public async Task<PartialViewResult> OnGetCartPartialAsync()
{
var userName = GetUserName();
if (userName != null)
{
Cart = await _cartRepository.GetCartByUserName(userName);
}
return Partial("_ToCart", model: Cart);
}
private string GetUserName()
{
return HttpContext.Session.GetString(SessionKeyName);
}
public async Task OnPostRemoveItemAsync(int cartId, int cartItemId)
{
await _cartRepository.RemoveItem(cartId, cartItemId);
}
}
}
Update 2
This is the modified code I used. This is the error in the console.
XML Parsing Error: no root element found Location: localhost:44331/sales/cart?handler=RemoveItem Line Number 1, Column 1
There is no error on the page just nothing happens on the click of the trash can.
<script type="text/javascript">
function removeItem(cartItemId, cardId) {
var removeUrl = "/sales/cart?handler=RemoveItem";
$.post(removeUrl,
{
cartItemId: cartItemId,
cardId: cardId
})
.done(function (data) {
alert(data); //usually return true or false if true
remove card
$('#card_' + cardId).remove();
});
}
</script>
I am not familiar with asp.net core, but I will show how I usually do it without focusing on syntax.
first on the view no need to add multiple form but should use card id as index and delete button sent selected index like this:
#foreach (var item in Model.Items)
{
<div id="card_#item.cardId">
<h4 class="text-left text-body">#item.Price.ToString("c")
<button class="btn btn-sm" onclick="removeItem('#item.cardId') title="Trash"><i style="font-size:large"
class="text-warning icon-Trash"></i></button>
</h4>
</div>
}
then the script function will call remove api and remove selected card with no need to re-render the page:
<script type="text/javascript">
function removeItem(cardId) {
var removeUrl = "your apiUrl";
$.post( "removeUrl", { cardId: cardId })
.done(function( data ) {
alert( data ); //usually return true or false if true remove card
$('#card_'+ cardId).remove();
});
}
</script>
i try to post with axios from an array to an api php file and get the responses one by one not just one request. I read something about axios.all() but can't figure it out i am new to javascript.
<div id="app">
<center>
<div id="area">
<textarea v-model="sent" name="sent" id="sent" cols="30" rows="10" class="form-control">
</textarea>
<br>
<button v-on:click="insert" class="btn btn-default">Send</button>
</div>
<div id="good" v-for="message of messages">
<span><h2>Good</h2></span>
{{ message }}
</div>
</center>
</div>
And here is the vuejs code.
<script>
new Vue({
el:'#app',
data:{
sent:[],
messages:[]
},
methods:{
insert:function (){
const vm = this;
splitz.forEach(function(entry){
axios.post('/one.php', {
sent: vm.entry
}).then(response => {
vm.messages.push(response.data.onefinal) ;
console.log(response.data);
}
).catch(function(error){ console.log(error); });
}
}
},
computed:{
splitz: function () {
return this.sent.split('\n')
}
}
});
</script>
You can do it this way:
// Create an array of post requests from splitz array
var requests = splitz.map(entry => axios.post('/one.php', { sent: this.entry }))
// Send all requests using axios.all
axios.all(requests)
.then(results => results.map(response => response.data.onefinal))
.then(newMessages => {
console.log('New Messages:', newMessages)
this.messages.push.apply(this.messages, newMessages)
})
Edit: to send the requests one by one:
insert: function() {
var vm = this;
function sendRequest(arr, i) {
var entry = arr[i];
axios.post('/one.php', { sent: entry }).then(function (response) {
vm.messages.push(response.data.onefinal);
if (i < arr.length - 1) {
sendRequest(arr, ++i);
}
})
.catch(function (error) {
console.log(error);
});
}
sendRequest(this.splitz, 0);
}
My thought process:
When the show page opens, get the article's id with JavaScript.
Check this id exist or not in cookie
If not exists, write it into cookie and send an ajax request, the backend updates view times.
If exists, do nothing.
Demo:
View:
<div class="card">
<div class="card-block text-xs-center">
<h5 class="card-title">{{$article->title}}</h5>
<hr class="m-y-2">
<h6 class="card-subtitle text-muted">date:{{$article->created_at->format('Y-m-d')}}
views:{{$article->view_times}}</h6>
</div>
<div class="card-block">
<p class="card-text">{{$article->content}}</p>
</div>
</div>
Controller:
class ArticlesController extends Controller
{
//`show` method
public function show($id)
{
$article = Article::findOrFail($id);
return view('show', compact('article'));
}
//the method of updating view times.
public function statistics(Request $request)
{
$id = $request->input('id');
$article = Article::findOrFail($id);
$view_time=$article->view_time;
$article->view_time=$view_time+1;
$article->save();
}
}
JavaScript:
Vue.http.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name=csrf-token]').getAttribute('content')
Vue.http.options.emulateJSON = true;
var vm = new Vue({
el: "body",
data: function(){
return{
id:[]
}
},
created() {
//1、Get the article's id.Do I have to send an ajax request? Is there any other way?
this.$http.get('article/get-id').then((response) => {
// success callback
this.id=response.data;
}, (response) => {
// error callback
});
//2、After Getting the `id`,check it in cookie,I don't know how to do it?
//3、If not exists,write it into cookie and send an ajax request,how to write the if() sentence?
if(){
var formData = new FormData();
var id=this.id;
formData.append('id',id);
this.$http.patch('article/statistics', formData,{
before(request) {
if (this.previousRequest) {
this.previousRequest.abort();
}
this.previousRequest = request;
}
}).then((response) => {
// success callback
}, (response) => {
// error callback
});
}
}
});
Questions:
There are three questions, shown as comments in JavaScript code above.
I'm trying build an Asp.net web api for posting files. I found the following example in
https://code.msdn.microsoft.com/AngularJS-with-Web-API-22f62a6e
The Web API method is:
[RoutePrefix("api/photo")]
public class PhotoController : ApiController
{
private IPhotoManager photoManager;
public PhotoController()
: this(new LocalPhotoManager(HttpRuntime.AppDomainAppPath + #"\Album"))
{
}
public PhotoController(IPhotoManager photoManager)
{
this.photoManager = photoManager;
}
// GET: api/Photo
public async Task<IHttpActionResult> Get()
{
var results = await photoManager.Get();
return Ok(new { photos = results });
}
// POST: api/Photo
public async Task<IHttpActionResult> Post()
{
// Check if the request contains multipart/form-data.
if(!Request.Content.IsMimeMultipartContent("form-data"))
{
return BadRequest("Unsupported media type");
}
try
{
var photos = await photoManager.Add(Request);
return Ok(new { Message = "Photos uploaded ok", Photos = photos });
}
catch (Exception ex)
{
return BadRequest(ex.GetBaseException().Message);
}
}
And the file uploader html code: (I added a text input <input type="text" id="test" value="testit" /> for test.
<form name="newPhotosForm" role="form" enctype="multipart/form-data" ng-disabled="appStatus.busy || photoManagerStatus.uploading">
<div class="form-group" ng-hide="hasFiles">
<label for="newPhotos">select and upload new photos</label>
<input type="file" id="newPhotos" class="uploadFile" accept="image/*" eg-files="photos" has-files="hasFiles" multiple>
<input type="text" id="test" value="testit" /> <!--- Added a text input for test -->
</div>
<div class="form-group" ng-show="hasFiles && !photoManagerStatus.uploading">
<ul class="list-inline">
<li><strong>files:</strong></li>
<li ng-repeat="photo in photos"> {{photo.name}}</li>
</ul>
<input class="btn btn-primary" type="button" eg-upload="upload(photos)" value="upload">
<input class="btn btn-warning" type="reset" value="cancel" />
</div>
<div class="form-group" ng-show="photoManagerStatus.uploading">
<p class="help-block">uploading</p>
</div>
</form>
The JS upload function:
function upload(photos)
{
service.status.uploading = true;
appInfo.setInfo({ busy: true, message: "uploading photos" });
var formData = new FormData();
angular.forEach(photos, function (photo) {
formData.append(photo.name, photo);
});
return photoManagerClient.save(formData)
.$promise
.then(function (result) {
if (result && result.photos) {
result.photos.forEach(function (photo) {
if (!photoExists(photo.name)) {
service.photos.push(photo);
}
});
}
appInfo.setInfo({message: "photos uploaded successfully"});
return result.$promise;
},
function (result) {
appInfo.setInfo({message: "something went wrong: " + result.data.message});
return $q.reject(result);
})
['finally'](
function () {
appInfo.setInfo({ busy: false });
service.status.uploading = false;
});
}
However, it seems the value of the added input test cannot be passed to the Web API code?
You need to add custom DTO/POCO class, set the values and then pass it as parameter to your post method. Since file is not a simple type default MediaTypeFormatter of webAPI won't work so you need to build your custom MediaTypeFormatter.
Sample POCO class
Public Class Attachment
{
public string Input {get;set;}
public byte[] Content{get;set;}
}
Custom Media formatter as below
public class CustomFormatter : MediaTypeFormatter
{
/// <summary>
///
/// </summary>
public CustomFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data"));
}
public override bool CanReadType(Type type)
{
return type == typeof(Attachment);
}
public override bool CanWriteType(Type type)
{
return false;
}
public async override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
var provider = await content.ReadAsMultipartAsync();
var modelContent = provider.Contents
.FirstOrDefault(c => c.Headers.ContentType.MediaType == "application/json");
var attachment = await modelContent.ReadAsAsync<Attachment>();
var fileContents = provider.Contents
.Where(c => c.Headers.ContentType.MediaType == "image/jpeg").FirstOrDefault(); // or whatever is the type of file to upload
attachment.Content = await fileContents.ReadAsByteArrayAsync();
return attachment;
}
}
Register the custom media formatter:
private void ConfigureWebApi(HttpConfiguration config)
{
//other code here
config.Formatters.Add(new CustomFormatter());
}
Pass the POCO to your Web-API Controller
public async Task<IHttpActionResult> Post(Attachment attachment)
{
I haven't tested this in Visual Studio, but this is the approach you need to follow
More information here:
http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters
And a sample here
http://blog.marcinbudny.com/2014/02/sending-binary-data-along-with-rest-api.html#.V5MDDzV7qYg