Trigger input file click event in AngularJS - javascript

I am trying to emulate a click event on a file input in AngularJS. I have seen working jQuery examples, but I don't want to use jQuery.
'use strict';
angular.module('MyApp', []).
controller('MyCtrl', function($scope) {
$scope.click = function() {
setTimeout(function() {
var element = angular.element(document.getElementById('input'));
element.triggerHandler('click');
$scope.clicked = true;
}, 0);
};
});
<script src="https://code.angularjs.org/1.3.14/angular.js"></script>
<div ng-app="MyApp" ng-controller="MyCtrl">
<input id="input" type="file"/>
<button ng-click="click()">Click me!</button>
<div ng-if="clicked">Clicked</div>
</div>
Note: For some reason the button needs to be pressed twice in order to trigger the timeout function.
I am using setTimeout because of this post.
How do I programmatically click a file input with just AngularJS / vanilla JavaScript?

You can simply use
<button type="button" onclick="document.getElementById('input').click()">Click me!</button>
OR
$scope.click = function() {
setTimeout(function() {
document.getElementById('input').click()
$scope.clicked = true;
}, 0);
};

Here's how to trigger file of type 'file' or open select-file window when click on icon, button or span as you like ;)
css :
.attachImageForCommentsIcon{
padding-top: 14px;
padding-right: 6px;
outline:none;
cursor:pointer;
}
HTML :
<input id="myInput" type="file" style="visibility:hidden" ng-file-model=""/>
<i onclick="$('#myInput').click();" class="attachImageForCommentsIcon blue-2 right-position material-icons">image</i>
all credits goes for this answer :
https://stackoverflow.com/questions/8595389/programmatically-trigger-select-file-dialog-box
Thus, we customized file input tag using this way.

Related

ng-click for an entire DIV in AngularJS

Whenever any element inside my DIV is clicked I want to execute a function in Angular controller.
How to do this?
Basically I am looking to place a ng-click on DIV element and expect the ng-click event be called when any/all elements nested inside the div are clicked.
How to achieve this requirement?
Here both the container and the button has click events. When you click the button, the click event of its parent will also be triggered. This is called Event Bubbling in JavaScript
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
$scope.clicked = function() {
console.log("Clicked Me");
};
$scope.secondclick = function() {
console.log("Button Clicked")
}
});
.container {
width: 100%;
height: 300px;
background: cyan;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div class="container" ng-click="clicked()">
<button ng-click="secondclick()">Click Me</button>
</div>
</div>

Run server-side script when jQuery Switch button is switched

I have the following jquery plugin on my client side which gives me a on/off switch. I need "off" and "on" to trigger different server side scripts. I know how this can be achieved with a regular "on-click" button, but not with a switch button.
Here is what's in client-side:
<div id="second_div">
<form>
<div style="float: left; width: 50%;">
<p style="padding-bottom: 13px;"><em>Checkbox</em></p>
<p><input type="checkbox" name="check-1" value="4" class="lcs_check" autocomplete="off" /></p>
</div>
</form>
<div style=" clear: both;"></div>
</div>
<div id="third_div">
<em style="color: #777; font-size: 14px;">Check your browser console to see triggered events</em>
</div>
<p></p>
I would like "off" to trigger one function "google.script.run.loggOff();
I would like "on" to trigger another function "google.script.run.loggOn();
This is usually how i do it with an 'onclick button':
Client Side (on-click button):
<button type="button" onclick="google.script.run.createDoc();">Create Google Doc</button>
<script>
google.script.run.createDoc();
</script>
Server Side (on-click button):
function createDoc() {
var copyDoc = DocumentApp.openById(copyId);
copyDoc.saveAndClose();
}
Maybe I'm misunderstanding the question, but if you want to add click functions the on and off you can do something like this.
//off
$('.lcs_check').click(function() {
$('.lcs_check').attr('id','loggOff');
google.script.run.loggOff();
});
//on
$('.lcs_check #loggOff').click(function() {
$('.lcs_check #loggOff').removeAttr('id','loggOff');
google.script.run.loggOn();
});
This plugin is LC-switch, i found the github page and a more detailled demo page.
In the demo page there is a Event section, there is 3 events for what you trying to accomplish.
// triggered each time a field changes status
$('body').delegate('.lcs_check', 'lcs-statuschange', function() {
var status = ($(this).is(':checked')) ? 'checked' : 'unchecked';
console.log('field changed status: '+ status );
});
// triggered each time a field is checked
$('body').delegate('.lcs_check', 'lcs-on', function() {
console.log('field is checked');
});
// triggered each time a field is unchecked
$('body').delegate('.lcs_check', 'lcs-off', function() {
console.log('field is unchecked');
});
But it look like each of this event are called after state has changed. I didn't find a way to have click information before state is changed.

Trigger file input dialog

How can I auto trigger file input? ie. in the link below I want to trigger upload button on load
DEMO
<form id="test_form">
<input type="file" id="test">
<div id="test1">
<button>Upload</button>
</div>
</form>
$("#test1").trigger('click');
$("#test").trigger('click');
File input can't be automatically triggered in onload due to security purpose. It can't be fired without any user interaction. It is very disgusting when a page activates anything itself when the page loads.
By the way.
You can use label instead of button like following:
<label for="test">Upload</label>
$("document").ready(function() {
setTimeout(function() {
$("#test1").trigger('click');
},10);
$('#test1').click(function(){
alert('hii');
})
});
click event triggerd.
http://jsfiddle.net/j9oL4nyn/1/
You can do it somthing like as :
<button id="upld_btn">Upload</button>
$(document).ready(function () {
$('#upld_btn').trigger('click');
});
you can write something like this
$(document).ready(function(){
$("input#test").click();
});
this should work fine
The problem with your code is that you are applying a click event to the input and also to the div enclosing the button, but not to the actual button.
if you change your fiddle to this
<form id="test_form">
<input type="file" id="test">
<div id="test1"><button onclick="alert('click');">Upload</button></div>
</form>
and
$("#test1 button").trigger('click');
then the click trigger will be applied to the button. Alternatively give your button an ID and fo
$("#buttonid").trigger('click');
<form id="test_form">
<input type="file" id="test">
<div id="test1"><button>Upload</button></div>
</form>
Change your JS code like below.
$("#test1 button").click(function() {
$("#test").trigger('click');
});
Working Demo
It is not possible to programically open "Open File" dialog utilizing javascript without user action ; see Trigger click on input=file on asynchronous ajax done() .
Could, alternatively, create an element to overlay html at document .ready() event to provide user with options to click to open "Open File" dialog by calling click on input type="file" element , or close overlay of html by clicking "Close" .
$(function() {
function openFileDialog() {
button.fadeTo(0,1).find(input)[0].click();
dialog.hide();
}
function closeDialog() {
dialog.hide();
button.fadeTo(0,1);
}
var input = $("input[type=file]")
, button = $("#button").on("click", function(e) {
e.stopPropagation();
this.firstElementChild.click()
})
, options = $("<button>", {
css: {
position: "relative",
top: "36vh",
left: "12vw",
fontSize: "3.6em"
}
})
, dialog = $("<div>", {
id: "dialog",
css: {
position: "absolute",
zIndex: 2,
opacity: 0.25,
background: "dodgerblue",
width: window.innerWidth - 30,
height: window.innerHeight
}
})
.append(
options
.clone(false)
.on("click", openFileDialog)
.html("Open File")
, options
.clone(false)
.on("click", closeDialog)
.html("Close")
)
.prependTo("body");
});
input {
width: 0;
opacity: 0;
}
#button {
position: relative;
font-size: 32px;
width: 150px;
left: 32vw;
opacity: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<form id="test_form">
<div id="test1">
<button id="button">Upload
<input type="file" id="test">
</button>
</div>
</form>
Show input file dialog on load?
As described here only Internet Explorer allows for programmatic opening of the File Upload dialog. So the short answer is no, there is no way to automatically open the File Upload dialog on page load.
The long answer that you might consider is that you can show it when the user clicks on anything. The fact that you prefer an AngularJS solution tells us that you are writing a Single Page Application. Also, I don't think you need to show the File Upload dialog when the app first loads. You most likely need it to show after some user interaction - after the user clicks on something. That something, using the an AngularJS directive from here, could look like anything but be a file input. On click (the same user interaction) you can also switch to another route in your AngularJS app, effectively simulating a user navigating to another page and automatically presenting him the File Upload dialog.

AngularJS in line edit

I have a small piece of code, which I would like to extend with in line editting possibilities:
HTML:
<h1>Schedule <label ng-click="modifyText(index)">{{th.schedules[index].label}} </label>
</h1>
JS:
$scope.modifyText = function(index) {
this.th.schedules[index].label = 'modifiedtext';
};
Hence I would like to be able to click {{th.schedules[index].label}}, modify it inline to the string: "modifiedtext", and save it.
How can I do that?
Thank you.
In order to edit a label inline, you would probably have to use the contentEditable attribute since it isn't directly an editable element. If you give it an ng-model changing that data could be easier but you will still have to make a UI for actually editing it.
Instead I made an example using a text input and some simple styling to make it seem as though it isn't a text input when it isn't focused
http://jsfiddle.net/yrakrj48/
//-- HTML
<body ng-app="TestApp">
<div ng-controller="TestController">
<input ng-class="editing ? 'hasBorder' : 'noBorder'" type="text" ng-model="myLabel" ng-focus="editing = true" />
<button ng-if="editing" ng-click="saveEdit()">done</button>
</div>
</body>
//-- JS
var app = angular.module('TestApp',[]);
app.controller('TestController', function($scope) {
$scope.myLabel = 'this is a label';
$scope.saveEdit = function() {
$scope.editing = false;
};
});
//-- CSS
.hasBorder {
border:1px solid #666;
}
.noBorder {
border:none;
}
You should look into directives because creating one would be easy and I am sure one already exists somewhere out on github
I think you use. contenteditable=true
<div contenteditable=true>
I am Editable
</div>

Using window.open() and passing a knockoutjs ViewModel for a view in the new window

I am currently working on an application which requires a new window to be open in the browser on the click of button and then as a user types into a textbox on the main window the new window will update accordingly. I have used knockout before, but for some reason I am having problems getting the second windows view to update. Here is my current code.
//main.js
$(function () {
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
var newwindow;
$("#new-window-btn").click(function () {
newwindow = window.open("a/path/to/newwindow.html", "New Window","status=1,width=350,height=350");
newwindow._ViewModel = viewModel;
});
});
function ViewModel() {
var self = this;
self.textbox = ko.observable("");
};
This is the index.html and contains a very basic button which will open the new window, a textbox which the user will type into and a span tag to show I am not crazy.
//index.html
<div id="new-window-btn" class="btn">new window</div>
<textarea cols="3" rows ="3" data-bind="value:textbox,valueUpdate:'afterkeydown'"></textarea>
<span data-bind="text: textbox"></span>
This is the code for the second window which pops up when the user clicks on the new window button in the index.html
//newwindow.html
<script type="text/javascript">
$(function () {
var viewModel = window._ViewModel;
ko.applyBindings(viewModel);
$("#alert-viewModel").click(function () {
alert(viewModel.textbox());
});
});
</script>
<span data-bind="text:textbox()"></span>
<div id="alert-viewModel" class="btn">show texbox value</div>
When the user types into the textbox on the main page, the span tag on that page updates automagically. When the user clicks on the new window button the new window pops up with the text the user just entered, when the user continues to type in the main windows textbox the span tag in the secondary window does NOT update. However when a user presses the "show texbox value" button the text is displayed in an alert box, and HAS BEEN UPDATED! So my question is why is my span tag in the second window not updating when the ViewModel clearly has been(because of the value displayed from the "show texbox value" button).
Quick Comment:
For some reason accessing a file through window.open("somepath"); does not actually work properly in the context of this question. I found that I need to load the new window file in a small HTTP server and make "somepath" an actual url. (Which is why there is not some example code attached to this question).
The two windows must also share the same instance of ko if they share the same view model. That's because observables created with one instance of Knockout will not work with a different instance.
Here is an example that uses iframe, but the same principles apply to window.open:
Parent: http://jsfiddle.net/eZMTM/; Child: http://jsfiddle.net/GrXhv/7/
Parent code:
childWindow = ...;
childWindow.initChild(ko, viewModel);
Child code:
window.initChild = function(ko, viewModel) {
window.ko = ko;
ko.applyBindings(viewModel, document.body);
}
As Michael has mentioned, you can just apply the binding to the body of the opened window, like this:
var mywindow = window.open('', '', 'height=400,width=600');
mywindow.document.write('<input id="testText" type="text" data-bind="textInput: text1"/>');
ko.applyBindings(viewmodel, mywindow.document);
If you would like to try a working example with a popup, here's a fiddle.
I Have attached the full code in a snippet below, however as the stackoverflow sandbox does not allow popups, it will fail in the snippet here. Still having the code in the post seems valuable enough.
PS: While old, this is one of the first hits on google I got, so i presumed adding a working example would help ...
$(function() {
var viewModel = function() {
var self = this;
//creating our observables
self.text1 = ko.observable("Hello World ...");
self.text2 = ko.observable("... how's it going");
//The magic happens here
self.newKOWindow = function() {
var mywindow = window.open('', '', 'height=400,width=600');
//just adding the html boilerplate Part1
mywindow.document.write('<html><head><title>The KO Popup</title>');
mywindow.document.write('</head><body>');
//manually creating the input the window
mywindow.document.write('<div class="dontCopyMe">');
mywindow.document.write('<h2>A Manually created input which is bound</h2>');
mywindow.document.write('<input id="testText" type="text" data-bind="textInput: text1"/>');
//just adding the html boilerplate Part2
mywindow.document.write('</div>');
mywindow.document.write('</body></html>');
mywindow.document.close();
//just copy our inputs into the new window
$(".copyMe").clone().appendTo(mywindow.document.body);
//copy our css
$("#compiled-css").clone().appendTo(mywindow.document.head);
//bind the viewmodel
window.ko = ko;
ko.applyBindings(self, mywindow.document.body);
return true;
}
};
model = new viewModel();
ko.applyBindings(model);
});
.copyMe,
.dontCopyMe {
border: 3px dashed limegreen;
padding: 0.5rem;
margin: 0.5rem;
max-width: 30rem;
}
.dontCopyMe {
border-color: grey;
}
h2 {
margin: 0 0 0.5rem;
font-size: 1rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<body>
<div>
<div class="copyMe">
<h2>Our inputs (will be copied into the popup window)</h2>
<input type="text" data-bind="textInput: text1" />
<input type="text" data-bind="textInput: text2" />
</div>
<div class="copyMe">
<h2>Same Inputs just to show this is working :)</h2>
<input type="text" data-bind="textInput: text1" />
<input type="text" data-bind="textInput: text2" />
</div>
<input id="NWO" type="button" value="NEW KO WIN OPEN" data-bind="click: newKOWindow" />
</div>
</body>

Categories

Resources