In my site, I have a form that users can click on a checkbox to select "available". I want to have "Yes" or "No" returned in the displayArticle function based on whether the box is checked or not. Right now it returns True or False, which is not optimal. How can I code this?
Here is my entire JS code:
App = {
web3Provider: null,
contracts: {},
account: 0x0,
loading: false,
init: function() {
return App.initWeb3();
},
initWeb3: function() {
// initialize web3
if(typeof web3 !== 'undefined') {
//reuse the provider of the Web3 object injected by Metamask
App.web3Provider = web3.currentProvider;
} else {
//create a new provider and plug it directly into our local node
App.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545');
}
web3 = new Web3(App.web3Provider);
App.displayAccountInfo();
return App.initContract();
},
displayAccountInfo: function() {
web3.eth.getCoinbase(function(err, account) {
if(err === null) {
App.account = account;
$('#account').text(account);
web3.eth.getBalance(account, function(err, balance) {
if(err === null) {
$('#accountBalance').text(web3.fromWei(balance, "ether") + " ETH");
}
})
}
});
},
initContract: function() {
$.getJSON('RentalContract.json', function(chainListArtifact) {
//added May24 to json file name
// get the contract artifact file and use it to instantiate a truffle contract abstraction
App.contracts.RentalContract = TruffleContract(chainListArtifact);
// set the provider for our contracts
App.contracts.RentalContract.setProvider(App.web3Provider);
// listen to events
App.listenToEvents();
// retrieve the article from the contract
return App.reloadArticles();
});
},
reloadArticles: function() {
//avoid reentry bugs
if(App.loading){
return;
}
App.loading = true;
// refresh account information because the balance might have changed
App.displayAccountInfo();
var chainListInstance;
App.contracts.RentalContract.deployed().then(function(instance) {
chainListInstance = instance;
return chainListInstance.getArticlesForSale();
}).then(function(articlesIds) {
// retrieve the article placeholder and clear it
$('#articlesRow').empty();
for(var i = 0; i < articlesIds.length; i++){
var articleId = articlesIds[i];
chainListInstance.articles(articleId.toNumber()).then(function(article){
App.displayArticle(article[0], article[1], article[3], article[4], article[5], article[6], article[7]);
});
}
App.loading = false;
}).catch(function(err) {
console.error(err.message);
App.loading = false;
});
},
//displayArticle: function(id, seller, beds, baths, propaddress, rental_price, property_type, description, available, contact_email) {
displayArticle: function(id, seller, propaddress, rental_price, description, available, contact) {
var articlesRow = $('#articlesRow');
//var etherPrice = web3.fromWei(price, "ether");
var articleTemplate = $("#articleTemplate");
//articleTemplate.find('.panel-title').text(propaddress);
//articleTemplate.find('.beds').text(beds);
//articleTemplate.find('.baths').text(baths);
articleTemplate.find('.propaddress').text(propaddress);
articleTemplate.find('.rental_price').text('$' + rental_price);
//articleTemplate.find('.property_type').text(property_type);
articleTemplate.find('.description').text(description);
articleTemplate.find('.available').text(available);
articleTemplate.find('.contact').text(contact);
// articleTemplate.find('.article_price').text(etherPrice + " ETH");
articleTemplate.find('.btn-buy').attr('data-id', id);
// articleTemplate.find('.btn-buy').attr('data-value', etherPrice);
//seller
if(seller == App.account){
articleTemplate.find('.article-seller').text("You");
articleTemplate.find('.btn-buy').hide();
}else{
articleTemplate.find('.article-seller').text(seller);
articleTemplate.find('.btn-buy').show();
}
//add this new article
articlesRow.append(articleTemplate.html());
},
sellArticle: function() {
// retrieve the detail of the article
// var _article_name = $('#article_name').val();
var _description = $('#description').val();
//var _beds = $('#beds').val();
//var _baths = $('#baths').val();
var _propaddress = $('#propaddress').val();
var _rental_price = $('#rental_price').val();
//var _property_type = $('#property_type').val();
var _available = $('#available').val();
var _contact = $('#contact').val();
// var _article_price = $('#article_price').val();
// var _price = web3.toWei(parseFloat($('#article_price').val() || 0), "ether");
// if((_description.trim() == '') || (rental_price == 0)) {
// nothing to sell
// return false;
// }
App.contracts.RentalContract.deployed().then(function(instance) {
//return instance.sellArticle(_description, _beds, _baths, _propaddress, _rental_price, _property_type, _available, _contact_email, {
return instance.sellArticle(_propaddress, _rental_price, _description, _available, _contact,{
from: App.account,
gas: 500000
});
}).then(function(result) {
}).catch(function(err) {
console.error(err);
});
},
// listen to events triggered by the contract
listenToEvents: function() {
App.contracts.RentalContract.deployed().then(function(instance) {
instance.LogSellArticle({}, {}).watch(function(error, event) {
if (!error) {
$("#events").append('<li class="list-group-item">' + event.args._propaddress + ' is now for sale</li>');
} else {
console.error(error);
}
App.reloadArticles();
});
instance.LogBuyArticle({}, {}).watch(function(error, event) {
if (!error) {
$("#events").append('<li class="list-group-item">' + event.args._buyer + ' bought ' + event.args._propaddress + '</li>');
} else {
console.error(error);
}
App.reloadArticles();
});
});
},
buyArticle: function() {
event.preventDefault();
// retrieve the article price and data
var _articleId = $(event.target).data('id');
var _price = parseFloat($(event.target).data('value'));
App.contracts.RentalContract.deployed().then(function(instance){
return instance.buyArticle(_articleId, {
from: App.account,
value: web3.toWei(_price, "ether"),
gas: 500000
});
}).catch(function(error) {
console.error(error);
});
}
};
$(function() {
$(window).load(function() {
App.init();
});
});
If I understand what you're trying to do, perhaps this will work for you.
var isChecked = '';
if (articleTemplate.find('.available').checked === true)
{ isChecked = 'yes'} else
{ isChecked = 'no'}
.
.
.
return isChecked;
Do this:
articleTemplate.find( '.available' ).text( available ? 'Yes' : 'No' );
Example:
function returnValue() {
$( '#val' ).text( $( '#chk' ).is( ':checked' ) ? 'Yes' : 'No' )
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" id="chk" onclick="returnValue()" />
<label for="chk">Available</label>
<h2 id="val"></h2>
Related
I'm using the TomTom FuzzySearch/Autocomplete API, to allow users to search for an address on a form and then the address input fields will prepopulate (with the address values), when the user selects an address.
My API call works absolutely fine and the input fields display the correct values.
The problem I have, is the input fields remain untouched, despite the fields having a value. (If I type document.getElementById("house-number-textbox").value, a value is returned).
How can I turned the input fields to be touched, when the input values are applied?
I noticed, if I type something in the input field, after my input values have been added, only then does the form register my inputs as valid/touched.
PS - The reason I am injecting my scripts is because I'm using an AB Testing tool. So despite the form/application being AngularJS, I can only manipulate the form via the AB Testing tool, (on top of the compiled codebase - hence why I'm using vanilla JS).
Here's my code:
function waitForElement(className, callBack){
window.setTimeout(function(){
var element = document.getElementById(className);
if(element) {
callBack(className, element);
} else {
waitForElement(className, callBack);
}
},2000)
};
// LOAD API SCRIPTS
function loadScript(scriptUrl) {
const script = document.createElement('script');
script.src = scriptUrl;
document.body.appendChild(script);
return new Promise((res, rej) => {
script.onload = function() {
res();
}
script.onerror = function () {
rej();
}
});
};
// RESULTS MANAGER
function appendParentSelector(parentSelector, selector) {
return parentSelector ? parentSelector + ' ' + selector : selector;
}
function ResultsManager(resultsElementSelector) {
this.resultsElement = document.querySelector(appendParentSelector(resultsElementSelector, '.js-results'));
this.resultsPlaceholder =
document.querySelector(appendParentSelector(resultsElementSelector, '.js-results-placeholder'));
this.resultsLoader = document.querySelector(appendParentSelector(resultsElementSelector, '.js-results-loader'));
}
ResultsManager.prototype.loading = function() {
this.resultsLoader.removeAttribute('hidden');
this.resultsElement.setAttribute('hidden', 'hidden');
this.resultsPlaceholder.setAttribute('hidden', 'hidden');
this.resultsElement.innerHTML = '';
};
ResultsManager.prototype.success = function() {
this.resultsLoader.setAttribute('hidden', 'hidden');
this.resultsElement.removeAttribute('hidden');
};
ResultsManager.prototype.resultsNotFound = function() {
this.resultsElement.setAttribute('hidden', 'hidden');
this.resultsLoader.setAttribute('hidden', 'hidden');
this.resultsPlaceholder.removeAttribute('hidden');
};
ResultsManager.prototype.append = function(element) {
this.resultsElement.appendChild(element);
};
ResultsManager.prototype.clear = function() {
for (var i = 0; i < this.resultsElement.children.length; i++) {
this.resultsElement.removeChild(this.resultsElement.children[i]);
}
};
waitForElement("house-number-textbox",function(){
console.log("WAIT FOR ELEMENT DONE");
window.ResultsManager = window.ResultsManager || ResultsManager;
console.log("document.getElementById(component)", document.getElementById("house-number-textbox") );
// use
loadScript('https://api.tomtom.com/maps-sdk-for-web/cdn/plugins/SearchBox/2.24.2//SearchBox-web.js')
.then(() => {
console.log('Script loaded!');
})
.catch(() => {
console.error('Script loading failed! Handle this error');
});
// use
loadScript('https://api.tomtom.com/maps-sdk-for-web/cdn/5.x/5.64.0/services/services-web.min.js')
.then(() => {
console.log('Script loaded!');
// HANDLE RESULTS
tt.setProductInfo('ABTest', '1');
// Options for the fuzzySearch service
var searchOptions = {
key: 'XXX',
language: 'en-Gb',
limit: 10,
countrySet: "GB"
};
var searchBoxOptions = {
minNumberOfCharacters: 1,
searchOptions: searchOptions
// autocompleteOptions: autocompleteOptions
};
var ttSearchBox = new tt.plugins.SearchBox(tt.services, searchBoxOptions);
document.querySelector('.tt-side-panel__header').appendChild(ttSearchBox.getSearchBoxHTML());
let componentForm = {
// streetName: "house-number-textbox",
municipalitySubdivision: "street-name-textbox",
localName: "town-city-textbox",
extendedPostalCode: "postcode-textbox"
};
function SidePanel(selector) {
// this.map = map;
this.element = document.querySelector(selector);
}
new SidePanel('.tt-side-panel');
var resultsManager = new ResultsManager();
ttSearchBox.on('tomtom.searchbox.resultscleared', handleResultsCleared);
ttSearchBox.on('tomtom.searchbox.resultsfound', handleResultsFound);
ttSearchBox.on('tomtom.searchbox.resultfocused', handleResultSelection);
ttSearchBox.on('tomtom.searchbox.resultselected', handleResultSelection);
function handleResultsCleared() {
resultsManager.clear();
}
// HANDLE RESULST
function handleResultsFound(event) {
// Display fuzzySearch results if request was triggered by pressing enter
if (event.data.results && event.data.results.fuzzySearch && event.data.metadata.triggeredBy === 'submit') {
var results = event.data.results.fuzzySearch.results;
if (results.length === 0) {
handleNoResults();
}
resultsManager.success();
console.log("results", results);
}
if (event.data.errors) {
console("event.data.errors", event.data.errors);
}
}
// RESPONSE
function handleResultSelection(event) {
if (isFuzzySearchResult(event)) {
// Display selected result on the map
var result = event.data.result;
console.log("THIS result", result);
;
resultsManager.success();
for (const component in componentForm) {
console.log("componentForm", componentForm);
document.getElementById(componentForm[component]).value = result.address[component];
document.getElementById(componentForm[component]).disabled = false;
console.log('component', componentForm[component]);
if (document.getElementById(componentForm[component]).value === 'undefined') {
document.getElementById(componentForm[component]).value = "";
}
};
if (result.address.streetNumber) {
document.getElementById("house-number-textbox").value = result.address.streetNumber + " " + result.address.streetName;
} else {
document.getElementById("house-number-textbox").value = result.address.streetName;
};
};
}
function isFuzzySearchResult(event) {
return !('matches' in event.data.result);
}
function handleNoResults() {
resultsManager.clear();
resultsManager.resultsNotFound();
searchMarkersManager.clear();
infoHint.setMessage(
'No results for "' +
ttSearchBox.getValue() +
'" found nearby. Try changing the viewport.'
);
};
document.querySelector(".tt-search-box-input").setAttribute("placeholder", "Enter your address...");
})
.catch(() => {
console.error('Script loading failed! Handle this error');
});
});
I am trying to save data using ajax. The ajax is inside my javascript file and passed to my controller and route. However the issue is it cannot save the data into my database.
Here is my jquery.hotspot.js file that include ajax:
(function ($) {
var defaults = {
// Object to hold the hotspot data points
data: [],
// Element tag upon which hotspot is (to be) build
tag: 'img',
// Specify mode in which the plugin is to be used
// `admin`: Allows to create hotspot from UI
// `display`: Display hotspots from `data` object
mode: 'display',
// HTML5 LocalStorage variable where hotspot data points are (will be) stored
LS_Variable: '__HotspotPlugin_LocalStorage',
// CSS class for hotspot data points
hotspotClass: 'HotspotPlugin_Hotspot',
// CSS class which is added when hotspot is to hidden
hiddenClass: 'HotspotPlugin_Hotspot_Hidden',
// Event on which the hotspot data point will show up
// allowed values: `click`, `hover`, `none`
interactivity: 'hover',
// Action button CSS classes used in `admin` mode
save_Button_Class: 'HotspotPlugin_Save',
remove_Button_Class: 'HotspotPlugin_Remove',
send_Button_Class: 'HotspotPlugin_Send',
// CSS class for hotspot data points that are yet to be saved
unsavedHotspotClass: 'HotspotPlugin_Hotspot_Unsaved',
// CSS class for overlay used in `admin` mode
hotspotOverlayClass: 'HotspotPlugin_Overlay',
// Enable `ajax` to read data directly from server
ajax: false,
ajaxOptions: { url: '' },
listenOnResize: true,
// Hotspot schema
schema: [
{
'property': 'Title',
'default': ''
},
{
'property': 'Message',
'default': ''
}
]
};
// Constructor
function Hotspot(element, options) {
var widget = this;
// Overwriting defaults with options
this.config = $.extend(true, {}, defaults, options);
this.element = element;
// `tagElement`: element for which hotspots are being done
this.tagElement = element.find(this.config.tag);
// Register event listeners
$.each(this.config, function (index, fn) {
if (typeof fn === 'function') {
widget.element.on(index + '.hotspot', function (event, err, data) {
fn(err, data);
});
}
});
if (this.config.mode != 'admin' && this.config.listenOnResize) {
$(window).on('resize', function () {
$(element).find('.' + widget.config.hotspotClass).remove();
widget.init();
});
}
if (this.config.tag !== 'img') {
widget.init();
return;
}
if (this.tagElement.prop('complete')) {
widget.init();
} else {
this.tagElement.one('load', function (event) {
widget.init();
});
}
}
Hotspot.prototype.init = function () {
this.parseData();
// Fetch data for `display` mode with `ajax` enabled
if (this.config.mode != 'admin' && this.config.ajax) {
this.fetchData();
}
// Nothing else to do here for `display` mode
if (this.config.mode != 'admin') {
return;
}
this.setupWorkspace();
};
Hotspot.prototype.createId = function () {
var id = "";
var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
for (var i = 0; i < 7; i++) {
id += letters.charAt(Math.floor(Math.random() * letters.length));
}
return id;
};
Hotspot.prototype.setupWorkspace = function () {
var widget = this;
// `data` array: to contain hotspot objects
var data = [];
var tHeight = $(widget.tagElement[0]).height(),
tWidth = $(widget.tagElement[0]).width(),
tOffset = widget.tagElement.offset(),
pHeight = $(widget.element[0]).height(),
pWidth = $(widget.element[0]).width(),
pOffset = widget.element.offset();
// Create overlay for the tagElement
$('<span/>', {
html: '<p>Click this Panel to Store Messages</p>'
}).css({
'height': (tHeight / pHeight) * 100 + '%',
'width': (tWidth / pWidth) * 100 + '%',
'left': (tOffset.left - pOffset.left) + 'px',
'top': (tOffset.top - pOffset.top) + 'px'
}).addClass(widget.config.hotspotOverlayClass).appendTo(widget.element);
// Handle click on overlay mask
this.element.delegate('span', 'click', function (event) {
event.preventDefault();
event.stopPropagation();
// Get coordinates
var offset = $(this).offset(),
relativeX = (event.pageX - offset.left),
relativeY = (event.pageY - offset.top);
var height = $(widget.tagElement[0]).height(),
width = $(widget.tagElement[0]).width();
var hotspot = { x: relativeX / width * 100, y: relativeY / height * 100 };
var schema = widget.config.schema;
for (var i = 0; i < schema.length; i++) {
var val = schema[i];
var fill = prompt('Please enter ' + val.property, val.default);
if (fill === null) {
return;
}
hotspot[val.property] = fill;
}
data.push(hotspot);
// Temporarily display the spot
widget.displaySpot(hotspot, true);
});
// Register admin controls
var button_id = this.createId();
$('<button/>', {
text: "Save data"
}).prop('id', ('save' + button_id)).addClass(this.config.save_Button_Class).appendTo(this.element);
$('<button/>', {
text: "Remove data"
}).prop('id', ('remove' + button_id)).addClass(this.config.remove_Button_Class).appendTo(this.element);
$(this.element).delegate('button#' + ('save' + button_id), 'click', function (event) {
event.preventDefault();
event.stopPropagation();
widget.saveData(data);
data = [];
});
$(this.element).delegate('button#' + ('remove' + button_id), 'click', function (event) {
event.preventDefault();
event.stopPropagation();
widget.removeData();
});
if (this.config.ajax) {
$('<button/>', {
text: "Send to server"
}).prop('id', ('send' + button_id)).addClass(this.config.send_Button_Class).appendTo(this.element);
$(this.element).delegate('button#' + ('send' + button_id), 'click', function (event) {
event.preventDefault();
event.stopPropagation();
widget.sendData();
});
}
};
Hotspot.prototype.fetchData = function () {
var widget = this;
// Fetch data from a server
var options = {
data: {
HotspotPlugin_mode: "Retrieve"
}
};
$.ajax($.extend({}, this.config.ajaxOptions, options))
.done(function (data) {
// Storing in localStorage
localStorage.setItem(widget.config.LS_Variable, data);
widget.parseData();
})
.fail($.noop);
};
Hotspot.prototype.parseData = function () {
var widget = this;
var data = this.config.data,
data_from_storage = localStorage.getItem(this.config.LS_Variable);
if (data_from_storage && (this.config.mode === 'admin' || !this.config.data.length)) {
data = JSON.parse(data_from_storage);
}
$.each(data, function (index, hotspot) {
widget.displaySpot(hotspot);
});
};
Hotspot.prototype.displaySpot = function (hotspot, unsaved) {
var widget = this;
var spot_html = $('<div/>');
$.each(hotspot, function (index, val) {
if (typeof val === "string") {
$('<div/>', {
html: val
}).addClass('Hotspot_' + index).appendTo(spot_html);
}
});
var height = $(this.tagElement[0]).height(),
width = $(this.tagElement[0]).width(),
offset = this.tagElement.offset(),
parent_offset = this.element.offset();
var spot = $('<div/>', {
html: spot_html
}).css({
'top': (hotspot.y * height / 100) + (offset.top - parent_offset.top) + 'px',
'left': (hotspot.x * width / 100) + (offset.left - parent_offset.left) + 'px'
}).addClass(this.config.hotspotClass).appendTo(this.element);
if (unsaved) {
spot.addClass(this.config.unsavedHotspotClass);
}
if (this.config.interactivity === 'hover') {
return;
}
// Overwrite CSS rule for `none` & `click` interactivity
spot_html.css('display', 'block');
// Initially keep hidden
if (this.config.interactivity !== 'none') {
spot_html.addClass(this.config.hiddenClass);
}
if (this.config.interactivity === 'click') {
spot.on('click', function (event) {
spot_html.toggleClass(widget.config.hiddenClass);
});
} else {
spot_html.removeClass(this.config.hiddenClass);
}
};
Hotspot.prototype.saveData = function (data) {
if (!data.length) {
return;
}
// Get previous data
var raw_data = localStorage.getItem(this.config.LS_Variable);
var hotspots = [];
if (raw_data) {
hotspots = JSON.parse(raw_data);
}
// Append to previous data
$.each(data, function (index, node) {
hotspots.push(node);
});
this.data=data;
$.ajax({
type:"POST",
url:"/store",
dataType:'json',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
data:{
Title:$('#Title').val(),
Message: $('#Message').val(),
x:$('#relativeX').val(),
y: $('#relativeY').val(),
},
success: function(data){
console.log(data,d);
},
error: function(data)
{
console.log(data);
},
});
localStorage.setItem(this.config.LS_Variable, JSON.stringify(hotspots));
this.element.trigger('afterSave.hotspot', [null, hotspots]);
};
Hotspot.prototype.removeData = function () {
if (localStorage.getItem(this.config.LS_Variable) === null) {
return;
}
if (!confirm("Are you sure you wanna do everything?")) {
return;
}
localStorage.removeItem(this.config.LS_Variable);
this.element.trigger('afterRemove.hotspot', [null, 'Removed']);
};
Hotspot.prototype.sendData = function () {
if (localStorage.getItem(this.config.LS_Variable) === null || !this.config.ajax) {
return;
}
var widget = this;
var options = {
data: {
HotspotPlugin_data: localStorage.getItem(this.config.LS_Variable),
HotspotPlugin_mode: "Store"
}
};
$.ajax($.extend({}, this.config.ajaxOptions, options))
.done(function () {
widget.element.trigger('afterSend.hotspot', [null, 'Sent']);
})
.fail(function (err) {
widget.element.trigger('afterSend.hotspot', [err]);
});
};
$.fn.hotspot = function (options) {
new Hotspot(this, options);
return this;
};
}(jQuery));
Here is my route:
Route::get('hotspots','ImageController#getPin');
Route::post('store','ImageController#storePin')->name('store.storePin');
Here is my ImageController.php:
public function getPin()
{
$pin= Pin::select('Title','Message','x','y');
return hotspot::of($pin)->make(true);
}
public function storePin(Request $request)
{
$validation = Validator::make($request->all(), [
'Title' => 'required',
'Message' => 'required',
'x'=>'required',
'y'=>'required',
]);
if ($request->get('save','button_id') == "insert")
{
$pin = new Pin();
$pin->Title=$request->Title;
$pin->Message= $request->Message;
$pin->x = $request->relativeX;
$pin->y =$request->relativeY;
$pin->save();
//return Request::json($request);
}
}
Here is my hotspot.blade.php:
<!DOCTYPE html>
<html>
<head>
<title>Picomment Hotspot</title>
<link rel="stylesheet" type="text/css" href="{{ asset ('css/bootsrap.min.css') }}">
<script type="text/javascript" src="{{ asset ('js/jquery.min.js') }}"></script>
<link rel="stylesheet" type="text/css" href="{{ asset ('css/jquery.hotspot.css') }}">
<link rel="stylesheet" type="text/css" href="{{ asset ('css/style.css') }}">
<meta name="csrf-token" content="{{ csrf_token() }}">
</head>
<body>
<div class="container">
<div class="col-md-6" style="margin-top: 40px;">
<div id="theElement-a">
<img src="{{ asset('storage/'.$files) }}" alt="" title="">
</div>
</div>
</div>
<script type="text/javascript" src="{{ asset ('js/jquery.hotspot.js') }}"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#theElement-a").hotspot({
mode: "admin",
// uncomment
/*ajax: true,
ajaxOptions: {
'url': 'links.to.server'
},*/
interactivity: "click",
LS_Variable: "HotspotPlugin-a",
afterSave: function(err, data) {
if (err) {
console.log('Error occurred', err);
return;
}
alert('Saved');
// `data` in json format can be stored
// & passed in `display` mode for the image
localStorage.clear();
console.log(data);
},
afterRemove: function(err, message) {
if (err) {
console.log('Error occurred', err);
return;
}
alert(message);
window.location.reload();
},
afterSend: function(err, message) {
if (err) {
console.log('Error occurred', err);
return;
}
alert(message);
}
});
});
</script>
</body>
</html>
Using the google chrome Api extension, I have the following code that show notification from JSON. Once notification is show, and when I clicked on it opened multiple tabs url (It's an error). I need to solve that problem because this should open only one tab url, this is the only problem. look the code below:
var timeChange = 1000, jsons = ['JSON_URL'];
updateValue = function() {
var colorStatus = 0;
chrome.storage.local.get(function (dataStorage) {
$.getJSON(jsons+'?'+$.now(), function (data) {
var jLastPost = {'LastNotification':''}, sizePost = (data.results.length - 1), dataLastPost = data.results[0];
totalEntradas = data.totalEntradas ? data.totalEntradas : '';
$.each(data.results, function (k,v) {
if (($.inArray('post-'+v.id, dataStorage.IDs) !== -1) && (v.date_status > 0)) {
colorStatus = 1;
}
});
chrome.browserAction.setBadgeText({'text': totalEntradas.toString()});
if (dataStorage.LastNotification !== dataLastPost.id)
{
jLastPost.LastNotification = dataLastPost.id;
chrome.storage.local.set(jLastPost);
chrome.notifications.create(dataLastPost.id,{
type: 'basic',
title: dataLastPost.titulo,
message: 'Now for you!',
iconUrl: dataLastPost.image
}, function (id) {});
chrome.notifications.onClicked.addListener(function () {
chrome.tabs.create({url: dataLastPost.uri});
});
chrome.notifications.clear(dataLastPost.id, function() {});
return false;
}
});
});
setTimeout(updateValue, timeChange);
}
updateValue();
You are attaching a chrome.notifications.onClicked listener every second when you run updateValue. At a minimum you should move the listener outside of the method.
Something along these lines should work.
var timeChange = 1000, jsons = ['JSON_URL'];
var lastPostUri;
chrome.notifications.onClicked.addListener(function () {
if (lastPostUri) {
chrome.tabs.create({url: lastPostUri});
}
});
updateValue = function() {
var colorStatus = 0;
chrome.storage.local.get(function (dataStorage) {
$.getJSON(jsons+'?'+$.now(), function (data) {
var jLastPost = {'LastNotification':''}, sizePost = (data.results.length - 1), dataLastPost = data.results[0];
totalEntradas = data.totalEntradas ? data.totalEntradas : '';
$.each(data.results, function (k,v) {
if (($.inArray('post-'+v.id, dataStorage.IDs) !== -1) && (v.date_status > 0)) {
colorStatus = 1;
}
});
chrome.browserAction.setBadgeText({'text': totalEntradas.toString()});
if (dataStorage.LastNotification !== dataLastPost.id)
{
jLastPost.LastNotification = dataLastPost.id;
chrome.storage.local.set(jLastPost);
lastPostUri = dataLastPost.uri
chrome.notifications.create(dataLastPost.id,{
type: 'basic',
title: dataLastPost.titulo,
message: 'Now for you!',
iconUrl: dataLastPost.image
}, function (id) {});
chrome.notifications.clear(dataLastPost.id, function() {});
return false;
}
});
});
setTimeout(updateValue, timeChange);
}
updateValue();
Hi i'm relatively new to JavaScript and i'm working on a winjs app project where i want to use the Bing image search data source example in my project to virtualize the datasource of a listview.
My problem is understanding how the asynchronous functions work together and how to implement an async xhr request within the existing one.
Currently i'm using a synchronous request but i would like to change that into a asynchronous one.
This is my data adapter:
(function () {
var xxxDataAdapter = WinJS.Class.define(
function (devkey, query, delay) {
this._minPageSize = 2;
this._maxPageSize = 5;
this._maxCount = 50;
this._devkey = devkey;
this._query = query;
this._delay = 0;
},
{
getCount: function () {
var that = this;
var requestStr = 'http://xxx/' + that._query;
return WinJS.xhr({ url: requestStr, type: "GET", /*user: "foo", password: that._devkey,*/ }).then(
function (request) {
var obj = JSON.parse(request.responseText);
if (typeof obj.error === "undefined") {
var count = obj.length;
if (count === 0) { console.log("The search returned 0 results.", "sample", "error"); }
return count;
} else {
console.log("Error fetching results from API", "sample", "error");
return 0;
}
},
function (request) {
if (request && request.name === "Canceled") {
return WinJS.Promise.wrapError(request);
} else {
if (request.status === 401) {
console.log(request.statusText, "sample", "error");
} else {
console.log("Error fetching data from the service. " + request.responseText, "sample", "error");
}
return 0;
}
});
},
itemsFromIndex: function (requestIndex, countBefore, countAfter)
{
var that = this;
if (requestIndex >= that._maxCount) {
return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist));
}
var fetchSize, fetchIndex;
if (countBefore > countAfter) {
//Limit the overlap
countAfter = Math.min(countAfter, 0);
//Bound the request size based on the minimum and maximum sizes
var fetchBefore = Math.max(Math.min(countBefore, that._maxPageSize - (countAfter + 1)), that._minPageSize - (countAfter + 1));
fetchSize = fetchBefore + countAfter + 1;
fetchIndex = requestIndex - fetchBefore;
} else {
countBefore = Math.min(countBefore, 10);
var fetchAfter = Math.max(Math.min(countAfter, that._maxPageSize - (countBefore + 1)), that._minPageSize - (countBefore + 1));
fetchSize = countBefore + fetchAfter + 1;
fetchIndex = requestIndex - countBefore;
}
var requestStr = 'http://xxx/' + that._query;
return WinJS.xhr({ url: requestStr, type: "GET", /*user: "foo", password: that._devkey,*/ }).then(
function (request)
{
var results = [], count;
var obj = JSON.parse(request.responseText);
if (typeof obj.error === "undefined")
{
var items = obj;
for (var i = 0, itemsLength = items.length; i < itemsLength; i++)
{
var dataItem = items[i];
var req = new XMLHttpRequest();
// false = synchronous
req.open("get", "http://xxxxx/" + dataItem.id, false);
req.send();
var jobj = JSON.parse(req.response);
if (typeof jobj.error === "undefined")
{
results.push({
key: (fetchIndex + i).toString(),
data: {
title: jobj.name.normal,
date: Date.jsonFormat(dataItem.calculatedAt, "Do, MMM HH:mm Z"),
result: "",
status: "",
}
});
}
}
return {
items: results, // The array of items
offset: requestIndex - fetchIndex, // The offset into the array for the requested item
};
} else {
console.log(request.statusText, "sample", "error");
return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist));
}
},
function (request)
{
if (request.status === 401) {
console.log(request.statusText, "sample", "error");
} else {
console.log("Error fetching data from the service. " + request.responseText, "sample", "error");
}
return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.noResponse));
}
);
}
});
WinJS.Namespace.define("xxx", {
datasource: WinJS.Class.derive(WinJS.UI.VirtualizedDataSource, function (devkey, query, delay) {
this._baseDataSourceConstructor(new xxxDataAdapter(devkey, query, delay));
})
});
})();
And this is the synchronous request i would like to change to an asynchronous one:
var req = new XMLHttpRequest();
// false = synchronous
req.open("get", "http://xxxxx/" + dataItem.id, false);
req.send();
you can use then function to chain promises. In your scenario, then function need to simple have a if statement.
return WinJS.xhr(params).then(function (req)
{
if (..)
return WinJS.xhr(params2);
else
return; // then function ensures wrapping your sync result in a completed promise
}, function onerror(e)
{
// todo - error handling code e.g. showing a message box based on your app requirement
});
This is what i came up with. Map the json objects received asynchronously and make another asynchronous call for each object to get additional data. Then the nested async calls are joined and returned when all are finished.
return WinJS.xhr({ url: 'http://xxx=' + that._query }).then(function (request) {
var results = [];
var obj = JSON.parse(request.responseText);
var xhrs = obj.map(function (dataItem, index) {
return WinJS.xhr({ url: 'http://xxxx' + dataItem.attrx }).then(
function completed(nestedRequest) {
var xxJobj = JSON.parse(nestedRequest.responseText);
var dataObj = {};
dataObj.title = xxJobj.name;
dataObj.date = Date.jsonFormat(dataItem.attrtrxx, "Do, MMM HH:mm Z");
dataObj.result = "open";
dataObj.status = "foo";
if (dataItem.xx.hasOwnProperty("attrx5")) {
dataObj.opponent = dataItem.attrx4;
} else {
dataObj.opponent = dataItem.attrx3;
}
dataObj.page_title = "xXx";
dataObj.match_id = dataItem.id;
dataObj.type = "largeListIconTextItem";
dataObj.bg_image = "http://xxx/" + xxJobj.attrx2 + "-portrait.jpg";
results.push({
key: (fetchIndex + index).toString(),
data: dataObj
});
},
function (err) {
console.log(err.status);
console.log(err.responseText);
}
);
});
return WinJS.Promise.join(xhrs).then(
function (promises) {
return {
items: results, // The array of items
offset: requestIndex - fetchIndex, // The offset into the array for the requested item
};
},
function (err) {
console.log(JSON.stringify(err));
}
);
});
I am trying to render a pdf in chrome using PDFJS
This is the function I am calling:
open: function pdfViewOpen(url, scale, password) {
var parameters = {password: password};
if (typeof url === 'string') { // URL
this.setTitleUsingUrl(url);
parameters.url = url;
} else if (url && 'byteLength' in url) { // ArrayBuffer
parameters.data = url;
}
if (!PDFView.loadingBar) {
PDFView.loadingBar = new ProgressBar('#loadingBar', {});
}
this.pdfDocument = null;
var self = this;
self.loading = true;
getDocument(parameters).then(
function getDocumentCallback(pdfDocument) {
self.load(pdfDocument, scale);
self.loading = false;
},
function getDocumentError(message, exception) {
if (exception && exception.name === 'PasswordException') {
if (exception.code === 'needpassword') {
var promptString = mozL10n.get('request_password', null,
'PDF is protected by a password:');
password = prompt(promptString);
if (password && password.length > 0) {
return PDFView.open(url, scale, password);
}
}
}
var loadingErrorMessage = mozL10n.get('loading_error', null,
'An error occurred while loading the PDF.');
if (exception && exception.name === 'InvalidPDFException') {
// change error message also for other builds
var loadingErrorMessage = mozL10n.get('invalid_file_error', null,
'Invalid or corrupted PDF file.');
//#if B2G
// window.alert(loadingErrorMessage);
// return window.close();
//#endif
}
var loadingIndicator = document.getElementById('loading');
loadingIndicator.textContent = mozL10n.get('loading_error_indicator',
null, 'Error');
var moreInfo = {
message: message
};
self.error(loadingErrorMessage, moreInfo);
self.loading = false;
},
function getDocumentProgress(progressData) {
self.progress(progressData.loaded / progressData.total);
}
);
}
This is the call:
PDFView.open('/MyPDFs/Pdf2.pdf', 'auto', null);
All I get is this:
If you notice, even the page number is retrieved but the content is not painted in the pages. CanĀ“t find why.. Is the any other function I should call next to PDFView.open?
Found the solution...!
This is the code that does the work.
$(document).ready(function () {
PDFView.initialize();
var params = PDFView.parseQueryString(document.location.search.substring(1));
//#if !(FIREFOX || MOZCENTRAL)
var file = params.file || DEFAULT_URL;
//#else
//var file = window.location.toString()
//#endif
//#if !(FIREFOX || MOZCENTRAL)
if (!window.File || !window.FileReader || !window.FileList || !window.Blob) {
document.getElementById('openFile').setAttribute('hidden', 'true');
} else {
document.getElementById('fileInput').value = null;
}
//#else
//document.getElementById('openFile').setAttribute('hidden', 'true');
//#endif
// Special debugging flags in the hash section of the URL.
var hash = document.location.hash.substring(1);
var hashParams = PDFView.parseQueryString(hash);
if ('disableWorker' in hashParams)
PDFJS.disableWorker = (hashParams['disableWorker'] === 'true');
//#if !(FIREFOX || MOZCENTRAL)
var locale = navigator.language;
if ('locale' in hashParams)
locale = hashParams['locale'];
mozL10n.setLanguage(locale);
//#endif
if ('textLayer' in hashParams) {
switch (hashParams['textLayer']) {
case 'off':
PDFJS.disableTextLayer = true;
break;
case 'visible':
case 'shadow':
case 'hover':
var viewer = document.getElementById('viewer');
viewer.classList.add('textLayer-' + hashParams['textLayer']);
break;
}
}
//#if !(FIREFOX || MOZCENTRAL)
if ('pdfBug' in hashParams) {
//#else
//if ('pdfBug' in hashParams && FirefoxCom.requestSync('pdfBugEnabled')) {
//#endif
PDFJS.pdfBug = true;
var pdfBug = hashParams['pdfBug'];
var enabled = pdfBug.split(',');
PDFBug.enable(enabled);
PDFBug.init();
}
if (!PDFView.supportsPrinting) {
document.getElementById('print').classList.add('hidden');
}
if (!PDFView.supportsFullscreen) {
document.getElementById('fullscreen').classList.add('hidden');
}
if (PDFView.supportsIntegratedFind) {
document.querySelector('#viewFind').classList.add('hidden');
}
// Listen for warnings to trigger the fallback UI. Errors should be caught
// and call PDFView.error() so we don't need to listen for those.
PDFJS.LogManager.addLogger({
warn: function () {
PDFView.fallback();
}
});
var mainContainer = document.getElementById('mainContainer');
var outerContainer = document.getElementById('outerContainer');
mainContainer.addEventListener('transitionend', function (e) {
if (e.target == mainContainer) {
var event = document.createEvent('UIEvents');
event.initUIEvent('resize', false, false, window, 0);
window.dispatchEvent(event);
outerContainer.classList.remove('sidebarMoving');
}
}, true);
document.getElementById('sidebarToggle').addEventListener('click',
function () {
this.classList.toggle('toggled');
outerContainer.classList.add('sidebarMoving');
outerContainer.classList.toggle('sidebarOpen');
PDFView.sidebarOpen = outerContainer.classList.contains('sidebarOpen');
PDFView.renderHighestPriority();
});
document.getElementById('viewThumbnail').addEventListener('click',
function () {
PDFView.switchSidebarView('thumbs');
});
document.getElementById('viewOutline').addEventListener('click',
function () {
PDFView.switchSidebarView('outline');
});
document.getElementById('previous').addEventListener('click',
function () {
PDFView.page--;
});
document.getElementById('next').addEventListener('click',
function () {
PDFView.page++;
});
document.querySelector('.zoomIn').addEventListener('click',
function () {
PDFView.zoomIn();
});
document.querySelector('.zoomOut').addEventListener('click',
function () {
PDFView.zoomOut();
});
document.getElementById('fullscreen').addEventListener('click',
function () {
PDFView.fullscreen();
});
document.getElementById('openFile').addEventListener('click',
function () {
document.getElementById('fileInput').click();
});
document.getElementById('print').addEventListener('click',
function () {
window.print();
});
document.getElementById('download').addEventListener('click',
function () {
PDFView.download();
});
document.getElementById('pageNumber').addEventListener('change',
function () {
PDFView.page = this.value;
});
document.getElementById('scaleSelect').addEventListener('change',
function () {
PDFView.parseScale(this.value);
});
document.getElementById('first_page').addEventListener('click',
function () {
PDFView.page = 1;
});
document.getElementById('last_page').addEventListener('click',
function () {
PDFView.page = PDFView.pdfDocument.numPages;
});
document.getElementById('page_rotate_ccw').addEventListener('click',
function () {
PDFView.rotatePages(-90);
});
document.getElementById('page_rotate_cw').addEventListener('click',
function () {
PDFView.rotatePages(90);
});
//#if (FIREFOX || MOZCENTRAL)
//if (FirefoxCom.requestSync('getLoadingType') == 'passive') {
// PDFView.setTitleUsingUrl(file);
// PDFView.initPassiveLoading();
// return;
//}
//#endif
//#if !B2G
PDFView.open(file, 0);
//#endif
});
The system must be initialized first before PDFView.open call!
Thanks