Skip to content

Commit c09ab4a

Browse files
committed
Add image-paste demo for Angular 7.2.15.
1 parent ab87e9d commit c09ab4a

28 files changed

Lines changed: 7567 additions & 0 deletions

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ with.
1010

1111
## My JavaScript Demos - I Love JavaScript!
1212

13+
* [Pasting Images Into Your App Using File Blobs And URL.createObjectURL() In Angular 7.2.15](https://bennadel.github.io/JavaScript-Demos/demos/pasting-images-angular7/)
1314
* [Creating An Inline Auto-Complete Directive Using NgModel And A Control Value Accessor In Angular 7.2.15](https://bennadel.github.io/JavaScript-Demos/demos/inline-auto-complete-input-angular7/)
1415
* [Desktop Safari Seems To Add Extra Padding To CSS Flexbox Item Inside List Item](https://bennadel.github.io/JavaScript-Demos/demos/safari-li-flexbox-wonky/)
1516
* [Trying To Center A Text-Overflow Ellipsis Using CSS Flexbox In Angular 7.2.15](https://bennadel.github.io/JavaScript-Demos/demos/center-ellipsis-angular7/)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
# Now that we're using Webpack, we can install modules locally and just ignore
3+
# them since the assets are baked into the compiled modules.
4+
node_modules/
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
:host {
3+
display: block ;
4+
font-size: 18px ;
5+
}
6+
7+
.sample-images {
8+
align-items: flex-start ;
9+
display: flex ;
10+
flex-wrap: wrap ;
11+
}
12+
13+
.sample-image {
14+
border-bottom: 1px solid #bababa ;
15+
border-radius: 5px 5px 5px 5px ;
16+
box-shadow: 0px 1px 3px rgba( 0, 0, 0, 0.2 ) ;
17+
flex: 0 0 auto ;
18+
margin: 0px 20px 20px 0px ;
19+
width: 200px ;
20+
}
21+
22+
.images {}
23+
24+
.image {
25+
border-bottom: 1px solid #bababa ;
26+
border-radius: 5px 5px 5px 5px ;
27+
box-shadow: 0px 1px 3px rgba( 0, 0, 0, 0.2 ) ;
28+
display: block ;
29+
margin: 20px 0px 20px 0px ;
30+
width: 500px;
31+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
2+
// Import the core angular services.
3+
import { Component } from "@angular/core";
4+
import { DomSanitizer } from "@angular/platform-browser";
5+
import { SafeUrl } from "@angular/platform-browser";
6+
7+
// ----------------------------------------------------------------------------------- //
8+
// ----------------------------------------------------------------------------------- //
9+
10+
@Component({
11+
selector: "my-app",
12+
host: {
13+
"(window:paste)": "handlePaste( $event )"
14+
},
15+
styleUrls: [ "./app.component.less" ],
16+
template:
17+
`
18+
<h2>
19+
Sample Images (That You Can Right-Click And Copy)
20+
</h2>
21+
22+
<p class="sample-images">
23+
<img src="./img/image-1.jpg" class="sample-image" />
24+
<img src="./img/image-2.jpg" class="sample-image" />
25+
<img src="./img/image-3.png" class="sample-image" />
26+
<img src="./img/image-4.jpg" class="sample-image" />
27+
<img src="./img/image-5.jpg" class="sample-image" />
28+
</p>
29+
30+
<h2>
31+
Pasted Images
32+
</h2>
33+
34+
<p class="images">
35+
<ng-template ngFor let-imageUrl [ngForOf]="imageUrls">
36+
37+
<img [src]="imageUrl" class="image" />
38+
39+
</ng-template>
40+
</p>
41+
`
42+
})
43+
export class AppComponent {
44+
45+
public imageUrls: SafeUrl[];
46+
47+
private lastObjectUrl: string;
48+
private sanitizer: DomSanitizer;
49+
50+
// I initialize the app component.
51+
constructor( sanitizer: DomSanitizer ) {
52+
53+
this.sanitizer = sanitizer;
54+
55+
this.imageUrls = [];
56+
this.lastObjectUrl = "";
57+
58+
}
59+
60+
// ---
61+
// PUBLIC METHODS.
62+
// ---
63+
64+
// I handle the paste event on the Window (see host bindings).
65+
public handlePaste( event: ClipboardEvent ) : void {
66+
67+
var pastedImage = this.getPastedImage( event );
68+
69+
if ( ! pastedImage ) {
70+
71+
return;
72+
73+
}
74+
75+
// When we create Object URLs, the browser will keep them in memory until the
76+
// document is unloaded or until the URL is explicitly released. Since we are
77+
// going to create a new URL every time the user pastes an image into the app (in
78+
// this particular demo), we need to be sure to release the previous Object URL
79+
// before we create the new one.
80+
// --
81+
// NOTE: One the Image is rendered in the DOM, releasing the Object URL will not
82+
// affect the rendering.
83+
if ( this.lastObjectUrl ) {
84+
85+
URL.revokeObjectURL( this.lastObjectUrl );
86+
87+
}
88+
89+
// At this point, the "pastedImage" is a File object, which is a specialized type
90+
// of "Blob". We can now generate a "blob:" URL using the given File.
91+
this.lastObjectUrl = URL.createObjectURL( pastedImage );
92+
93+
// By default, Angular WILL NOT TRUST this "blob:" style URLs. However, since we
94+
// know these are going to be expected, we can use the DOM Sanitizer to bypass
95+
// the security checks on these images.
96+
// --
97+
// NOTE: The sanitizer doesn't return Strings - it returns SafeUrls.
98+
this.imageUrls.unshift(
99+
this.sanitizer.bypassSecurityTrustUrl( this.lastObjectUrl )
100+
);
101+
102+
}
103+
104+
// ---
105+
// PRIVATE METHODS.
106+
// ---
107+
108+
// I return the first Image File from the given paste event (or null).
109+
private getPastedImage( event: ClipboardEvent ) : File | null {
110+
111+
// NOTE: I am not very familiar with the Paste Event. As such, I am probably
112+
// being more cautious here than I need to be. However, in an abundance of
113+
// caution, I am checking each part of the targeted object path.
114+
if (
115+
event.clipboardData &&
116+
event.clipboardData.files &&
117+
event.clipboardData.files.length &&
118+
this.isImageFile( event.clipboardData.files[ 0 ] )
119+
) {
120+
121+
return( event.clipboardData.files[ 0 ] );
122+
123+
}
124+
125+
return( null );
126+
127+
}
128+
129+
130+
// I determine if the given File is an Image (according do its Mime-Type).
131+
private isImageFile( file: File ) : boolean {
132+
133+
return( file.type.search( /^image\//i ) === 0 );
134+
135+
}
136+
137+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
// Import the core angular services.
3+
import { BrowserModule } from "@angular/platform-browser";
4+
import { NgModule } from "@angular/core";
5+
6+
// Import the application components and services.
7+
import { AppComponent } from "./app.component";
8+
9+
// ----------------------------------------------------------------------------------- //
10+
// ----------------------------------------------------------------------------------- //
11+
12+
@NgModule({
13+
imports: [
14+
BrowserModule
15+
],
16+
declarations: [
17+
AppComponent
18+
],
19+
bootstrap: [
20+
AppComponent
21+
]
22+
})
23+
export class AppModule {
24+
// ...
25+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
6+
<title>
7+
Pasting Images Into Your App Using File Blobs And URL.createObjectURL() In Angular 7.2.15
8+
</title>
9+
</head>
10+
<body>
11+
12+
<h1>
13+
Pasting Images Into Your App Using File Blobs And URL.createObjectURL() In Angular 7.2.15
14+
</h1>
15+
16+
<my-app>
17+
<p>
18+
<em>Loading files...</em>
19+
</p>
20+
21+
<p>
22+
npm Run Scripts:
23+
</p>
24+
25+
<ul>
26+
<li>
27+
<strong>npm run build</strong> &mdash; Compiles the .ts file into bundles.
28+
</li>
29+
<li>
30+
<strong>npm run watch</strong> &mdash; Compiles the .ts file into bundles and then watches files for changes.
31+
</li>
32+
</ul>
33+
</my-app>
34+
35+
</body>
36+
</html>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
// Import these libraries for their side-effects.
3+
import "core-js/es";
4+
import "zone.js/dist/zone.js";
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
// Import the core angular services.
3+
import { enableProdMode } from "@angular/core";
4+
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
5+
6+
// Import the root module for bootstrapping.
7+
import { AppModule } from "./app.module";
8+
9+
// ----------------------------------------------------------------------------------- //
10+
// ----------------------------------------------------------------------------------- //
11+
12+
// NOTE: This ENV value is being provided by Webpack's DefinePlugin. It is populated
13+
// on the mode in which the webpack-cli was invoked.
14+
if ( process.env.NODE_ENV === "production" ) {
15+
16+
enableProdMode();
17+
18+
}
19+
20+
platformBrowserDynamic().bootstrapModule( AppModule );

demos/pasting-images-angular7/build/main.aebf9f9ac20a08050410.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

demos/pasting-images-angular7/build/main.aebf9f9ac20a08050410.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)