I tried to make parts of code read-only in Ace editor.
I have tried by using code given in JsFiddle
$(function() {
var editor = ace.edit("editor1")
, session = editor.getSession()
, Range = require("ace/range").Range
, range = new Range(1, 4, 1, 10)
, markerId = session.addMarker(range, "readonly-highlight");
session.setMode("ace/mode/javascript");
editor.keyBinding.addKeyboardHandler({
handleKeyboard : function(data, hash, keyString, keyCode, event) {
if (hash === -1 || (keyCode <= 40 && keyCode >= 37)) return false;
if (intersects(range)) {
return {command:"null", passEvent:false};
}
}
});
before(editor, 'onPaste', preventReadonly);
before(editor, 'onCut', preventReadonly);
range.start = session.doc.createAnchor(range.start);
range.end = session.doc.createAnchor(range.end);
range.end.$insertRight = true;
function before(obj, method, wrapper) {
var orig = obj[method];
obj[method] = function() {
var args = Array.prototype.slice.call(arguments);
return wrapper.call(this, function(){
return orig.apply(obj, args);
}, args);
}
return obj[method];
}
function intersects(range) {
return editor.getSelectionRange().intersects(range);
}
function preventReadonly(next, args) {
if (intersects(range)) return;
next();
}
});
I got a problem when I keep pressing backspace it went into the read-only part and there was no editable part left.
How can I make multiple chunks of code read-only and avoid last character from read-only getting deleted.
Also, how to achieve the whole thing dynamically where I have markers in text specifying editable portions ?
Check the below code that allows multiple chunk of lines read-only with Enter at end of range to prevent non reversible delete and drag/drop handled.
function set_readonly(editor,readonly_ranges) {
var session = editor.getSession()
, Range = require("ace/range").Range;
ranges = [];
function before(obj, method, wrapper) {
var orig = obj[method];
obj[method] = function() {
var args = Array.prototype.slice.call(arguments);
return wrapper.call(this, function(){
return orig.apply(obj, args);
}, args);
}
return obj[method];
}
function intersects(range) {
return editor.getSelectionRange().intersects(range);
}
function intersectsRange(newRange) {
for (i=0;i<ranges.length;i++)
if(newRange.intersects(ranges[i]))
return true;
return false;
}
function preventReadonly(next, args) {
for(i=0;i<ranges.length;i++){if (intersects(ranges[i])) return;}
next();
}
function onEnd(position){
var row = position["row"],column=position["column"];
for (i=0;i<ranges.length;i++)
if(ranges[i].end["row"] == row && ranges[i].end["column"]==column)
return true;
return false;
}
function outSideRange(position){
var row = position["row"],column=position["column"];
for (i=0;i<ranges.length;i++){
if(ranges[i].start["row"]< row && ranges[i].end["row"]>row)
return false;
if(ranges[i].start["row"]==row && ranges[i].start["column"]<column){
if(ranges[i].end["row"] != row || ranges[i].end["column"]>column)
return false;
}
else if(ranges[i].end["row"] == row&&ranges[i].end["column"]>column){
return false;
}
}
return true;
}
for(i=0;i<readonly_ranges.length;i++){
ranges.push(new Range(...readonly_ranges[i]));
}
ranges.forEach(function(range){session.addMarker(range, "readonly-highlight");});
session.setMode("ace/mode/javascript");
editor.keyBinding.addKeyboardHandler({
handleKeyboard : function(data, hash, keyString, keyCode, event) {
if (Math.abs(keyCode) == 13 && onEnd(editor.getCursorPosition())){
return false;
}
if (hash === -1 || (keyCode <= 40 && keyCode >= 37)) return false;
for(i=0;i<ranges.length;i++){
if (intersects(ranges[i])) {
return {command:"null", passEvent:false};
}
}
}
});
before(editor, 'onPaste', preventReadonly);
before(editor, 'onCut', preventReadonly);
for(i=0;i<ranges.length;i++){
ranges[i].start = session.doc.createAnchor(ranges[i].start);
ranges[i].end = session.doc.createAnchor(ranges[i].end);
ranges[i].end.$insertRight = true;
}
var old$tryReplace = editor.$tryReplace;
editor.$tryReplace = function(range, replacement) {
return intersectsRange(range)?null:old$tryReplace.apply(this, arguments);
}
var session = editor.getSession();
var oldInsert = session.insert;
session.insert = function(position, text) {
return oldInsert.apply(this, [position, outSideRange(position)?text:""]);
}
var oldRemove = session.remove;
session.remove = function(range) {
return intersectsRange(range)?false:oldRemove.apply(this, arguments);
}
var oldMoveText = session.moveText;
session.moveText = function(fromRange, toPosition, copy) {
if (intersectsRange(fromRange) || !outSideRange(toPosition)) return fromRange;
return oldMoveText.apply(this, arguments);
}
}
function refresheditor(id,content,readonly) {
var temp_id=id+'_temp';
document.getElementById(id).innerHTML="<div id='"+temp_id+"'></div>";
document.getElementById(temp_id).innerHTML=content;
var editor = ace.edit(temp_id);
set_readonly(editor,readonly);
}
function get_readonly_by_editable_tag(id,content){
var text= content.split("\n");
var starts=[0],ends=[];
text.forEach(function(line,index){
if((line.indexOf("<editable>") !== -1))ends.push(index);
if((line.indexOf("</editable>") !== -1))starts.push(index+1);
});
ends.push(text.length);
var readonly_ranges=[];
for(i=0;i<starts.length;i++){
readonly_ranges.push([starts[i],0,ends[i],0])
}
refresheditor(id,content,readonly_ranges);
}
var content=document.getElementById("code").innerHTML;
function readonly_lines(id,content,line_numbers){
var readonly_ranges=[];
all_lines= line_numbers.sort();
for(i=0;i<line_numbers.length;i++){
readonly_ranges.push([line_numbers[i]-1,0,line_numbers[i],0]);
}
refresheditor(id,content,readonly_ranges);
}
get_readonly_by_editable_tag("myeditor",content)
//readonly_lines("myeditor",content,[5,7,9]);
.ace_editor {
width:100%;
height:300px;
}
.readonly-highlight{
background-color: red;
opacity: 0.2;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ace.c9.io/build/src/ace.js"></script>
<link rel="stylesheet" type="text/css" href="http://jsfiddle.net/css/normalize.css">
<link rel="stylesheet" type="text/css" href="http://jsfiddle.net/css/result-light.css">
<button onclick="get_readonly_by_editable_tag('myeditor',content)">Readonly by tags</button>
<button onclick="readonly_lines('myeditor',content,[3,7])">Readonly lines 3 and 7 </button>
<div id="myeditor" ></div>
<div id="code" style="display:none;">//<editable>
//</editable>
function refresheditor() {
//<editable>
document.getElementById("myeditor").innerHTML="<div id='editor'></div>";
document.getElementById("editor").innerHTML=document.getElementById("code").innerHTML;
//</editable>
var editor = ace.edit("editor")
, session = editor.getSession()
, Range = require("ace/range").Range;
ranges = [];
var text= document.getElementById("code").innerHTML.split("\n");
var starts=[0],ends=[];
text.forEach(function(line,index){
if((line.indexOf("<editable>") !== -1))ends.push(index);
if((line.indexOf("</editable>") !== -1))starts.push(index+1);
});
ends.push(text.length);
for(i=0;i<starts.length;i++){
ranges.push(new Range(starts[i], 0,ends[i] ,0));
}
ranges.forEach(function(range){session.addMarker(range, "readonly-highlight");});
session.setMode("ace/mode/javascript");
//<editable>
editor.keyBinding.addKeyboardHandler({
handleKeyboard : function(data, hash, keyString, keyCode, event) {
var pos=editor.getCursorPosition();
if (Math.abs(keyCode) == 13){
for (i=0;i<ranges.length;i++){
if((ranges[i].end["row"]==pos["row"])&&(ranges[i].end["column"]==pos["column"])){ return false;}
}
}
if (hash === -1 || (keyCode <= 40 && keyCode >= 37)) return false;
for(i=0;i<ranges.length;i++){
if (intersects(ranges[i])) {
return {command:"null", passEvent:false};
}
}
}
});
//</editable>
before(editor, 'onPaste', preventReadonly);
before(editor, 'onCut', preventReadonly);
for(i=0;i<ranges.length;i++){
ranges[i].start = session.doc.createAnchor(ranges[i].start);
ranges[i].end = session.doc.createAnchor(ranges[i].end);
ranges[i].end.$insertRight = true;
}
function before(obj, method, wrapper) {
var orig = obj[method];
obj[method] = function() {
var args = Array.prototype.slice.call(arguments);
return wrapper.call(this, function(){
return orig.apply(obj, args);
}, args);
}
return obj[method];
}
function intersects(range) {
return editor.getSelectionRange().intersects(range);
}
function preventReadonly(next, args) {
for(i=0;i<ranges.length;i++){if (intersects(ranges[i])) return;}
next();
}
}
refresheditor();
</div>
This code snippet will prevent the user from editing the first or last line of the editor:
editor.commands.on("exec", function(e) {
var rowCol = editor.selection.getCursor();
if ((rowCol.row == 0) || ((rowCol.row + 1) == editor.session.getLength())) {
e.preventDefault();
e.stopPropagation();
}
});
https://jsfiddle.net/tripflex/y0huvc1b/
Source:
https://groups.google.com/forum/#!topic/ace-discuss/yffGsSG7GSA
sorry: this code does not handle drag/drop
I added this last proposal last week: Ace Editor: Lock or Readonly Code Segment
After refreshing the page the label contenct vanishes.
What should i change so that this won't happen?
var versuche = 3; //login attempts
function validate(){
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
if ( username == "DjolePhillip" && password == "passwort12345")
{
alert ("Login erfolgreich");
window.location = "loggedin.html";
document.getElementById("loginname").innerHTML = username; //label gets the username
return false;
}
else{
versuche --;
alert("Du hast "+versuche+" uebrig;");
if( versuche == 0)// if no attempts left
{
document.getElementById("username").disabled = true;
document.getElementById("password").disabled = true;
document.getElementById("submit").disabled = true;
return false;
}
}
}
<div id="anmeldung">
<center id="anmeldename"><label id="loginname"></label></center>
</div>
There above is the full Code.
You have to persist the data somewhere. Server side with an ajax request, client side with SessionStorage or LocalStorage.
Example with LocalStorage
var localStorage = window.localStorage
var storedUsername = getUsernameInMemory()
var domUsername = getUsernameDomValue()
var username = storedUsername || domUsername || 'unknown'
if ( !isUsernameDefinedInDOM() ) {
setLoginname(username)
}
if ( isUsernameKnown() && !isUsernameDefinedInLocalStorage() ) {
storeUsername(username)
}
function isUsernameKnown () {
return username !== 'unknown'
}
function setLoginname (_username) {
document.getElementById('loginname').innerHTML = username
}
function storeUsername (_username) {
localStorage['username'] = _username
}
function getUsernameDomValue () {
return document.getElementById('username').value
}
function getUsernameInMemory () {
return localStorage['username']
}
function isUsernameDefinedInDOM () {
return !!getUsernameDomValue() // returns a boolean
}
function isUsernameDefinedInLocalStorage () {
return getUsernameDomValue() !== 'unknown'
}
JSHint Problems. console and FBT are also not defined.
As a result my button in page-signup does not work.
................................................................................................................................................................
(function () {
var emailAddressIsValid = function (email) {
var re = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
};
var passwordsMatch = function (password, passwordConfirm) {
return password === passwordConfirm;
};
var passwordIsComplex = function (password) {
// TODO: implement password complexity rules here. There should be similar rule on the server side.
return true;
};
$(document).delegate("#page-signup", "pagebeforecreate", function () {
var $signUpPage = $("#page-signup"),
$btnSubmit = $("#btn-submit", $signUpPage);
$btnSubmit.off("tap").on("tap", function () {
var $ctnErr = $("#ctn-err", $signUpPage),
$txtFirstName = $("#txt-first-name", $signUpPage),
$txtLastName = $("#txt-last-name", $signUpPage),
$txtEmailAddress = $("#txt-email-address", $signUpPage),
$txtPassword = $("#txt-password", $signUpPage),
$txtPasswordConfirm = $("#txt-password-confirm", $signUpPage);
var firstName = $txtFirstName.val().trim(),
lastName = $txtLastName.val().trim(),
emailAddress = $txtEmailAddress.val().trim(),
password = $txtPassword.val().trim(),
passwordConfirm = $txtPasswordConfirm.val().trim(),
invalidInput = false,
invisibleStyle = "bi-invisible",
invalidInputStyle = "bi-invalid-input";
// Reset styles.
$ctnErr.removeClass().addClass(invisibleStyle);
$txtFirstName.removeClass(invalidInputStyle);
$txtLastName.removeClass(invalidInputStyle);
$txtEmailAddress.removeClass(invalidInputStyle);
$txtPassword.removeClass(invalidInputStyle);
$txtPasswordConfirm.removeClass(invalidInputStyle);
// Flag each invalid field.
if (firstName.length === 0) {
$txtFirstName.addClass(invalidInputStyle);
invalidInput = true;
}
if (lastName.length === 0) {
$txtLastName.addClass(invalidInputStyle);
invalidInput = true;
}
if (emailAddress.length === 0) {
$txtEmailAddress.addClass(invalidInputStyle);
invalidInput = true;
}
if (password.length === 0) {
$txtPassword.addClass(invalidInputStyle);
invalidInput = true;
}
if (passwordConfirm.length === 0) {
$txtPasswordConfirm.addClass(invalidInputStyle);
invalidInput = true;
}
// Make sure that all the required fields have values.
if (invalidInput) {
$ctnErr.html("<p>Please enter all the required fields.</p>");
$ctnErr.addClass("bi-ctn-err").slideDown();
return;
}
if (!emailAddressIsValid(emailAddress)) {
$ctnErr.html("<p>Please enter a valid email address.</p>");
$ctnErr.addClass("bi-ctn-err").slideDown();
$txtEmailAddress.addClass(invalidInputStyle);
return;
}
if (!passwordsMatch(password, passwordConfirm)) {
$ctnErr.html("<p>Your passwords don't match.</p>");
$ctnErr.addClass("bi-ctn-err").slideDown();
$txtPassword.addClass(invalidInputStyle);
$txtPasswordConfirm.addClass(invalidInputStyle);
return;
}
if (!passwordIsComplex(password)) {
// TODO: Use error message to explain password rules.
$ctnErr.html("<p>Your password is very easy to guess. Please try a more complex password.</p>");
$ctnErr.addClass("bi-ctn-err").slideDown();
$txtPassword.addClass(invalidInputStyle);
$txtPasswordConfirm.addClass(invalidInputStyle);
return;
}
$.ajax({
type: 'POST',
url: FBT.Settings.signUpUrl,
data:"email=" + emailAddress + "&firstName=" + firstName + "&lastName=" + lastName + "&password=" + password + "&passwordConfirm=" + passwordConfirm,
success: function (resp) {
console.log("success");
if (resp.success === true) {
$.mobile.navigate("signup-succeeded.html");
return;
}
if (resp.extras.msg) {
switch (resp.extras.msg) {
case FBT.ApiMessages.DB_ERROR:
case FBT.ApiMessages.COULD_NOT_CREATE_USER:
// TODO: Use a friendlier error message below.
$ctnErr.html("<p>Oops! A problem occured while trying to register you. Please try again in a few minutes.</p>");
$ctnErr.addClass("bi-ctn-err").slideDown();
break;
case FBT.ApiMessages.EMAIL_ALREADY_EXISTS:
$ctnErr.html("<p>The email address that you provided is already registered.</p>");
$ctnErr.addClass("bi-ctn-err").slideDown();
$txtEmailAddress.addClass(invalidInputStyle);
break;
}
}
},
error: function (e) {
console.log(e.message);
// TODO: Use a friendlier error message below.
$ctnErr.html("<p>Oops! A problem occured while trying to register you. Please try again in a few minutes.</p>");
$ctnErr.addClass("bi-ctn-err").slideDown();
}
});
});
});
})();
I'm having a problem and don't know how the form will accept the username without email extension for example i can enter "pro" only in "pro#domain.com"
Here's my code:
function loginHI(menu){
$(".hopplerTextboxLogin").focusin(function(){
hopplerTextboxFocused($(this));
}).focusout(function(){
$(this).removeClass("hopplerTextboxBorderBlue").addClass("hopplerTextbox");
});
$("#loginForm input").keyup(function(e){
if(e.keyCode == 13){
$("#btnLogin").click();
}
});
$("#btnLogin, #btnLogin2").click(function(){
//variable for email
var get_email = $("#j_username").val();
var get_pass = $("#j_password").val();
//validation
if(get_email=="" && get_pass==""){
somethingIsWrongHere("divUsername_login","Required fields");
somethingIsWrongHere("divPassword_login","Required fields");
return false;
}
if(get_email=="" || !isValidEmailAddress(get_email)){
somethingIsWrongHere("divUsername_login","Invalid email address");
return false;
}
if(get_pass == ""){
somethingIsWrongHere("divPassword_login","Password is required");
return false;
}
var result_page = setProjectName + "/j_spring_security_check";
$("#loginForm_message").html("<div class=\"loading_message_login\">logging in...</div>").fadeIn();
$("#cboxContent").removeClass("cboxContentHeight").addClass("cboxContentHeightMessage");
$.ajax({
type: 'POST',
url: result_page,
data: $("#loginForm").serialize(),
beforeSend: function (xhr) {
xhr.setRequestHeader("X-Ajax-call", "true");
},
success: function(data) {
if(data.result==1){
localStorage.shortlists = "";
var sl_array = [];
localStorage.userFullName = data.firstName+" "+data.lastName;
var user_url = "HICollection3/select?q=id%3A"+data.userId+"&wt=json&indent=true";
var sl_url = "ShortList_Collection/select?q=removed%3Afalse+AND+user_id%3A"+data.userId+"&rows=1000&wt=json&indent=true&json.wrf=?";
$.get("properties/querySolr",{url : sl_url},function(result) {
solr_results = result;
var obj = $.parseJSON(solr_results);
console.log("obj.numFound" + obj.numFound);
var sl = obj.docs;
$.each(sl,function(index){
sl_array.push(sl[index].property_id);
});
localStorage.shortlists = sl_array;
/*EMBEDDED HIDDENLIST FXN*/
var hl_array = [];
var hl_url = "HiddenList_Collection/select?q=user_id%3A"+data.userId+"&rows=1000&wt=json&indent=true&json.wrf=?";
$.get("properties/querySolr",{url : hl_url},function(result2) {
solr_results2 = result2;
var obj2 = $.parseJSON(solr_results2);
console.log("obj2.numFound" + obj2.numFound);
var hl = obj2.docs;
$.each(hl,function(index){
hl_array.push(hl[index].property_id);
});
localStorage.hiddenlists = hl_array;
$.get("properties/querySolr",{url : user_url},function(result3) {
var solr_results3 = result3;
var obj3 = $.parseJSON(solr_results3);
console.log("obj3.numFound" + obj3.numFound);
var user_res = obj3.docs;
localStorage.userContact="";
localStorage.userFullName="";
localStorage.userEmail="";
$.each(user_res,function(index){
localStorage.userFullName = user_res[index].firstName+" "+user_res[index].lastName;
localStorage.userEmail = user_res[index].email;
if(user_res[index].mobile!=undefined || user_res[index].mobile!="")
localStorage.userContact = user_res[index].mobile;
else if(user_res[index].telephone!=undefined || user_res[index].telephone!="")
localStorage.userContact = user_res[index].telephone;
else
localStorage.userContact = "";
});
setTimeout(function(){
location.reload();
},1000);
});
});
});
}
else{
somethingIsWrongHere("",data.result);
}
}
});
return false;
});
$("#keepMeLoggedIn").click(function(){
$("#rememberMe").trigger("click");
});
}
the user log-in should accept also the the whole email address.
This is the code for isValidEmailAddress function
function isValidEmailAddress(emailAddress) {
var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))#((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
return pattern.test(emailAddress);
};
Once again... the function test you will use will depend on what characters you would like to allow. If you want to only allow letters and numbers you could use...
function isValidUsername(username) {
var pattern = new RegExp(/^[a-zA-Z0-9]+$/);
return pattern.test(username);
}
and if you wanted to allow periods and # symbols so that you could have emails used as the username as optional...
function isValidUserName(username) {
var pattern = new RegExp(/^[a-zA-Z0-9\.\#]+$/);
return pattern.test(username);
}
Note that the user could use any combination of letters numbers and # symbols and periods if you use the second function. So, they could enter ###... or ddd#example.com or adfsadf8347
Here is the js file. The function SubmitCheck is running but when there is a state, I want to do the address check and it doesn't appear to run. What am I doing wrong?
Thanks,
ck in San Diego
var prm = null;
Sys.Application.add_init(Init);
function Init(sender) {
prm = Sys.WebForms.PageRequestManager.getInstance();
WireEvents();
}
function WireEvents() {
var submit = $("#btnSubmit");
submit.click(SubmitCheck);
}
function SubmitCheck(){
var hasState = DoStateCheck();
if (!hasState) {
prm.abortPostBack();
return false;
} else {
var addressCheck = DoAddressCheck();
alert(addressCheck);
}
if (!addressCheck) {
prm.abortPostBack();
return false;
}
}
function DoAddressCheck(){
var add1 = $("#txtAddressMaintLine1");
if (add1.val().length < 1) {
return confirm("No Address was detected.\nClick OK to proceed or Cancel to provide an address.");
}
return;
}
function DoStateCheck() {
var tb = $("#txtState");
if (tb.val().length < 2) {
alert("A state must be provided when establishing a claim.");
tb.focus();
return false;
}
return;
}
Maybe replace
return;
in DoStateCheck() with
return true;
?