WebViewJavascriptBridge on iOS - javascript

So I'm creating an app in which there's a UIWebView which shows a list of locations. My goal is to make it possible that once the user clicks one of the locations, my app can get the lat and longitude of the spot and therefore launch an integrated Navigation SDK.
My point is how do I get and pass the location values from the webView to my Objective-C code?
I'm using WebViewJavascriptBridge.

You can set the hyperlinks on the locations.
For example: <a href="location1,latitude=21,longitude=22" id="location1" >Location1</a>
Once this Location1 gets clicked, - webView:shouldStartLoadWithRequest:navigationType: method will be called, and you can extract value of latitude and longitude

WebViewJavascriptBridge have no maintain for a long time.
Maybe you should change to use this library.
SDBridgeOC
self.bridge.consolePipeBlock = ^(id _Nonnull water) {
NSLog(#"Next line is javascript console.log------>>>>");
NSLog(#"%#",water);
};
This can easy to get javascript console.log.
Also have Swift language Version.
SDBridgeSwift
bridge.consolePipeClosure = { water in
guard let jsConsoleLog = water else {
print("Javascript console.log give native is nil!")
return
}
print("Next line is Javascript console.log----->>>>>>>")
print(jsConsoleLog)
}
Also have h5 demo for you.

Related

Here maps change language for map controls dynamically

With here maps there is possibility to change language for both layers and controls. Here is example from here maps. http://jsfiddle.net/gh/get/jquery/2.1.0/heremaps/jsfiddle-github/tree/master/map-multi-language-support . The problem I'm having with this example is that it changes control translation with this line of code:
var ui = H.ui.UI.createDefault(map, defaultLayers, 'zh-CN');.
It's good for initial language, but what if I have a button that would change language, would I need to recreate this ui variable every time I would want to change control language? Is there no method like H.ui.UI.setLocale or something(I tried to search but couldn't find).
We suggest removing the old instance of the UI element and then creating the new one with the desired language.
H.ui.UI class offers the dispose() method to remove the object. To learn more, please refer to the following online doc.
https://developer.here.com/documentation/maps/3.1.26.0/api_reference/H.ui.UI.html#dispose
Here are the sample codes, and hopefully, it helps.
var ui,defaultLayers,platform,map;
function switchMapLanguageToCN(){
switchLanguage("zh-CN")
}
function switchMapLanguageToEN(){
switchLanguage("en-US")
}
function switchLanguage(language){
if(typeof(ui) == "object"){
ui.dispose();
}
ui = H.ui.UI.createDefault(map, defaultLayers, language);
}

My JSLink script will not work

I am attempting to use JSLink ..finally.. and I am having some trouble that I cannot seem to straighten out. For my first venture down the rabbit hole I chose something super simple for use as proof of concept. So I looked up a tutorial and came up with a simple script to draw a box around the Title field of each entry and style the text. I cannot get this to work. Is there any chance you can take a look at this code for me? I used the following tokens in the JSLink box.
~sitecollection/site/folder/folder/file.js
And
~site/folder/folder/file.js
The .js file is stored on the same site as the List View WebPart I am attempting to modify. The list only has the default “Title” column.
(function () {
var overrideContext = {};
overrideContext.Templates = {};
overrideContext.Templates.Item = overrideTemplate;
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
}) ();
function overrideTemplate(ctx) {
return “<div style=’font-size:40px;border:solid 3px black;margin-bottom:6px;padding:4px;width:200px;’>” + ctx.CurrentItem.Title + “</div>”;
}
It looks as though you are attempting to override the context (ctx) item itself, where you actually just want to override the list field and the list view in which the field is displayed. Make sense?
Firstly, change overrideContext.Templates.Item to overrideContext.Templates.Fields :
(function () {
var overrideContext = {};
overrideContext.Templates = {};
overrideContext.Templates.Fields = {
// Add field and point it to your rendering function
"Title": { "View": overrideTemplate },
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
}) ();
Then when the JSLink runs the renderer looks for the Title field in the List view, and applies your overrideTemplate function.
function overrideTemplate(ctx) {
return “<div style=’font-size:40px;border:solid 3px black;margin-bottom:6px;padding:4px;width:200px;’>” + ctx.CurrentItem.Title + “</div>”;
}
In terms of running multiple JSLinks on a SharePoint page, it is quite possible to run multiple JSLink scripts, they just need to be separated by the pipe '|' symbol. I use SharePoint Online a lot and I see the following formatting working all the time (sorry Sascha!).
~site/yourassetfolder/yourfilename.js | ~site/yourassetfolder/anotherfilename.js
You can run as many scripts concurrently as you want, just keep separating them with the pipe. I've seen this on prem also, however you might want to swap out '~sites' for '~sitecollection' and make sure the js files you are accessing are at the top level site in the site collection if you do so!
I have noticed when running multiple JSLinks on a list or page because they are all doing Client Side Rendering, too many will slow your page down. If this happens, you might want to consider combining them into one JSLink script so that the server only has to call one file to return to the client to do all the rendering needed for your list.
Hope this helps.

Displaying hash in URL using location.replace(hash)

Tech Stack
AngularJS v1.2.28 - cannot change this
Angular Leaflet Directive
Leaflet 1.0.0-beta.2
Esri Leaflet v2.0.0-beta.6
Intro
I've run into some trouble. I'm trying to use leaflet-hash.js as a way to allow users to share their location with others. The problem is that I can get the hash to appear in the URL if I change location.replace(hash). But a few problems occur depending on what I change it to. Below I outline what I'm trying to achieve and what I've already tried and the outcome.
Desired Behavior
The user should be able to access the map page in 4 ways:
Type an address on the homepage and click the search button.
Click a county name on the homepage.
Enter a URL with the map coordinates (e.g.
http://www.myapp.com/map#10/39.4378/-76.5841).
Enter the URL for the map page without the coordinates (e.g.
http://www.myapp.com/map).
The user should also be able to zoom/move around on the map page and the coordinates will change in the URL hash.
If the user only enters the generic map URL (http://www.myapp.com/map) they are automatically taken to the statewide zoom level (http://www.myapp.com/map#8/38.903/-76.776).
The Problem
My problem only concerns numbers 3 and 4 above.
Using the plugin as-is I am redirected back to the homepage regardless of which of the 4 methods above I use. I believe this bit of code is the culprit:
location.replace(hash);
If I change it to:
location.hash = hash;
the hash will appear in the URL but I get the following error and constant page refreshing when I try to access the map page using method 4:
[$rootScope:infdig] 10 $digest() iterations reached. Aborting!
If I change the line to:
location.hash.replace(hash);
I won't get the digest error or the constant page refreshing but the hash isn't in the URL like it should be
(e.g. http://www.myapp.com/map instead of http://www.myapp.com/map#10/39.4378/-76.5841)
This happens regardless of whether I use access method 3 or 4.
My Code
On map load I check for the presence of # and then determine what, if any, geometry I should also be displaying:
leafletData.getMap("map").then(function(map) {
$scope.map = map;
var hash = new L.Hash($scope.map);
var checkLocation = window.location.href;
//No # in URL
if (checkLocation.indexOf("#") <= 0) {
if (searchResults.geojson) {
// dealing w/ polygon
// CODE TO DISPLAY POLYGON
} else if (searchResults.latlng) {
// dealing w/ point
// CODE TO DISPLAY POINT
} else {
// no geometry so go with default view
// CODE TO DISPLAY DEFAULT VIEW
}
}
// # in URL
else {
var url = decodeURIComponent(window.location.href);
if (searchResults.geojson) {
// dealing w/ polygon
// CODE TO DISPLAY POLYGON
} else if (searchResults.latlng) {
// dealing w/ point
// CODE TO DISPLAY POINT
} else {
// no geometry so go with default view
var n = url.lastIndexOf('#');
var hashOnly = url.substring(n);
var mapView = parseUrlHash(hashOnly);
console.log(mapView);
$scope.map.setView([mapView.lat, mapView.lng], mapView.zoom);
}
}
});
Leaflet Hash Plugin Code
I've only posted the part I think is relevant along with my comments. The full code can be found here:
leaflet-hash.js
onMapMove: function() {
// bail if we're moving the map (updating from a hash),
// or if the map is not yet loaded
if (this.movingMap || !this.map._loaded) {
return false;
}
var hash = this.formatHash(this.map);
hash = decodeURIComponent(hash);
if (this.lastHash != hash) {
//[A] Original code
// Automatically redirects you back to the home page
//location.replace(hash);
//[B] Suggestion from GitHub
//https://github.com/mlevans/leaflet-hash/issues/45
// Shows hash in URL but causes this: Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
// and constant page refreshing when trying to access map page using method 4.
location.hash = hash;
//[C] Fixes errors in [B] but hash does not appear in the URL
// I need it to be in the URL so users can share location
//location.hash.replace();
//[D] Same as [C]
//location.hash.replace(hash);
this.lastHash = hash;
}
},
I'm not sure where I'm going wrong. I thought the problem might be in the plugin but perhaps my code is what's causing it?
UPDATE
In app.js I have $locationProvider.html5Mode(true);. Could this be causing a conflict?
perhaps
var curHash = location.hash?location.hash.substring(1);
if (hash!=curHash) location.replace(
curHash?location.href.split("#")[0]+"#"+hash:location.href+"#"+hash
);

ExtJs 4.2 ref-selector vs Ext.getcmp() vs Ext.ComponentQuery.query()

I was asked to develop a tab panel with 6 tabs, each having 30 to 40 elements. Each tab is acting as a form in accumulating the details of a person and the last tab is a Summary page which displays all the values entered in the first five tabs. I was asked to provide summary as a tab because, the user can navigate to summary tab at any instance and look at the details entered by him/ or glace the summary. i am following ExtJs MVC pattern. Payload is coming from / going to Spring MVC Application. (JSON)
Using tab change event in controller and if the newtab is summary I am rendering the page with show hide functionality.
Method 1 :In controller I have used Ext.getCmp('id of each element inside the tabs') and show hide the components in summary tab based on the value entered by the user. This killed my app in IE8 popping a message saying that the "script is slow and blah blah..." i had to click on NO for 5 to 6 times for the summary tab to render and display the page.
Method 2 :In controller I used ref and selectos to acccess all the items in tabs. I have used itemId for each and every field in summary tab. like this.getXyz().show(). I thought it would be fast. Yes it was in Google chrome. but my app in IE8 is slow compared to goolge chrome/firefox
Any suggestions regarding this and plan to decrease page render time. The summary page has more than 1000 fields. Please feel free to shed ur thoughts or throw some ideas on this.
thank you!!
I've got a few suggestions you can try. First, to answer your title, I think the fastest simple way to lookup components in javascript is to build a hash map. Something like this:
var map = {};
Ext.each(targetComponents, function(item) {
map[item.itemId] = item;
});
// Fastest way to retrieve a component
var myField = map[componentId];
For the rendering time, be sure that the layout/DOM is not updated each time you call hide or show on a child component. Use suspendLayouts to do that:
summaryTabCt.suspendLayouts();
// intensive hide-and-seek business
// just one layout calculation and subsequent DOM manipulation
summaryTabCt.resumeLayouts(true);
Finally, if despite your best efforts you can't cut on the processing time, do damage control. That is, avoid freezing the UI the whole time, and having the browser telling the user your app is dead.
You can use setTimeout to limit the time your script will be holding the execution thread at once. The interval will let the browser some time to process UI events, and prevent it from thinking your script is lost into an infinite loop.
Here's an example:
var itemsToProcess = [...],
// The smaller the chunks, the more the UI will be responsive,
// but the whole processing will take longer...
chunkSize = 50,
i = 0,
slice;
function next() {
slice = itemsToProcess.slice(i, i+chunkSize);
i += chunkSize;
if (slice.length) {
Ext.each(slice, function(item) {
// costly business with item
});
// defer processing to give time
setTimeout(next, 50);
} else {
// post-processing
}
}
// pre-processing (eg. disabling the form submit button)
next(); // start the loop
up().down().action....did the magic. I have replaced each and every usage of Ext.getCmp('id'). Booooha... it's fast and NO issues.
this.up('tabpanel').down('tabName #itemIdOfField').actions.
actions= hide(), show(), setValues().
Try to check deferredRender is true. This should only render the active tab.
You also can try a different hideMode. Especially hideMode:'offsets ' sounds promising
Quote from the sencha API:
hideMode: 'offsets' is often the solution to layout issues in IE specifically when hiding/showing things
As I wrote in the comment, go through this performance guide: http://docs.sencha.com/extjs/4.2.2/#!/guide/performance
In your case, this will be very interesting for you:
{
Ext.suspendLayouts();
// batch of updates
// show() / hide() elements
Ext.resumeLayouts(true);
}

Javascript storing data

Hi I am a beginner web developer and am trying to build the interface of a simple e-commerce site as a personal project.The site has multiple pages with checkboxes.
When someone checks an element
it retrives the price of the element and
stores it in a variable.
But when I go to the next page and click on new checkboxes products the variable automaticly resets to its original state.
How can I save the value of that variable in Javascript?I am using the jQuery library.
EDIT:This is the code I've writen using sessionStorage but it still dosen't work when I move to next page the value is reseted.
How can I wright this code so that i dosen't reset on each page change.All pages on my website use the same script.
$(document).ready(function(){
var total = 0;
$('input.check').click(function(){
if($(this).attr('checked')){
var check = parseInt($(this).parent().children('span').text().substr(1 , 3));
total+=check;
sessionStorage.var_name=0 + total;
alert(sessionStorage.var_name);
}else{
var uncheck = parseInt($(this).parent().children('span').text().substr(1 , 3));
total-=uncheck;
}
})
The syntax for sessionStorage is simple, and it retains it's data until the browser window is closed. It acts exactly like any other javascript object. You can use dot-notation or square bracket notation (required for keys with spaces) to access stored values.
Storing values using sessionStorage
sessionStorage['value key'] = 'value to store';
Using stored values
alert(sessionStorage['value key']); // Alerts "value to store".
You could use localStorage to acomplish this. You'd need to set up a fallback for it, using localStorage however could be done like this:
Reading from storage:
if (localStorage['valueName'] !== undefined) {
input.value = localStorage['valueName'];
}
Writing to storage:
localStorage['valueName'] = input.value;
Here's a jsfiddle example: http://jsfiddle.net/yJjLe/
As already mentioned above you can use sessionStorage or localStorage. Another option available is HTML5 Web Databases
And take a look at this presentation.
Also keep in mind that html5 web storage is not secure as anyone can see your stored data simply from the console.

Categories