I am new to Firexfox Add-On development and I would like to parse meta-tags from a website in the internet. My Firefox Add-On development environment is setup completely and a panel in the toolbar appears as it should be. When I open the panel the current visited website should be read by its meta-tags. In the following you will see amazon.de as example.
This is how my main.js file looks like:
var { ToggleButton } = require('sdk/ui/button/toggle');
var panels = require("sdk/panel");
var self = require("sdk/self");
var button = ToggleButton({
id: "my-button",
label: "my button",
icon: {
"16": "./icon-16.png",
"32": "./icon-32.png",
"64": "./icon-64.png"
},
onChange: handleChange
});
var panel = panels.Panel({
contentURL: self.data.url("panel.html"),
onHide: handleHide
});
function handleChange(state) {
if (state.checked) {
panel.show({
position: button
});
}
}
function handleHide() {
button.state('window', {checked: false});
}
And this is the panel where the current visited website should be read by its meta-tags:
<script>
// https://developer.mozilla.org/en-US/docs/Introduction_to_using_XPath_in_JavaScript
var req = new XMLHttpRequest();
req.open("GET", "http://www.amazon.de/Apple-Smartphone-Retina-Display-Megapixel-Bluetooth/dp/B00F8JF2OM/", false);
req.send(null);
var xmlDoc = req.responseXML;
var nsResolver = xmlDoc.createNSResolver( xmlDoc.ownerDocument == null ? xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement);
//XPath 'html//meta[#name="title"]/#content'
var itemIterator = xmlDoc.evaluate('html//meta[#name="title"]/#content', xmlDoc, nsResolver, XPathResult.ANY_TYPE, null );
var thisHeading = itemIterator.iterateNext();
var alertText = 'Items:\n'
while (thisHeading) {
alertText += thisHeading.textContent + '\n';
thisHeading = itemIterator.iterateNext();
}
</script>
I don't get any errors and don't get any alert or output data.
However the Firfox XPath add-on tells me the path is correct and shows the data.
Related
I have a model say 'my.attendance' , also have a form view for this which contains some attendance details.What i need is when i open this form view it should always open in Edit mode.So i can directly enter the attendance without clicking Edit button each time.
You have to extend the ViewManager to achieve this.
odoo.define('my_module.view_manager', function (require) {
"use strict";
var ViewManager = require('web.ViewManager');
ViewManager.include({
custom_events: {
execute_action: function(event) {
var data = event.data;
this.do_execute_action(data.action_data, data.env, data.on_closed)
.then(data.on_success, data.on_fail);
},
search: function(event) {
var d = event.data;
_.extend(this.env, this._process_search_data(d.domains, d.contexts, d.groupbys));
this.active_view.controller.reload(_.extend({offset: 0}, this.env));
},
switch_view: function(event) {
if ('res_id' in event.data) {
this.env.currentId = event.data.res_id;
}
var options = {};
console.log(event.data)
if (event.data.view_type === 'form' && !this.env.currentId) {
options.mode = 'edit';
} else if (event.data.mode) {
options.mode = event.data.mode;
}
// Extra added code
if (event.data.model){
if (event.data.model == 'my.model'){ // Checking the particular model.
options.mode = 'edit';
}
}
this.switch_mode(event.data.view_type, options);
},
env_updated: function(event) {
_.extend(this.env, event.data);
},
push_state: function(event) {
this.do_push_state(event.data);
},
get_controller_context: '_onGetControllerContext',
switch_to_previous_view: '_onSwitchToPreviousView',
},
});
});
I'm developing an Ionic App using Cordova File Transfer Plugging to download set of images into the device. Currently it downloads images successfully and I need to restrict 1 download job at a time. Following is the code :
$scope.activeDownload = false;
// Download the current magazine
$scope.downloadMagazine = function() {
if($rootScope.user.user_id == undefined) {
$scope.showLoginAlert = function() {
var alertPopup = $ionicPopup.alert({
title: 'Oops!',
template: "Your must login to download magazines"
});
};
$scope.showLoginAlert();
return;
}
document.addEventListener('deviceready', function () {
var dirName = $rootScope.currentIssue.slug+'_VOL_'+$rootScope.currentIssue.vol+'_ISU_'+$rootScope.currentIssue.issue;
// First create the directory
$cordovaFile.createDir(cordova.file.dataDirectory, dirName, false)
.then(function (success) {
var count = 1;
$scope.loadedCount = 0;
$ionicLoading.show({template : "<progress max=\"100\" value=\"0\" id=\"dw-prog\"></progress><p> Downloading pages...</p><p>Please wait...</p> <button ng-controller=\"magazineIssueCtrl\" ng-click=\"downloadBackground()\" class=\"button button-full button-positive\">Continue in Background</button>"});
angular.forEach($scope.pages, function(value, key) {
function wait() {
if($scope.proceed == false) {
window.setTimeout(wait,50);
}
else {
var imgName = count+".png";
$scope.saveImage(dirName,value.link,imgName); // Then save images one by one to the created directory.
count++;
}
};
wait();
});
}, function (error) {
// Directory already exists means that the magazine is already downloaded.
$scope.showDownloadedAlert = function() {
var alertPopup = $ionicPopup.alert({
title: 'Why worry!',
template: "Your have already downloaded this magazine. You can view it on downloads"
});
};
$scope.showDownloadedAlert();
});
}, false);
};
// Save a image file in a given directory
$scope.saveImage = function(dir,imgUrl,imageName) {
$scope.proceed = false;
var url = imgUrl;
var targetPath = cordova.file.dataDirectory+ dir+"/" + imageName;
var trustHosts = true;
var options = {};
// Download the image using cordovafiletransfer plugin
$cordovaFileTransfer.download(url, targetPath, options, trustHosts)
.then(function(result) {
$scope.proceed = true;
$scope.loadedCount ++;
document.getElementById("dw-prog").value = ($scope.loadedCount / $scope.pages.length )*100;
if($scope.loadedCount == $scope.pages.length) {
$scope.activeDownload = false;
$ionicLoading.hide();
$scope.showDownloadSuccessAlert = function() {
var alertPopup = $ionicPopup.alert({
title: 'Success!',
template: "Your magazine successfully downloaded. You can view it on Downloads!"
});
};
$scope.showDownloadSuccessAlert();
}
}, function(err) {
//alert(JSON.stringify(err));
}, function (progress) {
});
};
// Continue download in background
$scope.downloadBackground = function () {
$scope.activeDownload = true;
$ionicLoading.hide();
$scope.showAlert = function() {
var alertPopup = $ionicPopup.alert({
title: 'Sent to Background!',
template: "You can view it on downloads tab"
});
};
$scope.showAlert();
$rootScope.downloadInBackground.dirName = $rootScope.currentIssue.slug+'_VOL_'+$rootScope.currentIssue.vol+'_ISU_'+$rootScope.currentIssue.issue;
};
Here everything happens as expected but I need the $scope.activeDownload variable to be true when a download is sent to background so that I can refer to that variable before starting another download job. But the problem here is that variable seems to be set to false always. Could you please help me to identify the problem here?
I'm working on hybrid mobile app using html5/js. It has a function download zip file then unzip them. The download function is not problem but I don't know how to unzip file (using javascript).
Many people refer to zip.js but it seems only reading zip file (not unzip/extract to new folder)
Very appreciate if someone could help me !!!
Have a look at zip.js documentation and demo page. Also notice the use of JavaScript filesystem API to read/write files and create temporary files.
If the zip file contains multiple entries, you could read the zip file entries and display a table of links to download each individual file as in the demo above.
If you look the source of the demo page, you see the following code (code pasted from Github demo page for zip.js) (I've added comments to explain):
function(obj) {
//Request fileSystemObject from JavaScript library for native support
var requestFileSystem = obj.webkitRequestFileSystem || obj.mozRequestFileSystem || obj.requestFileSystem;
function onerror(message) {
alert(message);
}
//Create a data model to handle unzipping and downloading
var model = (function() {
var URL = obj.webkitURL || obj.mozURL || obj.URL;
return {
getEntries : function(file, onend) {
zip.createReader(new zip.BlobReader(file), function(zipReader) {
zipReader.getEntries(onend);
}, onerror);
},
getEntryFile : function(entry, creationMethod, onend, onprogress) {
var writer, zipFileEntry;
function getData() {
entry.getData(writer, function(blob) {
var blobURL = creationMethod == "Blob" ? URL.createObjectURL(blob) : zipFileEntry.toURL();
onend(blobURL);
}, onprogress);
}
//Write the entire file as a blob
if (creationMethod == "Blob") {
writer = new zip.BlobWriter();
getData();
} else {
//Use the file writer to write the file clicked by user.
createTempFile(function(fileEntry) {
zipFileEntry = fileEntry;
writer = new zip.FileWriter(zipFileEntry);
getData();
});
}
}
};
})();
(function() {
var fileInput = document.getElementById("file-input");
var unzipProgress = document.createElement("progress");
var fileList = document.getElementById("file-list");
var creationMethodInput = document.getElementById("creation-method-input");
//The download function here gets called when the user clicks on the download link for each file.
function download(entry, li, a) {
model.getEntryFile(entry, creationMethodInput.value, function(blobURL) {
var clickEvent = document.createEvent("MouseEvent");
if (unzipProgress.parentNode)
unzipProgress.parentNode.removeChild(unzipProgress);
unzipProgress.value = 0;
unzipProgress.max = 0;
clickEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
a.href = blobURL;
a.download = entry.filename;
a.dispatchEvent(clickEvent);
}, function(current, total) {
unzipProgress.value = current;
unzipProgress.max = total;
li.appendChild(unzipProgress);
});
}
if (typeof requestFileSystem == "undefined")
creationMethodInput.options.length = 1;
fileInput.addEventListener('change', function() {
fileInput.disabled = true;
//Create a list of anchor links to display to download files on the web page
model.getEntries(fileInput.files[0], function(entries) {
fileList.innerHTML = "";
entries.forEach(function(entry) {
var li = document.createElement("li");
var a = document.createElement("a");
a.textContent = entry.filename;
a.href = "#";
//Click event handler
a.addEventListener("click", function(event) {
if (!a.download) {
download(entry, li, a);
event.preventDefault();
return false;
}
}, false);
li.appendChild(a);
fileList.appendChild(li);
});
});
}, false);
})();
})(this);
I'm following this tutorial on how to create a context menu when a user right clicks on selected text, the menu offers the user the option to send the text to a server:
http://vikku.info/programming/chrome-extension/get-selected-text-send-to-web-server-in-chrome-extension-communicate-between-content-script-and-background-page.htm#Comments
Here are the files:
The myscript.js file:
document.addEventListener('mouseup',function(event)
{
var sel = window.getSelection().toString();
alert('selection is '+sel)
if(sel.length)
chrome.extension.sendRequest({'message':'setText','data': sel},function(response){})
})
The background.html file:
<script>
var seltext = null;
chrome.extension.onRequest.addListener(function(request, sender, sendResponse)
{
switch(request.message)
{
case 'setText':
window.seltext = request.data
break;
default:
sendResponse({data: 'Invalid arguments'});
break;
}
});
function savetext(info,tab)
{
var jax = new XMLHttpRequest();
jax.open("POST","http://localhost/text/");
jax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
jax.send("text="+seltext);
jax.onreadystatechange = function() { if(jax.readyState==4) { alert(jax.responseText); }}
}
alert('here')
var contexts = ["selection"];
for (var i = 0; i < contexts.length; i++)
{
var context = contexts[i];
chrome.contextMenus.create({"title": "Send to Server", "contexts":[context], "onclick": savetext});
}
</script>
The manifest.json file:
<script>
var seltext = null;
chrome.extension.onRequest.addListener(function(request, sender, sendResponse)
{
switch(request.message)
{
case 'setText':
window.seltext = request.data
break;
default:
sendResponse({data: 'Invalid arguments'});
break;
}
});
function savetext(info,tab)
{
var jax = new XMLHttpRequest();
jax.open("POST","http://localhost/text/");
jax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
jax.send("text="+seltext);
jax.onreadystatechange = function() { if(jax.readyState==4) { alert(jax.responseText); }}
}
alert('here')
var contexts = ["selection"];
for (var i = 0; i < contexts.length; i++)
{
var context = contexts[i];
chrome.contextMenus.create({"title": "Send to Server", "contexts":[context], "onclick": savetext});
}
</script>
The popup.html file:
<body>
Just a sample popup
</body>
In myscript.js the function document.addEventListener('mouseup',function(event) is called every time a mouseup event is fired ed but I think this should be called if the user decides to send the request to the server. The context menu should be fired when the user right clicks selected text but I don't know why this is occurring? I needed to update the manifest version to 2.
i don't know, if i got you right...the user select text, press the right mouse button and than you want to do "something"...
try this:
'get the right mouse click
window.oncontextmenu = function ()
{
showSelection(); // call a function or do something here
return false; // cancel the default right click mouse menu (necessary)
}
'in the function get the selected text and do something
function showSelection()
{
var sel = window.getSelection().toString();
alert('selection is '+sel);
.....
}
i understood that your problem is that context menu is not firing... for that you need to do small changes to your manifest
add manifest vesrion as 2
change background_page as background which is a key and value as {scripts:["background.js"]}
create a new javascript file with name as background.js and copy the script tag which is there in background html.i added manifest and javascript. let me know if you found any difficulty.
manifest:
{
"name": "Word Reminder",
"version": "1.0",
"manifest_version": 2,
"description": "Word Reminder.",
"browser_action": {
"default_icon": "images/stick-man1.gif",
"popup":"popup.html"
},
"background": {
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["js/myscript.js"]
}
],
"permissions": [
"http://*/*",
"https://*/*",
"contextMenus",
"tabs"
],
"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'"
}
background.js(new file in the same folder should contain below code):
var seltext = null;
chrome.extension.onRequest.addListener(function(request, sender, sendResponse)
{
switch(request.message)
{
case 'setText':
window.seltext = request.data
break;
default:
sendResponse({data: 'Invalid arguments'});
break;
}
});
function savetext(info,tab)
{
var jax = new XMLHttpRequest();
jax.open("POST","http://localhost/text/");
jax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
jax.send("text="+seltext);
jax.onreadystatechange = function() { if(jax.readyState==4) { alert(jax.responseText); }}
}
var contexts = ["selection"];
for (var i = 0; i < contexts.length; i++)
{
var context = contexts[i];
chrome.contextMenus.create({"title": "Send to Server", "contexts":[context], "onclick": savetext});
}
I am developing an iOS 6.1 app using Titanium Studio, build: 3.1.2.201307091805, I am testing on the iPhone simulator and iPad device. I have a search field that gets JSON results from a remote server. The screen I am having issues with has the search box at the top and a couple of messages below. When the user types in the search field and hits return, the messages are hidden and a table is placed ready to receive the results from the database. All of that is working fine. When the user types in something that is not in the database I have a message appear "No results found, please try again". I made a button to "Clear" the table or "Not Found" message. Here is the button code I have so far:
var clear = Ti.UI.createButton({
title: "Clear",
style:Titanium.UI.iPhone.SystemButtonStyle.BORDERED
});
clear.addEventListener("click", function() {
message.hide();
table.setData([]);
});
Ti.UI.currentWindow.setRightNavButton(clear);
This code does clear the message or the results in the table but when I do another search the previous result appears above the new result even if the searches were totally unrelated. Here is my code.
var win = Titanium.UI.currentWindow;
win.backgroundImage='images/background.png';
win.barColor='#28517A';
win.title='Product Search';
var message = Ti.UI.createLabel({
text: 'No results found, please try again',
top:'100dp',
left:'20dp',
right:'20dp'
});
var customSearchBar = Ti.UI.createView({
backgroundColor: '#28517A',
height: 42,
top: '0dp',
width: Ti.UI.FILL
});
var customSearchField = Ti.UI.createTextField({
autocorrect: false,
borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED,
clearOnEdit: true,
height: 28,
hintText: 'Search For Product or Service',
textAlign: 'center',
width: '90%',
});
customSearchBar.add(customSearchField);
win.add(customSearchBar);
var nolist= Ti.UI.createLabel({
text: 'XXXXXX',
color: '#000',
font: {fontSize:'16dp', fontWeight:'bold'},
top:'50dp',
left:'20dp',
right:'20dp'
});
win.add(nolist);
var businessowner = Ti.UI.createLabel({
text: 'XXXXXX',
color: '#000',
font: {fontSize:'16dp', fontWeight:'bold'},
bottom:'10dp',
left:'20dp',
right:'20dp'
});
win.add(businessowner);
var view = Ti.UI.createView({
backgroundColor: 'transparent',
top: '100dp',
bottom:'60dp'
});
var table = Ti.UI.createTableView({
backgroundColor: 'transparent',
top: '0dp',
height:'auto',
bottom:'0dp'
});
view.add(table);
table.show();
var tableData = [];
function checkInternetConnection(){
return Ti.Network.online ? true : false;
}
customSearchField.addEventListener("return", function(e) {
if(checkInternetConnection()){
nolist.hide();
businessowner.hide();
getdata();
win.add(view);
function getdata(){
var url = "http://mydomain.com/filename.php?title="+e.value;
var xhr = Ti.Network.createHTTPClient({
onload: function() {
Ti.API.debug(this.responseText);
var json = JSON.parse(this.responseText);
if (json.cms_list.length< 1){
win.add(message);
}
for (i = 0; i < json.cms_list.length; i++) {
client = json.cms_list[i];
row = Ti.UI.createTableViewRow({
height:'44dp',
hasChild:true
});
var clientlist = Ti.UI.createLabel({
text:client.clientname,
font:{fontSize:'16dp', fontWeight:'bold'},
height:'auto',
left:'10dp',
color:'#000'
});
row.add(clientlist);
tableData.push(row);
}
table.addEventListener('click',function(e){
var row = e.row;
var clientlist = row.children[0];
var win = Ti.UI.createWindow({
url: 'clientdetail.js',
title: clientlist.text
});
var clientlist = clientlist.text;
win.clientlist = clientlist;
customSearchField.blur();
Titanium.UI.currentTab.open(win,{animated:true});});
table.setData(tableData);
},
onerror: function(e) {
Ti.API.debug("STATUS: " + this.status);
Ti.API.debug("TEXT: " + this.responseText);
Ti.API.debug("ERROR: " + e.error);
alert('There was an error retrieving the remote data. Try again.');
},
timeout:5000
});
xhr.open("GET", url);
xhr.send();
}
}
else{
alert('Your internet connection is not available');
}
});
var clear = Ti.UI.createButton({
title: "Clear",
style:Titanium.UI.iPhone.SystemButtonStyle.BORDERED
});
clear.addEventListener("click", function() {
message.hide();
table.setData([]);
});
Ti.UI.currentWindow.setRightNavButton(clear);
If I press my back button and then return to this screen, the search is fine. How can I completely clear the previous results without leaving the screen and then returning?
You are adding the table to the window every time you click "return". Change your event listener by removing win.add(view); from it, and replace that line with table.show(); like this:
customSearchField.addEventListener("return", function(e) {
if(checkInternetConnection()){
nolist.hide();
businessowner.hide();
getdata();
//win.add(view); dont do this!!!!
table.show();
.....
});
Then, change this:
var table = Ti.UI.createTableView({
backgroundColor: 'transparent',
top: '0dp',
height:'auto',
bottom:'0dp'
});
view.add(table);
//table.show();
win.add(table);
table.hide();
Now you will only have one instance of a table, and you can use setData inside the return listener every time you want to change all the rows.
You are not clearing data from var tabledata. It should be cleared when you are setting table.setData([]); . It is pushing the same data after setting the table as empty.
Your code should look like this:
clear.addEventListener("click", function() {
message.hide();
tableData = [];
table.setData([]);
});