Algolia redirect to search results - javascript

I'm having problem with redirecting search results to page that I want to display results. Want to have search bar in header so that my results are displayed on results page or something similar. All was done by tutorial (Laracasts), still learning javascript, so I'm a bit stuck here.. Some help would be great!
index.blade.php
<script src="http://code.jquery.com/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.11.1/typeahead.bundle.min.js"></script>
<script src="http://cdn.jsdelivr.net/algoliasearch/3/algoliasearch.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.12.1/vue.js"></script>
<script>
new Vue({
el: 'body',
data: {
query: '',
users: []
},
ready: function () {
this.client = algoliasearch('', '');
this.index = this.client.initIndex('test_drive_contacts');
$('#typeahead').typeahead(null, {
source: this.index.ttAdapter(),
displayKey: 'firstname',
templates: {
suggestion: function (hit) {
return '<div>' +
'<h4 class="high">' + hit._highlightResult.firstname.value + '</h4>' +
'<h5 class="high">' + hit._highlightResult.company.value + '</h5>'
+ '</div>';
}
}
})
.on('typeahead:select', function (e, suggestion) {
this.query = suggestion.firstname;
}.bind(this));
},
methods: {
search: function () {
this.index.search(this.query, function (error, results) {
this.users = results.hits;
}.bind(this));
}
}
});
</script>
This is the search input:
<input id="typeahead" type="text" class="form-control" v-model="query"
v-on="keyup: search | key 'enter'">
<article v-repeat="user: users">
<h2>#{{ user.firstname }}</h2>
<h4>#{{ user.company }}</h4
</article>

Redirecting users to a page in JavaScript is as easy as doing
window.location = 'your_url_here'
If you're just looking to redirect to a /search?q=query page when the user types Enter, that's as easy as wrapping the input you're using inside a form.
<form action="/search" method="GET">
<input type="search" id="your-input" name="q" />
</form>
If you want to redirect to an item page, the typeahead:select event gives you the selected option :
$('#your-input')
.typeahead(/* ... */)
.on('typeahead:select', function (e, suggestion) {
window.location = suggestion.url;
});

Related

Knockout JS How to Access a Value from Second View Model / Binding

I am new to Knockout JS and think it is great. The documentation is great but I cannot seem to use it to solve my current problem.
The Summary of my Code
I have two viewmodels represented by two js scripts. They are unified in a parent js file. The save button's event is outside
both foreach binders. I can save all data in the details foreach.
My Problem
I need to be able to include the value from the contacts foreach binder with the values from the details foreach binder.
What I have tried
I have tried accessig the data from both viewmodels from the parent viewmodel and sending the POST request to the controller from there but the observeableArrays show undefined.
Create.CSHTML (Using MVC5 no razor)
<div id="container1" data-bind="foreach: contacts">
<input type="text" data-bind="value: contactname" />
</div>
<div data-bind="foreach: details" class="card-body">
<input type="text" data-bind="value: itemValue" />
</div>
The save is outside of both foreach binders
<div class="card-footer">
<button type="button" data-bind="click: $root.save" class="btn
btn-success">Send Notification</button>
</div>
<script src="~/Scripts/ViewScripts/ParentVM.js" type="text/javascript"></script>
<script src="~/Scripts/ViewScripts/ViewModel1.js" type="text/javascript"></script>
<script src="~/Scripts/ViewScripts/ViewModel2.js" type="text/javascript"></script>
ViewModel1
var ViewModel1 = function (contacts) {
var self = this;
self.contacts = ko.observableArray(ko.utils.arrayMap(contacts, function (contact) {
return {
contactName: contact.contactName
};
}));
}
ViewModel2
var ViewModel2 = function (details) {
var self = this;
self.details = ko.observableArray(ko.utils.arrayMap(details, function (detail) {
return {
itemNumber: detail.itemValue
};
}));
}
self.save = function () {
$.ajax({
url: baseURI,
type: "POST",
data: ko.toJSON(self.details),
dataType: "json",
contentType: "application/json",
success: function (data) {
console.log(data);
window.location.href = "/Home/Create/";
},
error: function (error) {
console.log(error);
window.location.href = "/Homel/Create/";
}
});
};
ParentViewModel
var VM1;
var VM2;
var initialContactInfo = [
{
contactPhone: ""
}
]
var initialForm = [
{
itemValue: ""
]
}
$(document).ready(function () {
if ($.isEmptyObject(VM1)) {
ArnMasterData = new ViewModel1(initialContactInfo);
ko.applyBindings(VM1, document.getElementById("container1"));
}
if ($.isEmptyObject(VM2)) {
VM2 = new ViewModel2(initialForm);
ko.applyBindings(VM2, document.getElementById("container2"));
}
});

Dropdown list is bottom of the site

I have a little problem with my select2 display.
The request work perfectly, I've got the right items, the problem is not here, the problem is the list is completely bottom of the site (after the footer).
the code is :
<input type="hidden" class="select2 form-control" id="select2" placeholder="search ..." name="q" value="{{ searchTerm ?: '' }}">
and :
<script type="text/javascript">
function format(product) {
return '<img src="/media/images/'+product.image+'" alt="" class="imgmedia-object" height="60" width="60"/><h5>'+product.name</h5><hr>';
}
$(document).ready(function() {
// Get this orders sku
var skus = [];
$('.sku').each(function(){
skus.push($(this).text().trim());
});
$(".select2").select2({
multiple: true,
minimumInputLength: 2,
tokenSeparators: [',', ' '],
ajax: {
url: "{{ url('sylius_backend_product_find') }}",
dataType: 'json',
data: function (term, page) {
return {
criteria: {
sku: term
}
};
},
results: function (data, page) {
return {
results: data
};
}
},
formatResult: format
}).on("select2-selecting", function(e) {
window.location = e.choice.url;
});
});
</script>
And I have a warning when I search terms :
This site appears to use a scroll-linked positioning effect. This may not work well with asynchronous panning; see https://developer.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects for further details and to join the discussion on related tools and features!
The problem probably come from the warning, but I don't know how to solve it.
Thx in advance
It was simply because I didn't add the 'bundles/syliusweb/css/select2.css' line ...

Best way to integrate captcha in angularJS

I'm relatively new to angularJS and I wonder what would be the cleanest solution to the following problem.
Let's say I have a form such as follows
<form name="contactform">
<select id="salutation" name="salutation" required="true" ng-model="contactRequest.salutation"><option value="Herr" selected="">Herr</option><option value="Frau">Frau</option></select>
<img width="255" height="70" alt="" src="/website/var/tmp/aed4d639a26c4614cdac2a967381c61c.png" name="captcha[img]">
<captcha-reloader reload-url="/refresh-captcha" img-tag-name="captcha[img]" hidden-field-name="captcha[id]"></captcha-reloader>
<input type="text" name="captcha[input]" required="true" ng-model="contactRequest.captcha.input">
<input type="text" style="display: none;" ng-model="contactRequest.captcha.id" value="aed4d639a26c4614cdac2a967381c61c" name="captcha[id]">
...
As you can see, it uses a directive to display a button which will reload the CAPTCHA. It is defined as
myApp.directive('captchaReloader', function () {
return {
restrict: 'E',
scope: {
reloadUrl: '#',
imgTagName: '#',
hiddenFieldName: '#'
}, //isolate scope
template: '',
link: function (scope, element, attrs) {
},
controller: function ($scope, $element, $attrs, $http) {
$scope.reloadCaptcha = function () {
$http.get($attrs.reloadUrl).then(function (res) {
angular.element('img[name="' + $attrs.imgTagName + '"]').attr('src', res.data.imgSrc);
angular.element('input[name="' + $attrs.hiddenFieldName + '"]').val(res.data.id);
angular.element('input[name="' + $attrs.hiddenFieldName + '"]').trigger('input');
});
};
}
};
)};
If I click on the button, the captcha image and value (hidden field) are updated. It works fine so far.
Now, I want to handle form submission in controller (see methode below). If there is an error (server-side validation), the captcha has to be updated. I don't know whats the best way to trigger the updated-process defined in the directive. Can anyone help?
myApp.controller('KontaktCtrl', function ($scope, $location, CustomerDataService, CaptchaService) {
$scope.contactRequest = {
salutation: 'Herr',
captcha: {
id: initialCaptchaId
}
};
$scope.errors = {};
$scope.submitAction = function () {
CustomerDataService.sendRequest($scope.contactRequest).then(function (res) {
var data = res.data;
if (res.data.data !== null) { //errors in form. Display them
//error handling
$scope.reloadCaptcha();
} else {
goToHomeView();
}
}, function (error) {
console.log('An error occurred while updating!', error);
});
};
var goToHomeView = function () {
$location.path('/');
};
});
Additionally, I have to init the values of select-box and captcha, cause otherwise they are not sent (because the are untouched). Is there any way to avoid this?
PS: I found a reCAPTCHA directive, but reCAPTCHA is no option due to styling limitations.
Its very simple follow the steps...
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
async defer></script>
<script>
var onloadCallback = function() {
widgetId1 = grecaptcha.render('example1', {
'sitekey' : 'Site-Key-',
'theme' : 'light'
});
};
</script>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
async defer>
Now at the form put it
<div id="example1"></div>
<p style="color:red;">{{ captcha_status }}</p>
Validate with angular
if(grecaptcha.getResponse(widgetId1)==''){
$scope.captcha_status='Please verify captha.';
return;
}

Allowing select2 jquery ajax in tag mode to repeat tags

I am using select2-jquery to bring several items from the server (ajax) and the allow the user to select several of them, it works fine but I cannot select any given tag more than once and that's a requirement I'll paste some of my code, hopefully it helps. I have inspected the ajax requests and i can see the same data getting back from the server under the same search terms, but once an item is selected the select2 does NOT displays it anymore
This is a part of my View:
<div class="form-group">
#Html.LabelFor(m => m.Vals, T("Values"), new { #class = "control-label col-md-2" })
<div class="col-md-7">
<input id="Values" name="Values" type="hidden" style="width: 100%" data-url="#Url.Action("Action", "Controller")" />
</div>
</div>
And this is the JS part:
$(function () {
var fullTemplateString = 'some template string';
var resultTemplateString = 'other template';
var $selectInput = $('#Values');
initilizeSelect2($selectInput, fullTemplateString, resultTemplateString);
});
function initilizeSelect2($selectInput, fullTemplate, resultTemplate) {
$selectInput.select2({
placeholder: "Select Labs",
minimumInputLength: 2,
multiple: true,
tokenSeparators: [","],
tags: false,
ajax: {
url: $selectInput.data('url'),
dataType: 'json',
quietMillis: 250,
data: function(term, page) {
return {
term: term,
};
},
results: function(data, page) {
return {
results: data
};
}
},
formatSelection: function (item) {
return format(item, resultTemplate);
},
formatResult: function (item) {
return format(item, fullTemplate);
},
escapeMarkup: function (m) { return m; }
});
}
function format(item, templateString) {
var result = templateString
.replace(/\^\^id\^\^/g, item.id)
.replace(/\^\^icon\^\^/g, item.icon)
.replace(/\^\^text\^\^/g, item.name)
.replace(/\^\^desc\^\^/g, item.desc);
return result;
}
I am using select2 version:3.4.5 extensively in this project so any changes in this regard would be very painful
Thanks in advance
after a lot of search and debugging through the select2 code i found a way (hack) to pull this out by removing the css class .select2-selected that prevents already selected elements from displaying again. I know this isn't the best solution there is, but it is working now. I really welcome any improvements or better solutions

Uploading image to Kinvey and Angularjs

I am trying to change what my app currently does so that instead of inputing a url to reference an image, it uploads the image to the Kinvey collection instead.
Here is a JSfiddle of how I am currently saving the info from my form to my kinvey collection.
http://jsfiddle.net/k6MQK/
Heres my angular code for saving the form data:
$scope.savePeep = function () {
var dataObj = angular.copy($scope.peep);
delete dataObj['$$hashKey'];
// Add the ad hoc fields to the peep object if they are filled out
if ($scope.adHocItem) {
dataObj.adHocLocation = $scope.adHocItem.normalized_location;
dataObj.adHocLocation_display = $scope.adHocItem.display_location;
}
KinveyService.savePeep(dataObj, function (_result) {
debugger;
// update local collection
KinveyService.setCollectionObject(_result.data, $stateParams.peepId);
$state.transitionTo('home');
});
};
I want to change it so that instead of a Text input like this:
<input type="text" id="menu_url" name="menu_url"
placeholder="" class="form-control" ng-model="peep.menu_url">
its a file upload input that works.
<input type="file" id="menu_url" name="menu_url"
placeholder="" class="form-control" ng-model="peep.menu_url">
Simple File Upload with Kinvey & AngularJS http://bit.ly/1ncdQLq
<!DOCTYPE html>
<html>
<head>
<title>Kinvey File Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
<script src="https://da189i1jfloii.cloudfront.net/js/kinvey-angular-1.1.4.min.js"></script>
</head>
<body ng-app="kinveyUploadApp" ng-controller="MainCtrl">
<input type="file" id="files" name="files[]" />
<p ng-if="fileModel">
File Size: {{fileModel.size}} Last Modified: {{fileModel['_kmd'].lmt | date:'yyyy-MM-dd HH:mm:ss Z'}}
</p>
<script>
angular.module('kinveyUploadApp', ['kinvey'])
.run(['$kinvey', function ($kinvey) {
// Kinvey initialization starts
var promise = $kinvey.init({
appKey: 'appKey',
appSecret: 'appSecret'
});
promise.then(function () {
// Kinvey initialization finished with success
console.log("Kinvey init with success");
}, function (errorCallback) {
// Kinvey initialization finished with error
console.log("Kinvey init with error: " + JSON.stringify(errorCallback));
});
}])
.controller('MainCtrl', ['$scope', '$kinvey', function ($scope, $kinvey) {
$scope.fileModel = {};
angular.element(document).find('input')[0].addEventListener('change', function (e) {
var theFile = e.target.files[0];
var promise = $kinvey.File.upload(theFile, {
_filename: theFile.name,
public: true,
size: theFile.size,
mimeType: theFile.type
}).then(function (_data) {
console.log("[$upload] success: " + JSON.stringify(_data, null, 2));
$scope.fileModel = _data;
}, function error(err) {
console.log('[$upload] received error: ' + JSON.stringify(err, null, 2));
});
}, false);
}]);
</script>
</body>

Categories