I need to draw google custom search engine result and form in different div and allowOverwrite - google-custom-search

I want to display the google custom search engine in two different dom.
I know about the
and
But with this option I should be able to use
allow google.search.Csedr.addOverride("mysite_");
so the searchbox-only and searchresults-only didnot fulfill the purpose.
I tried with various option , like
google.load('search', '1') and the rest as from documentation
And
<script>
(function() {
var cx = '111111111111111111:111111';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
'//www.google.com/cse/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
})();
</script>
with both this style I was failed to do the desired task.
I have use the google.setOnLoadCallback or window.__gcse both.But no hope.Can any one help me please.

Finally I got the solution
<!-- ON searchbox page actually header-->
<div id="search">
<script>
function mycallBack(){
google.search.Csedr.addOverride("mysite_");
}
window.__gcse = {
callback : mycallBack
};
(function() {
var cx = 'xxxxxxxxxxxxx:yyyyyyy';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
'//www.google.com/cse/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
})();
</script>
<gcse:searchbox-only></gcse:searchbox-only>
<!-- Header end -->
<!-- Result page start -->
<div style="display:none"><!-- Return the unescaped result URL.-->
<div id="mysite_webResult">
<div class="gs-webResult gs-result" data-vars="{longUrl:function() {
var i = unescapedUrl.indexOf(visibleUrl);
return i < 1 ? visibleUrl : unescapedUrl.substring(i);}}"><!-- Build the result data structure.-->
<table cellspacing="1">
<tbody>
<tr>
<td style="margin-left:30px;" valign="top"><a class="gs-title" data-attr="{href:unescapedUrl,target:target}" data-elif="typeof title !== 'undefined'" style="text-decoration:none !important;"> <img data-attr="{src:richSnippet.product.image, width:160, height:120}" data-if="typeof richSnippet !== 'undefined' && typeof richSnippet.product !== 'undefined' && typeof richSnippet.product.image !== 'undefined'" /> <img data-attr="{src:richSnippet.cseImage.src, width:160, height:120}" data-elif="typeof richSnippet !== 'undefined' && typeof richSnippet.cseImage !== 'undefined' && typeof richSnippet.cseImage.src !== 'undefined'" /> </a></td>
<td style="width:40px;"></td>
<td valign="top"><!-- Append results within the table cell.-->
<div class="gs-title" style="text-decoration:none; font-family:'ubuntu' sans-sertif;"> </div>
<div class="gs-snippet" data-body="html(content)" style="margin-bottom:30px;"></div>
<div data-if="Vars.richSnippet && typeof richSnippet.product !== 'undefined' && richSnippet.product.productid" style="color:#676767"><span class="gs-product-code-label" style="font-size:13px;font-weight:bold;color:black;">Product code: </span></div>
<div data-if="Vars.richSnippet && typeof richSnippet.product !== 'undefined' && richSnippet.product.oepartnumber" style="color:#676767"><span class="gs-oeproduct-code-label" style="font-size:13px;font-weight:bold;color:black;">OE Part Numbers: </span></div>
<div data-if="Vars.richSnippet && typeof richSnippet.offer !== 'undefined' && richSnippet.offer.price" style="color:#676767"><span class="gs-offer-price-label" style="font-size:20px;font-weight:bold;color:red;">£</span></div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<gcse:searchresults-only></gcse:searchresults-only>
<!-- Result page end -->

Related

How to modify and convert Google app UI into HTML

I try to convert this simple google apps script code below to HTML services code. The code below is written with the deprecated google apps script UI services! Could anyone please help me with HTML services example code in this usecase?
I'm not really sure how to approach it as I haven't been coding for too long.
A little bit of help would be very much appreciated.
Thanks!!
Mireia
function() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var app = UiApp.createApplication();
app.setHeight(400);
var scriptProps = PropertiesService.getScriptProperties();
var label1 = app.createLabel('XERO Settings').setStyleAttribute('font-weight', 'bold').setStyleAttribute('padding', '5px').setId('label1');
var panel1 = app.createVerticalPanel().setId('panel1');
var grid = app.createGrid(7, 2);
var absPanel = app.createAbsolutePanel();
var handler = app.createServerHandler('saveSettings');
var clientHandler1 = app.createClientHandler();
var clientHandler2 = app.createClientHandler();
var clientHandler3 = app.createClientHandler();
var btnSave = app.createButton('Save Settings', handler);
var lblAppType = app.createLabel('Application Type: ');
var appTypes = {Private:0, Public:1, Partner:2};
var listAppType = app.createListBox().setName('appType').addItem('Private').addItem('Public').addItem('Partner').addChangeHandler(clientHandler1).
addChangeHandler(clientHandler2).addChangeHandler(clientHandler3).setSelectedIndex(appTypes[(scriptProps.getProperty('appType') != null ? scriptProps.getProperty('appType'): 'Private')]);
handler.addCallbackElement(listAppType);
var lblAppName = app.createLabel('Application Name: ');
var txtAppName = app.createTextBox().setName('userAgent').setWidth("350")
.setValue((scriptProps.getProperty('userAgent') != null ? scriptProps.getProperty('userAgent'): ""));
handler.addCallbackElement(txtAppName);
var lblConsumerKey = app.createLabel('Consumer Key: ');
var txtConsumerKey = app.createTextBox().setName('consumerKey').setWidth("350")
.setValue((scriptProps.getProperty('consumerKey') != null ? scriptProps.getProperty('consumerKey'): ""));
handler.addCallbackElement(txtConsumerKey);
var lblConsumerSecret = app.createLabel('Consumer Secret: ');
var txtConsumerSecret = app.createTextBox().setName('consumerSecret').setWidth("350")
.setValue((scriptProps.getProperty('consumerSecret') != null ? scriptProps.getProperty('consumerSecret'): ""));
handler.addCallbackElement(txtConsumerSecret);
var lblcallBack = app.createLabel('Callback URL:');
var txtcallBack = app.createTextBox().setName('callBack').setWidth("350")
.setValue((scriptProps.getProperty('callbackURL') != null ? scriptProps.getProperty('callbackURL'): ""));
handler.addCallbackElement(txtcallBack);
var lblRSA = app.createLabel('RSA Private Key:');
var txtareaRSA = app.createTextArea().setName('RSA').setWidth("350").setHeight("150")
.setValue((scriptProps.getProperty('rsaKey') != null ? scriptProps.getProperty('rsaKey'): ""));
if (scriptProps.getProperty('appType') == "Private" || scriptProps.getProperty('appType') == null)
txtcallBack.setEnabled(false);
else if (scriptProps.getProperty('appType') == "Public")
txtareaRSA.setEnabled(false);
handler.addCallbackElement(txtareaRSA);
clientHandler1.validateMatches(listAppType, 'Private').forTargets(txtcallBack).setEnabled(false).forTargets(txtareaRSA).setEnabled(true);
clientHandler2.validateMatches(listAppType, 'Public').forTargets(txtcallBack).setEnabled(true).forTargets(txtareaRSA).setEnabled(false);
clientHandler3.validateMatches(listAppType, 'Partner').forTargets(txtcallBack).setEnabled(true).forTargets(txtareaRSA).setEnabled(true);
grid.setBorderWidth(0);
grid.setWidget(0, 0, lblAppType);
grid.setWidget(0, 1, listAppType);
grid.setWidget(1, 0, lblAppName);
grid.setWidget(1, 1, txtAppName);
grid.setWidget(2, 0, lblConsumerKey);
grid.setWidget(2, 1, txtConsumerKey);
grid.setWidget(3, 0, lblConsumerSecret);
grid.setWidget(3, 1, txtConsumerSecret);
grid.setWidget(4, 0, lblcallBack);
grid.setWidget(4, 1, txtcallBack);
grid.setWidget(5, 0, lblRSA);
grid.setWidget(5, 1, txtareaRSA);
grid.setWidget(6, 1, btnSave);
panel1.add(grid).setStyleAttributes(subPanelCSS);
app.add(label1);
app.add(panel1);
ss.show(app);
}
Description
Unfortunately there is no converter. Your dialog is relatively simple and I think I have captured everything of interest. I expect you to handle the property services.
In the dialog I changed the appType from Public to Private to show that the changed values are sent to the server for property service as shown in the execution log.
I inadvertently put include in Code.gs because I normally put CSS in one file, HTML another and js in a third. I didn't do that in this instance.
HTML_Test
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<style>
#label1 { font-weight: bold; }
.textBox { width: 350px; }
.table { display: table; }
.table-row { display: table-row; }
.table-cell { display: table-cell; }
</style>
</head>
<body>
<p id="label1">XERO Settings</p>
<div class="panel1">
<div class="table">
<div class="table-row">
<div class="table-cell">Application Type:</div>
<div class="table-cell">
<select class="textBox" id="appType" onchange="appTypeOnChange()">
<option>Private</option>
<option>Public</option>
<option>Partner</option>
</select>
</div>
</div>
<div class="table-row">
<div class="table-cell">Application Name:</div>
<div class="table-cell">
<input class="textBox" id="userAgent" value=<?= userAgent?>>
</div>
</div>
<div class="table-row">
<div class="table-cell">Consumer Key:</div>
<div class="table-cell">
<input class="textBox" id="consumerKey" value=<?= consumerKey ?>>
</div>
</div>
<div class="table-row">
<div class="table-cell">Consumer Secret:</div>
<div class="table-cell">
<input class="textBox" id="consumerSecret" value=<?= consumerSecret ?>>
</div>
</div>
<div class="table-row">
<div class="table-cell">Callback URL:</div>
<div class="table-cell">
<input class="textBox" id="callBack" value=<?= callBack ?>>
</div>
</div>
<div class="table-row">
<div class="table-cell">RSA Private Key:</div>
<div class="table-cell">
<input class="textBox" id="rsaKey" value=<?= rsaKey ?>>
</div>
</div>
</div>
</div>
<input class="btnSave" type="button" value="Save Settings" onclick="saveSettings()">
<script>
function appTypeOnChange() {
let value = document.getElementById("appType").value;
if( value == "Private" ) {
document.getElementById("callBack").disabled = true;
document.getElementById("rsaKey").disabled = false;
}
else if( appType == "Public" ) {
document.getElementById("callBack").disabled = false;
document.getElementById("rsaKey").disabled = true;
}
else {
document.getElementById("callBack").disabled = false;
document.getElementById("rsaKey").disabled = false;
}
}
function saveSettings() {
let props = {};
props.appType = document.getElementById("appType").value;
props.userAgent = document.getElementById("userAgent").value;
props.consumerKey = document.getElementById("consumerKey").value;
props.consumerSecret = document.getElementById("consumerSecret").value;
props.callBack = document.getElementById("callBack").value;
props.rsaKey = document.getElementById("rsaKey").value;
props = JSON.stringify(props);
google.script.run.setProperties(props);
}
(function () {
let appType = <?= appType ?>;
document.getElementById("appType").value=appType;
if( appType == "Private" ) {
document.getElementById("callBack").disabled = true;
}
else if( appType == "Public" ) {
document.getElementById("rsaKey").disabled = true;
}
}());
</script>
</body>
</html>
Dialog
Code.gs
function showTest() {
try {
let html = HtmlService.createTemplateFromFile('HTML_Test');
html.appType = "Public";
html.userAgent = "John Smith";
html.consumerKey = "12345678";
html.consumerSecret = "My Secret";
html.callBack = "www.goggle.com";
html.rsaKey = "abcdefg";
html = html.evaluate();
SpreadsheetApp.getUi().showModalDialog(html,"Show Test");
}
catch(err) {
SpreadsheetApp.getUi().alert(err);
}
}
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
};
function setProperties(props) {
Logger.log(props);
}
Execution log
Head setProperties Unknown May 11, 2022, 8:27:15 AM 0.57 s
Completed
Cloud logs
May 11, 2022, 8:27:16 AM Info {"appType":"Private","userAgent":"John Smith","consumerKey":"12345678","consumerSecret":"My Secret","callBack":"www.goggle.com","rsaKey":"abcdefg"}
Reference
HTML Service Templated HTML

window.location.href in VUE 3 JS

I didn't get the issue here.
When I use
return window.location.href = 'https://www.google.com';
it works fine.
However, if I use my string variable. It doesn't work.Reloads back to page.
return window.location.href = this.navigationURL;
Full code:-
<table class="">
<tr
class="cursor-pointer"
v-for="currentView in authenticationMethodsAvailable"
:key="currentView.id"
>
<td class=""> (HERE)
**<button type= "button" #click="authenticationChoice(currentView['name'])" >**
<img
class="w-12 inline-block align-middle"
:src="showAuthenticationIcon(currentView['gitType'])"
/>
</button>
</td>
</tr>
</table>
The function being triggered
authenticationChoice(recieved) {
this.$store.state.gitSourceAuthenticationChoice = recieved;
this.$store.dispatch("gitSourceAuthenticationURL").then((response) => {
this.navigationURL = response["oauth2_redirect"];
console.log(this.navigationURL)
});
return this.navigationURL ;
// return window.location.href = String(this.navigationURL);
},
Remove the return which's breaking the code and move the code inside the then block as follows :
authenticationChoice(recieved) {
this.$store.state.gitSourceAuthenticationChoice = recieved;
this.$store.dispatch("gitSourceAuthenticationURL").then((response) => {
this.navigationURL = response["oauth2_redirect"];
console.log(this.navigationURL)
window.location.href = String(this.navigationURL);
});
},

Date range inside loop of multiple datatable in the same page

I came from the issue [https://datatables.net/forums/discussion/51949/looping-multiple-datatables-on-the-same-page#latest] and found an issue that comes from filtering of dates: if I filter and on change of this date range, it triggers table.draw() for the first one if it is inside of the loop of multiple datatable in the same page
My intention is to have the data range to work on each datatable individually
Here is a sample of what I already done
http://live.datatables.net/magokusa/4/edit
HTML
<div class="container">
<h3>Table 1</h3>
<div class="input-group input-group-sm">
<input type="date" id="dateFromupper" placeholder="Date from" value="2017-04-10">
<div>
<div>to</div>
</div>
<input type="date" id="dateToupper" placeholder="Date to" value="2018-09-10">
</div>
<table id="upper" data-action="https://demo.wp-api.org/wp-json/wp/v2/posts?per_page=5" class="display nowrap datatable" width="100%">
<thead>
<tr>
<th>col1</th>
<th>col2</th>
<th>col3</th>
</tr>
</thead>
</table>
<hr>
<h3>Table 2</h3>
<div class="input-group input-group-sm">
<input type="date" id="dateFromlower" placeholder="Date from" value="2016-04-10">
<div>
<div>to</div>
</div>
<input type="date" id="dateTolower" placeholder="Date to" value="2018-09-12">
</div>
<table id="lower" data-action="https://css-tricks.com/wp-json/wp/v2/posts?per_page=5" class="display nowrap datatable" width="100%">
<thead>
<tr>
<th>col1</th>
<th>col2</th>
<th>col3</th>
</tr>
</thead>
</table>
</div>
JS
$(document).ready( function () {
$.each($('.datatable'), function () {
var dt_id = $(this).attr('id');
var dt_action = $(this).data('action');
$.fn.dataTable.ext.search.push(
function (settings, data, dataIndex) {
var min = $("#dateFrom" + dt_id).val();
var max = $("#dateTo" + dt_id).val();
if (min != null && max != null) {
min = new Date(min);
max = new Date(max);
var startDate = new Date(data[1]);
if (min == null && max == null) {
return true;
}
if (min == null && startDate <= max) {
return true;
}
if (max == null && startDate >= min) {
return true;
}
if (startDate <= max && startDate >= min) {
return true;
}
} else {
return true;
}
}
);
$("#dateFrom" + dt_id + ", #dateTo" + dt_id).change(function () {
table.draw();
});
if (dt_action != null) {
var dt_ajax = dt_action;
var table = $('#' + dt_id).DataTable({
ajax: {
"url": dt_ajax,
"dataSrc": ""
},
columns: [
{ "data": "status" },
{ "data": "date" },
{ "data": "date_gmt" },
]
});
} else {
var table = $('.datatable').DataTable({
retrieve: true,
responsive: true,
});
}
});
});
Since you already are declaring two different filters, you can just check if the current draw process is related to the filter itself :
$.fn.dataTable.ext.search.push(
function (settings, data, dataIndex) {
if (settings.sInstance != dt_id) return true
...
}
)

VueJS Computed Data Search Not Functioning

I am attempting to create a search function in my Vue.js 2 application. However, even though my algorithm is giving me the right results, I am not getting the proper filter. Right now, whenever I run a search, I get nothing on the page. Here is my code:
computed:{
filteredSmoothies: function(){
return this.smoothies.filter(smoothie => {
var stuff = smoothie.title.split(" ").concat(smoothie.description.split(" ")).concat(smoothie.category)
var sorted = [];
for (var i = 0; i < stuff.length; i++) {
sorted.push(stuff[i].toLowerCase());
}
console.log(sorted)
if(this.search != null){
var indivthings = this.search.split(" ")
indivthings.forEach(item => {
if(sorted.includes(item.toLowerCase())){console.log("true")} else {console.log("false")}
if(sorted.includes(item.toLowerCase())){return true}
})
} else {
return true
}
})
}
}
Here is my relevant HTML:
<div class="container">
<label for="search">Search: </label>
<input type="text" name="search" v-model="search">
</div>
<div class="index container">
<div class="card" v-for="smoothie in filteredSmoothies" :key="smoothie.id">
<div class="card-content">
<i class="material-icons delete" #click="deleteSmoothie(smoothie.id)">delete</i>
<h2 class="indigo-text">{{ smoothie.title }}</h2>
<p class="indigo-text">{{ smoothie.description }}</p>
<ul class="ingredients">
<li v-for="(ing, index) in smoothie.category" :key="index">
<span class="chip">{{ ing }}</span>
</li>
</ul>
</div>
<span class="btn-floating btn-large halfway-fab pink">
<router-link :to="{ name: 'EditSmoothie', params: {smoothie_slug: smoothie.slug}}">
<i class="material-icons edit">edit</i>
</router-link>
</span>
</div>
</div>
As the discussions in the comments, the root cause should be:
you didn't return true/false apparently inside if(this.search != null){}, it causes return undefined defaultly.
So my opinion is use Javascript Array.every or Array.some. Also you can use for loop + break to implement the goal.
Below is one simple demo for Array.every.
computed:{
filteredSmoothies: function(){
return this.smoothies.filter(smoothie => {
var stuff = smoothie.title.split(" ").concat(smoothie.description.split(" ")).concat(smoothie.category)
var sorted = [];
for (var i = 0; i < stuff.length; i++) {
sorted.push(stuff[i].toLowerCase());
}
console.log(sorted)
if(this.search != null){
var indivthings = this.search.split(" ")
return !indivthings.every(item => { // if false, means item exists in sorted
if(sorted.includes(item.toLowerCase())){return false} else {return true}
})
} else {
return true
}
})
}
or you can still use forEach, the codes will be like:
let result = false
var indivthings = this.search.split(" ")
indivthings.forEach(item => {
if(sorted.includes(item.toLowerCase())){result = true}
})
return result
filteredSmoothies is not returning a list. You iterate over to see if indivthings is contained within sorted, but you don't do anything with that information. I think you need to modify your sorted list based on the results of indivthings.

cant get multiple methods in vuejs instance to work

I have two v-on:click events attached to html elements. the one calling method1 works but the other one doesnt work. i cant imagine what the issue is. i have no errors in the console
heres the the entire html page.
<div class="col-md-10" id="deckBuilder">
<button class="ClassTabs" id="classCardsTab">"#ViewData["ClassChoice"]"</button>
<button class="ClassTabs" id="neutralCardsTab">Neutral</button>
<div class="well col-md-9" id="classCards">
#foreach (var card in Model.ClassCards)
{
<img v-on:click="addCard" class="card" id="#card.CardID;#card.Name" style="width:200px;height:260px;" src="#Url.Content(card.Image)" alt="#card.Name" />
}
</div>
<div class="well col-md-3" id="tableWrapper">
<table id="deckTable">
<tr>
<th colspan="3" style="font-size:24px;"><input style="text-align:center;" placeholder="My #ViewData["ClassChoice"] Deck" v-model="deckName" /></th>
</tr>
<tr>
<th style="text-align:center;font-size:20px;">Name</th>
<th style="text-align:center;font-size:20px;">Count</th>
<th></th>
</tr>
</table>
</div>
<div class="well col-md-9" id="neutralCards">
#foreach (var item in Model.NeutralCards)
{
<img v-on:click="addCard" class="card" id="#item.CardID;#item.Name" style="width:200px;height:260px;" src="#Url.Content(item.Image)" alt="#item.Name" />
}
</div>
</div>
#section Scripts {
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script>
var deckBuilder = new Vue({
el: '#deckBuilder',
data: {
deckList: [],
deckCards: 0,
deckName: ''
},
methods: {
addCard: function(event) {
var count = 0;
var foundCard = false;
var cardInfo = event.path[0].id.split(';');
var cardId = cardInfo[0];
var cardName = cardInfo[1];
var deckTable = document.getElementById('deckTable');
var row;
for (var i = 0; i < this.deckList.length; i++) {
if (this.deckList[i].id === cardId && this.deckList[i].count < 3 && this.deckCards < 30) {
this.deckList[i].count++;
foundCard = true;
this.deckCards++;
for (var x = 0; x < deckTable.rows.length; x++) {
if (deckTable.rows[x].id === cardId) {
deckTable.rows[x].cells[1].innerHTML = this.deckList[i].count;
break;
}
}
break;
} else if (this.deckList[i].id === cardId && this.deckList[i].count === 3 && this.deckCards < 30) {
alert('Deck limit reached for this card.');
foundCard = true;
break;
}
}
if ((this.deckList.length === 0 || !foundCard) && this.deckCards < 30) {
this.deckList.push({ id: cardId, count: 1 });
this.deckCards++;
row = deckTable.insertRow(-1);
row.insertCell(0).innerHTML = '<a class="cardLink" href="#Url.Action("Details", "Cards")/' + cardId + '" >' + cardName + '</a>';
row.insertCell(1).innerHTML = 1;
row.insertCell(2).innerHTML = '<button v-on:click="removeCard">X</button>';
row.id = cardId;
}
console.log(this.deckCards);
},
removeCard: function (event) {
console.log("remove card");
}
}
})
</script>
}
You could try writing it like this:
var vueInstanct = new Vue({
el: "#myVueInstance",
methods: {
method1() {
console.log('method1 hit');
},
method2() {
console.log('method2 hit');
}
}
})
But there doesn't seem to be anything wrong with your code... maybe post the html elements these methods are attached to? Could be something there.