I have a simple ion-img element:
<ion-img *ngIf="images.length" [width]="w" [height]="h" [src]="thumb"></ion-img>
Problem: Image doesn't show, even if I place hard-coded URL
<ion-img *ngIf="images.length" [width]="w" [height]="h" src="http://img.mako.co.il/2017/04/05/141414_x5.jpg"></ion-img>
Inspecting the element shows that the src has a truncated string of the thumb URL ( 31 characters exactly for each entire array )
just FYI, if I console.log("thumb:", thumb) -> show a valid thumb URL ...
I was able to pin-point the issue, and if I remove the *ngIf="images.length" - the image is shown .... but the above was just for the example ( this is how I caught this case ) - the real code is that - I'm waiting for an Array to be filled from an Http request ...
Plunker: http://plnkr.co/edit/433y7EIjWBsEzbPkCi7H?p=preview, the code is in home.ts & home.html, click the button called Set True - an and you'll see a small gray square next to it, remove the *ngIf="ionimg" - you'll see the img just fine ....
How can I solve it ?
Just like you can see in the docs:
Note: ion-img is only meant to be used inside of virtual-scroll
So if you're not using a virtual-scroll, you'll need to use the standard img element or a div and set the image as the background.
Related
I am loading an local disk drive _test.htm file through IPersistMoniker Load method. From what I believe, it is supposed to add the path to the relative URLs as base path. Problem is - it does not do so. Instead, it takes a very long time trying to resolve the path from Internet until it gives up (about 20-30 seconds). What I want is to give up instantly, as soon as the unsolvable path is detected (since it is a local disk file anyway).
This is an example HTML I am loading:
<html>
<head>
<script src="//test/test.js"></script>
<head>
<body>
<img src="image.jpg">
<img src="/image.jpg">
<img src="//image.jpg">
</body>
</html>
Simplified code (C++ Builder) with no error checking:
WideString URL = "file:///" + StringReplace(ExtractFilePath(Application->ExeName), "\\", "/", TReplaceFlags() << rfReplaceAll) + "_test.htm";
TCppWebBrowser* WB = CppWebBrowser1;
DelphiInterface<IMoniker> pMoniker;
OleCheck(CreateURLMonikerEx(NULL, URL.c_bstr(), &pMoniker, URL_MK_UNIFORM));
DelphiInterface<IHTMLDocument2> diDoc2 = WB->Document;
DelphiInterface<IPersistMoniker> pPrstMnkr;
OleCheck(diDoc2->QueryInterface(IID_IPersistMoniker, (LPVOID*)&pPrstMnkr));
DelphiInterface<IBindCtx> pBCtx;
OleCheck(CreateBindCtx(0, &pBCtx));
pPrstMnkr->Load(0, pMoniker, pBCtx, STGM_READWRITE);
Problem - image.jpg loads fine, but the paths //test/test.js and /image.jpg and //image.jpg take a very long time to resolve/load. From what I understand CreateURLMonikerEx is supposed to use file:///path/to/executable/ and prepend that automatically to these paths in which case they would fail instantly - file:///path/to/executable//test/test.js for example. That does not happen.
I additionally tried to move image.jpg to a subfolder and then create custom IMoniker interface with the GetDisplayName and BindToStorage implementation which loaded the image from a custom path. However it doesn't do the same for paths which start with // or /. Even though I output file:///path/to/executable/ in the GetDisplayName through the *ppszDisplayName parameter.
How can I avoid extended time loading such unusable links (discard them), or redirect them to local path as above?
I found a partial solution to use about:blank in the *ppszDisplayName but then it doesn't load images with the valid path image.jpg as then it loads them as about:image.jpg which again is invalid path.
Additionally - I've tried adding IDocHostUIHandler interface with the implementation of Invoke method (DISPID_AMBIENT_DLCONTROL) with the pVarResult->lVal = DLCTL_NO_SCRIPTS | DLCTL_NO_JAVA | DLCTL_NO_RUNACTIVEXCTLS | DLCTL_NO_DLACTIVEXCTLS | DLCTL_NO_FRAMEDOWNLOAD | DLCTL_FORCEOFFLINE; - it it blocks the download of images entirely, but still does check 20-30 seconds for the links starting with // or /.
Update - this doesn't work well!
The code below doesn't work well! The problem is - it loses <BODY>
tag attributes. BODY tag turns out entirely empty after loading. I
ended up loading the message using IHTMLDocument2.write method.
See: Assigning IHTMLDocument2 instance to a TWebBrowser instance
After spending lots of time and no guidance of any kind here, I believe that it is not possible to avoid this wait 20-30 sec when the links are invalid. I found another solution and if someone wants to supplement this solution, feel free to do so.
Instead what I had to do is to create an instance of CLSID_HTMLDocument (IHTMLDocument3 or IHTMLDocument2 interface) and then load the document into that container and parse the links prior to doing anything with them. This is described on:
https://learn.microsoft.com/en-us/previous-versions/aa703592(v=vs.85)
This also helped:
How to load html contents from stream and then how to create style sheet to display the html file in preview pane (like HTML preview handler)
After parsing the document URLs and fixing the invalid ones, it can be saved/displayed in the actual TWebBrowser.
Rough solution (C++ Builder):
try
{
DelphiInterface<IHTMLDocument2> diDoc2;
OleCheck(CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_IHTMLDocument2, (void**)&diDoc2));
DelphiInterface<IPersistStreamInit> diPersist;
OleCheck(diDoc2->QueryInterface(IID_IPersistStreamInit, (void**)&diPersist));
OleCheck(diPersist->InitNew());
DelphiInterface<IMarkupServices> diMS;
OleCheck(diDoc2->QueryInterface(IID_IMarkupServices, (void**)&diMS));
DelphiInterface<IMarkupPointer> diMkStart;
DelphiInterface<IMarkupPointer> diMkFinish;
OleCheck(diMS->CreateMarkupPointer(&diMkStart));
OleCheck(diMS->CreateMarkupPointer(&diMkFinish));
// ...Load from file or memory stream into your WideString here...
DelphiInterface<IMarkupContainer> diMC;
OleCheck(diMS->ParseString(WideString(MsgHTMLSrc).c_bstr(), 0, &diMC, diMkStart, diMkFinish));
DelphiInterface<IHTMLDocument2> diDoc;
OleCheck(diMC->QueryInterface(IID_PPV_ARGS(&diDoc)));
DelphiInterface<IHTMLElementCollection> diCol;
OleCheck(diDoc->get_all(&diCol));
long ColLen = 0;
OleCheck(diCol->get_length(&ColLen));
for (int i = 0; i < ColLen; ++i)
{
DelphiInterface<IDispatch> diItem;
diCol->item(OleVariant(i), OleVariant(i), &diItem);
DelphiInterface<IHTMLElement> diElem;
OleCheck(diItem->QueryInterface(IID_IHTMLElement, (void**)&diElem));
WideString wTagName;
OleCheck(diElem->get_tagName(&wTagName));
if (StartsText("img", wTagName))
{
OleVariant vSrc;
OleCheck(diElem->getAttribute(OleVariant("src"), 4, vSrc));
// Make changes to vSrc here....
// And save it back to src
OleCheck(diElem->setAttribute(OleVariant("src"), vSrc, 0));
}
else if (StartsText("script", wTagName))
{
// More parsing here...
}
}
}
catch (EOleSysError& e)
{
// Process exception as needed
}
catch (Exception& e)
{
// Process exception as needed
}
After full parsing of all required elements (img/src, script/src, base/href etc.) save and load into TWebBrowser.
I only now have to see if the parsed HTML IHTMLDocument2 can be directly assigned to TWebBrowser without loading it again, but that is another question (See - Assigning IHTMLDocument2 instance to a TWebBrowser instance)
I use MSHTML (IHTMLDocument) to display offline HTML which may contain various links. These are loaded from email HTML.
Some of them have URLs starting with // or / for example:
<img src="//www.example.com/image.jpg">
<img src="/www.example.com/image.jpg">
This takes a lot of time to resolve and show the document because it cannot find the URL obviously as it doesn't start with http:// or https://
I tried injecting <base> tag into <head> and adding a local known folder (which is empty) and that stopped this problem. For example:
<base href="C:\myemptypath\">
However, if links begin with \\ (UNC path) the same problem and long loading time begin again. Like:
<img src="\\www.something.com\image.jpg">
I also tried placing WebBrowser control into "offline" mode and all other tricks I could think of and couldn't come up with anything short of RegEx and replacing all the links in the HTML which would be terribly slow solution (or parsing HTML myself which defeats the purpose of MSHTML).
Is there a way to:
Detect these invalid URLs before the document is loaded? - Note: I already did navigate through DOM e.g. WebBrowser1.Document.body.all collection, to get all possible links from all tags and modify them and that works, but it only happens after the document is already loaded so the long waiting time before loading gives up is still happening
Maybe trigger some event to avoid loading these invalid links and simply replace them with about:blank or empty "" text like some sort of "OnURLPreview" event which I could inspect and reject loading of URLs that are invalid? There is only OnDownloadBegin event which is not it.
Any examples in any language are welcome although I use Delphi and C++ (C++ Builder) as I only need the principle here in what direction to look at.
After a long time this is the solution I used:
Created an instance of CLSID_HTMLDocument to parse HTML:
DelphiInterface<IHTMLDocument2> diDoc;
OleCheck(CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&diDoc)));
Write IHTMLDocument2 to diDoc using Document->write
// Creates a new one-dimensional array
WideString HTML = "Example HTML here...";
SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT,0,1);
if (psaStrings)
{
VARIANT *param;
BSTR bstr = SysAllocString(HTML.c_bstr());
SafeArrayAccessData(psaStrings, (LPVOID*)¶m);
param->vt = VT_BSTR;
param->bstrVal = bstr;
SafeArrayUnaccessData(psaStrings);
diDoc->write(psaStrings);
diDoc->close();
// SafeArrayDestroy calls SysFreeString for each BSTR
//SysFreeString(bstr); // SafeArrayDestroy should be enough
SafeArrayDestroy(psaStrings);
return S_OK;
}
Parse unwanted links in diDoc
DelphiInterface<IHTMLElementCollection> diCol;
if (SUCCEEDED(diDoc->get_all(&diCol)) && diCol)
{
// Parse IHTMLElementCollection here...
}
Extract parsed HTML into WideString and write into TWebBrowser
DelphiInterface<IHTMLElement> diBODY;
OleCheck(diDoc->get_body(&diBODY));
if (diBODY)
{
DelphiInterface<IHTMLElement> diHTML;
OleCheck(diBODY->get_parentElement(&diHTML));
if (diHTML)
{
WideString wsHTML;
OleCheck(diHTML->get_outerHTML(&wsHTML));
// And finally use the `Document->write` like above to write into your final TWebBrowser document here...
}
}
i want display PDF file into region , i tried that by call application process using below code but always same file open.( plsql dynamic content region)
DECLARE
V_URL VARCHAR2(2500);
BEGIN
V_URL :='f?p=&APP_ID.:1:&APP_SESSION.:APPLICATION_PROCESS=display_emp_blob:::FILE_ID:' ||:P6_ID;
Sys.htp.p('<p align="center">');
sys.htp.p('<iframe src="'||V_URL||'"width="99%" height="1000">');
sys.htp.p('</iframe>');
sys.htp.p('</p>');
END;
and the application process code in below
CREATE OR REPLACE PROCEDURE OPEN_FILE (P_ID NUMBER)
IS
vBlob blob;
vmimetype varchar2(50);
BEGIN
SELECT ORG_FILES.FILE_CONTENT,MIME_TYPE INTO vBlob, vmimetype
FROM ORG_FILES
WHERE ID =P_ID ;
sys.HTP.init;
owa_util.mime_header(vmimetype,false);
htp.p('Content-Length: ' || dbms_lob.getlength(vBlob));
owa_util.http_header_close;
wpg_docload.download_file(vBlob);
apex_application.stop_apex_engine;
exception
when no_data_found then
null;
END;
How i can open different PDF file into region based a value in ITEM (P6_ID) .
I think the problem you have is that the browser caches the file.
You can specify the time the browser caches with the "Cache-control" header option. Below, you have the code that I use (I have this code in the application process, not in the database):
sys.htp.init;
sys.owa_util.mime_header( 'application/pdf', FALSE );
sys.htp.p('Content-length: ' || sys.dbms_lob.getlength( v_blob));
sys.htp.p('Content-Disposition: inline; filename="'|| v_filename || '"' ); -- "attachment" for download, "inline" for display
sys.htp.p('Cache-Control: max-age=3600'); -- in seconds. Tell the browser to cache for one hour, adjust as necessary
sys.owa_util.http_header_close;
sys.wpg_docload.download_file( v_blob );
apex_application.stop_apex_engine;
You can also try some lazy load, which is the way I access my files (It may be that the way to access your file is also part of the problem). This way you make the page load without waiting for the user and then it loads and shows the file. I don't use the iframe tag but the embed tag. The way to do it is as follows:
Create a region with static content with this html
<div id="view_pdf"></div>
creates a dynamic action when the page loads, which executes javascript and add the following code
$('#view_pdf').html('');
var url = 'f?p=&APP_ID.:1:&APP_SESSION.:APPLICATION_PROCESS=display_emp_blob:::FILE_ID:' + apex.item('P6_ID').getValue();
var preview = document.createElement('embed');
preview.type = "application/pdf";
preview.width="100%";
preview.height="625px";
preview.src = url;
$("#view_pdf").append(preview);
You can modify the values depending on what you need. The embed tag uses the default way to view pdf files from browsers.
Also if what you want is to change the pdf without reloading the page you must use the previous javacript in a dynamic action when you change the value of the item.
I hope you find it useful.
My apologies, on the rare occasion I use this region type, I always think it can be refreshed.
https://spendolini.blogspot.com/2015/11/refreshing-plsql-regions-in-apex.html
The solution is to create a classic report that calls a PL/SQL function that returns your HTML.
SELECT package_name.function_name(p_item => :P1_ITEM) result FROM dual
Just tired of typing console.log again and again, and do not find a way like Sysout + Control + Space in Eclipse will create System.out.println().
There's a predefined Postfix template that allows you to type .log after a JavaScript expression or string and hit Tab to transform it to console.log().
You can also create a Live template (see Preferences | Editor | Live templates) that would expand into a code snippet once you type the selected abbreviation and hit Tab.
Update: there's now also a plugin that allows you to add console.log with a shortcut: https://plugins.jetbrains.com/plugin/10986-console-log
Yes it does,
<anything>.log and press Tab key. This will result in console.log(<anything>);
ie,
<anything>.log + Tab => console.log(<anything>);
eg1: variable
let my_var = 'Hello, World!';
my_var.log + Tab => console.log(my_var);
eg2: string
'hello'.log + Tab => console.log('hello');
eg3: string and variable
'hello', my_var.log + Tab => console.log('hello', my_var);
[UPDATE 2020]
Typing log + Enter autocompletes to console.log()
I made my own template that seems to work.
It may be useful for somebody.
Abbreviation: ll
Template text:
console.log('$NAME$ ', $VALUE$);
$END$
Variables: (just select the given field values by clicking drop down box)
NAME - jsDefineParameter()
VALUE - jsSuggestVariableName
I'm including what I find to be the most efficient, which I added via live templates -> javascript -> applicable to "Everything". Hopefully someone finds it useful.
console.log('L$LINE$ $MYSTRING$ ===', $MYVAR$);$END$
What it does:
When I type cl and press tab, it creates the log and the first thing you type fills both MYSTRING and MYVAR variables. If you tab again, it selects MYVAR where you can rewrite/delete as desired. The third time you hit tab will take you to the end of the line at $END.
This snippet also prints the line number like L123 but you can easily remove that if it isn't helpful because obviously most browsers show line number anyway.
You also have to set the variables' behaviour as seen in the image below:
Edit variables setup
use Macros!
https://www.jetbrains.com/help/webstorm/using-macros-in-the-editor.html
I recorded a macro that takes the name my cursor is on and create
console.log("#### name = ", name);
on the next line.
and assigned a keyboard shortcut to it :)
super easy, and couldn't get Live Template to get the same result with 1 action.
to create a new macro: Edit -> Macros -> Start Macro Recording. then record your next moves and create the desired result.
this is mine:
This is my solution, it somewhat mimics a turbo-console approach and gives you certain freedoms to build on it.
Step 1: Go to Editor > General > Postfix Completion;
Step 2: Click on JavaScript, click the + button, select JavaScript and TypeScript;
Step 3: In the Key input, type a alias for your command, I choose 'cl' for mine;
Step 4: In the 'Minimum language level' select your desired preference, I choose ECMAScript 6+;
Step 5: In the bellow text area, add your logic, for me it is console.log('$EXPR$', $EXPR$, '$END$');
Step 6: Customize however you like.
So what does all of this do?
Lets consider the following:
const willNeedToBeLogged = 'some value you want to check';
All you need to do for a console long is type
willNeedToBeLogged.cl + press (Tab, Enter or Spance)
And you will get this
console.log('willNeedToBeLogged', willNeedToBeLogged, '');
With your cursor being on the $END$ variable, where you could write, a line, or anything you like.
Have fun!
I made a custom template. This can help you.
Abbreviation: clog
Template code:
console.log("\n\n--------------------------------");
console.log($END$);
console.log("--------------------------------\n\n");
Simplest live template text:
console.log($END$);
Maybe it is a recent addition but you can write log and hit tab and console.log() will appear with the caret in between the braces.
The answer from Ekaterina Prigara (https://stackoverflow.com/a/32975087/5653914) was very useful to me but if you want to log a string like "Test" this method is quicker.
Try a logit plugin. It provides the next logging pattern by default:
const data = 'data';
console.log('-> data', data);
You can configure it.
Try Dot Log (vscode extension), It can automatically transfer aaa.log to console.log('aaa', aaa )
I want to display large photos in my Facebook app's feed view immediately. Is it possible to get the large photo src URL from a stream/feed using one API call? The photo id is returned in the stream/feed and one can of course then supply this photo id in an additional FQL or graph API call to retrieve all the information about that photo. However, is there a way using multi-query or batch calls to get a larger photo src url using one API roundtrip?
I haven't tried this with stream/feed photos, but the generally accepted way of doing this is:
http://graph.facebook.com/{ID of object}/picture
If you want the "large" version, you would do:
http://graph.facebook.com/{ID of object}/picture?type=large
I'm not 100% sure if this would work for an actual photo (instead of a user profile picture or page profile pic), but I have a hunch it will - the only caveat is that you obviously must have a logged in user that is authorized to view the photo (unless it's public).
If anybody is looking to this and type large is not enough, I found other solutions.
Type large is kind of small anyway (close to 200px). You can get larger image by adding i.e. ?width=1000 or ?height=1000. Facebook will return picture closest to given dimension and preserve aspect ratio. When passing both dimenstions like ?width=1000&height=1000, facebook will cut image to given dimensions (in this case square).
Use Facebook UserId (Oject ID) to get the picture.
https://graph.facebook.com/173xxxx8635/picture?type=large&redirect=false
which returns JSON data with picture URL.
{
"data": {
"is_silhouette": false,
"url": "https://fbcdn-profile-a.akamaihd.net/xxx/xyz/1cc066a2cae3f301d"
}
}
A good trick with the new api is to get the pic_cover field from the event table and to process it according to the size you want to use
I found when I was having this trouble that it turned out to be the picture I was downloading rather than the size I was setting it.
If for example I downloaded all my photos with a request of
[FBRequestConnection startWithGraphPath:#"/me/photos?fields=created_time,name,picture&type=tagged" parameters:nil HTTPMethod:#"GET" completionHandler:^(FBRequestConnection * connection, id result, NSError *error) {
NSDictionary * userData = (NSDictionary *)result;
NSMutableArray * array = [[NSMutableArray alloc] initWithArray:userData[#"data"]];
for (NSDictionary * dict in eventsToAdd) {
UIImage * image = dict[#"picture"]
}
}];
I am using the dictionary key search "picture" as I want the picture.
This though will get me a lower quality picture than if I searched for "source" in this search:
[FBRequestConnection startWithGraphPath:#"/me/photos?fields=created_time,name,source&type=tagged" parameters:nil HTTPMethod:#"GET" completionHandler:^(FBRequestConnection * connection, id result, NSError *error) {
NSDictionary * userData = (NSDictionary *)result;
NSMutableArray * array = [[NSMutableArray alloc] initWithArray:userData[#"data"]];
for (NSDictionary * dict in eventsToAdd) {
UIImage * image = dict[#"source"]
}
}];
If you go on the Facebook API explorer and search for photos and then click on the picture and source jpg links you can see the difference in size and quality.
Since changing this method I have managed to get rid of using the type parameters as it doesn't seem to make a different.
Note: I am using iPhone and not iPad or a larger screen so I don't know how this affects bigger screens.
The answer by #streetlogics works fine but only on pictures that have {object_id}.
http://graph.facebook.com/{object_id}/picture
But I also wanted large pictures for the feed's shared links, which sometimes don't have {object_id}. I finally realized that the {picture} thumbnail URL contains the encoded URL for the original site's large image:
https://external.xx.fbcdn.net/safe_image.php?d=AQBe9UvGd0vPbAHP&w=130&h=130&url=http%3A%2F%2Fskift.com%2Fwp-content%2Fuploads%2F2015%2F12%2Fpollution.jpg&cfs=1
--> contains -->
http://skift.com/wp-content/uploads/2015/12/pollution.jpg
So I made a loop that checks for {object_id} and if not present then extracts the URL from {picture}:
if(isset($post['object_id'])) {
echo "http://graph.facebook.com/".$post['object_id']."/picture";
}
elseif(isset($post['picture'])) {
echo urldecode(preg_replace('/&cfs.*/', '', preg_replace('/.*url=/', '', $post['picture'])));
}
else {
echo "no_large_image";
}