I want to be able to insert images, wrapped in a span, into a contenteditable div. I can do this no problem but then when I go to type, after the image, it inserts my text into the images span. How do I position the cursor AFTER the span that I just inserted?
Here is my fiddle (click "Add Image at Cursor" and the enter text into the content editable. Observe the text is inside the images parent span.)
Here is my image insert function:
function insertElementAtCursor(elm) {
var sel, range, html;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
range.insertNode(elm);
placeCaretAfterNode(elm);
updateTextArea();
}
}
}
Added a text node after the span and moved the range to that
function insertElementAtCursor(elm) {
var sel, range, html;
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
range.insertNode(elm);
var textNode = document.createTextNode('\u00A0');
range.setStartAfter(elm);
range.insertNode(textNode);
range.setStartAfter(textNode);
range.collapse(true);
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
}
}
Related
I trying to make a SwiftUI app where after entering one letter in a TextField the cursor automatically moves to the next TextField. The UI is pretty much like this.
In Swift/IB, it looks like this was done with delegates and adding a target like in this post:
How to move to the next UITextField automatically in Swift
But can't find any documentation for using delegates/targets in SwiftUI.
I tried following this post:
SwiftUI TextField max length
But this has not worked for me. Setting the .prefix(1) does not seem to make a difference. The TextField still accepts any amount of characters and when moved to the next TextField does not reduce the characters entered to only the first character.
In SwiftUI's current state, is it possible to automatically move to the next TextField after 1 character is entered?
Thanks for any help!
It can be done in iOS 15 with FocusState
import SwiftUI
///Sample usage
#available(iOS 15.0, *)
struct PinParentView: View {
#State var pin: Int = 12356
var body: some View {
VStack{
Text(pin.description)
PinView(pin: $pin)
}
}
}
#available(iOS 15.0, *)
struct PinView: View {
#Binding var pin: Int
#State var pinDict: [UniqueCharacter] = []
#FocusState private var focusedField: UniqueCharacter?
var body: some View{
HStack{
ForEach($pinDict, id: \.id, content: { $char in
TextField("pin digit", text:
Binding(get: {
char.char.description
}, set: { newValue in
let newest: Character = newValue.last ?? "0"
//This check is only needed if you only want numbers
if Int(newest.description) != nil{
char.char = newest
}
//Set the new focus
DispatchQueue.main.async {
setFocus()
}
})
).textFieldStyle(.roundedBorder)
.focused($focusedField, equals: char)
})
}.onAppear(perform: {
//Set the initial value of the text fields
//By using unique characters you can keep the order
pinDict = pin.description.uniqueCharacters()
})
}
func setFocus(){
//Default to the first box when focus is not set or the user reaches the last box
if focusedField == nil || focusedField == pinDict.last{
focusedField = pinDict.first
}else{
//find the index of the current character
let idx = pinDict.firstIndex(of: focusedField!)
//Another safety check for the index
if idx == nil || pinDict.last == pinDict[idx!]{
focusedField = pinDict.first
}else{
focusedField = pinDict[idx! + 1]
}
}
//Update the Binding that came from the parent
setPinBinding()
}
///Updates the binding from the parent
func setPinBinding(){
var newPinInt = 0
for n in pinDict{
if n == pinDict.first{
newPinInt = Int(n.char.description) ?? 0
}else{
newPinInt = Int(String(newPinInt) + n.char.description) ?? 0
}
}
pin = newPinInt
}
}
//Convert String to Unique characers
extension String{
func uniqueCharacters() -> [UniqueCharacter]{
let array: [Character] = Array(self)
return array.uniqueCharacters()
}
func numberOnly() -> String {
self.trimmingCharacters(in: CharacterSet(charactersIn: "-0123456789.").inverted)
}
}
extension Array where Element == Character {
func uniqueCharacters() -> [UniqueCharacter]{
var array: [UniqueCharacter] = []
for char in self{
array.append(UniqueCharacter(char: char))
}
return array
}
}
//String/Characters can be repeating so yu have to make them a unique value
struct UniqueCharacter: Identifiable, Equatable, Hashable{
var char: Character
var id: UUID = UUID()
}
#available(iOS 15.0, *)
struct PinView_Previews: PreviewProvider {
static var previews: some View {
PinParentView()
}
}
I need to draw an image on a page that has a specific form field. Using pdfsharp, given a field name, how do I find the pdf page associated with that field?
Here an improvement with corrections which gives also back the pagenum:
PdfPage GetPageFromField(PdfDocument myDocument, string focusFieldName, out int pageNum)
{
// get the field we're looking for
PdfAcroField currentField = (PdfAcroField)(myDocument.AcroForm.Fields[focusFieldName]);
pageNum = 0;
if (currentField != null)
{
// get the page element
var focusPageReference = (PdfReference)currentField.Elements["/P"];
// loop through our pages to match the reference
foreach (var page in myDocument.Pages)
{
pageNum++;
if (page.Reference == focusPageReference)
{
return page;
}
}
}
// could not find a page for this field
return null;
}
You can access the page reference for the field using the page element of the field object. Then use this reference to match the page in the document.
public PdfPage GetPageFromField( PdfDocument myDocument, string focusFieldName )
{
// get the field we're looking for
PdfTextField currentField = (PdfTextField)( fillablePdf.AcroForm.Fields["MyFocusField"]);
if( currentField != null )
{
// get the page element
var focusPageReference = (PdfReference)currentField.Elements["/P"];
// loop through our pages to match the reference
foreach( var page in myDocument.Pages )
{
if( page.Reference = focusPageReference )
{
return page;
}
}
}
// could not find a page for this field
return null;
}
I'm trying to modify the below script so that it will automatically drop the first instance of "_item" and snap it to the nearest "slot"
The code works great except I cannot find a way to make it drop the item without the user clicking on it first. This is not my script. You can see it in action here- http://www.freeactionscript.com/2008/11/drag-drop-snap-inventory-system-v2/
Any help greatly appreciated, thanks!
/**
* Drag, Drop and Snap Inventory System
*
* Version: 2.0
* Author: Philip Radvan
* URL: http://www.freeactionscript.com
*/
var slots_array:Array = new Array(slot0, slot1, slot2, slot3, slot4, slot5, slot6, slot7, slot8, slot9, slot10, slot11, slot12, slot13, slot14, slot15);
var items_array:Array;
var uniqueItemId:Number = 0;
//
//start dragging
function dragItem(_item:Object):Void
{
//save position before dragging
_item.nowX = _item._x;
_item.nowY = _item._y;
//drag
_item.startDrag(true);
_item.onMouseMove = updateDrag;
}
//stop dragging
function dropItem(_item:Object):Void
{
//stop dragging
_item.stopDrag();
//delete mouse event
delete _item.onMouseMove;
//run loop on slots array
for (i=0; i<slots_array.length; i++)
{
//set temp slot var
currentSlot = eval(slots_array[i]);
//check slot hittest and slot itemID; if item is over slot and slot is empty, drop
if ((eval(_item._droptarget) == currentSlot) && (currentSlot.itemID == "empty"))
{
//place item in slot
_item._x = currentSlot._x;
_item._y = currentSlot._y;
//update current slot itemID
currentSlot.itemID = this;
//update previous slot itemID
temp = eval(_item.slotID);
temp.itemID = "empty";
//update current item slotID
_item.slotID = currentSlot.myName;
//item moved, end loop
return;
}
else
{
//return item to previous position if: item is NOT over slot or slot is NOT empty
_item._x = _item.nowX;
_item._y = _item.nowY;
}
}
}
/*
* updateAfterEven re-renders the screen
*/
function updateDrag():Void
{
updateAfterEvent();
}
/*
* Create Slots
*/
for (i=0; i<slots_array.length; i++)
{
var _currentSlot = slots_array[i];
_currentSlot.itemID = "empty";
_currentSlot.num = i;
_currentSlot.myName = "slot"+i;
}
/*
* Create Item
*/
function createInventoryItem()
{
//attach item to stage
var _item = attachMovie("item", "item"+uniqueItemId, _root.getNextHighestDepth());
//set item position
_item._x = 280;
_item._y = 320;
//set item settings
_item.myName = "item"+uniqueItemId;
_item.slotID = "empty";
//make item a button
_item.onPress = function()
{
dragItem(this)
}
_item.onRelease = _item.onReleaseOutside = function()
{
dropItem(this);
}
//add item to array
items_array.push(_item);
//update unique Item Id
uniqueItemId++;
}
//button to create a new inventory item
create_item_btn.onRelease = function()
{
createInventoryItem();
}
Fixed it. Rather than modifying this one I wrote my own. Thanks everyone : )
By placing the hit test code on the movie clip "_item" itself, a small array loop sorts it's position on clip event load, and snaps it to the slot. Super easy.
I am working on an EXTJS grid whose row-color will be set according to a field(status field) value from the table.
User can edit the fields of the row and after clicking update, the color of the row will change according to status field value set for that row.
I need the row background color should be set fetching from a table in db.
Currently I am setting different css class with checking the status field value using following code.
getRowClass: function(record, rowIndex, rp, ds)
{
if( record.get('status') == 'xxxxx' )
{
return 'status-xxxxx';
}
else if( record.get('status') == 'yyyyy' )
{
return 'status-yyyyy';
}
else
{
return 'status-zzzzzz';
}
}
I have the color in the store with the status value for each row.
But I need the color should be fetched from db and set as row background.
Can any one help me to achieve this.
Thanks
If you want to use as row background-color color from row record you will have to set background color of each row td elements after row is rendered.
You can do this in refresh event of gridView. So in grid config you should define something like this:
viewConfig: {
listeners: {
refresh: function(view) {
// get all grid view nodes
var nodes = view.getNodes();
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
// get node record
var record = view.getRecord(node);
// get color from record data
var color = record.get('color');
// get all td elements
var cells = Ext.get(node).query('td');
// set bacground color to all row td elements
for(var j = 0; j < cells.length; j++) {
console.log(cells[j]);
Ext.fly(cells[j]).setStyle('background-color', color);
}
}
}
}
}
Fiddle with live example: https://fiddle.sencha.com/#fiddle/2m8
I want to disable one specific row in datagrid in following manner:
1) Highlight one row with a different color
2) Disable checkbox/radio button selection of that row
3) Disable inline editing of cells present in that row but allow inline editing for other rows.
Pls. help if you have any ideas.
You can use a combination of the following functions to extract stuff
// as example, one of youre items uses identifier:'id' and 'id:10'
var identifier = '10';
var item = store._arrayOfTopLevelItems[10]; // you probably have this allready
var index = grid.getItemIndex(item); // find which index it has in grid
var rowNode = grid.getRowNode(index); // find a DOM element at that index
You will have the <div> as rowNode, it contains a table with cells (as many as you got columns). Set its background-color
The checkbox thing, you will prly know which cell-index it has
var cellNode = dojo.query('td[idx='+cellIndex+']', rowNode)[0];
// with cellType Bool, td contains an input
var checkbox = cellNode.firstChild;
Editing is another store really.. works in focus handlers. To override it, you must keep like an array of rows which you dont want editable (allthough the cell.editable == true).
function inarray(arr, testVal) {
return dojo.some(arr, function(val) { return val == testVal }).length > 0
}
grid.setNonEditable = function (rowIndex) {
if(! inarray(this.nonEditable,rowIndex) )
this.nonEditable.push(rowIndex);
}
grid.setEditable = function (rowIndex) {
this.nonEditable = dojo.filter(this.nonEditable, function(val) { return val != rowIndex; });
}
var originalApply = grid.onApplyEdit
grid.onApplyEdit = function(inValue, inRowIndex) {
if(! inarray(this.nonEditable,inRowIndex) )
originalApply.apply(this, arguments);
}
If you are using dojox.grid.DataGrid you can use canEdit function to disable row editing or cell editing :
grid = new dojox.grid.DataGrid({
canEdit: function(inCell, inRowIndex) {
var item = this.getItem(inRowIndex);
var value = this.store.getValue(item, "name");
return value == null; // allow edit if value is null
}
}