Demo cordova application reverse image search

 

This application uses google reverse image search , in order to try and guess what an image represents . It simply returns the text found in the topstuff element , returned by google , when submitting an image , to google reverse image search .

To create this application , execute these commands :

$ cordova create what-is-this-img com.twiserandom.mobileapps.demo.whatIsThisImg "What is this img"

$ cordova platform add ios
$ cordova platform add android

$ cordova plugin add cordova-plugin-camera
$ cordova plugin add cordova-plugin-file-transfer

Edit www/index.html to look like this :

<!DOCTYPE html>

<html>
    <head >
        <meta charset="utf-8">
        <meta http-equiv="Content-Security-Policy" >
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
        <meta name="color-scheme" content="light dark">
        <title>What is this img ?</title>
    </head>
    <body >

        <div id="wisThisImgApp">
        </div>

        <script src="cordova.js"></script>
        <script src="js/imgSearchBtn.js"></script>
        <script src="js/imgSearchForm.js"></script>
        <script src="js/searchResult.js"></script>
        <script src="js/wisThisImgApp.js"></script>
        <script src="js/googleImageSearch.js"></script>
        <script src="js/index.js"></script>
        <script>
            window.addEventListener('load', wisThisImgApp );
        </script>
        
    </body>
</html>

Edit www/js/index.js , to look like this :

/*File : www/js/index.js .*/

document.addEventListener('deviceready', onDeviceReady, false );

let isDeviceReady = false; 

function onDeviceReady( ){
    isDeviceReady = true ; }

function userSelectionMade( ){

    function cameraSuccess(imageURI ){
        switch(searchPreferences.searchProvider ){
            case searchOptions.searchProvider.googleImageSearch:
                googleImageSearch(imageURI );
                break; } }

    function cameraFailure(errorMsg ){
        togleIsSearchPerformed( );
        toggleSearch_ResultMessage(errorMsg );}

    if(isDeviceReady && !searchPreferences.isSearchPerformed ){
        togleIsSearchPerformed( );
        toggleSearch_ResultMessage( );
        let pictureOptions = { } ;
        if(searchPreferences.imageSource == searchOptions.imageSource.Gallery )
            pictureOptions = {sourceType: Camera.PictureSourceType.PHOTOLIBRARY }

        navigator
            .camera
            .getPicture(cameraSuccess , 
                        cameraFailure , 
                        pictureOptions ); } }

Add the following javascript files :

www/js/imgSearchBtn.js

/*File : www/js/imgSearchBtn.js .*/

function imgSearchBtn(){
    let style = `
    #imgSearchBtn{
        background-color: white;
        color : black;
        text-align: center;
        font-size : 1.625rem;
        margin-top : 0.25rem;
        margin-bottom: 0.75rem;
        border-radius: 20% 30% 5% 5%;
        box-shadow: 0px 0px 0.25rem 0.25rem black;
        text-shadow: -0.0625rem -0.0625rem 0.125rem  black ; } `;
    
    
    let html = `
    <div  
        id="imgSearchBtn" 
        onclick="userSelectionMade( )" >
        Search  </div>`;

    return {
        html : html ,
        style : style } }

www/js/imgSearchForm.js

/*File : www/js/imgSearchForm.js*/

function imageSource(){

    let style = `
    #imageSource{
        display: flex; 
        flex-wrap: wrap;
        border-bottom: 0.0625rem solid;
        border-top: 0.0625rem dashed;
        margin-bottom: 1rem;
        padding: 0.375rem 0px 0.5rem;
        justify-content: center; }

    #imageSourceTitle{
        padding-bottom: 0.25rem;
        font-family: monospace;
        font-size: 1.375rem;
        text-align: center; 
        margin-bottom: 0.25rem;
        width: 100%; 
        align-content: center; }

    .imageSourceName{
        margin-right: 0.375rem; }`;

    let html =`
        <div 
                id="imageSource" >
            <p 
                    id="imageSourceTitle"> 
                Image Source </p>
                
            <span 
                    class="imageSourceName">
                Camera </span>                        
            <input 
                    oninput="imageSourceSelected(this );"
                    style="margin-right: 20%;"
                    type="radio" 
                    value="${searchOptions.imageSource.Camera}" 
                    name="imageSource" 
                    checked >

            <span
                    class="imageSourceName" >   
                Gallery </span>
            <input 
                    oninput="imageSourceSelected(this );"
                    type="radio" 
                    value="${searchOptions.imageSource.Gallery}" 
                    name="imageSource">
        </div> `;

    let script = `function imageSourceSelected(inputElem ){
        switch(inputElem.value ){
            case searchOptions.imageSource.Gallery:
                searchPreferences.imageSource = searchOptions.imageSource.Gallery;
                break;
            case searchOptions.imageSource.Camera:
                searchPreferences.imageSource = searchOptions.imageSource.Camera;
                break; } }`; 

    return{
        html: html,
        style: style , 
        script: script } }


function searchProvider( ){
    let style= `
        #searchProviders{
            display: flex; 
            flex-wrap: wrap;
            border-bottom: 0.0625rem solid;
            border-top: 0.0625rem dashed;
            margin-bottom: 1rem;
            padding: 0.5rem 0px 0.5rem;
            justify-content: center }

        #searchProvidersTitle{
            padding-bottom: 0.375rem;
            font-family: monospace;
            font-size: 1.375rem;
            text-align: center; 
            margin-bottom: 0.5rem;
            width: 100%; 
            align-content: center; }

        #searchProvidersOptions{
            width: 100%;
            margin: 0px 0.625rem;
            color: black; }

        #googleImageSearch{
            background-color: white;
            padding-top: 0.125rem;
            padding-left: 0.1875rem;
            padding-bottom: 0.25rem;
            box-shadow: 0px 0px 0.25rem 0.25rem white; }

        #bingImageSearch{
            background-color: black;
            color: white;
            padding-top: 0.4375rem;
            padding-bottom: 0.3125rem;
            padding-left: 0.5rem;
            border: 0.0625rem solid; }

        #yandexImageSearch{
            background-color: white;
            padding-top: 0.3125rem;
            padding-bottom: 0.3125rem;
            padding-left: 1rem; }

        #notYetImplemented{
            background-color: black;
            color: white;
            border: 0.0625rem solid;
            padding-top: 0.4375rem;
            padding-bottom: 0.3125rem;
            padding-left: 1.625rem; }`;

    let html=`
            <div 
                id = "searchProviders" >
            <p 
                    id = "searchProvidersTitle" > 
                Search Providers </p>
            
            <div
                    id = "searchProvidersOptions" >
                <p
                        id = "googleImageSearch"
                        data-option-value = "${searchOptions.searchProvider.googleImageSearch}" > 
                    Google Image Search &#x2714; </p>
                <p 
                        id = "bingImageSearch"
                        data-option-value = "${searchOptions.searchProvider.bingImageSearch}" >
                        Bing Image Search </p>
                <p
                        id = "yandexImageSearch"
                        data-option-value = "${searchOptions.searchProvider.yandexImageSearch}" > 
                    Yandex Image Search  </p>
                <p 
                        id="notYetImplemented"
                        data-option-value = "${searchOptions.searchProvider.notYetImplemented}" >
                    &#x1F556; Not Yet Implemented </p>
            </div>
        </div>`;


    return{
        style : style ,
        html : html  } }


function searchForm( ){
    let html=`
    <form 
            id="imgSearchForm"
            onsubmit="return false;" >
    </form>`; 
    return{
        html : html , 
        id: "imgSearchForm",
        childrens :[
            imageSource() , 
            searchProvider()
        ] }}

www/js/searchResult.js

/*File : www/js/searchResult.js .*/

function searchResult( ){
    let componentGlobalName = 'searchResult' ;

    let style=`
        #searchResult{
            text-align:center; }`;

    let html=`
    <div
        id = "searchResult" >
    </div>`;

    let script=`
        function toggleSearch_ResultMessage(result ){
            result = result || "Performing search" ;
            this.innerText = result ; }
            
        toggleSearch_ResultMessage = toggleSearch_ResultMessage.bind(document.getElementById('${componentGlobalName}' ) );`;

    return{
        style : style , 
        html : html ,
        script : script }; }

www/js/googleImageSearch.js

function googleImageSearch(imageURI ){

    postImgGoogle(imageURI );

    function postImgError(fileTransferError ){
        toggleSearch_ResultMessage(JSON.stringify(fileTransferError , null , 4 ) );
        togleIsSearchPerformed( ); }
    
    function postImgSuccess(fileUploadResult ){
            let domParser = new DOMParser( );
            let domDocument = domParser.parseFromString(fileUploadResult.response , 'text/html' );
            let topSuggestion_Element = domDocument.getElementById("topstuff" );
            toggleSearch_ResultMessage(topSuggestion_Element
                                        .textContent
                                        .trim( )
                                        .split("\n" )
                                        .pop( )
                                        .trim( ) );

            togleIsSearchPerformed( ); }


    function postImgGoogle(imageURI){
        let googleImageUploadUrl = encodeURI("https://www.google.com/searchbyimage/upload" );
        let options = new FileUploadOptions();
        options.fileKey = "encoded_image";
        options.fileName = "encoded_image";
        var params = {
            image_url : "" ,
            image_content : "",
            filename : "",
            hl : "en" };
        options.params = params;
        let fileTransfer = new FileTransfer();
        fileTransfer
            .upload(
                imageURI , 
                googleImageUploadUrl , 
                postImgSuccess,
                postImgError, 
                options ); } }

Edit the file config.xml in the root of your app , to look like this :

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.twiserandom.mobileapps.demo.whatIsThisImg" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>What is this img</name>
    <description>
        A sample Apache Cordova application that responds to the deviceready event.
    </description>
    <author email="dev@cordova.apache.org" href="http://cordova.io">
        Apache Cordova Team
    </author>
    <content src="index.html" />
    <access origin="*" />
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <platform name="android">
        <allow-intent href="market:*" />
    </platform>
    <platform name="ios">
        <allow-intent href="itms:*" />
        <allow-intent href="itms-apps:*" />
    </platform>

<!-- Android manifest permission internet -->
    <config-file target="AndroidManifest.xml" parent="/manifest" xmlns:android="http://schemas.android.com/apk/res/android">
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    </config-file>

<!-- IOS  camera access  , for cordova camera plugin -->
    <edit-config target="NSCameraUsageDescription" file="*-Info.plist" mode="merge">
        <string>need camera access to take pictures</string>
    </edit-config>

    <edit-config target="NSPhotoLibraryUsageDescription" file="*-Info.plist" mode="merge">
        <string>need photo library access to get pictures from there</string>
    </edit-config>

    <edit-config target="NSLocationWhenInUseUsageDescription" file="*-Info.plist" mode="merge">
        <string>need location access to find things nearby</string>
    </edit-config>

    <edit-config target="NSPhotoLibraryAddUsageDescription" file="*-Info.plist" mode="merge">
        <string>need photo library access to save pictures there</string>
    </edit-config>

    <preference name="CameraUsesGeolocation" value="false" />
<!-- IOS  camera access  , for cordova camera plugin -->
</widget>

Now you can run the application , by using :

$ cordova emulate android 
$ cordova emulate ios