I'm newbie at chrome extension. I'm making chrome extension that play youtube chromeless player.
It worked on chrome web browser. But, it isn't working on chrome extension.
I tested local .swf file. That is worked on chrome extension.
I think, chrome extension can't call onYouTubePlayerReady().
So I called window.onYouTubePlayerReady() after swfobject.embedSWF(). But, it isn't worked at ytplayer.loadVideoById("xa8TBfPw3u0", 0); with error message.
The error message was Uncaught TypeError: Object #<HTMLObjectElement> has no method 'loadVideoById'.
Is there a problem in manifest.json? Or in YouTube API? I don't know why isn't working on chrome extension.
popup.html is
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>YouTube Play</title>
</head>
<body>
<table width="1000" height="390">
<tr>
<td>
<div id="videoDiv">
Loading...
</div></td>
<td valign="top">
<div id="videoInfo">
<p>
Player state: <span id="playerState">--</span>
</p>
<p>
Current Time: <span id="videoCurrentTime">--:--</span> | Duration: <span id="videoDuration">--:--</span>
</p>
<p>
Bytes Total: <span id="bytesTotal">--</span> | Start Bytes: <span id="startBytes">--</span> | Bytes Loaded: <span id="bytesLoaded">--</span>
</p>
<p>
Controls: <input type="button" id="play" value="Play" />
<input type="button" id="pause" value="Pause" />
<input type="button" id="mute" value="Mute" />
<input type="button" id="unmute" value="Unmute" />
</p>
<p>
<input id="volumeSetting" type="text" size="3" />
<input type="button" id="setVolume" value="Set Volume" /> | Volume: <span id="volume">--</span>
</p>
</div></td>
</tr>
</table>
<script type="text/javascript" src="jsapi.js"></script>
<script type="text/javascript" src="my_script.js"></script>
<script type="text/javascript" src="swfobject.js"></script>
</body>
</html>
manifest.json is
{
"manifest_version": 2,
"name": "YouTube Player",
"description": "This extension is YouTube Player",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": ["tabs", "http://*/*", "https://*/*", "background"],
"content_scripts": [
{
"matches": ["http://www.youtube.com/*"],
"js": ["my_script.js", "swfobject.js", "jsapi.js"]
}
]
}
my_script.js is
/*
* Chromeless player has no controls.
*/
// Update a particular HTML element with a new value
function updateHTML(elmId, value) {
document.getElementById(elmId).innerHTML = value;
}
// This function is called when an error is thrown by the player
function onPlayerError(errorCode) {
alert("An error occured of type:" + errorCode);
}
// This function is called when the player changes state
function onPlayerStateChange(newState) {
updateHTML("playerState", newState);
}
// Display information about the current state of the player
function updatePlayerInfo() {
// Also check that at least one function exists since when IE unloads the
// page, it will destroy the SWF before clearing the interval.
if (ytplayer && ytplayer.getDuration) {
updateHTML("videoDuration", ytplayer.getDuration());
updateHTML("videoCurrentTime", ytplayer.getCurrentTime());
updateHTML("bytesTotal", ytplayer.getVideoBytesTotal());
updateHTML("startBytes", ytplayer.getVideoStartBytes());
updateHTML("bytesLoaded", ytplayer.getVideoBytesLoaded());
updateHTML("volume", ytplayer.getVolume());
}
}
// Allow the user to set the volume from 0-100
function setVideoVolume() {
var volume = parseInt(document.getElementById("volumeSetting").value);
if (isNaN(volume) || volume < 0 || volume > 100) {
alert("Please enter a valid volume between 0 and 100.");
} else if (ytplayer) {
ytplayer.setVolume(volume);
}
}
function playVideo() {
if (ytplayer) {
ytplayer.playVideo();
}
}
function pauseVideo() {
if (ytplayer) {
ytplayer.pauseVideo();
}
}
function muteVideo() {
if (ytplayer) {
ytplayer.mute();
}
}
function unMuteVideo() {
if (ytplayer) {
ytplayer.unMute();
}
}
// This function is automatically called by the player once it loads
function onYouTubePlayerReady(playerId) {
ytplayer = document.getElementById("ytPlayer");
// This causes the updatePlayerInfo function to be called every 250ms to
// get fresh data from the player
setInterval(updatePlayerInfo, 250);
updatePlayerInfo();
ytplayer.addEventListener("onStateChange", "onPlayerStateChange");
ytplayer.addEventListener("onError", "onPlayerError");
//Load an initial video into the player
ytplayer.loadVideoById("xa8TBfPw3u0", 0);
}
// The "main method" of this sample. Called when someone clicks "Run".
function loadPlayer() {
// Lets Flash from another domain call JavaScript
var params = {
allowScriptAccess : "always"
};
// The element id of the Flash embed
var atts = {
id : "ytPlayer"
};
// All of the magic handled by SWFObject (http://code.google.com/p/swfobject/)
swfobject.embedSWF("http://www.youtube.com/apiplayer?" + "&enablejsapi=1&playerapiid=ytplayer", "videoDiv", "640", "390", "8", null, null, params, atts);
//window.onYouTubePlayerReady();
document.getElementById("play").onclick = playVideo;
document.getElementById("pause").onclick = pauseVideo;
document.getElementById("mute").onclick = muteVideo;
document.getElementById("unmute").onclick = unMuteVideo;
document.getElementById("setVolume").onclick = setVideoVolume;
}
function _run() {
loadPlayer();
}
google.setOnLoadCallback(_run);
Please help me.
Recently I've encountered the same issue when working on a Chrome extension. When testing, the calls are simply not triggered. Until I've read this:
To test any of these calls, you must have your file running on a webserver, as the Flash player restricts calls between local files and the internet.
From YouTube's Player API Documentation
Related
When I try to load my Google Chrome extension into the browser, I get the above error for my options.js file:
Here are my options.js:
var email_addr = document.getElementById("email_addr");
var email_password = document.getElementById("email_password");
var registerButton = document.getElementById("register");
var url = document.getElementById("url");
var port = document.getElementById("port");
var password = document.getElementById("password");
var ecs_mode = document.getElementById("ecs_mode");
var encrypt = document.getElementById("encrypt");
var include_content = document.getElementById("include_content");
var saveButton = document.getElementById("save");
debugger;
restore_settings();
chrome.storage.sync.get({"emailAddr": email_addr.value,
"emailPassword": email_password.value,
"contentServerURL": url.value,
"contentServerPort": port.value,
"contentServerPassword": password.value,
"ecs_mode": ecs_mode.checked,
"encrypt": encrypt.checked,
"include_content": include_content.checked},
function() {
// Update status to let user know settings were saved.
var status = document.getElementById("status");
status.innerHTML = "Settings Saved.";
setTimeout(function() {
status.innerHTML = "";
}, 750);
});
function register_addr() {
}
// Saves settings to chrome.storage.
function save_settings() {
if (!password.value) return;
chrome.storage.sync.set({"emailAddr": email_addr.value,
"emailPassword": email_password.value,
"contentServerURL": url.value,
"contentServerPort": port.value,
"contentServerPassword": password.value,
"ecs_mode": ecs_mode.checked,
"encrypt": encrypt.checked,
"include_content": include_content.checked},
function() {
// Update status to let user know settings were saved.
var status = document.getElementById("status");
status.innerHTML = "Settings Saved.";
setTimeout(function() {
status.innerHTML = "";
}, 750);
});
}
// Restores select box state to saved value from localStorage.
function restore_settings() {
chrome.storage.sync.get("emailAddr", function(val) {
email_addr.value = val.emailAddr;
});
chrome.storage.sync.get("emailPassword", function(val) {
email_password.value = val.emailPassword;
});
chrome.storage.sync.get("contentServerPassword", function(val) {
password.value = val.contentServerPassword;
});
chrome.storage.sync.get("contentServerURL", function(val) {
url.value = val.contentServerURL;
});
chrome.storage.sync.get("contentServerPort", function(val) {
port.value = val.contentServerPort;
});
chrome.storage.sync.get("ecs_mode", function(val) {
ecs_mode.checked = val.ecs_mode;
});
chrome.storage.sync.get("encrypt", function(val) {
encrypt.checked = val.encrypt;
});
chrome.storage.sync.get("include_content", function(val) {
include_content.checked = val.include_content;
});
registerButton.disabled = false;
saveButton.disabled = false;
}
function ecs_mode_fn() {
if (ecs_mode.checked) {
encrypt.disabled = false;
include_content.disabled = false;
}
else {
encrypt.disabled = true;
include_content.disabled = true;
}
}
function toggleButton() {
if (email_addr.value.length == 0) {
registerButton.disabled = true;
saveButton.disabled = true;
}
else {
registerButton.disabled = false;
saveButton.disabled = false;
}
}
document.addEventListener('DOMContentReady', restore_settings);
if (document.querySelector('#save, #ecs_mode, #save, #restore, #register') != null) {
document.querySelector('#ecs_mode').addEventListener('click', ecs_mode_fn);
document.querySelector('#save').addEventListener('click', save_settings);
document.querySelector('#restore').addEventListener('click', restore_settings);
document.querySelector('#email_addr').addEventListener('keyup', toggleButton);
document.querySelector('#register').addEventListener('click', register_addr);
}
options.html:
<html>
<head><title>ECS Extension Settings</title>
<style type="text/css">
body {
width: 800px;
height: 200px;
}
</style>
</head>
<body>
<center><h1>ECS Content Server Settings</h1></center>
<div title="Enter your e-mail address and password here. The address can be a regular Gmail address ('<someone>#gmail.com') or an e-mail address associated with a Google business account.">
<b>Your e-mail address:</b>
<input type="text" id="email_addr">
<b>Password:</b>
<input type="password" id="email_password">
<button id="register" disabled>Register</button>
</div>
<br>
After entering your e-mail address and password, press the <b>Register</b> button to register your address with the ChiaraMail content server. You will then be sent a registration confirmation e-mail containing a link. Select the link to show your content server password and enter the password in the <b>Content server password</b> field below.
<p>
<div title="The name and port number of the content server are fixed. Enter the password you were assigned during registration. You may change your password later at https://www.chiaramail.com/login.jsp">
<b>Content server URL:</b>
<input type="text" id="url" value="www.chiaramail.com" disabled>
<b>Content server port:</b>
<input type="text" id="port" value="443" size="4" disabled>
<b>Content server password:</b>
<input type="password" id="password" maxlength="8" size="8">
<p>
</div>
<div title="Check the 'Send as ECS' box if you want to send e-mail by default using the ECS technology. You will have the option of changing this setting when you compose your message.">
<b>Send as ECS: </b>
<input type="checkbox" id="ecs_mode" checked>
</div>
<div title="Check the 'Encrypt message' box if you want the message to be stored encrypted on the content server. You will have the option of changing this setting when you compose your message.">
<b>Encrypt message: </b>
<input type="checkbox" id="encrypt">
</div>
<div title="Check the 'Include content' box if you want the message content to be sent along with the mail headers (useful when sending to mixed recipients, some enabled for ECS and others who are not). You will have the option of changing this setting when you compose your message.">
<b>Include content: </b>
<input type="checkbox" id="include_content" checked>
</div>
<!--<div title="Select the 'Show ECS users' box to display message senders in magenta if the sender's e-mail address is registered with the ChiaraMail content server. This enables you to know which of your recipients are able to read ECS messages, but setting this option may adversely affect performance.">
<p>
<b>Show ECS users:</b>
<input type="checkbox" id="ecsusers" checked>-->
</div>
<br>
<div id="status"></div>
<div title="Press 'Save settings' to save your settings and 'Restore settings' to display them. Changes made to your account are propagated to all your devices and systems.">
<button id="save" disabled>Save settings</button>
<button id="restore">Restore settings</button>
</div>
<script src="options.js"></script>
</body>
</html>
and manifest.json:
"name": "Envelope-Content Splitting (ECS) Support for Gmail",
"version": "1.0",
"manifest_version": 2,
"description": "Add ECS support for Gmail running in Chrome. This enables Gmail users who access their accounts via the Google Chrome browser to send and read ECS mail. Check out http://www.chiaramail.com for information about ECS and for links to other FREE ECS-enabled mail clients and extensions.",
"browser_action": {
"default_icon": {"19": "ecs_icon_19.png", "38": "ecs_icon_38.png"},
"default_title": "Press here to configure ECS settings",
"default_popup": "options.html"
},
"options_page": "options.html",
"icons": { "16": "ecs_icon_16.png", "48": "ecs_icon_48.png", "128": "ecs_icon_128.png"},
"background": {
"scripts": ["background.js"]
},
"content_scripts": [
{
"run_at": "document_idle",
"matches": ["https://mail.google.com/mail/*"],
"js": ["updateContent.js", "colorHeaders.js", "renderContent.js", "sendOptions.js", "base64.js", "jsaes.js"]
}
],
"permissions": ["tabs",
"activeTab",
"storage",
"https://mail.google.com/mail/*"],
"content_security_policy": "script-src 'self' https://www.chiaramail.com; object-src 'self'"
}
I suspect the problem is with the way I coded chrome.storage.get(), but I couldn't find the API reference, only an example of how to call it. I'm pretty sure I coded the call to chrome.storage.get() correctly, though. What am I missing?
It turns out that I needed to clear the errors after correcting a missing UI element. I don't understand why Google requires users to clear the errors before reloading the extension; the reload should clear them.
I am creating an add-on which would ask the user to select music from a list and it would play it as background music. But previous posts show a sidebar with the user manually pressing the play button. I am wondering if there is a way to play it with Google Apps Script only. Also what would be helpful is if there was a volume property to set the volume?
My Code:
function onOpen(){
DocumentApp.getUi()
.createMenu("Background Music Add-On")
.addItem("Select Music","music")
.addItem("Set Volume","musicVol")
.addToUi();
}
//music selection
function music(){
var musicName = DocumentApp.getUi()
.prompt("Please select one of the music names:\n\nElevator Music,\nLeaf Rag.\nso on...")
switch(musicName){
case "Elevator":
//code to play music Elevator
break;
//So On
}
}
Playing music from a Playlist stored on your Google Drive
This script allows you to store mp3's on your Google Drive. It allows you to select which files you wish to listen too via a playlist. You must start the playlist the first time manually but then the rest of the selections play automatically. The script converts the mp3 files into dataURI's and loads them into the audio element. You can skip over the current selection and you can restart the playlist when it completes.
Code.gs
function onOpen() {
SpreadsheetApp.getUi().createMenu('My Music')
.addItem('Launch Music', 'launchMusicDialog')
.addItem('Create New Music List', 'createMusicList')
.addToUi();
}
function convMediaToDataUri(filename){
var filename=filename || "default.mp3";
var folder=DriveApp.getFolderById("Music Folder Id");
var files=folder.getFilesByName(filename);
var n=0;
while(files.hasNext()) {
var file=files.next();
n++;
}
if(n==1) {
var blob=file.getBlob();
var b64DataUri='data:' + blob.getContentType() + ';base64,' + Utilities.base64Encode(blob.getBytes());
Logger.log(b64DataUri)
var fObj={filename:file.getName(),uri:b64DataUri}
return fObj;
}
throw("Multiple Files with same name.");
return null;
}
function launchMusicDialog() {
var userInterface=HtmlService.createHtmlOutputFromFile('music1');
SpreadsheetApp.getUi().showModelessDialog(userInterface, 'Music');
}
function createMusicList() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName("MusicList");
var folder=DriveApp.getFolderById("Music Folder Id");
var files=folder.getFiles();
var mA=[['Item','File Name','File Type','File Id','Play List']];
sh.clearContents()
var n=1;
while(files.hasNext()) {
var file=files.next();
mA.push([n++,file.getName(),file.getMimeType(),file.getId(),'']);
}
sh.getRange(1,1,mA.length,mA[0].length).setValues(mA);
sh.getRange(2,2,sh.getLastRow()-1,sh.getLastColumn()-1).sort({column:2,ascending:true});
sh.getRange(2,5,sh.getLastRow()-1,1).insertCheckboxes();
}
function getPlaylist() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('MusicList');
var rg=sh.getRange(2,1,sh.getLastRow()-1,sh.getLastColumn());
var vA=rg.getValues();
var pl=[];
for(var i=0;i<vA.length;i++) {
if(vA[i][4]) {
pl.push(vA[i][1]);
}
}
return pl;
}
music1.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<style>
label{margin:2px 10px;}
</style>
</head>
<script>
var selectionList=[];
var gVolume=0.2;
var index=0;
$(function(){
document.getElementById('msg').innerHTML="Loading Playlist";
google.script.run
.withSuccessHandler(function(pl){
selectionList=pl;
console.log(pl);
google.script.run
.withSuccessHandler(function(fObj){
$('#audio1').attr('src',fObj.uri);
var audio=document.getElementById("audio1");
audio.volume=gVolume;
audio.onended=function() {
document.getElementById('status').innerHTML='Ended...';
playnext();
}
var msg=document.getElementById('msg');
msg.innerHTML="Click play to begin playlist. Additional selections will begin automatically";
audio.onplay=function() {
document.getElementById('msg').innerHTML='Playing: ' + selectionList[index-1];
document.getElementById('status').innerHTML='Playing...';
document.getElementById('skipbtn').disabled=false;
}
audio.onvolumechange=function(){
gVolume=audio.volume;
}
})
.convMediaToDataUri(selectionList[index++]);
})
.getPlaylist();
});
function playnext() {
if(index<selectionList.length) {
document.getElementById('status').innerHTML='Loading...';
document.getElementById('msg').innerHTML='Next Selection: ' + selectionList[index];
google.script.run
.withSuccessHandler(function(fObj){
$('#audio1').attr('src',fObj.uri);
var audio=document.getElementById('audio1');
audio.volume=gVolume;
audio.play();
})
.convMediaToDataUri(selectionList[index++]);
}else{
document.getElementById('status').innerHTML='Playlist Complete';
document.getElementById('msg').innerHTML='';
document.getElementById('cntrls').innerHTML='<input type="button" value="Replay Playlist" onClick="replayPlaylist()" />';
}
}
function replayPlaylist() {
index=0;
document.getElementById('cntrls').innerHTML='';
playnext();
}
function skip() {
var audio=document.getElementById('audio1');
document.getElementById('skipbtn').disabled=true;
audio.pause();
index++;
playnext();
}
</script>
<body>
<div id="msg"></div>
<audio controls id="audio1" src=""></audio><br />
<div id="status"></div>
<div><input type="button" id="skipbtn" value="Skip" onClick="skip()" disabled /></div>
<div id="cntrls"></div>
</body>
</html>
Please read through the code. You need to add a music folder id and a couple of default.mp3's. The createMusicList() function reads your Music Folder and Loads them into a sheet named 'MusicList' with columns of "Item", "File Name", "File Type" ,"File Id", and PlayList. The last column is just a column of unchecked checkboxes for you to make your current playlist selection. Only one playlist for now, so you can enjoy building your own.
Here's what the dialog looks like:
And here's an image of my MusicList Sheet:
This is where you make your playlist selections.
Audio Properties and Methods
Apps Script Documentation
Latest Script Code
I used the answer to this question as a starting point: playing sound with google script
You would need to open a html sidebar and use an audio tag, to do this you can use the HtmlService class [1].
As a total background you can't, the sidebar must be always open to play the music. But you could still play the audio while editing the document.
To add the audio setting you can add the controls attribute to the audio tag [2]. For playing the audio automatically you can add the autoplay attibute [3].
Here is the code I implemented to achieve your goal. The code gets the selected value and uses it to change the autoplay value to true and to display the audio as well. Also, when the select element is on focus, it gets the previous selected value so later (when a new value is selected) it can be used to stop the previous audio selection and not display it anymore. For these purposes I used the onchange [4] and the onfocus [5] events.
Code.gs
var SIDEBAR_TITLE = 'Sidebar Musicbox';
function onOpen(e) {
DocumentApp.getUi()
.createMenu('Custom Menu')
.addItem('Show sidebar', 'showSidebar')
.addToUi();
}
function showSidebar() {
var ui = HtmlService.createHtmlOutputFromFile('Sidebar')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setTitle(SIDEBAR_TITLE);
DocumentApp.getUi().showSidebar(ui);
}
Sidebar.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div class="sidebar branding-below">
<p>
A little music for your enjoyment!
</p>
<form>
<select id="music" onchange="playSelection();" onfocus="setOldValue(this.value);">
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
</form>
<br>
<audio id="player0" controls style="display:none">
<source src="[WEB-URL-FOR-MP3-FILE]" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
<audio id="player1" controls style="display:none">
<source src="[WEB-URL-FOR-MP3-FILE]" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
<audio id="player2" controls style="display:none">
<source src="[WEB-URL-FOR-MP3-FILE]" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
<br>
<div id="sidebar-status"></div>
</div>
<div class="sidebar bottom">
<span class="gray branding-text">Docs Add-on Sound Demo</span>
</div>
</body>
<script>
var previousValue;
//Function called when select onFocus
function setOldValue(e) {
previousValue = e;
}
//Function called when selected value change
function playSelection() {
//Get the value for the selected option
var selectedValue = document.getElementById("music").value;
//Latest and previous selection IDs
var player = "player" + selectedValue;
var previousPlayer = "player" + previousValue;
//Stop and don't display the previous selection of audio
document.getElementById(previousPlayer).style.display = "none";
document.getElementById(previousPlayer).autoplay = false;
document.getElementById(previousPlayer).load();
//Play and display the new selection and put the focus on it
document.getElementById(player).style.display = "block";
document.getElementById(player).autoplay = true;
document.getElementById(player).load();
document.getElementById(player).focus();
}
</script>
</html>
[1] https://developers.google.com/apps-script/guides/html/
[2] https://www.w3schools.com/tags/att_audio_controls.asp
[3] https://www.w3schools.com/tags/att_audio_autoplay.asp
[4] https://www.w3schools.com/jsref/event_onchange.asp
[5] https://www.w3schools.com/jsref/event_onfocus.asp
I am new to YUI but I veteran of JQuery UI. So this one has me stumped. I cannot get my Datatable to render with the Rest service. I have two version of the code. One that I use the captured JSON object from the service as just a data object and a local datasource. That one works fine. When I attempt to switch to the GET plugin and get it from the service. It just never renders.
My local example:
#main("Play 2.1") {
<script type="text/javascript">
YUI().use("datatable", "datasource-local", "datasource-jsonschema", "datatable-datasource", function (Y) {
var data = [
{"script":{"id":34534,
"scriptText":"234523452345234",
"modifiedDate":1367525647000,
"status":"Reviewed",
"qcDate":1367526006000,
"location":{"id":1},
"orderInfo":{"id":1,
"orderName":"Order Name",
"dealerName":"Dealer Name"}
}},
{"script":{"id":656435,
"scriptText":"36536543636365",
"modifiedDate":1367525646000,
"status":"Reviewed",
"qcDate":1367526017000,
"location":{"id":1},
"orderInfo":{"id":43534534,
"orderName":"Order Name",
"dealerName":"Dealer Name"}
}}
];
var localDataSource = new Y.DataSource.Local({source:data});
localDataSource.plug(Y.Plugin.DataSourceJSONSchema, {
schema:{
resultListLocator:"",
resultFields:[
{
key:"id",
locator:"script.id"
},
{
key:"scriptText",
locator:"script.scriptText"
},
{
key:"modifiedDate",
locator:"script.modifiedDate"
}
]
}
});
var simple = new Y.DataTable({
columns:["id", "scriptText", "modifiedDate"],
summary:"Example Summary",
caption:"Example Caption"
});
simple.plug(Y.Plugin.DataTableDataSource, {
datasource:localDataSource
});
simple.render("#dataGrid");
simple.datasource.load();
});
</script>
<span id="listView">
<div id="dataGrid" style="height: 95%;width: 100%;"></div>
</span>
<div id="dataCheckArea">
<h3>RAW DATA AREA</h3>
<ul>
#records.map {record =>
<li>#record.toString</li>
}
</ul>
</div>
}
My REST Service example:
#main("Welcome to Play 2.1") {
<script type="text/javascript">
YUI().use("datatable", "datasource-get", "datasource-jsonschema", "datatable-datasource", function (Y) {
var dataSource = new Y.DataSource.Get({
source:"http://localhost:9000/reviewRecords?q=query"
});
dataSource.plug(Y.Plugin.DataSourceJSONSchema, {
schema:{
resultListLocator:"",
resultFields:[
{
key:"id",
locator:"script.id"
},
{
key:"scriptText",
locator:"script.scriptText"
},
{
key:"modifiedDate",
locator:"script.modifiedDate"
}
]
}
});
var dataGrid = new Y.DataTable({
columns:["id", "scriptText", "modifiedDate"],
summary:"Example Summary",
caption:"Example Caption"
});
dataGrid.plug(Y.Plugin.DataTableDataSource, { datasource:dataSource });
dataGrid.render("#dataGrid");
dataGrid.datasource.load();
});
</script>
<span id="listView">
<div id="dataGrid" style="height: 95%;width: 100%;"></div>
</span>
** edited because the original submission lost my second code block.
The problem wasn't with my javascript code. The issue was with how I was sending the response. The YUI framework expects that the response will be wrapped in a callback function. When I changed my response to give a JSONP response with the callback it all started working.
YUI.Env.DataSource.callbacks.yui_3_11_0_1_1379097239018_187([
{"script":{"id":34534,
"scriptText":"234523452345234",
"modifiedDate":1367525647000,
"status":"Reviewed",
"qcDate":1367526006000,
"location":{"id":1},
"orderInfo":{"id":1,
"orderName":"Order Name",
"dealerName":"Dealer Name"}
}},
{"script":{"id":656435,
"scriptText":"36536543636365",
"modifiedDate":1367525646000,
"status":"Reviewed",
"qcDate":1367526017000,
"location":{"id":1},
"orderInfo":{"id":43534534,
"orderName":"Order Name",
"dealerName":"Dealer Name"}
}}
])
I did this by using a JSONP call in the method response from Scala/Play 2.1
def reviewRecords(q: String, callback: String) = Action {
val reviewRecords = reviewRecordsService.currentReviewRecords
Ok(new Jsonp(callback, Json.toJson(DataTablesReturnObject(reviewRecords.size, reviewRecords.toArray)))).as("application/json")
}
I am going to edit the title of my original question to include the keywords for Play 2.1 and Scala because this ends up being a little different than a Java response.
I want to create a chrome extension which takes input from a "form" in popup.html and uses popup.js to open the website selected in a new tab.
**manifest.json**
{
"manifest_version": 2,
"name": "Question Searcher",
"description": "This extension displays the problem from popular online judges like UVA, SPOJ, Topcoder and Codeforces on serching the keyword. It also searches for a list of problems based on problem type.",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"tabs"
]
}
popup.html:
<!DOCTYPE html>
<html>
<head>
<script src = "popup.js" > </script>
<link rel = "stylesheet" type = "text/css" href = "theme.css" >
</head>
<body>
<h1> Search </h1>
<form name = "input">
<p>
Judge:
<select name = "judge">
<option value = "uva" selected> UVA </option>
<option value = "spoj" > SPOJ </option>
<option value = "tc" > Topcoder </option>
<option value = "tcat" > Topcoder Category </option>
<option value = "cf" > Codeforces Category </option>
</select>
<input type = "text" name = "keyword"<br>
<button type="button" onclick="return validate_register()">Go!</button>
</p>
</form>
</body>
</html>
**popup.js**
function validate_register()
{
alert("beep");
var str=document.forms["input"]["keyword"].value;
//alert(str);
switch(document.forms["input"]["judge"].value)
{
case "uva":
return chrome.tabs.create({url: 'http://www.uva.onlinejudge.org/external/'+str.substring(0,str.length-2)+'/'+str+'.html'});
break;
case "spoj":
return chrome.tabs.create({url: 'https://www.spoj.pl/problems/'+str.toUpperCase()+'/'});
break;
case "tc":
return chrome.tabs.create({url: 'http://www.topcoder.com/tc?module=ProblemArchive&class='+str});
break;
case "tcat":
return chrome.tabs.create({url: 'http://www.topcoder.com/tc?module=ProblemArchive&cat='+str});
break;
case "cf":
return chrome.tabs.create({url: 'http://www.codeforces.com/problemset/tags/'+str});
break;
}
}
This code is not working. I think the problem might be in the JS file, in chrome.tabs.create but i am not able to figure it out. Could someone point to the problem.
The problem is about Content Security Policy. When you're using manifest v2 for your chrome extension it doesn't allow to execute inline JavaScript in HTML code. (You can inspect popup with DevTools by right clicking on BrowserAction icon).
So that's why your onclick attribute isn't working. To fix this, you'll need to remove this attribute from HTML, and add code like this inside popup.js:
window.onload = function() {
document.querySelector('button').onclick = function(e) {
e.preventDefault();
validate_register();
};
};
Does anyone have an example of sending a geolocation from a mobile phone to a JSF backing bean?
Would like to get the customers address using geolocation? (Will need to convert from geolocation co-ordinates to a drop down list of nearby roads).
Thanks,
D
Not sure if this will help u get started...
This pulls GPS Geolocation Data from Mobile Devices into a Form...
Then do whatever with it from there...
<script type="text/javascript">
function getLocationConstant()
{
if(navigator.geolocation)
{
navigator.geolocation.getCurrentPosition(onGeoSuccess,onGeoError);
} else {
alert("Your browser or device doesn't support Geolocation");
}
}
// If we have a successful location update
function onGeoSuccess(event)
{
document.getElementById("Latitude").value = event.coords.latitude;
document.getElementById("Longitude").value = event.coords.longitude;
}
// If something has gone wrong with the geolocation request
function onGeoError(event)
{
alert("Error code " + event.code + ". " + event.message);
}
</script>
<cfform action="gps2.cfm" method="post">
Latitude: <input type="text" id="Latitude" name="Latitude" value="">
<br><br>
Longitude: <input type="text" id="Longitude" name="Longitude" value="">
<br><br>
<input type="button" value="Get Location" onclick="getLocationConstant()"/>
<br><br>
<input type="submit" value="Add GPS Location" class=small>
</cfform>
View this links please:
https://developers.google.com/maps/documentation/javascript/examples/map-geolocation - Google Developers
https://goo.gl/TD7aiq - JsFiddle
JS:
// Note: This example requires that you consent to location sharing when
// prompted by your browser. If you see the error "The Geolocation service
// failed.", it means you probably did not give permission for the browser to
// locate you.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 6
});
var infoWindow = new google.maps.InfoWindow({map: map});
// Try HTML5 geolocation.
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
infoWindow.setPosition(pos);
infoWindow.setContent('Location found.');
map.setCenter(pos);
}, function() {
handleLocationError(true, infoWindow, map.getCenter());
});
} else {
// Browser doesn't support Geolocation
handleLocationError(false, infoWindow, map.getCenter());
}
}
function handleLocationError(browserHasGeolocation, infoWindow, pos) {
infoWindow.setPosition(pos);
infoWindow.setContent(browserHasGeolocation ?
'Error: The Geolocation service failed.' :
'Error: Your browser doesn\'t support geolocation.');
}
Using the Javascript you can get the co-ordinates and you can set the backend variable using document.getElementById("id")) in javascript.
Example:
<h:inputText value="{myBean.latitude}" id="latitudeID" />
<!DOCTYPE html>
<html>
<body>
<p>Click the button to get your coordinates.</p>
<button onclick="getLocation()">Try It</button>
<p id="demo"></p>
<script>
var x = document.getElementById("demo");
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
x.innerHTML = "Geolocation is not supported by this browser.";
}
}
function showPosition(position) {
x.innerHTML = "Latitude: " + position.coords.latitude +
"<br>Longitude: " + position.coords.longitude;
document.getElementById("formName:latitudeID").value=position.coords.latitude; /* this will set the value in variable */
}
</script>
</body>
</html>